diff --git a/README.md b/README.md index 252203f4..da0707c1 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Alternatively, feel free to contact me on my [Discord Server](https://discord.gg ## License ![gplv3-with-text-136x68](https://user-images.githubusercontent.com/52102823/199572700-4e02ed70-74ef-4d67-991e-3168d93aac0d.png) -Copyright © 2023 Manu098vm +Copyright © 2024 Manu098vm This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/TeraFinder.Core/Classes/ConcurrentList.cs b/TeraFinder.Core/Classes/ConcurrentList.cs new file mode 100644 index 00000000..96c4b314 --- /dev/null +++ b/TeraFinder.Core/Classes/ConcurrentList.cs @@ -0,0 +1,127 @@ +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Immutable; +using System.ComponentModel; + +namespace TeraFinder.Core; + +public class ConcurrentList : ConcurrentBag, IBindingList +{ + public bool IsFinalized { get; private set; } = false; + + private ImmutableArray _binding; + + public void FinalizeElements() + { + _binding = [.. this]; + IsFinalized = true; + } + + public new void Clear() + { + base.Clear(); + _binding = _binding.Clear(); + IsFinalized = false; + } + + object? IList.this[int index] + { + get => GetElement(index); + set => throw new AccessViolationException("The List can not be edited."); + } + + private T GetElement(int index) + { + if (IsFinalized) + return _binding[index]; + + throw new AccessViolationException("The List has not been finalized."); + } + + bool IBindingList.AllowEdit => IsFinalized; + bool IBindingList.AllowNew => !IsFinalized; + bool IBindingList.AllowRemove => false; + bool IBindingList.IsSorted => false; + + ListSortDirection IBindingList.SortDirection => throw new NotImplementedException(); + PropertyDescriptor? IBindingList.SortProperty => throw new NotImplementedException(); + bool IBindingList.SupportsChangeNotification => false; + bool IBindingList.SupportsSearching => IsFinalized; + bool IBindingList.SupportsSorting => false; + + bool IList.IsFixedSize => false; + bool IList.IsReadOnly => false; + + event ListChangedEventHandler IBindingList.ListChanged + { + add => throw new NotImplementedException(); + remove => throw new NotImplementedException(); + } + + int IList.Add(object? value) + { +#pragma warning disable CS8600 +#pragma warning disable CS8604 + Add((T)value); +#pragma warning restore CS8600 +#pragma warning restore CS8604 + return 0; + } + + void IBindingList.AddIndex(PropertyDescriptor property) + { + throw new NotImplementedException(); + } + + object? IBindingList.AddNew() + { + throw new NotImplementedException(); + } + + void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) + { + throw new NotImplementedException(); + } + + void IList.Clear() => Clear(); + + bool IList.Contains(object? value) + { + throw new NotImplementedException(); + } + + int IBindingList.Find(PropertyDescriptor property, object key) + { + throw new NotImplementedException(); + } + + int IList.IndexOf(object? value) + { + throw new NotImplementedException(); + } + + void IList.Insert(int index, object? value) + { + throw new NotImplementedException(); + } + + void IList.Remove(object? value) + { + throw new NotImplementedException(); + } + + void IList.RemoveAt(int index) + { + throw new NotImplementedException(); + } + + void IBindingList.RemoveIndex(PropertyDescriptor property) + { + throw new NotImplementedException(); + } + + void IBindingList.RemoveSort() + { + throw new NotImplementedException(); + } +} diff --git a/TeraFinder.Core/Classes/DataBlocks.cs b/TeraFinder.Core/Classes/DataBlocks.cs index 214f9035..70a4b230 100644 --- a/TeraFinder.Core/Classes/DataBlocks.cs +++ b/TeraFinder.Core/Classes/DataBlocks.cs @@ -2,7 +2,7 @@ namespace TeraFinder.Core; -public class DataBlock +public struct BlockDefinition { public string? Name { get; set; } public uint Key { get; set; } @@ -14,12 +14,12 @@ public class DataBlock } //Thanks Anubis, Lincoln-LM, santacrab2 and Zyro670 for a lot of Pointers and offsets!! -public static class Blocks +public static class BlockDefinitions { public static readonly long[] SaveBlockKeyPointer = [0x47350D8, 0xD8, 0x0, 0x0, 0x30, 0x08]; #region DataSAV - public static readonly DataBlock KTeraRaidPaldea = new() + public static readonly BlockDefinition KTeraRaidPaldea = new() { Name = "KTeraRaidPaldea", Key = 0xCAAC8800, @@ -29,7 +29,7 @@ public static class Blocks Size = 0xC98, }; - public static readonly DataBlock KTeraRaidDLC = new() + public static readonly BlockDefinition KTeraRaidDLC = new() { Name = "KTeraRaidDLC", Key = 0x100B93DA, @@ -39,7 +39,7 @@ public static class Blocks Size = 0x1910, }; - public static readonly DataBlock KTeraRaidBlueberry = new() + public static readonly BlockDefinition KTeraRaidBlueberry = new() { Name = "KTeraRaidBlueberry", Key = 0x100B93DA, @@ -49,7 +49,7 @@ public static class Blocks Size = 0xC90, }; - public static readonly DataBlock KSevenStarRaidsCapture = new() + public static readonly BlockDefinition KSevenStarRaidsCapture = new() { Name = "KSevenStarRaidsCapture", Key = 0x8B14392F, @@ -59,7 +59,7 @@ public static class Blocks Size = 0x5DC0, }; - public static readonly DataBlock KMyStatus = new() + public static readonly BlockDefinition KMyStatus = new() { Name = "KMyStatus", Key = 0xE3E89BD1, @@ -69,7 +69,7 @@ public static class Blocks Size = 0x68, }; - public static readonly DataBlock KOutbreakMainNumActive = new() + public static readonly BlockDefinition KOutbreakMainNumActive = new() { Name = "KOutbreakMainNumActive", Key = 0x6C375C8A, @@ -79,7 +79,7 @@ public static class Blocks Size = 0x01, }; - public static readonly DataBlock KOutbreakDLC1NumActive = new() + public static readonly BlockDefinition KOutbreakDLC1NumActive = new() { Name = "KOutbreakDLC1NumActive", Key = 0xBD7C2A04, @@ -89,7 +89,7 @@ public static class Blocks Size = 0x01, }; - public static readonly DataBlock KOutbreakDLC2NumActive = new() + public static readonly BlockDefinition KOutbreakDLC2NumActive = new() { Name = "KOutbreakDLC2NumActive", Key = 0x19A98811, @@ -101,7 +101,7 @@ public static class Blocks #endregion #region DataBCAT - public static readonly DataBlock KBCATEventRaidIdentifier = new() + public static readonly BlockDefinition KBCATEventRaidIdentifier = new() { Name = "KBCATEventRaidIdentifier", Key = 0x37B99B4D, @@ -111,7 +111,7 @@ public static class Blocks Size = 0x04, }; - public static readonly DataBlock KBCATFixedRewardItemArray = new() + public static readonly BlockDefinition KBCATFixedRewardItemArray = new() { Name = "KBCATFixedRewardItemArray", Key = 0x7D6C2B82, @@ -121,7 +121,7 @@ public static class Blocks Size = 0x6B40, }; - public static readonly DataBlock KBCATLotteryRewardItemArray = new() + public static readonly BlockDefinition KBCATLotteryRewardItemArray = new() { Name = "KBCATLotteryRewardItemArray", Key = 0xA52B4811, @@ -131,7 +131,7 @@ public static class Blocks Size = 0xD0D8, }; - public static readonly DataBlock KBCATRaidEnemyArray = new() + public static readonly BlockDefinition KBCATRaidEnemyArray = new() { Name = "KBCATRaidEnemyArray", Key = 0x0520A1B0, @@ -141,7 +141,7 @@ public static class Blocks Size = 0x7530, }; - public static readonly DataBlock KBCATRaidPriorityArray = new() + public static readonly BlockDefinition KBCATRaidPriorityArray = new() { Name = "KBCATRaidPriorityArray", Key = 0x095451E4, @@ -153,7 +153,7 @@ public static class Blocks #endregion #region UnlockedFlags - public static readonly DataBlock KUnlockedTeraRaidBattles = new() + public static readonly BlockDefinition KUnlockedTeraRaidBattles = new() { Name = "KUnlockedTeraRaidBattles", Key = 0x27025EBF, @@ -163,7 +163,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KUnlockedRaidDifficulty3 = new() + public static readonly BlockDefinition KUnlockedRaidDifficulty3 = new() { Name = "KUnlockedRaidDifficulty3", Key = 0xEC95D8EF, @@ -173,7 +173,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KUnlockedRaidDifficulty4 = new() + public static readonly BlockDefinition KUnlockedRaidDifficulty4 = new() { Name = "KUnlockedRaidDifficulty4", Key = 0xA9428DFE, @@ -183,7 +183,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KUnlockedRaidDifficulty5 = new() + public static readonly BlockDefinition KUnlockedRaidDifficulty5 = new() { Name = "KUnlockedRaidDifficulty5", Key = 0x9535F471, @@ -193,7 +193,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KUnlockedRaidDifficulty6 = new() + public static readonly BlockDefinition KUnlockedRaidDifficulty6 = new() { Name = "KUnlockedRaidDifficulty6", Key = 0x6E7F8220, @@ -205,7 +205,7 @@ public static class Blocks #endregion #region Outbreak1 - public static readonly DataBlock KOutbreak01MainCenterPos = new() + public static readonly BlockDefinition KOutbreak01MainCenterPos = new() { Name = "KOutbreak01MainCenterPos", Key = 0x2ED42F4D, @@ -215,7 +215,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak01MainDummyPos = new() + public static readonly BlockDefinition KOutbreak01MainDummyPos = new() { Name = "KOutbreak01MainDummyPos", Key = 0x4A13BE7C, @@ -225,7 +225,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak01MainSpecies = new() + public static readonly BlockDefinition KOutbreak01MainSpecies = new() { Name = "KOutbreak01MainSpecies", Key = 0x76A2F996, @@ -235,7 +235,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak01MainForm = new() + public static readonly BlockDefinition KOutbreak01MainForm = new() { Name = "KOutbreak01MainForm", Key = 0x29B4615D, @@ -245,7 +245,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak01MainFound = new() + public static readonly BlockDefinition KOutbreak01MainFound = new() { Name = "KOutbreak01MainFound", Key = 0x7E203623, @@ -255,7 +255,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak01MainNumKOed = new() + public static readonly BlockDefinition KOutbreak01MainNumKOed = new() { Name = "KOutbreak01MainNumKOed", Key = 0x4B16FBC2, @@ -265,7 +265,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak01MainTotalSpawns = new() + public static readonly BlockDefinition KOutbreak01MainTotalSpawns = new() { Name = "KOutbreak01MainTotalSpawns", Key = 0xB7DC495A, @@ -277,7 +277,7 @@ public static class Blocks #endregion #region Outbreak2 - public static readonly DataBlock KOutbreak02MainCenterPos = new() + public static readonly BlockDefinition KOutbreak02MainCenterPos = new() { Name = "KOutbreak02MainCenterPos", Key = 0x2ED5F198, @@ -287,7 +287,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak02MainDummyPos = new() + public static readonly BlockDefinition KOutbreak02MainDummyPos = new() { Name = "KOutbreak02MainDummyPos", Key = 0x4A118F71, @@ -297,7 +297,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak02MainSpecies = new() + public static readonly BlockDefinition KOutbreak02MainSpecies = new() { Name = "KOutbreak02MainSpecies", Key = 0x76A0BCF3, @@ -307,7 +307,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak02MainForm = new() + public static readonly BlockDefinition KOutbreak02MainForm = new() { Name = "KOutbreak02MainForm", Key = 0x29B84368, @@ -317,7 +317,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak02MainFound = new() + public static readonly BlockDefinition KOutbreak02MainFound = new() { Name = "KOutbreak02MainFound", Key = 0x7E22DF86, @@ -327,7 +327,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak02MainNumKOed = new() + public static readonly BlockDefinition KOutbreak02MainNumKOed = new() { Name = "KOutbreak02MainNumKOed", Key = 0x4B14BF1F, @@ -337,7 +337,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak02MainTotalSpawns = new() + public static readonly BlockDefinition KOutbreak02MainTotalSpawns = new() { Name = "KOutbreak02MainTotalSpawns", Key = 0xB7DA0CB7, @@ -349,7 +349,7 @@ public static class Blocks #endregion #region Outbreak3 - public static readonly DataBlock KOutbreak03MainCenterPos = new() + public static readonly BlockDefinition KOutbreak03MainCenterPos = new() { Name = "KOutbreak03MainCenterPos", Key = 0x2ECE09D3, @@ -359,7 +359,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak03MainDummyPos = new() + public static readonly BlockDefinition KOutbreak03MainDummyPos = new() { Name = "KOutbreak03MainDummyPos", Key = 0x4A0E135A, @@ -369,7 +369,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak03MainSpecies = new() + public static readonly BlockDefinition KOutbreak03MainSpecies = new() { Name = "KOutbreak03MainSpecies", Key = 0x76A97E38, @@ -379,7 +379,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak03MainForm = new() + public static readonly BlockDefinition KOutbreak03MainForm = new() { Name = "KOutbreak03MainForm", Key = 0x29AF8223, @@ -389,7 +389,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak03MainFound = new() + public static readonly BlockDefinition KOutbreak03MainFound = new() { Name = "KOutbreak03MainFound", Key = 0x7E25155D, @@ -399,7 +399,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak03MainNumKOed = new() + public static readonly BlockDefinition KOutbreak03MainNumKOed = new() { Name = "KOutbreak03MainNumKOed", Key = 0x4B1CA6E4, @@ -409,7 +409,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak03MainTotalSpawns = new() + public static readonly BlockDefinition KOutbreak03MainTotalSpawns = new() { Name = "KOutbreak03MainTotalSpawns", Key = 0xB7E1F47C, @@ -421,7 +421,7 @@ public static class Blocks #endregion #region Outbreak4 - public static readonly DataBlock KOutbreak04MainCenterPos = new() + public static readonly BlockDefinition KOutbreak04MainCenterPos = new() { Name = "KOutbreak04MainCenterPos", Key = 0x2ED04676, @@ -431,7 +431,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak04MainDummyPos = new() + public static readonly BlockDefinition KOutbreak04MainDummyPos = new() { Name = "KOutbreak04MainDummyPos", Key = 0x4A0BD6B7, @@ -441,7 +441,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak04MainSpecies = new() + public static readonly BlockDefinition KOutbreak04MainSpecies = new() { Name = "KOutbreak04MainSpecies", Key = 0x76A6E26D, @@ -451,7 +451,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak04MainForm = new() + public static readonly BlockDefinition KOutbreak04MainForm = new() { Name = "KOutbreak04MainForm", Key = 0x29B22B86, @@ -461,7 +461,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak04MainFound = new() + public static readonly BlockDefinition KOutbreak04MainFound = new() { Name = "KOutbreak04MainFound", Key = 0x7E28F768, @@ -471,7 +471,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak04MainNumKOed = new() + public static readonly BlockDefinition KOutbreak04MainNumKOed = new() { Name = "KOutbreak04MainNumKOed", Key = 0x4B1A77D9, @@ -481,7 +481,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak04MainTotalSpawns = new() + public static readonly BlockDefinition KOutbreak04MainTotalSpawns = new() { Name = "KOutbreak04MainTotalSpawns", Key = 0xB7DFC571, @@ -493,7 +493,7 @@ public static class Blocks #endregion #region Outbreak5 - public static readonly DataBlock KOutbreak05MainCenterPos = new() + public static readonly BlockDefinition KOutbreak05MainCenterPos = new() { Name = "KOutbreak05MainCenterPos", Key = 0x2EC78531, @@ -503,7 +503,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak05MainDummyPos = new() + public static readonly BlockDefinition KOutbreak05MainDummyPos = new() { Name = "KOutbreak05MainDummyPos", Key = 0x4A1FFBD8, @@ -513,7 +513,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak05MainSpecies = new() + public static readonly BlockDefinition KOutbreak05MainSpecies = new() { Name = "KOutbreak05MainSpecies", Key = 0x76986F3A, @@ -523,7 +523,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak05MainForm = new() + public static readonly BlockDefinition KOutbreak05MainForm = new() { Name = "KOutbreak05MainForm", Key = 0x29A9D701, @@ -533,7 +533,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak05MainFound = new() + public static readonly BlockDefinition KOutbreak05MainFound = new() { Name = "KOutbreak05MainFound", Key = 0x7E13F8C7, @@ -543,7 +543,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak05MainNumKOed = new() + public static readonly BlockDefinition KOutbreak05MainNumKOed = new() { Name = "KOutbreak05MainNumKOed", Key = 0x4B23391E, @@ -553,7 +553,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak05MainTotalSpawns = new() + public static readonly BlockDefinition KOutbreak05MainTotalSpawns = new() { Name = "KOutbreak05MainTotalSpawns", Key = 0xB7E886B6, @@ -565,7 +565,7 @@ public static class Blocks #endregion #region Outbreak6 - public static readonly DataBlock KOutbreak06MainCenterPos = new() + public static readonly BlockDefinition KOutbreak06MainCenterPos = new() { Name = "KOutbreak06MainCenterPos", Key = 0x2ECB673C, @@ -575,7 +575,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak06MainDummyPos = new() + public static readonly BlockDefinition KOutbreak06MainDummyPos = new() { Name = "KOutbreak06MainDummyPos", Key = 0x4A1C868D, @@ -585,7 +585,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak06MainSpecies = new() + public static readonly BlockDefinition KOutbreak06MainSpecies = new() { Name = "KOutbreak06MainSpecies", Key = 0x76947F97, @@ -595,7 +595,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak06MainForm = new() + public static readonly BlockDefinition KOutbreak06MainForm = new() { Name = "KOutbreak06MainForm", Key = 0x29AB994C, @@ -605,7 +605,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak06MainFound = new() + public static readonly BlockDefinition KOutbreak06MainFound = new() { Name = "KOutbreak06MainFound", Key = 0x7E16A22A, @@ -615,7 +615,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak06MainNumKOed = new() + public static readonly BlockDefinition KOutbreak06MainNumKOed = new() { Name = "KOutbreak06MainNumKOed", Key = 0x4B208FBB, @@ -625,7 +625,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak06MainTotalSpawns = new() + public static readonly BlockDefinition KOutbreak06MainTotalSpawns = new() { Name = "KOutbreak06MainTotalSpawns", Key = 0xB7E49713, @@ -637,7 +637,7 @@ public static class Blocks #endregion #region Outbreak7 - public static readonly DataBlock KOutbreak07MainCenterPos = new() + public static readonly BlockDefinition KOutbreak07MainCenterPos = new() { Name = "KOutbreak07MainCenterPos", Key = 0x2EC1CC77, @@ -647,7 +647,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak07MainDummyPos = new() + public static readonly BlockDefinition KOutbreak07MainDummyPos = new() { Name = "KOutbreak07MainDummyPos", Key = 0x4A1A50B6, @@ -657,7 +657,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak07MainSpecies = new() + public static readonly BlockDefinition KOutbreak07MainSpecies = new() { Name = "KOutbreak07MainSpecies", Key = 0x769D40DC, @@ -667,7 +667,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak07MainForm = new() + public static readonly BlockDefinition KOutbreak07MainForm = new() { Name = "KOutbreak07MainForm", Key = 0x29A344C7, @@ -677,7 +677,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak07MainFound = new() + public static readonly BlockDefinition KOutbreak07MainFound = new() { Name = "KOutbreak07MainFound", Key = 0x7E1A8B01, @@ -687,7 +687,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak07MainNumKOed = new() + public static readonly BlockDefinition KOutbreak07MainNumKOed = new() { Name = "KOutbreak07MainNumKOed", Key = 0x4B28E440, @@ -697,7 +697,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak07MainTotalSpawns = new() + public static readonly BlockDefinition KOutbreak07MainTotalSpawns = new() { Name = "KOutbreak07MainTotalSpawns", Key = 0xB7EE31D8, @@ -709,7 +709,7 @@ public static class Blocks #endregion #region Outbreak8 - public static readonly DataBlock KOutbreak08MainCenterPos = new() + public static readonly BlockDefinition KOutbreak08MainCenterPos = new() { Name = "KOutbreak08MainCenterPos", Key = 0x2EC5BC1A, @@ -719,7 +719,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak08MainDummyPos = new() + public static readonly BlockDefinition KOutbreak08MainDummyPos = new() { Name = "KOutbreak08MainDummyPos", Key = 0x4A166113, @@ -729,7 +729,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak08MainSpecies = new() + public static readonly BlockDefinition KOutbreak08MainSpecies = new() { Name = "KOutbreak08MainSpecies", Key = 0x769B11D1, @@ -739,7 +739,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak08MainForm = new() + public static readonly BlockDefinition KOutbreak08MainForm = new() { Name = "KOutbreak08MainForm", Key = 0x29A5EE2A, @@ -749,7 +749,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak08MainFound = new() + public static readonly BlockDefinition KOutbreak08MainFound = new() { Name = "KOutbreak08MainFound", Key = 0x7E1C4D4C, @@ -759,7 +759,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak08MainNumKOed = new() + public static readonly BlockDefinition KOutbreak08MainNumKOed = new() { Name = "KOutbreak08MainNumKOed", Key = 0x4B256EF5, @@ -769,7 +769,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak08MainTotalSpawns = new() + public static readonly BlockDefinition KOutbreak08MainTotalSpawns = new() { Name = "KOutbreak08MainTotalSpawns", Key = 0xB7EABC8D, @@ -781,7 +781,7 @@ public static class Blocks #endregion #region Outbreak01DLC1 - public static readonly DataBlock KOutbreak01DLC1CenterPos = new() + public static readonly BlockDefinition KOutbreak01DLC1CenterPos = new() { Name = "KOutbreak01DLC1CenterPos", Key = 0x411A0C07, @@ -791,7 +791,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak01DLC1DummyPos = new() + public static readonly BlockDefinition KOutbreak01DLC1DummyPos = new() { Name = "KOutbreak01DLC1DummyPos", Key = 0x632EFBFE, @@ -801,7 +801,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak01DLC1Species = new() + public static readonly BlockDefinition KOutbreak01DLC1Species = new() { Name = "KOutbreak01DLC1Species", Key = 0x37E55F64, @@ -811,7 +811,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak01DLC1Form = new() + public static readonly BlockDefinition KOutbreak01DLC1Form = new() { Name = "KOutbreak01DLC1Form", Key = 0x69A930AB, @@ -821,7 +821,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak01DLC1Found = new() + public static readonly BlockDefinition KOutbreak01DLC1Found = new() { Name = "KOutbreak01DLC1Found", Key = 0x7B688081, @@ -831,7 +831,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak01DLC1NumKOed = new() + public static readonly BlockDefinition KOutbreak01DLC1NumKOed = new() { Name = "KOutbreak01DLC1NumKOed", Key = 0xB29D7978, @@ -841,7 +841,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak01DLC1TotalSpawns = new() + public static readonly BlockDefinition KOutbreak01DLC1TotalSpawns = new() { Name = "KOutbreak01DLC1TotalSpawns", Key = 0x9E0CEC77, @@ -853,7 +853,7 @@ public static class Blocks #endregion #region Outbreak02DLC1 - public static readonly DataBlock KOutbreak02DLC1CenterPos = new() + public static readonly BlockDefinition KOutbreak02DLC1CenterPos = new() { Name = "KOutbreak02DLC1CenterPos", Key = 0x411CB56A, @@ -863,7 +863,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak02DLC1DummyPos = new() + public static readonly BlockDefinition KOutbreak02DLC1DummyPos = new() { Name = "KOutbreak02DLC1DummyPos", Key = 0x632D2C1B, @@ -873,7 +873,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak02DLC1Species = new() + public static readonly BlockDefinition KOutbreak02DLC1Species = new() { Name = "KOutbreak02DLC1Species", Key = 0x37E33059, @@ -883,7 +883,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak02DLC1Form = new() + public static readonly BlockDefinition KOutbreak02DLC1Form = new() { Name = "KOutbreak02DLC1Form", Key = 0x69AD204E, @@ -893,7 +893,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak02DLC1Found = new() + public static readonly BlockDefinition KOutbreak02DLC1Found = new() { Name = "KOutbreak02DLC1Found", Key = 0x7B6A42CC, @@ -903,7 +903,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak02DLC1NumKOed = new() + public static readonly BlockDefinition KOutbreak02DLC1NumKOed = new() { Name = "KOutbreak02DLC1NumKOed", Key = 0xB29ADDAD, @@ -913,7 +913,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak02DLC1TotalSpawns = new() + public static readonly BlockDefinition KOutbreak02DLC1TotalSpawns = new() { Name = "KOutbreak02DLC1TotalSpawns", Key = 0x9E10DC1A, @@ -925,7 +925,7 @@ public static class Blocks #endregion #region Outbreak03DLC1 - public static readonly DataBlock KOutbreak03DLC1CenterPos = new() + public static readonly BlockDefinition KOutbreak03DLC1CenterPos = new() { Name = "KOutbreak03DLC1CenterPos", Key = 0x411EEB41, @@ -935,7 +935,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak03DLC1DummyPos = new() + public static readonly BlockDefinition KOutbreak03DLC1DummyPos = new() { Name = "KOutbreak03DLC1DummyPos", Key = 0x633580A0, @@ -945,7 +945,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak03DLC1Species = new() + public static readonly BlockDefinition KOutbreak03DLC1Species = new() { Name = "KOutbreak03DLC1Species", Key = 0x37DFB442, @@ -955,7 +955,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak03DLC1Form = new() + public static readonly BlockDefinition KOutbreak03DLC1Form = new() { Name = "KOutbreak03DLC1Form", Key = 0x69AEE965, @@ -965,7 +965,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak03DLC1Found = new() + public static readonly BlockDefinition KOutbreak03DLC1Found = new() { Name = "KOutbreak03DLC1Found", Key = 0x7B61EE47, @@ -975,7 +975,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak03DLC1NumKOed = new() + public static readonly BlockDefinition KOutbreak03DLC1NumKOed = new() { Name = "KOutbreak03DLC1NumKOed", Key = 0xB298A7D6, @@ -985,7 +985,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak03DLC1TotalSpawns = new() + public static readonly BlockDefinition KOutbreak03DLC1TotalSpawns = new() { Name = "KOutbreak03DLC1TotalSpawns", Key = 0x9E12A531, @@ -997,7 +997,7 @@ public static class Blocks #endregion #region Outbreak04DLC1 - public static readonly DataBlock KOutbreak04DLC1CenterPos = new() + public static readonly BlockDefinition KOutbreak04DLC1CenterPos = new() { Name = "KOutbreak04DLC1CenterPos", Key = 0x4122608C, @@ -1007,7 +1007,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak04DLC1DummyPos = new() + public static readonly BlockDefinition KOutbreak04DLC1DummyPos = new() { Name = "KOutbreak04DLC1DummyPos", Key = 0x6332E4D5, @@ -1017,7 +1017,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak04DLC1Species = new() + public static readonly BlockDefinition KOutbreak04DLC1Species = new() { Name = "KOutbreak04DLC1Species", Key = 0x37DD779F, @@ -1027,7 +1027,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak04DLC1Form = new() + public static readonly BlockDefinition KOutbreak04DLC1Form = new() { Name = "KOutbreak04DLC1Form", Key = 0x69B2CB70, @@ -1037,7 +1037,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak04DLC1Found = new() + public static readonly BlockDefinition KOutbreak04DLC1Found = new() { Name = "KOutbreak04DLC1Found", Key = 0x7B6497AA, @@ -1047,7 +1047,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak04DLC1NumKOed = new() + public static readonly BlockDefinition KOutbreak04DLC1NumKOed = new() { Name = "KOutbreak04DLC1NumKOed", Key = 0xB294B833, @@ -1057,7 +1057,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak04DLC1TotalSpawns = new() + public static readonly BlockDefinition KOutbreak04DLC1TotalSpawns = new() { Name = "KOutbreak04DLC1TotalSpawns", Key = 0x9E16873C, @@ -1069,7 +1069,7 @@ public static class Blocks #endregion #region Outbreak01DLC2 - public static readonly DataBlock KOutbreak01DLC2CenterPos = new() + public static readonly BlockDefinition KOutbreak01DLC2CenterPos = new() { Name = "KOutbreak01DLC2CenterPos", Key = 0xCE463C0C, @@ -1079,7 +1079,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak01DLC2DummyPos = new() + public static readonly BlockDefinition KOutbreak01DLC2DummyPos = new() { Name = "KOutbreak01DLC2DummyPos", Key = 0x0B0C71CB, @@ -1089,7 +1089,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak01DLC2Species = new() + public static readonly BlockDefinition KOutbreak01DLC2Species = new() { Name = "KOutbreak01DLC2Species", Key = 0xB8E99C8D, @@ -1099,7 +1099,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak01DLC2Form = new() + public static readonly BlockDefinition KOutbreak01DLC2Form = new() { Name = "KOutbreak01DLC2Form", Key = 0xEFA6983A, @@ -1109,7 +1109,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak01DLC2Found = new() + public static readonly BlockDefinition KOutbreak01DLC2Found = new() { Name = "KOutbreak01DLC2Found", Key = 0x32074910, @@ -1119,7 +1119,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak01DLC2NumKOed = new() + public static readonly BlockDefinition KOutbreak01DLC2NumKOed = new() { Name = "KOutbreak01DLC2NumKOed", Key = 0x4EF9BC25, @@ -1129,7 +1129,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak01DLC2TotalSpawns = new() + public static readonly BlockDefinition KOutbreak01DLC2TotalSpawns = new() { Name = "KOutbreak01DLC2TotalSpawns", Key = 0x4385E0AD, @@ -1141,7 +1141,7 @@ public static class Blocks #endregion #region Outbreak02DLC2 - public static readonly DataBlock KOutbreak02DLC2CenterPos = new() + public static readonly BlockDefinition KOutbreak02DLC2CenterPos = new() { Name = "KOutbreak02DLC2CenterPos", Key = 0xCE42C6C1, @@ -1151,7 +1151,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak02DLC2DummyPos = new() + public static readonly BlockDefinition KOutbreak02DLC2DummyPos = new() { Name = "KOutbreak02DLC2DummyPos", Key = 0x0B10616E, @@ -1161,7 +1161,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak02DLC2Species = new() + public static readonly BlockDefinition KOutbreak02DLC2Species = new() { Name = "KOutbreak02DLC2Species", Key = 0xB8ED11D8, @@ -1171,7 +1171,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak02DLC2Form = new() + public static readonly BlockDefinition KOutbreak02DLC2Form = new() { Name = "KOutbreak02DLC2Form", Key = 0xEFA2A897, @@ -1181,7 +1181,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak02DLC2Found = new() + public static readonly BlockDefinition KOutbreak02DLC2Found = new() { Name = "KOutbreak02DLC2Found", Key = 0x32051A05, @@ -1191,7 +1191,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak02DLC2NumKOed = new() + public static readonly BlockDefinition KOutbreak02DLC2NumKOed = new() { Name = "KOutbreak02DLC2NumKOed", Key = 0x4EFBEB30, @@ -1201,7 +1201,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak02DLC2TotalSpawns = new() + public static readonly BlockDefinition KOutbreak02DLC2TotalSpawns = new() { Name = "KOutbreak02DLC2TotalSpawns", Key = 0x43887C78, @@ -1213,7 +1213,7 @@ public static class Blocks #endregion #region Outbreak03DLC2 - public static readonly DataBlock KOutbreak03DLC2CenterPos = new() + public static readonly BlockDefinition KOutbreak03DLC2CenterPos = new() { Name = "KOutbreak03DLC2CenterPos", Key = 0xCE4090EA, @@ -1223,7 +1223,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak03DLC2DummyPos = new() + public static readonly BlockDefinition KOutbreak03DLC2DummyPos = new() { Name = "KOutbreak03DLC2DummyPos", Key = 0x0B130405, @@ -1233,7 +1233,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak03DLC2Species = new() + public static readonly BlockDefinition KOutbreak03DLC2Species = new() { Name = "KOutbreak03DLC2Species", Key = 0xB8E37713, @@ -1243,7 +1243,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak03DLC2Form = new() + public static readonly BlockDefinition KOutbreak03DLC2Form = new() { Name = "KOutbreak03DLC2Form", Key = 0xEFAB69DC, @@ -1253,7 +1253,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak03DLC2Found = new() + public static readonly BlockDefinition KOutbreak03DLC2Found = new() { Name = "KOutbreak03DLC2Found", Key = 0x3202776E, @@ -1263,7 +1263,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak03DLC2NumKOed = new() + public static readonly BlockDefinition KOutbreak03DLC2NumKOed = new() { Name = "KOutbreak03DLC2NumKOed", Key = 0x4EF4036B, @@ -1273,7 +1273,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak03DLC2TotalSpawns = new() + public static readonly BlockDefinition KOutbreak03DLC2TotalSpawns = new() { Name = "KOutbreak03DLC2TotalSpawns", Key = 0x437FBB33, @@ -1285,7 +1285,7 @@ public static class Blocks #endregion #region Outbreak04DLC2 - public static readonly DataBlock KOutbreak04DLC2CenterPos = new() + public static readonly BlockDefinition KOutbreak04DLC2CenterPos = new() { Name = "KOutbreak04DLC2CenterPos", Key = 0xCE3DE787, @@ -1295,7 +1295,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak04DLC2DummyPos = new() + public static readonly BlockDefinition KOutbreak04DLC2DummyPos = new() { Name = "KOutbreak04DLC2DummyPos", Key = 0x0B153310, @@ -1305,7 +1305,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak04DLC2Species = new() + public static readonly BlockDefinition KOutbreak04DLC2Species = new() { Name = "KOutbreak04DLC2Species", Key = 0xB8E766B6, @@ -1315,7 +1315,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak04DLC2Form = new() + public static readonly BlockDefinition KOutbreak04DLC2Form = new() { Name = "KOutbreak04DLC2Form", Key = 0xEFA93AD1, @@ -1325,7 +1325,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak04DLC2Found = new() + public static readonly BlockDefinition KOutbreak04DLC2Found = new() { Name = "KOutbreak04DLC2Found", Key = 0x31FE87CB, @@ -1335,7 +1335,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak04DLC2NumKOed = new() + public static readonly BlockDefinition KOutbreak04DLC2NumKOed = new() { Name = "KOutbreak04DLC2NumKOed", Key = 0x4EF6400E, @@ -1345,7 +1345,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak04DLC2TotalSpawns = new() + public static readonly BlockDefinition KOutbreak04DLC2TotalSpawns = new() { Name = "KOutbreak04DLC2TotalSpawns", Key = 0x4383AAD6, @@ -1357,7 +1357,7 @@ public static class Blocks #endregion #region Outbreak05DLC2 - public static readonly DataBlock KOutbreak05DLC2CenterPos = new() + public static readonly BlockDefinition KOutbreak05DLC2CenterPos = new() { Name = "KOutbreak05DLC2CenterPos", Key = 0xCE513328, @@ -1367,7 +1367,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak05DLC2DummyPos = new() + public static readonly BlockDefinition KOutbreak05DLC2DummyPos = new() { Name = "KOutbreak05DLC2DummyPos", Key = 0x0B01E76F, @@ -1377,7 +1377,7 @@ public static class Blocks Size = 12, }; - public static readonly DataBlock KOutbreak05DLC2Species = new() + public static readonly BlockDefinition KOutbreak05DLC2Species = new() { Name = "KOutbreak05DLC2Species", Key = 0xB8DEA571, @@ -1387,7 +1387,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak05DLC2Form = new() + public static readonly BlockDefinition KOutbreak05DLC2Form = new() { Name = "KOutbreak05DLC2Form", Key = 0xEFB12296, @@ -1397,7 +1397,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak05DLC2Found = new() + public static readonly BlockDefinition KOutbreak05DLC2Found = new() { Name = "KOutbreak05DLC2Found", Key = 0x31FCBEB4, @@ -1407,7 +1407,7 @@ public static class Blocks Size = 1, }; - public static readonly DataBlock KOutbreak05DLC2NumKOed = new() + public static readonly BlockDefinition KOutbreak05DLC2NumKOed = new() { Name = "KOutbreak05DLC2NumKOed", Key = 0x4EED7EC9, @@ -1417,7 +1417,7 @@ public static class Blocks Size = 4, }; - public static readonly DataBlock KOutbreak05DLC2TotalSpawns = new() + public static readonly BlockDefinition KOutbreak05DLC2TotalSpawns = new() { Name = "KOutbreak05DLC2TotalSpawns", Key = 0x437A1011, @@ -1429,7 +1429,7 @@ public static class Blocks #endregion #region KBCATOutbreaks - public static readonly DataBlock KBCATOutbreakZonesPaldea = new() + public static readonly BlockDefinition KBCATOutbreakZonesPaldea = new() { Name = "KBCATOutbreakZonesPaldea", Key = 0x3FDC5DFF, @@ -1439,7 +1439,7 @@ public static class Blocks Size = 0x300, }; - public static readonly DataBlock KBCATOutbreakZonesKitakami = new() + public static readonly BlockDefinition KBCATOutbreakZonesKitakami = new() { Name = "KBCATOutbreakZonesKitakami", Key = 0xF9F156A3, @@ -1449,7 +1449,7 @@ public static class Blocks Size = 0x300, }; - public static readonly DataBlock KBCATOutbreakZonesBlueberry = new() + public static readonly BlockDefinition KBCATOutbreakZonesBlueberry = new() { Name = "KBCATOutbreakZonesBlueberry", Key = 0x1B45E41C, @@ -1459,7 +1459,7 @@ public static class Blocks Size = 0x300, }; - public static readonly DataBlock KBCATOutbreakPokeData = new() + public static readonly BlockDefinition KBCATOutbreakPokeData = new() { Name = "KBCATOutbreakPokeData", Key = 0x6C1A131B, @@ -1469,7 +1469,7 @@ public static class Blocks Size = 0xE18, }; - public static readonly DataBlock KBCATOutbreakEnabled = new() + public static readonly BlockDefinition KBCATOutbreakEnabled = new() { Name = "KBCATOutbreakEnabled", Key = 0x61552076, diff --git a/TeraFinder.Core/Classes/Encounter9RNG.cs b/TeraFinder.Core/Classes/Encounter9RNG.cs deleted file mode 100644 index c69532eb..00000000 --- a/TeraFinder.Core/Classes/Encounter9RNG.cs +++ /dev/null @@ -1,146 +0,0 @@ -using PKHeX.Core; - -namespace TeraFinder.Core; - -//Tera Finder Adaptations of the Encounter9RNG class from PKHeX -//https://github.com/kwsch/PKHeX/blob/master/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs -public static class Encounter9RNG -{ - private static readonly PersonalTable9SV Table = PersonalTable.SV; - - public static bool GenerateData(TeraDetails pk, in GenerateParam9 enc, uint id32, in ulong seed) - { - var criteria = EncounterCriteria.Unrestricted; - var rand = new Xoroshiro128Plus(seed); - pk.EC = (uint)rand.NextInt(uint.MaxValue); - pk.PID = GetAdaptedPID(ref rand, pk, id32, enc); - - const int UNSET = -1; - const int MAX = 31; - Span ivs = [UNSET, UNSET, UNSET, UNSET, UNSET, UNSET]; - if (enc.IVs.IsSpecified) - { - enc.IVs.CopyToSpeedLast(ivs); - } - else - { - for (int i = 0; i < enc.FlawlessIVs; i++) - { - int index; - do { index = (int)rand.NextInt(6); } - while (ivs[index] != UNSET); - ivs[index] = MAX; - } - } - - for (int i = 0; i < 6; i++) - { - if (ivs[i] == UNSET) - ivs[i] = (int)rand.NextInt(MAX + 1); - } - - if (!criteria.IsIVsCompatibleSpeedLast(ivs, 9)) - return false; - - pk.HP = ivs[0]; - pk.ATK = ivs[1]; - pk.DEF = ivs[2]; - pk.SPA = ivs[3]; - pk.SPD = ivs[4]; - pk.SPE = ivs[5]; - - int abil = enc.Ability switch - { - AbilityPermission.Any12H => (int)rand.NextInt(3) << 1, - AbilityPermission.Any12 => (int)rand.NextInt(2) << 1, - _ => (int)enc.Ability, - }; - - pk.RefreshAbility(abil >> 1); - - var gender_ratio = enc.GenderRatio; - pk.Gender = gender_ratio switch - { - PersonalInfo.RatioMagicGenderless => Gender.Genderless, - PersonalInfo.RatioMagicFemale => Gender.Female, - PersonalInfo.RatioMagicMale => Gender.Male, - _ => GetGender(gender_ratio, rand.NextInt(100)), - }; ; - - var nature = enc.Nature != Nature.Random ? enc.Nature : enc.Species == (int)Species.Toxtricity - ? ToxtricityUtil.GetRandomNature(ref rand, pk.Form) - : (Nature)rand.NextInt(25); - if (criteria.Nature != Nature.Random && nature != criteria.Nature) - return false; - pk.Nature = (byte)(pk.StatNature = nature); - - pk.Height = enc.Height != 0 ? enc.Height : (byte)(rand.NextInt(0x81) + rand.NextInt(0x80)); - pk.Weight = enc.Weight != 0 ? enc.Weight : (byte)(rand.NextInt(0x81) + rand.NextInt(0x80)); - pk.Scale = enc.ScaleType.GetSizeValue(enc.Scale, ref rand); - return true; - } - - private static uint GetAdaptedPID(ref Xoroshiro128Plus rand, TeraDetails pk, uint id32, in GenerateParam9 enc) - { - var fakeTID = (uint)rand.NextInt(); - uint pid = (uint)rand.NextInt(); - if (enc.Shiny == Shiny.Random) // let's decide if it's shiny or not! - { - int i = 1; - bool isShiny; - uint xor; - while (true) - { - xor = ShinyUtil.GetShinyXor(pid, fakeTID); - isShiny = xor < 16; - if (isShiny) - { - if (xor != 0) - xor = 1; - break; - } - if (i >= enc.RollCount) - break; - pid = (uint)rand.NextInt(); - i++; - } - ShinyUtil.ForceShinyState(isShiny, ref pid, id32, xor); - pk.Shiny = xor > 15 ? TeraShiny.No : xor == 0 ? TeraShiny.Square : TeraShiny.Star; - } - else if (enc.Shiny == Shiny.Always) - { - var tid = (ushort)fakeTID; - var sid = (ushort)(fakeTID >> 16); - if (!ShinyUtil.GetIsShiny(fakeTID, pid)) // battled - pid = ShinyUtil.GetShinyPID(tid, sid, pid, 0); - if (!ShinyUtil.GetIsShiny(id32, pid)) // captured - pid = ShinyUtil.GetShinyPID(TeraUtil.GetTID16(id32), TeraUtil.GetSID16(id32), pid, ShinyUtil.GetShinyXor(pid, fakeTID) == 0 ? 0u : 1u); - } - else // Never - { - if (ShinyUtil.GetIsShiny(fakeTID, pid)) // battled - pid ^= 0x1000_0000; - if (ShinyUtil.GetIsShiny(id32, pid)) // captured - pid ^= 0x1000_0000; - } - return pid; - } - - private static void RefreshAbility(this TeraDetails pkm, int n) - { - var pi = Table[pkm.Species, pkm.Form]; - if ((uint)n < pi.AbilityCount) - pkm.Ability = pi.GetAbilityAtIndex(n); - } - - private static Gender GetGender(in int ratio, in ulong rand100) => ratio switch - { - 0x1F => rand100 < 12 ? Gender.Female : Gender.Male, // 12.5% - 0x3F => rand100 < 25 ? Gender.Female : Gender.Male, // 25% - 0x7F => rand100 < 50 ? Gender.Female : Gender.Male, // 50% - 0xBF => rand100 < 75 ? Gender.Female : Gender.Male, // 75% - 0xE1 => rand100 < 89 ? Gender.Female : Gender.Male, // 87.5% - - _ => throw new ArgumentOutOfRangeException(nameof(ratio)), - }; -} diff --git a/TeraFinder.Core/Classes/EncounterDist9.cs b/TeraFinder.Core/Classes/EncounterDist9.cs deleted file mode 100644 index 21712188..00000000 --- a/TeraFinder.Core/Classes/EncounterDist9.cs +++ /dev/null @@ -1,304 +0,0 @@ -using PKHeX.Core; -using static PKHeX.Core.AbilityPermission; -using static System.Buffers.Binary.BinaryPrimitives; - -//Extension of https://github.com/kwsch/PKHeX/blob/master/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterDist9.cs -namespace TeraFinder.Core; - -public sealed record EncounterDist9 : IEncounterable, IEncounterConvertible, ITeraRaid9, IExtendedTeraRaid9, IMoveset, IFlawlessIVCount, IFixedGender, IFixedNature -{ - //TeraFinder Serialization - public uint Identifier { get; private init; } - public ulong FixedRewardHash { get; private init; } - public ulong LotteryRewardHash { get; private init; } - public int Item { get; private init; } - public required ExtraMoves ExtraMoves { get; init; } - - public int Generation => 9; - ushort ILocation.Location => Location; - public const ushort Location = Locations.TeraCavern9; - public EntityContext Context => EntityContext.Gen9; - public GameVersion Version => GameVersion.SV; - public bool IsDistribution => Index != 0; - public Ball FixedBall => Ball.None; - public bool EggEncounter => false; - public bool IsShiny => Shiny == Shiny.Always; - public int EggLocation => 0; - - public required ushort Species { get; init; } - public required byte Form { get; init; } - public required byte Gender { get; init; } - public required AbilityPermission Ability { get; init; } - public required byte FlawlessIVCount { get; init; } - public required Shiny Shiny { get; init; } - public required Nature Nature { get; init; } - public required byte Level { get; init; } - public required Moveset Moves { get; init; } - public required IndividualValueSet IVs { get; init; } - public required GemType TeraType { get; init; } - public byte Index { get; private init; } - public byte Stars { get; private init; } - public byte RandRate { get; private init; } // weight chance of this encounter - - /// Indicates how the value is used, if at all. - public SizeType9 ScaleType { get; private init; } - /// Used only for == - public byte Scale { get; private init; } - - public ushort RandRate0MinScarlet { get; private init; } - public ushort RandRate0MinViolet { get; private init; } - public ushort RandRate0TotalScarlet { get; private init; } - public ushort RandRate0TotalViolet { get; private init; } - - public ushort RandRate1MinScarlet { get; private init; } - public ushort RandRate1MinViolet { get; private init; } - public ushort RandRate1TotalScarlet { get; private init; } - public ushort RandRate1TotalViolet { get; private init; } - - public ushort RandRate2MinScarlet { get; private init; } - public ushort RandRate2MinViolet { get; private init; } - public ushort RandRate2TotalScarlet { get; private init; } - public ushort RandRate2TotalViolet { get; private init; } - - public ushort RandRate3MinScarlet { get; private init; } - public ushort RandRate3MinViolet { get; private init; } - public ushort RandRate3TotalScarlet { get; private init; } - public ushort RandRate3TotalViolet { get; private init; } - - public string Name => "Distribution Tera Raid Encounter"; - public string LongName => Name; - public byte LevelMin => Level; - public byte LevelMax => Level; - - public ushort GetRandRateTotalScarlet(int stage) => stage switch - { - 0 => RandRate0TotalScarlet, - 1 => RandRate1TotalScarlet, - 2 => RandRate2TotalScarlet, - 3 => RandRate3TotalScarlet, - _ => throw new ArgumentOutOfRangeException(nameof(stage)), - }; - - public ushort GetRandRateTotalViolet(int stage) => stage switch - { - 0 => RandRate0TotalViolet, - 1 => RandRate1TotalViolet, - 2 => RandRate2TotalViolet, - 3 => RandRate3TotalViolet, - _ => throw new ArgumentOutOfRangeException(nameof(stage)), - }; - - public ushort GetRandRateMinScarlet(int stage) => stage switch - { - 0 => RandRate0MinScarlet, - 1 => RandRate1MinScarlet, - 2 => RandRate2MinScarlet, - 3 => RandRate3MinScarlet, - _ => throw new ArgumentOutOfRangeException(nameof(stage)), - }; - - public ushort GetRandRateMinViolet(int stage) => stage switch - { - 0 => RandRate0MinViolet, - 1 => RandRate1MinViolet, - 2 => RandRate2MinViolet, - 3 => RandRate3MinViolet, - _ => throw new ArgumentOutOfRangeException(nameof(stage)), - }; - - private const int StageCount = 4; - private const int StageNone = -1; - - public bool CanBeEncountered(uint seed) => GetProgressMaximum(seed) != StageNone; - - public int ProgressStageMin - { - get - { - for (int stage = 0; stage < StageCount; stage++) - { - if (GetRandRateTotalScarlet(stage) != 0 || GetRandRateTotalViolet(stage) != 0) - return stage; - } - return StageNone; - } - } - - public int ProgressStageMax - { - get - { - for (int stage = StageCount - 1; stage >= 0; stage--) - { - if (GetRandRateTotalScarlet(stage) != 0 || GetRandRateTotalViolet(stage) != 0) - return stage; - } - return StageNone; - } - } - - byte IGeneration.Generation => throw new NotImplementedException(); - - ushort ILocation.EggLocation => throw new NotImplementedException(); - - public int GetProgressMaximum(uint seed) - { - // We loop from the highest progress, since that is where the majority of samples will be from. - for (int i = StageCount - 1; i >= 0; i--) - { - if (GetIsPossibleSlot(seed, i)) - return i; - } - return StageNone; - } - - private bool GetIsPossibleSlot(uint seed, int stage) - { - var totalScarlet = GetRandRateTotalScarlet(stage); - if (totalScarlet != 0) - { - var rand = new Xoroshiro128Plus(seed); - _ = rand.NextInt(100); - var val = rand.NextInt(totalScarlet); - var min = GetRandRateMinScarlet(stage); - if ((uint)((int)val - min) < RandRate) - return true; - } - - var totalViolet = GetRandRateTotalViolet(stage); - if (totalViolet != 0) - { - var rand = new Xoroshiro128Plus(seed); - _ = rand.NextInt(100); - var val = rand.NextInt(totalViolet); - var min = GetRandRateMinViolet(stage); - if ((uint)((int)val - min) < RandRate) - return true; - } - return false; - } - - public static EncounterDist9[] GetArray(ReadOnlySpan data) - { - var count = data.Length / SerializedSize; - var result = new EncounterDist9[count]; - for (int i = 0; i < result.Length; i++) - result[i] = ReadEncounter(data.Slice(i * SerializedSize, SerializedSize)); - return result; - } - - public const int SerializedSize = 0x62; - private const int WeightStart = 0x14; - - private static EncounterDist9 ReadEncounter(ReadOnlySpan data) => new() - { - Species = ReadUInt16LittleEndian(data), - Form = data[0x02], - Gender = (byte)(data[0x03] - 1), - Ability = GetAbility(data[0x04]), - FlawlessIVCount = data[5], - Shiny = data[0x06] switch { 0 => Shiny.Random, 1 => Shiny.Never, 2 => Shiny.Always, _ => throw new ArgumentOutOfRangeException(nameof(data)) }, - Level = data[0x07], - Moves = new Moveset( - ReadUInt16LittleEndian(data[0x08..]), - ReadUInt16LittleEndian(data[0x0A..]), - ReadUInt16LittleEndian(data[0x0C..]), - ReadUInt16LittleEndian(data[0x0E..])), - TeraType = (GemType)data[0x10], - Index = data[0x11], - Stars = data[0x12], - RandRate = data[0x13], - - RandRate0MinScarlet = ReadUInt16LittleEndian(data[WeightStart..]), - RandRate0MinViolet = ReadUInt16LittleEndian(data[(WeightStart + sizeof(ushort))..]), - RandRate0TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 2))..]), - RandRate0TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 3))..]), - - RandRate1MinScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 4))..]), - RandRate1MinViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 5))..]), - RandRate1TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 6))..]), - RandRate1TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 7))..]), - - RandRate2MinScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 8))..]), - RandRate2MinViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 9))..]), - RandRate2TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 10))..]), - RandRate2TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 11))..]), - - RandRate3MinScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 12))..]), - RandRate3MinViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 13))..]), - RandRate3TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 14))..]), - RandRate3TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 15))..]), - - Nature = (Nature)data[0x34], - IVs = new IndividualValueSet((sbyte)data[0x35], (sbyte)data[0x36], (sbyte)data[0x37], (sbyte)data[0x38], (sbyte)data[0x39], (sbyte)data[0x3A], (IndividualValueSetType)data[0x3B]), - ScaleType = (SizeType9)data[0x3C], - Scale = data[0x3D], - Identifier = ReadUInt32LittleEndian(data[0x3E..]), - FixedRewardHash = ReadUInt64LittleEndian(data[0x42..]), - LotteryRewardHash = ReadUInt64LittleEndian(data[0x4A..]), - Item = (int)ReadUInt32LittleEndian(data[0x52..]), - ExtraMoves = new ExtraMoves( - ReadUInt16LittleEndian(data[0x56..]), - ReadUInt16LittleEndian(data[0x58..]), - ReadUInt16LittleEndian(data[0x5A..]), - ReadUInt16LittleEndian(data[0x5C..]), - ReadUInt16LittleEndian(data[0x5E..]), - ReadUInt16LittleEndian(data[0x60..])), - }; - - private static AbilityPermission GetAbility(byte b) => b switch - { - 0 => Any12, - 1 => Any12H, - 2 => OnlyFirst, - 3 => OnlySecond, - 4 => OnlyHidden, - _ => throw new ArgumentOutOfRangeException(nameof(b), b, null), - }; - - #region Generating - PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria); - PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr); - public PK9 ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted); - public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) - { - byte lang = (byte)Language.GetSafeLanguage((byte)Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion(tr.Version); - var pk = new PK9 - { - Language = lang, - Species = Species, - Form = Form, - CurrentLevel = LevelMin, - OriginalTrainerFriendship = PersonalTable.SV[Species, Form].BaseFriendship, - MetLocation = Location, - MetLevel = LevelMin, - Version = (GameVersion)(int)version, - Ball = (byte)Ball.Poke, - - Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, (byte)Generation), - Obedience_Level = LevelMin, - }; - SetPINGA(pk, criteria); - pk.SetMoves(Moves); - - pk.ResetPartyStats(); - return pk; - } - - private void SetPINGA(PK9 pk, EncounterCriteria criteria) - { - const byte rollCount = 1; - const byte undefinedSize = 0; - var pi = PersonalTable.SV.GetFormEntry(Species, Form); - var param = new GenerateParam9(Species, pi.Gender, FlawlessIVCount, rollCount, - undefinedSize, undefinedSize, ScaleType, Scale, - Ability, Shiny, IVs: IVs, Nature: Nature); - - var init = Util.Rand.Rand64(); - var success = this.TryApply32(pk, init, param, criteria); - if (!success) - this.TryApply32(pk, init, param, EncounterCriteria.Unrestricted); - } - #endregion -} diff --git a/TeraFinder.Core/Classes/EncounterMight9.cs b/TeraFinder.Core/Classes/EncounterMight9.cs deleted file mode 100644 index 6f9a4d71..00000000 --- a/TeraFinder.Core/Classes/EncounterMight9.cs +++ /dev/null @@ -1,313 +0,0 @@ -using PKHeX.Core; -using static System.Buffers.Binary.BinaryPrimitives; - -namespace TeraFinder.Core; - -//Extension of https://github.com/kwsch/PKHeX/blob/master/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterMight9.cs -public sealed record EncounterMight9 : IEncounterable, IEncounterConvertible, ITeraRaid9, IExtendedTeraRaid9, IMoveset, IFlawlessIVCount, IFixedGender -{ - //TeraFinder Serialization - public uint Identifier { get; private init; } - public ulong FixedRewardHash { get; private init; } - public ulong LotteryRewardHash { get; private init; } - public int Item { get; private init; } - public required ExtraMoves ExtraMoves { get; init; } - - public int Generation => 9; - ushort ILocation.Location => Location; - public const ushort Location = Locations.TeraCavern9; - public EntityContext Context => EntityContext.Gen9; - public GameVersion Version => GameVersion.SV; - public bool IsDistribution => Index != 0; - public Ball FixedBall => Ball.None; - public bool EggEncounter => false; - public bool IsShiny => Shiny == Shiny.Always; - public int EggLocation => 0; - - public required Moveset Moves { get; init; } - public required IndividualValueSet IVs { get; init; } - public required ushort Species { get; init; } - public required byte Form { get; init; } - public required byte Level { get; init; } - public required byte Gender { get; init; } - public required byte FlawlessIVCount { get; init; } - public required AbilityPermission Ability { get; init; } - public required Shiny Shiny { get; init; } - public required Nature Nature { get; init; } - public required GemType TeraType { get; init; } - public required byte Index { get; init; } - public required byte Stars { get; init; } - public required byte RandRate { get; init; } // weight chance of this encounter - - /// Indicates how the value is used, if at all. - public SizeType9 ScaleType { get; private init; } - /// Used only for == - public byte Scale { get; private init; } - - public ushort RandRate0MinScarlet { get; private init; } - public ushort RandRate0MinViolet { get; private init; } - public ushort RandRate0TotalScarlet { get; private init; } - public ushort RandRate0TotalViolet { get; private init; } - - public ushort RandRate1MinScarlet { get; private init; } - public ushort RandRate1MinViolet { get; private init; } - public ushort RandRate1TotalScarlet { get; private init; } - public ushort RandRate1TotalViolet { get; private init; } - - public ushort RandRate2MinScarlet { get; private init; } - public ushort RandRate2MinViolet { get; private init; } - public ushort RandRate2TotalScarlet { get; private init; } - public ushort RandRate2TotalViolet { get; private init; } - - public ushort RandRate3MinScarlet { get; private init; } - public ushort RandRate3MinViolet { get; private init; } - public ushort RandRate3TotalScarlet { get; private init; } - public ushort RandRate3TotalViolet { get; private init; } - - public string Name => "7-Star Tera Raid Encounter"; - public string LongName => Name; - public byte LevelMin => Level; - public byte LevelMax => Level; - - public ushort GetRandRateTotalScarlet(int stage) => stage switch - { - 0 => RandRate0TotalScarlet, - 1 => RandRate1TotalScarlet, - 2 => RandRate2TotalScarlet, - 3 => RandRate3TotalScarlet, - _ => throw new ArgumentOutOfRangeException(nameof(stage)), - }; - - public ushort GetRandRateTotalViolet(int stage) => stage switch - { - 0 => RandRate0TotalViolet, - 1 => RandRate1TotalViolet, - 2 => RandRate2TotalViolet, - 3 => RandRate3TotalViolet, - _ => throw new ArgumentOutOfRangeException(nameof(stage)), - }; - - public ushort GetRandRateMinScarlet(int stage) => stage switch - { - 0 => RandRate0MinScarlet, - 1 => RandRate1MinScarlet, - 2 => RandRate2MinScarlet, - 3 => RandRate3MinScarlet, - _ => throw new ArgumentOutOfRangeException(nameof(stage)), - }; - - public ushort GetRandRateMinViolet(int stage) => stage switch - { - 0 => RandRate0MinViolet, - 1 => RandRate1MinViolet, - 2 => RandRate2MinViolet, - 3 => RandRate3MinViolet, - _ => throw new ArgumentOutOfRangeException(nameof(stage)), - }; - - private const int StageCount = 4; - private const int StageNone = -1; - - public bool CanBeEncountered(uint seed) => GetProgressMaximum(seed) != StageNone; - - public int ProgressStageMin - { - get - { - for (int stage = 0; stage < StageCount; stage++) - { - if (GetRandRateTotalScarlet(stage) != 0 || GetRandRateTotalViolet(stage) != 0) - return stage; - } - return StageNone; - } - } - - public int ProgressStageMax - { - get - { - for (int stage = StageCount - 1; stage >= 0; stage--) - { - if (GetRandRateTotalScarlet(stage) != 0 || GetRandRateTotalViolet(stage) != 0) - return stage; - } - return StageNone; - } - } - - byte IGeneration.Generation => throw new NotImplementedException(); - - ushort ILocation.EggLocation => throw new NotImplementedException(); - - public int GetProgressMaximum(uint seed) - { - // We loop from the highest progress, since that is where the majority of samples will be from. - for (int i = StageCount - 1; i >= 0; i--) - { - if (GetIsPossibleSlot(seed, i)) - return i; - } - return StageNone; - } - - private bool GetIsPossibleSlot(uint seed, int stage) - { - var totalScarlet = GetRandRateTotalScarlet(stage); - if (totalScarlet != 0) - { - var rand = new Xoroshiro128Plus(seed); - _ = rand.NextInt(100); - var val = rand.NextInt(totalScarlet); - var min = GetRandRateMinScarlet(stage); - if ((uint)((int)val - min) < RandRate) - return true; - } - - var totalViolet = GetRandRateTotalViolet(stage); - if (totalViolet != 0) - { - var rand = new Xoroshiro128Plus(seed); - _ = rand.NextInt(100); - var val = rand.NextInt(totalViolet); - var min = GetRandRateMinViolet(stage); - if ((uint)((int)val - min) < RandRate) - return true; - } - return false; - } - - public static EncounterMight9[] GetArray(ReadOnlySpan data) - { - var count = data.Length / SerializedSize; - var result = new EncounterMight9[count]; - for (int i = 0; i < result.Length; i++) - result[i] = ReadEncounter(data.Slice(i * SerializedSize, SerializedSize)); - return result; - } - - private const int SerializedSize = 0x62; - private const int WeightStart = 0x14; - - private static EncounterMight9 ReadEncounter(ReadOnlySpan data) => new() - { - Species = ReadUInt16LittleEndian(data), - Form = data[0x02], - Gender = (byte)(data[0x03] - 1), - Ability = GetAbility(data[0x04]), - FlawlessIVCount = data[5], - Shiny = data[0x06] switch { 0 => Shiny.Random, 1 => Shiny.Never, 2 => Shiny.Always, _ => throw new ArgumentOutOfRangeException(nameof(data)) }, - Level = data[0x07], - Moves = new Moveset( - ReadUInt16LittleEndian(data[0x08..]), - ReadUInt16LittleEndian(data[0x0A..]), - ReadUInt16LittleEndian(data[0x0C..]), - ReadUInt16LittleEndian(data[0x0E..])), - TeraType = (GemType)data[0x10], - Index = data[0x11], - Stars = data[0x12], - RandRate = data[0x13], - - RandRate0MinScarlet = ReadUInt16LittleEndian(data[WeightStart..]), - RandRate0MinViolet = ReadUInt16LittleEndian(data[(WeightStart + sizeof(ushort))..]), - RandRate0TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 2))..]), - RandRate0TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 3))..]), - - RandRate1MinScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 4))..]), - RandRate1MinViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 5))..]), - RandRate1TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 6))..]), - RandRate1TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 7))..]), - - RandRate2MinScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 8))..]), - RandRate2MinViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 9))..]), - RandRate2TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 10))..]), - RandRate2TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 11))..]), - - RandRate3MinScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 12))..]), - RandRate3MinViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 13))..]), - RandRate3TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 14))..]), - RandRate3TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 15))..]), - - Nature = (Nature)data[0x34], - IVs = new IndividualValueSet((sbyte)data[0x35], (sbyte)data[0x36], (sbyte)data[0x37], (sbyte)data[0x38], (sbyte)data[0x39], (sbyte)data[0x3A], (IndividualValueSetType)data[0x3B]), - ScaleType = (SizeType9)data[0x3C], - Scale = data[0x3D], - - Identifier = ReadUInt32LittleEndian(data[0x3E..]), - FixedRewardHash = ReadUInt64LittleEndian(data[0x42..]), - LotteryRewardHash = ReadUInt64LittleEndian(data[0x4A..]), - Item = (int)ReadUInt32LittleEndian(data[0x52..]), - ExtraMoves = new ExtraMoves( - ReadUInt16LittleEndian(data[0x56..]), - ReadUInt16LittleEndian(data[0x58..]), - ReadUInt16LittleEndian(data[0x5A..]), - ReadUInt16LittleEndian(data[0x5C..]), - ReadUInt16LittleEndian(data[0x5E..]), - ReadUInt16LittleEndian(data[0x60..])), - }; - - private static AbilityPermission GetAbility(byte b) => b switch - { - 0 => AbilityPermission.Any12, - 1 => AbilityPermission.Any12H, - 2 => AbilityPermission.OnlyFirst, - 3 => AbilityPermission.OnlySecond, - 4 => AbilityPermission.OnlyHidden, - _ => throw new ArgumentOutOfRangeException(nameof(b), b, null), - }; - - private byte GetGender() => Gender switch - { - 0 => PersonalInfo.RatioMagicMale, - 1 => PersonalInfo.RatioMagicFemale, - 2 => PersonalInfo.RatioMagicGenderless, - _ => PersonalTable.SV.GetFormEntry(Species, Form).Gender, - }; - - #region Generating - PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria); - PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr); - public PK9 ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted); - public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) - { - int lang = (int)Language.GetSafeLanguage((byte)Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion(tr.Version); - var pk = new PK9 - { - Language = lang, - Species = Species, - Form = Form, - CurrentLevel = LevelMin, - OriginalTrainerFriendship = PersonalTable.SV[Species, Form].BaseFriendship, - MetLocation = Location, - MetLevel = LevelMin, - Version = (GameVersion)(int)version, - Ball = (byte)Ball.Poke, - - Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, (byte)Generation), - Obedience_Level = LevelMin, - RibbonMarkMightiest = true, - }; - SetPINGA(pk, criteria); - pk.SetMoves(Moves); - - pk.ResetPartyStats(); - return pk; - } - - private void SetPINGA(PK9 pk, EncounterCriteria criteria) - { - const byte rollCount = 1; - const byte undefinedSize = 0; - byte gender = GetGender(); - var param = new GenerateParam9(Species, gender, FlawlessIVCount, rollCount, - undefinedSize, undefinedSize, ScaleType, Scale, - Ability, Shiny, Nature, IVs); - - var init = Util.Rand.Rand64(); - var success = this.TryApply32(pk, init, param, criteria); - if (!success) - this.TryApply32(pk, init, param, EncounterCriteria.Unrestricted); - } - #endregion -} \ No newline at end of file diff --git a/TeraFinder.Core/Classes/EncounterRaid9.cs b/TeraFinder.Core/Classes/EncounterRaid9.cs deleted file mode 100644 index 8a906af3..00000000 --- a/TeraFinder.Core/Classes/EncounterRaid9.cs +++ /dev/null @@ -1,220 +0,0 @@ -using PKHeX.Core; - -namespace TeraFinder.Core; - -public class EncounterRaid9(ITeraRaid9 encounter) : IEncounterable, IEncounterConvertible, ITeraRaid9, IExtendedTeraRaid9, IMoveset, IFlawlessIVCount, IFixedGender -{ - protected ITeraRaid9 EncounterRaid { get; init; } = encounter as ITeraRaid9; - protected IEncounterable Encounterable { get; init; } = (encounter as IEncounterable)!; - protected IEncounterConvertible EncounterConvertible { get; init; } = (encounter as IEncounterConvertible)!; - protected IMoveset EncounterMoveset { get; init; } = (encounter as IMoveset)!; - protected IFlawlessIVCount EncounterIV { get; init; } = (encounter as IFlawlessIVCount)!; - protected IFixedGender EncounterGender { get; init; } = (encounter as IFixedGender)!; - - protected IExtendedTeraRaid9? EncounterRaidExtended => encounter as IExtendedTeraRaid9; - - public bool IsDistribution => EncounterRaid.IsDistribution; - public byte Index => EncounterRaid.Index; - public byte Stars => EncounterRaid.Stars; - public byte RandRate => EncounterRaid.RandRate; - public GemType TeraType => EncounterRaid.TeraType; - public ushort Species => Encounterable.Species; - public byte Form => Encounterable.Form; - public GameVersion Version => Encounterable.Version; - public byte FlawlessIVCount => EncounterIV.FlawlessIVCount; - public AbilityPermission Ability => Encounterable.Ability; - public Shiny Shiny => Encounterable.Shiny; - public byte Gender => EncounterGender.Gender; - public byte Level => Encounterable.LevelMin; - public Moveset Moves => EncounterMoveset.Moves; - public string Name => Encounterable.Name; - public string LongName => Encounterable.LongName; - public EntityContext Context => Encounterable.Context; - public bool EggEncounter => Encounterable.EggEncounter; - public int Generation => Encounterable.Generation; - public bool IsShiny => Encounterable.IsShiny; - public byte LevelMin => Encounterable.LevelMin; - public byte LevelMax => Encounterable.LevelMax; - public int Location => Encounterable.Location; - public int EggLocation => Encounterable.EggLocation; - public Ball FixedBall => Encounterable.FixedBall; - public TeraRaidMapParent Map => GetEncounterMap(); - public RaidContent Content => GetRaidContent(); - - public uint Identifier => GetIdentifier(); - public int Item => GetItem(); - public Nature Nature => GetNature(); - public SizeType9 ScaleType => GetScaleType(); - public byte Scale => GetScale(); - public IndividualValueSet IVs => GetIVs(); - public ulong FixedRewardHash => GetFixedRewardHash(); - public ulong LotteryRewardHash => GetLotteryRewardHash(); - public ushort RandRateMinScarlet => GetRandRateMinScarlet(); - public ushort RandRateMinViolet => GetRandRateMinViolet(); - public ExtraMoves ExtraMoves => GetExtraMoves(); - public bool CanBeEncounteredScarlet => GetCanBeEncountered(GameVersion.SL); - public bool CanBeEncounteredViolet => GetCanBeEncountered(GameVersion.VL); - - byte IGeneration.Generation => throw new NotImplementedException(); - - ushort ILocation.Location => throw new NotImplementedException(); - - ushort ILocation.EggLocation => throw new NotImplementedException(); - - public Type GetEncounterType() => EncounterRaid.GetType(); - public bool CanBeEncountered(uint seed) => EncounterRaid.CanBeEncountered(seed); - - public static EncounterRaid9[] GetEncounters(ITeraRaid9[] encounters) - { - var res = new List(); - foreach (var encounter in encounters) - res.Add(new EncounterRaid9(encounter)); - return [.. res]; - } - - PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria); - PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr); - public PK9 ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted); - public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => EncounterConvertible.ConvertToPKM(tr, criteria); - - public ushort GetRandRateTotalScarlet(int stage) => - EncounterRaid switch - { - EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.GetRandRateTotalScarlet(stage), - PKHeX.Core.EncounterDist9 => (ushort)((dynamic)EncounterRaid).GetRandRateTotalScarlet(stage), - _ => 0, - }; - - public ushort GetRandRateTotalViolet(int stage) => - EncounterRaid switch - { - EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.GetRandRateTotalViolet(stage), - PKHeX.Core.EncounterDist9 => (ushort)((dynamic)EncounterRaid).GetRandRateTotalViolet(stage), - _ => 0, - }; - - public ushort GetRandRateMinScarlet(int stage = 0) => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.GetRandRateMinScarlet(stage), - PKHeX.Core.EncounterTera9 => (ushort)((dynamic)EncounterRaid).RandRateMinScarlet, - _ => (ushort)((dynamic)EncounterRaid).GetRandRateMinScarlet(stage), - }; - - public ushort GetRandRateMinViolet(int stage = 0) => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.GetRandRateMinViolet(stage), - PKHeX.Core.EncounterTera9 => (ushort) ((dynamic) EncounterRaid).RandRateMinViolet, - _ => (ushort) ((dynamic)EncounterRaid).GetRandRateMinViolet(stage), - }; - - private Nature GetNature() => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.Nature, - PKHeX.Core.EncounterTera9 => Nature.Random, - _ => ((dynamic)EncounterRaid).Nature - }; - - private SizeType9 GetScaleType() => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.ScaleType, - PKHeX.Core.EncounterTera9 => SizeType9.RANDOM, - _ => ((dynamic)EncounterRaid).ScaleType - }; - - private byte GetScale() => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.Scale, - PKHeX.Core.EncounterTera9 => 0, - _ => ((dynamic)EncounterRaid).Scale - }; - - private IndividualValueSet GetIVs() => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.IVs, - PKHeX.Core.EncounterTera9 => default, - _ => ((dynamic)EncounterRaid).IVs - }; - - private uint GetIdentifier() => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.Identifier, - _ => 0, - }; - - private ulong GetFixedRewardHash() => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.FixedRewardHash, - _ => 0, - }; - - private ulong GetLotteryRewardHash() => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.LotteryRewardHash, - _ => 0, - }; - - private int GetItem() => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.Item, - _ => 0, - }; - - private ExtraMoves GetExtraMoves() => - EncounterRaid switch - { - EncounterTera9 or EncounterDist9 or EncounterMight9 => EncounterRaidExtended!.ExtraMoves, - _ => new(), - }; - - private bool GetCanBeEncountered(GameVersion version) => - EncounterRaid switch - { - EncounterTera9 t => version switch { GameVersion.SL => t.IsAvailableHostScarlet, _ => t.IsAvailableHostViolet }, - PKHeX.Core.EncounterTera9 t => version switch { GameVersion.SL => t.IsAvailableHostScarlet, _ => t.IsAvailableHostViolet }, - _ => CanDistBeEncountered(version), - }; - - private bool CanDistBeEncountered(GameVersion version) - { - for (var progress = 0; progress <= 3; progress++) - { - var maxRate = version switch { GameVersion.SL => GetRandRateTotalScarlet(progress), _ => GetRandRateTotalViolet(progress) }; - var minRate = version switch { GameVersion.SL => GetRandRateMinScarlet(progress), _ => GetRandRateMinViolet(progress) }; - - if (minRate >= 0 && maxRate > 0) - return true; - } - - return false; - } - - private TeraRaidMapParent GetEncounterMap() => - EncounterRaid switch - { - EncounterTera9 tera9 => tera9.Map, - PKHeX.Core.EncounterTera9 tera9 => tera9.Map, - _ => TeraRaidMapParent.Paldea, - }; - - private RaidContent GetRaidContent() - { - if (Stars == 7) - return RaidContent.Event_Mighty; - if (IsDistribution) - return RaidContent.Event; - if (Stars == 6) - return RaidContent.Black; - - return RaidContent.Standard; - } -} diff --git a/TeraFinder.Core/Classes/EncounterTF9/EncounterEventTF9.cs b/TeraFinder.Core/Classes/EncounterTF9/EncounterEventTF9.cs new file mode 100644 index 00000000..cd61f4d8 --- /dev/null +++ b/TeraFinder.Core/Classes/EncounterTF9/EncounterEventTF9.cs @@ -0,0 +1,281 @@ +using PKHeX.Core; +using static System.Buffers.Binary.BinaryPrimitives; + +namespace TeraFinder.Core; + +public sealed record EncounterEventTF9 : EncounterRaidTF9, IEventRaid9 +{ + public const int SerializedSize = 0x62; + + public ushort RandRate0MinScarlet { get; private init; } + public ushort RandRate0MinViolet { get; private init; } + public ushort RandRate0TotalScarlet { get; private init; } + public ushort RandRate0TotalViolet { get; private init; } + + public ushort RandRate1MinScarlet { get; private init; } + public ushort RandRate1MinViolet { get; private init; } + public ushort RandRate1TotalScarlet { get; private init; } + public ushort RandRate1TotalViolet { get; private init; } + + public ushort RandRate2MinScarlet { get; private init; } + public ushort RandRate2MinViolet { get; private init; } + public ushort RandRate2TotalScarlet { get; private init; } + public ushort RandRate2TotalViolet { get; private init; } + + public ushort RandRate3MinScarlet { get; private init; } + public ushort RandRate3MinViolet { get; private init; } + public ushort RandRate3TotalScarlet { get; private init; } + public ushort RandRate3TotalViolet { get; private init; } + + private const int StageCount = 4; + private const int StageNone = -1; + + public override bool CanBeEncountered(uint seed) => (int)GetProgressMaximum(seed) != StageNone; + + public static EncounterEventTF9[] GetArray(ReadOnlySpan data, Dictionary> fixedRewards, Dictionary> lotteryRewards) + { + var count = data.Length / SerializedSize; + var encounters = new EncounterEventTF9[count]; + for (var i = 0; i < count; i++) + encounters[i] = ReadEncounter(data.Slice(i * SerializedSize, SerializedSize), fixedRewards, lotteryRewards); + return encounters; + } + + private static EncounterEventTF9 ReadEncounter(ReadOnlySpan data, Dictionary> fixedRewards, Dictionary> lotteryRewards) + { + var species = ReadUInt16LittleEndian(data); + var form = data[0x02]; + var gender = (byte)(data[0x03] - 1); + var stars = data[0x12]; + var personal = PersonalTable.SV.GetFormEntry(species, form); + + var fxRewards = DeepCopyList(GetRewardList(ReadUInt64LittleEndian(data[0x42..]), fixedRewards)); + var ltRewards = DeepCopyList(GetRewardList(ReadUInt64LittleEndian(data[0x4A..]), lotteryRewards)); + fxRewards.ReplaceMaterialReward((Species)species); + ltRewards.ReplaceMaterialReward((Species)species); + + const int WeightStart = 0x14; + var enc = new EncounterEventTF9() + { + Personal = personal, + Species = species, + Form = form, + Gender = gender, + GenderRatio = GetGenderRatio(gender, stars, personal), + Ability = GetAbility(data[0x04]), + FlawlessIVCount = data[5], + Shiny = data[0x06] switch { 0 => Shiny.Random, 1 => Shiny.Never, 2 => Shiny.Always, _ => throw new ArgumentOutOfRangeException(nameof(data)) }, + Level = data[0x07], + Moves = new Moveset( + ReadUInt16LittleEndian(data[0x08..]), + ReadUInt16LittleEndian(data[0x0A..]), + ReadUInt16LittleEndian(data[0x0C..]), + ReadUInt16LittleEndian(data[0x0E..])), + TeraType = (GemType)data[0x10], + Index = data[0x11], + Stars = stars, + RandRate = data[0x13], + + RandRate0MinScarlet = ReadUInt16LittleEndian(data[WeightStart..]), + RandRate0MinViolet = ReadUInt16LittleEndian(data[(WeightStart + sizeof(ushort))..]), + RandRate0TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 2))..]), + RandRate0TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 3))..]), + + RandRate1MinScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 4))..]), + RandRate1MinViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 5))..]), + RandRate1TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 6))..]), + RandRate1TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 7))..]), + + RandRate2MinScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 8))..]), + RandRate2MinViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 9))..]), + RandRate2TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 10))..]), + RandRate2TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 11))..]), + + RandRate3MinScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 12))..]), + RandRate3MinViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 13))..]), + RandRate3TotalScarlet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 14))..]), + RandRate3TotalViolet = ReadUInt16LittleEndian(data[(WeightStart + (sizeof(ushort) * 15))..]), + + Nature = (Nature)data[0x34], + IVs = new IndividualValueSet((sbyte)data[0x35], (sbyte)data[0x36], (sbyte)data[0x37], (sbyte)data[0x38], (sbyte)data[0x39], (sbyte)data[0x3A], (IndividualValueSetType)data[0x3B]), + ScaleType = (SizeType9)data[0x3C], + Scale = data[0x3D], + + Map = TeraRaidMapParent.Paldea, + ContentType = stars == 7 ? RaidContent.Event_Mighty : RaidContent.Event, + + Identifier = ReadUInt32LittleEndian(data[0x3E..]), + FixedRewards = fxRewards, + LotteryRewards = ltRewards, + HeldItem = (int)ReadUInt32LittleEndian(data[0x52..]), + ExtraMoves = new ExtraMoves( + ReadUInt16LittleEndian(data[0x56..]), + ReadUInt16LittleEndian(data[0x58..]), + ReadUInt16LittleEndian(data[0x5A..]), + ReadUInt16LittleEndian(data[0x5C..]), + ReadUInt16LittleEndian(data[0x5E..]), + ReadUInt16LittleEndian(data[0x60..])), + }; + + enc.CanBeEncounteredScarlet = enc.CanBeEncountered(GameVersion.SL); + enc.CanBeEncounteredViolet = enc.CanBeEncountered(GameVersion.VL); + return enc; + } + + private static List DeepCopyList(List list) => + list.Select(reward => new Reward { ItemID = reward.ItemID, Amount = reward.Amount, Probability = reward.Probability, Aux = reward.Aux }).ToList(); + + private static List GetRewardList(ulong hash, Dictionary> dic) => dic.GetValueOrDefault(hash) ?? []; + + private static byte GetGenderRatio(byte gender, byte stars, PersonalInfo9SV personal) => stars switch + { + 7 => gender switch + { + 0 => PersonalInfo.RatioMagicMale, + 1 => PersonalInfo.RatioMagicFemale, + 2 => PersonalInfo.RatioMagicGenderless, + _ => personal.Gender, + }, + _ => personal.Gender, + }; + + private static AbilityPermission GetAbility(byte b) => b switch + { + 0 => AbilityPermission.Any12, + 1 => AbilityPermission.Any12H, + 2 => AbilityPermission.OnlyFirst, + 3 => AbilityPermission.OnlySecond, + 4 => AbilityPermission.OnlyHidden, + _ => throw new ArgumentOutOfRangeException(nameof(b), b, null), + }; + + public static EncounterRaidTF9? GetEncounterFromSeed(uint seed, EncounterEventTF9[] encounters, GameVersion game, EventProgress progress, int groupid) + { + foreach (var enc in encounters) + { + if (enc.Index != groupid) + continue; + + var max = game switch { GameVersion.VL => enc.GetRandRateTotalViolet(progress), _ => enc.GetRandRateTotalScarlet(progress) }; + if (max > 0) + { + var xoro = new Xoroshiro128Plus(seed); + xoro.NextInt(100); + var rateRand = xoro.NextInt(max); + var min = game switch { GameVersion.VL => enc.GetRandRateMinViolet(progress), _ => enc.GetRandRateMinScarlet(progress) }; + if ((uint)(rateRand - min) < enc.RandRate) + return enc; + } + } + + return null; + } + + public bool CanBeEncountered(GameVersion version) + { + for (var progress = EventProgress.Stage0; progress <= EventProgress.Stage3; progress++) + if (CanBeEncounteredFromStage(progress, version)) + return true; + + return false; + } + + public bool CanBeEncounteredFromStage(EventProgress progress, GameVersion version) + { + var maxRate = version switch { GameVersion.SL => GetRandRateTotalScarlet(progress), _ => GetRandRateTotalViolet(progress) }; + + if (maxRate > 0) + return true; + + return false; + } + + public ushort GetRandRateTotalScarlet(EventProgress stage) => stage switch + { + EventProgress.Stage0 => RandRate0TotalScarlet, + EventProgress.Stage1 => RandRate1TotalScarlet, + EventProgress.Stage2 => RandRate2TotalScarlet, + EventProgress.Stage3 => RandRate3TotalScarlet, + _ => throw new ArgumentOutOfRangeException(nameof(stage)), + }; + + public ushort GetRandRateTotalViolet(EventProgress stage) => stage switch + { + EventProgress.Stage0 => RandRate0TotalViolet, + EventProgress.Stage1 => RandRate1TotalViolet, + EventProgress.Stage2 => RandRate2TotalViolet, + EventProgress.Stage3 => RandRate3TotalViolet, + _ => throw new ArgumentOutOfRangeException(nameof(stage)), + }; + + public ushort GetRandRateMinScarlet(EventProgress stage) => stage switch + { + EventProgress.Stage0 => RandRate0MinScarlet, + EventProgress.Stage1 => RandRate1MinScarlet, + EventProgress.Stage2 => RandRate2MinScarlet, + EventProgress.Stage3 => RandRate3MinScarlet, + _ => throw new ArgumentOutOfRangeException(nameof(stage)), + }; + + public ushort GetRandRateMinViolet(EventProgress stage) => stage switch + { + EventProgress.Stage0 => RandRate0MinViolet, + EventProgress.Stage1 => RandRate1MinViolet, + EventProgress.Stage2 => RandRate2MinViolet, + EventProgress.Stage3 => RandRate3MinViolet, + _ => throw new ArgumentOutOfRangeException(nameof(stage)), + }; + + public EventProgress GetProgressMaximum(uint seed) + { + for (var i = (EventProgress)(StageCount - 1); i >= 0; i--) + if (GetIsPossibleSlot(seed, i)) + return i; + + return (EventProgress)StageNone; + } + + private bool GetIsPossibleSlot(uint seed, EventProgress stage) => GetIsPossibleSlotScarlet(seed, stage) || GetIsPossibleSlotViolet(seed, stage); + + private bool GetIsPossibleSlotScarlet(uint seed, EventProgress stage) + { + var totalScarlet = GetRandRateTotalScarlet(stage); + if (totalScarlet != 0) + { + var rand = new Xoroshiro128Plus(seed); + _ = rand.NextInt(100); + var val = rand.NextInt(totalScarlet); + var min = GetRandRateMinScarlet(stage); + if ((uint)((int)val - min) < RandRate) + return true; + } + + return false; + } + + private bool GetIsPossibleSlotViolet(uint seed, EventProgress stage) + { + var totalViolet = GetRandRateTotalViolet(stage); + if (totalViolet != 0) + { + var rand = new Xoroshiro128Plus(seed); + _ = rand.NextInt(100); + var val = rand.NextInt(totalViolet); + var min = GetRandRateMinViolet(stage); + if ((uint)((int)val - min) < RandRate) + return true; + } + + return false; + } + + public static HashSet GetPossibleEventStars(EncounterEventTF9[] encounters, EventProgress progress, GameVersion version) + { + var set = new HashSet(); + foreach (var enc in encounters) + if (version switch { GameVersion.VL => enc.GetRandRateTotalViolet(progress), _ => enc.GetRandRateTotalScarlet(progress) } > 0) + set.Add(enc.Stars); + + return set; + } +} diff --git a/TeraFinder.Core/Classes/EncounterTF9/EncounterRaidTF9.cs b/TeraFinder.Core/Classes/EncounterTF9/EncounterRaidTF9.cs new file mode 100644 index 00000000..b3f042ee --- /dev/null +++ b/TeraFinder.Core/Classes/EncounterTF9/EncounterRaidTF9.cs @@ -0,0 +1,236 @@ +using PKHeX.Core; + +namespace TeraFinder.Core; + +public abstract record EncounterRaidTF9 : IExtendedTeraRaid9 +{ + public required PersonalInfo9SV Personal { get; init; } + public required ushort Species { get; init; } + public required byte Form { get; init; } + public required byte Gender { get; init; } + public required byte GenderRatio { get; init; } + public required AbilityPermission Ability { get; init; } + public required byte FlawlessIVCount { get; init; } + public required Shiny Shiny { get; init; } + public required Nature Nature { get; init; } + public required byte Level { get; init; } + public required Moveset Moves { get; init; } + public required ExtraMoves ExtraMoves { get; init; } + public required IndividualValueSet IVs { get; init; } + public required GemType TeraType { get; init; } + public required byte Index { get; init; } + public required byte Stars { get; init; } + public required byte RandRate { get; init; } + public required SizeType9 ScaleType { get; init; } + public required byte Scale { get; init; } + public required TeraRaidMapParent Map { get; init; } + public required RaidContent ContentType { get; init; } + public required int HeldItem { get; init; } + public required uint Identifier { get; init; } + public required List FixedRewards { get; init; } + public required List LotteryRewards { get; init; } + + public virtual bool CanBeEncounteredScarlet { get; protected set; } + public virtual bool CanBeEncounteredViolet { get; protected set; } + + public bool IsDistribution => Index != 0; + public bool IsMighty => IsDistribution && Stars == 7; + public bool IsBlack => !IsDistribution && Stars >= 6; + public bool IsRandomUnspecificForm => Form >= EncounterUtil.FormDynamic; + + public abstract bool CanBeEncountered(uint seed); + + //Generate Tera Details with no Filters; + //Assume there is at least a Stars filter + public static bool TryGenerateTeraDetails(in uint seed, in EncounterRaidTF9[] encounters, in GameVersion version, in GameProgress progress, + in EventProgress eventProgress, in RaidContent content, in TeraRaidMapParent map, in uint id32, in byte groupid, out EncounterRaidTF9? encounter, out TeraDetails? result) + { + result = null; + encounter = content switch + { + RaidContent.Standard or RaidContent.Black => EncounterTeraTF9.GetEncounterFromSeed(seed, encounters, version, progress, content, map), + RaidContent.Event or RaidContent.Event_Mighty => EncounterEventTF9.GetEncounterFromSeed(seed, encounters as EncounterEventTF9[], version, eventProgress, groupid), + _ => throw new ArgumentOutOfRangeException(nameof(content)), + }; + + if (encounter is null) + return false; + + result = encounter.GenerateData(seed, id32, groupid); + return true; + } + + //Generate Tera Details with Filters; assumes the encounters pool to be already filtered based on species and stars + public static bool TryGenerateTeraDetails(in uint seed, in EncounterRaidTF9[] encounters, in TeraFilter filter, in short romTotal, in GameVersion version, + in GameProgress progress, in EventProgress eventProgress, in RaidContent content, in uint id32, in byte groupid, out EncounterRaidTF9? encounter, out TeraDetails? result) + { + result = null; + + encounter = content switch + { + RaidContent.Standard or RaidContent.Black => EncounterTeraTF9.GetEncounterFromSeed(seed, encounters as EncounterTeraTF9[], romTotal, version, progress, content), + RaidContent.Event or RaidContent.Event_Mighty => EncounterEventTF9.GetEncounterFromSeed(seed, encounters as EncounterEventTF9[], version, eventProgress, groupid), + _ => throw new ArgumentOutOfRangeException(nameof(content)), + }; + + if (encounter is null) + return false; + + if (!encounter.GenerateData(filter, seed, id32, groupid, out result)) + return false; + + return true; + } + + //Generate RNG Details and Reward Dtails with no Filters + public static bool TryGenerateRewardDetails(in uint seed, in EncounterRaidTF9[] encounters, in GameVersion version, in GameProgress progress, in EventProgress eventProgress, + RaidContent content, in TeraRaidMapParent map, uint id32, byte groupid, in int boost, out TeraDetails? teraRes, out RewardDetails? rewardRes) + { + teraRes = null; + rewardRes = null; + + var encounter = content switch + { + RaidContent.Standard or RaidContent.Black => EncounterTeraTF9.GetEncounterFromSeed(seed, encounters, version, progress, content, map), + RaidContent.Event or RaidContent.Event_Mighty => EncounterEventTF9.GetEncounterFromSeed(seed, encounters as EncounterEventTF9[], version, eventProgress, groupid), + _ => throw new ArgumentOutOfRangeException(nameof(content)), + }; + + if (encounter is null) + return false; + + teraRes = encounter.GenerateData(seed, id32, groupid); + var rewards = RewardUtil.GetCombinedRewardList(teraRes.Value, encounter.FixedRewards, encounter.LotteryRewards, boost); + rewardRes = new RewardDetails { Seed = seed, Rewards = rewards, Species = encounter.Species, Stars = encounter.Stars, Shiny = teraRes.Value.Shiny, TeraType = teraRes.Value.TeraType, EventIndex = groupid }; + + return true; + } + + //Generate RNG Details and Reward Details with Filters; assumes the encounters pool to be already filtered based on species and stars + //Assume there is at least a Stars filter + public static bool TryGenerateRewardDetails(uint seed, EncounterRaidTF9[] encounters, RewardFilter filter, in short romTotal, GameVersion version, + GameProgress progress, EventProgress eventProgress, RaidContent content, uint id32, byte groupid, in int boost, out TeraDetails? teraRes, out RewardDetails? rewardRes) + { + teraRes = null; + rewardRes = null; + + var encounter = content switch + { + RaidContent.Standard or RaidContent.Black => EncounterTeraTF9.GetEncounterFromSeed(seed, encounters as EncounterTeraTF9[], romTotal, version, progress, content), + RaidContent.Event or RaidContent.Event_Mighty => EncounterEventTF9.GetEncounterFromSeed(seed, encounters as EncounterEventTF9[], version, eventProgress, groupid), + _ => throw new ArgumentOutOfRangeException(nameof(content)), + }; + + if (encounter is null) + return false; + + teraRes = encounter.GenerateData(seed, id32, groupid); + var rewards = RewardUtil.GetCombinedRewardList(teraRes.Value, encounter.FixedRewards, encounter.LotteryRewards, boost); + rewardRes = new RewardDetails { Seed = seed, Rewards = rewards, Species = encounter.Species, Stars = encounter.Stars, Shiny = teraRes.Value.Shiny, TeraType = teraRes.Value.TeraType, EventIndex = groupid }; + + if (!filter.IsFilterMatch(rewardRes.Value)) + return false; + + return true; + } + + //Generate a PK9 from an RNG result + public bool GeneratePK9(TeraDetails rngResult, uint id32, GameVersion version, string ot_name, int ot_language, byte ot_gender, out PK9 result, out LegalityAnalysis legality) + { + result = new PK9(Properties.Resources.template) + { + Species = Species, + HeldItem = HeldItem, + MetLevel = Level, + CurrentLevel = Level, +#if USE_PKHEX_MASTER + ObedienceLevel = Level, +#else + Obedience_Level = Level, +#endif + RibbonMarkMightiest = IsMighty, + ID32 = id32, + Version = version, + Language = ot_language, + HandlingTrainerLanguage = (byte)ot_language, + OriginalTrainerName = ot_name, + HandlingTrainerName = ot_name, + OriginalTrainerGender = ot_gender, + TeraTypeOriginal = (MoveType)rngResult.TeraType, + EncryptionConstant = rngResult.EC, + Form = rngResult.Form, + PID = rngResult.PID, + IV_HP = rngResult.HP, + IV_ATK = rngResult.ATK, + IV_DEF = rngResult.DEF, + IV_SPA = rngResult.SPA, + IV_SPD = rngResult.SPD, + IV_SPE = rngResult.SPE, + Gender = (byte)rngResult.Gender, + Nature = rngResult.Nature, + StatNature = rngResult.Nature, + HeightScalar = rngResult.Height, + WeightScalar = rngResult.Weight, + Scale = rngResult.Scale, + Move1 = rngResult.Move1, + Move2 = rngResult.Move2, + Move3 = rngResult.Move3, + Move4 = rngResult.Move4, + Ability = rngResult.Ability, + AbilityNumber = rngResult.AbilityNumber, + MetDate = DateOnly.FromDateTime(DateTime.Now), + }; + + result.HealPP(); + result.ClearNickname(); + result.ClearRecordFlags(); + result.RefreshChecksum(); + + legality = new LegalityAnalysis(result); + if (!legality.Valid) + { + //CHS, CHT, KOR and JPN have OT Name length restrictions + var la_ot = legality.Results.Where(l => l.Identifier is CheckIdentifier.Trainer).FirstOrDefault(); + if (la_ot.Judgement is Severity.Invalid && (LanguageID)result.Language is LanguageID.ChineseS or LanguageID.ChineseT or LanguageID.Korean or LanguageID.Japanese) + { + result.OriginalTrainerName = "TF"; + result.RefreshChecksum(); + legality = new LegalityAnalysis(result); + } + + //Seed 0xC4C200B6 produces equal EC and PID, which PKHeX flags as invalid + if (!legality.Valid) + { + var la_ec = legality.Results.Where(l => l.Identifier is CheckIdentifier.EC).FirstOrDefault(); + if (la_ec.Judgement is Severity.Invalid && rngResult.EC == rngResult.PID) + return true; + } + } + return legality.Valid; + } + + + //Get the encounter names from a pool of encounters + public static HashSet GetAvailableSpecies(EncounterRaidTF9[] encounters, byte stars, string[] speciesNames, string[] formsNames, string[] typesNames, Dictionary pluginStrings) + { + HashSet list = []; + foreach (var encounter in encounters) + { + if (stars != 0 && encounter.Stars != stars) + continue; + + var formlist = FormConverter.GetFormList(encounter.Species, typesNames, formsNames, GameInfo.GenderSymbolASCII, EntityContext.Gen9); + var str = $"{speciesNames[encounter.Species]}{(formlist.Length > 1 ? $"-{$"{formlist[encounter.Form]}"}" : "")}" + + $"{(encounter.Index > 0 ? $" ({encounter.Index})" : "")}"; + + if (!encounter.CanBeEncounteredScarlet) + str += $" ({pluginStrings["GameVersionVL"]})"; + + if (!encounter.CanBeEncounteredViolet) + str += $" ({pluginStrings["GameVersionSL"]})"; + + list.Add(str); + } + return list; + } +} \ No newline at end of file diff --git a/TeraFinder.Core/Classes/EncounterTF9/EncounterTF9RNG.cs b/TeraFinder.Core/Classes/EncounterTF9/EncounterTF9RNG.cs new file mode 100644 index 00000000..b7c5b418 --- /dev/null +++ b/TeraFinder.Core/Classes/EncounterTF9/EncounterTF9RNG.cs @@ -0,0 +1,273 @@ +using PKHeX.Core; + +namespace TeraFinder.Core; + +//Tera Finder Adaptations of the Encounter9RNG class from PKHeX +//https://github.com/kwsch/PKHeX/blob/master/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs +public static class EncounterTF9RNG +{ + public static bool GenerateData(this EncounterRaidTF9 encounter, in TeraFilter filter, in uint seed, in uint id32, in byte groupid, out TeraDetails? result) + { + result = null; + + var gemtype = Tera9RNG.GetTeraType(seed, encounter.TeraType, encounter.Species, encounter.Form); + if (!filter.IsTeraMatch(gemtype)) + return false; + + var rand = new Xoroshiro128Plus(seed); + + var ec = (uint)rand.NextInt(uint.MaxValue); + if (!filter.IsECMatch(ec)) + return false; + + var pid = GetAdaptedPID(ref rand, encounter, id32, out var shiny); + if (!filter.IsShinyMatch(shiny)) + return false; + + const int UNSET = -1; + const int MAX = 31; + Span ivs = [UNSET, UNSET, UNSET, UNSET, UNSET, UNSET]; + if (encounter.IVs.IsSpecified) + { + encounter.IVs.CopyToSpeedLast(ivs); + } + else + { + for (int i = 0; i < encounter.FlawlessIVCount; i++) + { + int index; + do { index = (int)rand.NextInt(6); } + while (ivs[index] != UNSET); + ivs[index] = MAX; + } + } + + for (int i = 0; i < 6; i++) + { + if (ivs[i] == UNSET) + ivs[i] = (int)rand.NextInt(MAX + 1); + } + + if (!filter.IsIVMatch(ivs)) + return false; + + int abilNum = encounter.Ability switch + { + AbilityPermission.Any12H => (int)rand.NextInt(3) << 1, + AbilityPermission.Any12 => (int)rand.NextInt(2) << 1, + _ => (int)encounter.Ability, + }; + + if (!filter.IsAbilityMatch(abilNum)) + return false; + + var abil = GetRefreshedAbility(encounter.Personal, abilNum >> 1); + + var gender = encounter.GenderRatio switch + { + PersonalInfo.RatioMagicGenderless => Gender.Genderless, + PersonalInfo.RatioMagicFemale => Gender.Female, + PersonalInfo.RatioMagicMale => Gender.Male, + _ => GetGender(encounter.GenderRatio, rand.NextInt(100)), + }; + + if (!filter.IsGenderMatch(gender)) + return false; + + var nature = encounter.Nature != Nature.Random ? encounter.Nature : encounter.Species == (ushort)Species.Toxtricity + ? ToxtricityUtil.GetRandomNature(ref rand, encounter.Form) + : (Nature)rand.NextInt(25); + + if (!filter.IsNatureMatch(nature)) + return false; + + var height = (byte)(rand.NextInt(0x81) + rand.NextInt(0x80)); + var weight = (byte)(rand.NextInt(0x81) + rand.NextInt(0x80)); + var scale = encounter.ScaleType.GetSizeValue(encounter.Scale, ref rand); + + if (!filter.IsScaleMatch(scale)) + return false; + + result = new TeraDetails() + { + Seed = seed, + Shiny = shiny, + Stars = encounter.Stars, + Species = encounter.Species, + Form = encounter.Form, + Level = encounter.Level, + TeraType = gemtype, + EC = ec, + PID = pid, + HP = ivs[0], + ATK = ivs[1], + DEF = ivs[2], + SPA = ivs[3], + SPD = ivs[4], + SPE = ivs[5], + Ability = abil, + AbilityNumber = abilNum == 0 ? 1 : abilNum, + Nature = nature, + Gender = gender, + Height = height, + Weight = weight, + Scale = scale, + Move1 = encounter.Moves.Move1, + Move2 = encounter.Moves.Move2, + Move3 = encounter.Moves.Move3, + Move4 = encounter.Moves.Move4, + EventIndex = groupid, + }; + + return true; + } + + public static TeraDetails GenerateData(this EncounterRaidTF9 encounter, in uint seed, in uint id32, in byte groupid = 0) + { + var tera = Tera9RNG.GetTeraType(seed, encounter.TeraType, encounter.Species, encounter.Form); + var rand = new Xoroshiro128Plus(seed); + var ec = (uint)rand.NextInt(uint.MaxValue); + var pid = GetAdaptedPID(ref rand, encounter, id32, out var shiny); + + const int UNSET = -1; + const int MAX = 31; + Span ivs = [UNSET, UNSET, UNSET, UNSET, UNSET, UNSET]; + if (encounter.IVs.IsSpecified) + { + encounter.IVs.CopyToSpeedLast(ivs); + } + else + { + for (int i = 0; i < encounter.FlawlessIVCount; i++) + { + int index; + do { index = (int)rand.NextInt(6); } + while (ivs[index] != UNSET); + ivs[index] = MAX; + } + } + + for (int i = 0; i < 6; i++) + { + if (ivs[i] == UNSET) + ivs[i] = (int)rand.NextInt(MAX + 1); + } + + int abilNum = encounter.Ability switch + { + AbilityPermission.Any12H => (int)rand.NextInt(3) << 1, + AbilityPermission.Any12 => (int)rand.NextInt(2) << 1, + _ => (int)encounter.Ability, + }; + + var abil = GetRefreshedAbility(encounter.Personal, abilNum >> 1); + + var gender = encounter.GenderRatio switch + { + PersonalInfo.RatioMagicGenderless => Gender.Genderless, + PersonalInfo.RatioMagicFemale => Gender.Female, + PersonalInfo.RatioMagicMale => Gender.Male, + _ => GetGender(encounter.GenderRatio, rand.NextInt(100)), + }; + + var nature = encounter.Nature != Nature.Random ? encounter.Nature : encounter.Species == (ushort)Species.Toxtricity + ? ToxtricityUtil.GetRandomNature(ref rand, encounter.Form) + : (Nature)rand.NextInt(25); + + var height = (byte)(rand.NextInt(0x81) + rand.NextInt(0x80)); + var weight = (byte)(rand.NextInt(0x81) + rand.NextInt(0x80)); + var scale = encounter.ScaleType.GetSizeValue(encounter.Scale, ref rand); + + return new TeraDetails() + { + Seed = seed, + Shiny = shiny, + Stars = encounter.Stars, + Species = encounter.Species, + Form = encounter.Form, + Level = encounter.Level, + TeraType = tera, + EC = ec, + PID = pid, + HP = ivs[0], + ATK = ivs[1], + DEF = ivs[2], + SPA = ivs[3], + SPD = ivs[4], + SPE = ivs[5], + Ability = abil, + AbilityNumber = abilNum == 0 ? 1 : abilNum, + Nature = nature, + Gender = gender, + Height = height, + Weight = weight, + Scale = scale, + Move1 = encounter.Moves.Move1, + Move2 = encounter.Moves.Move2, + Move3 = encounter.Moves.Move3, + Move4 = encounter.Moves.Move4, + EventIndex = groupid, + }; + } + + private static uint GetAdaptedPID(ref Xoroshiro128Plus rand, EncounterRaidTF9 encounter, uint id32, out TeraShiny shiny) + { + var fakeTID = (uint)rand.NextInt(); + var pid = (uint)rand.NextInt(); + + if (encounter.Shiny is Shiny.Random) + { + var xor = ShinyUtil.GetShinyXor(pid, fakeTID); + if (xor < 16) + { + if (xor != 0) xor = 1; + ShinyUtil.ForceShinyState(true, ref pid, id32, xor); + shiny = xor == 0 ? TeraShiny.Square : TeraShiny.Star; + } + else + { + ShinyUtil.ForceShinyState(false, ref pid, id32, xor); + shiny = TeraShiny.No; + } + } + else if (encounter.Shiny is Shiny.Always) + { + var tid = (ushort)fakeTID; + var sid = (ushort)(fakeTID >> 16); + var xor = ShinyUtil.GetShinyXor(pid, fakeTID); + if (xor > 16) + pid = ShinyUtil.GetShinyPID(tid, sid, pid, 0); + if (!ShinyUtil.GetIsShiny(id32, pid)) + pid = ShinyUtil.GetShinyPID(tid, sid, pid, xor == 0 ? 0u : 1u); + shiny = xor == 0 ? TeraShiny.Square : TeraShiny.Star; + } + else + { + if (ShinyUtil.GetIsShiny(fakeTID, pid)) + pid ^= 0x1000_0000; + if (ShinyUtil.GetIsShiny(id32, pid)) + pid ^= 0x1000_0000; + shiny = TeraShiny.No; + } + return pid; + } + + private static int GetRefreshedAbility(PersonalInfo9SV info, int n) + { + if ((uint)n < info.AbilityCount) + n = info.GetAbilityAtIndex(n); + + return n; + } + + private static Gender GetGender(in int ratio, in ulong rand100) => ratio switch + { + 0x1F => rand100 < 12 ? Gender.Female : Gender.Male, // 12.5% + 0x3F => rand100 < 25 ? Gender.Female : Gender.Male, // 25% + 0x7F => rand100 < 50 ? Gender.Female : Gender.Male, // 50% + 0xBF => rand100 < 75 ? Gender.Female : Gender.Male, // 75% + 0xE1 => rand100 < 89 ? Gender.Female : Gender.Male, // 87.5% + + _ => throw new ArgumentOutOfRangeException(nameof(ratio)), + }; +} diff --git a/TeraFinder.Core/Classes/EncounterTF9/EncounterTeraTF9.cs b/TeraFinder.Core/Classes/EncounterTF9/EncounterTeraTF9.cs new file mode 100644 index 00000000..81722cd4 --- /dev/null +++ b/TeraFinder.Core/Classes/EncounterTF9/EncounterTeraTF9.cs @@ -0,0 +1,182 @@ +using PKHeX.Core; +using static System.Buffers.Binary.BinaryPrimitives; + +namespace TeraFinder.Core; + +public sealed record EncounterTeraTF9 : EncounterRaidTF9 +{ + public const int SerializedSize = 0x3C; + + public required short RandRateMinScarlet { get; init; } + public required short RandRateMinViolet { get; init; } + + public override bool CanBeEncountered(uint seed) => Tera9RNG.IsMatchStarChoice(seed, Stars, RandRate, RandRateMinScarlet, RandRateMinViolet, Map); + + public static EncounterTeraTF9[] GetArray(ReadOnlySpan data, Dictionary> fixedRewards, Dictionary> lotteryRewards, TeraRaidMapParent map) + { + var count = data.Length / SerializedSize; + var encounters = new EncounterTeraTF9[count]; + for (var i = 0; i < count; i++) + encounters[i] = ReadEncounter(data.Slice(i * SerializedSize, SerializedSize), fixedRewards, lotteryRewards, map); + return encounters; + } + + private static EncounterTeraTF9 ReadEncounter(ReadOnlySpan data, Dictionary> fixedRewards, Dictionary> lotteryRewards, TeraRaidMapParent map) + { + var species = ReadUInt16LittleEndian(data); + var form = data[0x02]; + var stars = data[0x12]; + var randRateMinScarlet = ReadInt16LittleEndian(data[0x14..]); + var randRateMinViolet = ReadInt16LittleEndian(data[0x16..]); + var personal = PersonalTable.SV.GetFormEntry(species, form); + + var fxRewards = DeepCopyList(GetRewardList(ReadUInt64LittleEndian(data[0x1C..]), fixedRewards)); + var ltRewards = DeepCopyList(GetRewardList(ReadUInt64LittleEndian(data[0x24..]), lotteryRewards)); + fxRewards.ReplaceMaterialReward((Species)species); + ltRewards.ReplaceMaterialReward((Species)species); + + return new() + { + Personal = personal, + Species = species, + Form = form, + Gender = (byte)(data[0x03] - 1), + GenderRatio = GetGenderRatio(personal), + Ability = GetAbility(data[0x04]), + FlawlessIVCount = data[5], + Shiny = data[0x06] switch { 0 => Shiny.Random, 1 => Shiny.Never, 2 => Shiny.Always, _ => throw new ArgumentOutOfRangeException(nameof(data)) }, + Level = data[0x07], + Moves = new Moveset( + ReadUInt16LittleEndian(data[0x08..]), + ReadUInt16LittleEndian(data[0x0A..]), + ReadUInt16LittleEndian(data[0x0C..]), + ReadUInt16LittleEndian(data[0x0E..])), + TeraType = (GemType)data[0x10], + Index = data[0x11], + Stars = stars, + RandRate = data[0x13], + RandRateMinScarlet = randRateMinScarlet, + RandRateMinViolet = randRateMinViolet, + Identifier = ReadUInt32LittleEndian(data[0x18..]), + FixedRewards = fxRewards, + LotteryRewards = ltRewards, + HeldItem = (int)ReadUInt32LittleEndian(data[0x2C..]), + ExtraMoves = new ExtraMoves(ReadUInt16LittleEndian(data[0x30..]), + ReadUInt16LittleEndian(data[0x32..]), + ReadUInt16LittleEndian(data[0x34..]), + ReadUInt16LittleEndian(data[0x36..]), + ReadUInt16LittleEndian(data[0x38..]), + ReadUInt16LittleEndian(data[0x3A..])), + ContentType = GetContentType(stars), + IVs = default, + Nature = Nature.Random, + ScaleType = SizeType9.RANDOM, + Scale = 0, + CanBeEncounteredScarlet = randRateMinScarlet != -1, + CanBeEncounteredViolet = randRateMinViolet != -1, + Map = map, + }; + } + + private static List DeepCopyList(List list) => + list.Select(reward => new Reward { ItemID = reward.ItemID, Amount = reward.Amount, Probability = reward.Probability, Aux = reward.Aux }).ToList(); + + private static List GetRewardList(ulong hash, Dictionary> dic) => dic.GetValueOrDefault(hash) ?? []; + + private static byte GetGenderRatio(PersonalInfo9SV personal) => personal.Gender; + + private static AbilityPermission GetAbility(byte b) => b switch + { + 0 => AbilityPermission.Any12, + 1 => AbilityPermission.Any12H, + 2 => AbilityPermission.OnlyFirst, + 3 => AbilityPermission.OnlySecond, + 4 => AbilityPermission.OnlyHidden, + _ => throw new ArgumentOutOfRangeException(nameof(b), b, null), + }; + + private static RaidContent GetContentType(byte stars) => stars < 6 ? RaidContent.Standard : RaidContent.Black; + + public static EncounterRaidTF9? GetEncounterFromSeed(in uint seed, in EncounterTeraTF9[] encounters, in short rateTotal, in GameVersion game, GameProgress progress, RaidContent content) + { + var xoro = new Xoroshiro128Plus(seed); + var randStars = content is RaidContent.Standard ? GetSeedStars(ref xoro, progress) : (byte)6; + var rateRand = (int)xoro.NextInt((uint)rateTotal); + + foreach (var encounter in encounters) + { + if (randStars != encounter.Stars) + continue; + + var min = game is GameVersion.SL ? encounter.RandRateMinScarlet : encounter.RandRateMinViolet; + + if (min < 0) + continue; + + if ((uint)(rateRand - min) < encounter.RandRate) + return encounter; + } + return null; + } + + public static EncounterRaidTF9? GetEncounterFromSeed(uint seed, EncounterRaidTF9[] encounters, GameVersion game, GameProgress progress, RaidContent content, TeraRaidMapParent map) + { + var xoro = new Xoroshiro128Plus(seed); + var randStars = content is RaidContent.Standard ? GetSeedStars(ref xoro, progress) : (byte)6; + var max = game is GameVersion.SL ? EncounterTera9.GetRateTotalSL(randStars, map) : EncounterTera9.GetRateTotalVL(randStars, map); + var rateRand = (int)xoro.NextInt((uint)max); + + foreach (var encounter in (EncounterTeraTF9[])encounters) + { + if (randStars != encounter.Stars) + continue; + + var min = game is GameVersion.SL ? encounter.RandRateMinScarlet : encounter.RandRateMinViolet; + + if (min < 0) + continue; + + if ((uint)(rateRand - min) < encounter.RandRate) + return encounter; + } + return null; + } + + public static byte GetSeedStars(ref Xoroshiro128Plus xoro, GameProgress progress) + { + var rand = xoro.NextInt(100); + return progress switch + { + GameProgress.Unlocked6Stars => rand switch + { + > 70 => 5, + > 30 => 4, + _ => 3, + }, + GameProgress.Unlocked5Stars => rand switch + { + > 75 => 5, + > 40 => 4, + _ => 3, + }, + GameProgress.Unlocked4Stars => rand switch + { + > 70 => 4, + > 40 => 3, + > 20 => 2, + _ => 1, + }, + GameProgress.Unlocked3Stars => rand switch + { + > 70 => 3, + > 30 => 2, + _ => 1, + }, + _ => rand switch + { + > 80 => 2, + _ => 1, + }, + }; + } +} diff --git a/TeraFinder.Core/Classes/EncounterTera9.cs b/TeraFinder.Core/Classes/EncounterTera9.cs deleted file mode 100644 index c9713363..00000000 --- a/TeraFinder.Core/Classes/EncounterTera9.cs +++ /dev/null @@ -1,255 +0,0 @@ -using PKHeX.Core; -using System.Buffers.Binary; -using static PKHeX.Core.AbilityPermission; - -//Extension of https://github.com/kwsch/PKHeX/blob/master/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterTera9.cs -namespace TeraFinder.Core; - -/// -/// Generation 9 Tera Raid Encounter -/// -public sealed record EncounterTera9 : IEncounterable, IEncounterConvertible, ITeraRaid9, IExtendedTeraRaid9, IMoveset, IFlawlessIVCount, IFixedGender -{ - //TeraFinder Serialization - public uint Identifier { get; private init; } - public ulong FixedRewardHash { get; private init; } - public ulong LotteryRewardHash { get; private init; } - public int Item { get; private init; } - public required ExtraMoves ExtraMoves { get; init; } - public required Nature Nature { get; init; } - public required SizeType9 ScaleType { get; init; } - public required byte Scale { get; init; } - public required IndividualValueSet IVs { get; init; } - - //PKHeX Serialization - public int Generation => 9; - public EntityContext Context => EntityContext.Gen9; - public GameVersion Version => GameVersion.SV; - ushort ILocation.Location => Location; - public const ushort Location = Locations.TeraCavern9; - public bool IsDistribution => Index != 0; - public Ball FixedBall => Ball.None; - public bool EggEncounter => false; - public bool IsShiny => Shiny == Shiny.Always; - public int EggLocation => 0; - - public required ushort Species { get; init; } - public required byte Form { get; init; } - public required byte Gender { get; init; } - public required AbilityPermission Ability { get; init; } - public required byte FlawlessIVCount { get; init; } - public required Shiny Shiny { get; init; } - public required byte Level { get; init; } - public required Moveset Moves { get; init; } - public required GemType TeraType { get; init; } - public required byte Index { get; init; } - public required byte Stars { get; init; } - public required byte RandRate { get; init; } // weight chance of this encounter - public required short RandRateMinScarlet { get; init; } // weight chance total of all lower index encounters, for Scarlet - public required short RandRateMinViolet { get; init; } // weight chance total of all lower index encounters, for Violet - public bool IsAvailableHostScarlet => RandRateMinScarlet != -1; - public bool IsAvailableHostViolet => RandRateMinViolet != -1; - public required TeraRaidMapParent Map { get; init; } - - public string Name => "Tera Raid Encounter"; - public string LongName => Name; - public byte LevelMin => Level; - public byte LevelMax => Level; - - byte IGeneration.Generation => throw new NotImplementedException(); - - ushort ILocation.EggLocation => throw new NotImplementedException(); - - public bool CanBeEncountered(uint seed) => Tera9RNG.IsMatchStarChoice(seed, Stars, RandRate, RandRateMinScarlet, RandRateMinViolet, Map); - - /// - /// Fetches the rate sum for the base ROM raid, depending on star count. - /// - /// Raid Difficulty - /// Map the encounter originates on. - /// Total rate value the game uses to call rand(x) with. - public static short GetRateTotalSL(int star, TeraRaidMapParent map) => map switch - { - TeraRaidMapParent.Paldea => GetRateTotalBaseSL(star), - TeraRaidMapParent.Kitakami => GetRateTotalKitakamiSL(star), - TeraRaidMapParent.Blueberry => GetRateTotalBlueberry(star), - _ => 0, - }; - - /// "/> - public static short GetRateTotalVL(int star, TeraRaidMapParent map) => map switch - { - TeraRaidMapParent.Paldea => GetRateTotalBaseVL(star), - TeraRaidMapParent.Kitakami => GetRateTotalKitakamiVL(star), - TeraRaidMapParent.Blueberry => GetRateTotalBlueberry(star), - _ => 0, - }; - - public static short GetRateTotalBaseSL(int star) => star switch - { - 1 => 5800, - 2 => 5300, - 3 => 7400, - 4 => 8800, // Scarlet has one more encounter. - 5 => 9100, - 6 => 6500, - _ => 0, - }; - - public static short GetRateTotalBaseVL(int star) => star switch - { - 1 => 5800, - 2 => 5300, - 3 => 7400, - 4 => 8700, // Violet has one less encounter. - 5 => 9100, - 6 => 6500, - _ => 0, - }; - - public static short GetRateTotalKitakamiSL(int star) => star switch - { - 1 => 1500, - 2 => 1500, - 3 => 2500, - 4 => 2100, - 5 => 2250, - 6 => 2475, // -99 - _ => 0, - }; - - public static short GetRateTotalKitakamiVL(int star) => star switch - { - 1 => 1500, - 2 => 1500, - 3 => 2500, - 4 => 2100, - 5 => 2250, - 6 => 2574, // +99 - _ => 0, - }; - - public static short GetRateTotalBlueberry(int star) => star switch - { - 1 => 1100, - 2 => 1100, - 3 => 2000, - 4 => 1900, - 5 => 2100, - 6 => 2600, - _ => 0, - }; - - public ushort GetRandRateTotalScarlet(int stage) => 0; - public ushort GetRandRateTotalViolet(int stage) => 0; - public ushort GetRandRateMinScarlet(int stage) => (ushort)RandRateMinScarlet; - public ushort GetRandRateMinViolet(int stage) => (ushort)RandRateMinViolet; - - public static EncounterTera9[] GetArray(ReadOnlySpan data, TeraRaidMapParent map) - { - var count = data.Length / SerializedSize; - var result = new EncounterTera9[count]; - for (int i = 0; i < result.Length; i++) - result[i] = ReadEncounter(data.Slice(i * SerializedSize, SerializedSize), map); - return result; - } - - private const int SerializedSize = 0x3C; - - private static EncounterTera9 ReadEncounter(ReadOnlySpan data, TeraRaidMapParent map) => new() - { - Species = BinaryPrimitives.ReadUInt16LittleEndian(data), - Form = data[0x02], - Gender = (byte)(data[0x03] - 1), - Ability = GetAbility(data[0x04]), - FlawlessIVCount = data[5], - Shiny = data[0x06] switch { 0 => Shiny.Random, 1 => Shiny.Never, 2 => Shiny.Always, _ => throw new ArgumentOutOfRangeException(nameof(data)) }, - Level = data[0x07], - Moves = new Moveset( - BinaryPrimitives.ReadUInt16LittleEndian(data[0x08..]), - BinaryPrimitives.ReadUInt16LittleEndian(data[0x0A..]), - BinaryPrimitives.ReadUInt16LittleEndian(data[0x0C..]), - BinaryPrimitives.ReadUInt16LittleEndian(data[0x0E..])), - TeraType = (GemType)data[0x10], - Index = data[0x11], - Stars = data[0x12], - RandRate = data[0x13], - RandRateMinScarlet = BinaryPrimitives.ReadInt16LittleEndian(data[0x14..]), - RandRateMinViolet = BinaryPrimitives.ReadInt16LittleEndian(data[0x16..]), - Identifier = BinaryPrimitives.ReadUInt32LittleEndian(data[0x18..]), - FixedRewardHash = BinaryPrimitives.ReadUInt64LittleEndian(data[0x1C..]), - LotteryRewardHash = BinaryPrimitives.ReadUInt64LittleEndian(data[0x24..]), - Item = (int)BinaryPrimitives.ReadUInt32LittleEndian(data[0x2C..]), - ExtraMoves = new ExtraMoves(BinaryPrimitives.ReadUInt16LittleEndian(data[0x30..]), - BinaryPrimitives.ReadUInt16LittleEndian(data[0x32..]), - BinaryPrimitives.ReadUInt16LittleEndian(data[0x34..]), - BinaryPrimitives.ReadUInt16LittleEndian(data[0x36..]), - BinaryPrimitives.ReadUInt16LittleEndian(data[0x38..]), - BinaryPrimitives.ReadUInt16LittleEndian(data[0x3A..])), - IVs = default, - Nature = Nature.Random, - ScaleType = SizeType9.RANDOM, - Scale = 0, - Map = map, - }; - - private static AbilityPermission GetAbility(byte b) => b switch - { - 0 => Any12, - 1 => Any12H, - 2 => OnlyFirst, - 3 => OnlySecond, - 4 => OnlyHidden, - _ => throw new ArgumentOutOfRangeException(nameof(b), b, null), - }; - - #region Generating - PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria); - PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr); - public PK9 ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted); - public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) - { - int lang = (int)Language.GetSafeLanguage((byte)Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion(tr.Version); - var pi = PersonalTable.SV[Species, Form]; - var pk = new PK9 - { - Language = lang, - Species = Species, - Form = Form, - CurrentLevel = LevelMin, - OriginalTrainerFriendship = pi.BaseFriendship, - MetLocation = Location, - MetLevel = LevelMin, - MetDate = EncounterDate.GetDateSwitch(), - Version = (GameVersion)(byte)version, - Ball = (byte)Ball.Poke, - - Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, (byte)Generation), - Obedience_Level = LevelMin, - OriginalTrainerName = tr.OT, - OriginalTrainerGender = tr.Gender, - ID32 = tr.ID32, - }; - SetPINGA(pk, criteria, pi); - pk.SetMoves(Moves); - - pk.ResetPartyStats(); - return pk; - } - - private void SetPINGA(PK9 pk, EncounterCriteria criteria, PersonalInfo9SV pi) - { - const byte rollCount = 1; - const byte undefinedSize = 0; - var param = new GenerateParam9(Species, pi.Gender, FlawlessIVCount, rollCount, - undefinedSize, undefinedSize, undefinedSize, undefinedSize, - Ability, Shiny); - - var init = Util.Rand.Rand64(); - var success = this.TryApply32(pk, init, param, criteria); - if (!success) - this.TryApply32(pk, init, param, EncounterCriteria.Unrestricted); - } - #endregion -} \ No newline at end of file diff --git a/TeraFinder.Core/Classes/ExtraMoves.cs b/TeraFinder.Core/Classes/ExtraMoves.cs index 176e51b7..8459a73e 100644 --- a/TeraFinder.Core/Classes/ExtraMoves.cs +++ b/TeraFinder.Core/Classes/ExtraMoves.cs @@ -2,8 +2,12 @@ namespace TeraFinder.Core; -public class ExtraMoves +/// +/// Set of (up to) 6 moves that are in a HashSet of moves. +/// +public readonly record struct ExtraMoves { + public bool HasMoves => ExtraMove1 != 0; public HashSet ExtraMoveList { get; private init; } public Move ExtraMove1 { get => ExtraMoveList.Count > 0 ? ExtraMoveList.ElementAt(0) : Move.None; } diff --git a/TeraFinder.Core/Classes/MassOutbreak.cs b/TeraFinder.Core/Classes/MassOutbreak.cs index 570a5b1d..caaf7fb1 100644 --- a/TeraFinder.Core/Classes/MassOutbreak.cs +++ b/TeraFinder.Core/Classes/MassOutbreak.cs @@ -45,7 +45,7 @@ public MassOutbreak(SAV9SV sav, int id, TeraRaidMapParent map) SAV = sav; LocationMap = map switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}CenterPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}CenterPos")!.GetValue(new BlockDefinition())!; var block = sav.Accessor.GetBlockSafe(blockInfo.Key); if (block.Type is SCTypeCode.Array) @@ -53,7 +53,7 @@ public MassOutbreak(SAV9SV sav, int id, TeraRaidMapParent map) else LocationCenter = null; - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}DummyPos")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}DummyPos")!.GetValue(new BlockDefinition())!; block = sav.Accessor.GetBlockSafe(blockInfo.Key); if (block.Type is SCTypeCode.Array) @@ -99,7 +99,7 @@ public void RestoreFromJson(string json) public sbyte GetAmountAvailable() { - var info = LocationMap switch { "DLC1" => Blocks.KOutbreakDLC1NumActive, "DLC2" => Blocks.KOutbreakDLC2NumActive, _ => Blocks.KOutbreakMainNumActive }; + var info = LocationMap switch { "DLC1" => BlockDefinitions.KOutbreakDLC1NumActive, "DLC2" => BlockDefinitions.KOutbreakDLC2NumActive, _ => BlockDefinitions.KOutbreakMainNumActive }; var block = SAV.Accessor.GetBlockSafe(info.Key); if (block.Type is SCTypeCode.SByte) @@ -110,7 +110,7 @@ public sbyte GetAmountAvailable() private void SetAmountAvailable(sbyte value) { - var info = LocationMap switch { "DLC1" => Blocks.KOutbreakDLC1NumActive, "DLC2" => Blocks.KOutbreakDLC2NumActive, _ => Blocks.KOutbreakMainNumActive }; + var info = LocationMap switch { "DLC1" => BlockDefinitions.KOutbreakDLC1NumActive, "DLC2" => BlockDefinitions.KOutbreakDLC2NumActive, _ => BlockDefinitions.KOutbreakMainNumActive }; var block = SAV.Accessor.GetBlockSafe(info.Key); if (block.Type is SCTypeCode.SByte) @@ -132,7 +132,7 @@ private void SetEnabled(bool value) private bool GetFound() { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}Found")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}Found")!.GetValue(new BlockDefinition())!; var block = SAV.Accessor.FindOrDefault(blockInfo.Key); if (block.Type.IsBoolean() && block.Type is SCTypeCode.Bool2) @@ -143,7 +143,7 @@ private bool GetFound() private void SetFound(bool value) { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}Found")!.GetValue(new DataBlock())!; ; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}Found")!.GetValue(new BlockDefinition())!; ; var block = SAV.Accessor.FindOrDefault(blockInfo.Key); if (block.Type.IsBoolean()) @@ -157,7 +157,7 @@ private void SetFound(bool value) private uint GetSpecies() { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}Species")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}Species")!.GetValue(new BlockDefinition())!; var block = SAV.Accessor.GetBlockSafe(blockInfo.Key); if (block.Type is SCTypeCode.UInt32) @@ -168,7 +168,7 @@ private uint GetSpecies() private void SetSpecies(uint value) { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}Species")!.GetValue(new DataBlock())!; ; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}Species")!.GetValue(new BlockDefinition())!; ; var block = SAV.Accessor.GetBlockSafe(blockInfo.Key); if(block.Type is SCTypeCode.UInt32) @@ -177,7 +177,7 @@ private void SetSpecies(uint value) private byte GetForm() { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}Form")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}Form")!.GetValue(new BlockDefinition())!; var block = SAV.Accessor.GetBlockSafe(blockInfo.Key); if (block.Type is SCTypeCode.Byte or SCTypeCode.SByte) @@ -188,7 +188,7 @@ private byte GetForm() private void SetForm(byte value) { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}Form")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}Form")!.GetValue(new BlockDefinition())!; var block = SAV.Accessor.GetBlockSafe(blockInfo.Key); if (block.Type is SCTypeCode.Byte or SCTypeCode.SByte) @@ -197,7 +197,7 @@ private void SetForm(byte value) private int GetNumKO() { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}NumKOed")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}NumKOed")!.GetValue(new BlockDefinition())!; var block = SAV.Accessor.GetBlockSafe(blockInfo.Key); if (block.Type is SCTypeCode.Int32) @@ -208,7 +208,7 @@ private int GetNumKO() private void SetNumKO(int value) { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}NumKOed")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}NumKOed")!.GetValue(new BlockDefinition())!; var block = SAV.Accessor.GetBlockSafe(blockInfo.Key); if (block.Type is SCTypeCode.Int32) @@ -217,7 +217,7 @@ private void SetNumKO(int value) private int GetMaxSpawns() { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}TotalSpawns")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}TotalSpawns")!.GetValue(new BlockDefinition())!; var block = SAV.Accessor.GetBlockSafe(blockInfo.Key); if (block.Type is SCTypeCode.Int32) @@ -228,7 +228,7 @@ private int GetMaxSpawns() private void SetMaxSpawns(int value) { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{ID}{LocationMap}TotalSpawns")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{ID}{LocationMap}TotalSpawns")!.GetValue(new BlockDefinition())!; var block = SAV.Accessor.GetBlockSafe(blockInfo.Key); if (block.Type is SCTypeCode.Int32) diff --git a/TeraFinder.Core/Classes/RewardDetails.cs b/TeraFinder.Core/Classes/RewardDetails.cs index cbef0b95..eda8f09e 100644 --- a/TeraFinder.Core/Classes/RewardDetails.cs +++ b/TeraFinder.Core/Classes/RewardDetails.cs @@ -2,89 +2,75 @@ namespace TeraFinder.Core; -public class Reward +public record Reward { public int ItemID { get; set; } public int Amount { get; set; } public int Probability { get; set; } public int Aux { get; set; } - public string GetItemName(string[]? itemnames = null, string language = "en", bool quantity = false) + public string GetItemName(MoveType tera, string[]? itemnames = null, string language = "en", bool quantity = false) { - if (ItemID == ushort.MaxValue) - return $"{RewardUtil.Material[GameLanguage.GetLanguageIndex(language)]} {(quantity ? $"x{Amount}" : "")} {GetClientOrHostString()}"; - else if(ItemID == ushort.MaxValue-1) - return $"{RewardUtil.TeraShard[GameLanguage.GetLanguageIndex(language)]} {(quantity ? $"x{Amount}" : "")} {GetClientOrHostString()}"; - else if (RewardUtil.IsTM(ItemID)) + itemnames ??= GameInfo.GetStrings(language).itemlist; + + if (RewardUtil.IsTM(ItemID)) return $"{RewardUtil.GetNameTM(ItemID, itemnames, GameInfo.GetStrings(language).movelist)} {(quantity ? $"x{Amount}" : "")} {GetClientOrHostString()}"; - itemnames ??= GameInfo.GetStrings(language).itemlist; + if (RewardUtil.IsTeraShard(ItemID)) + return $"{itemnames[RewardUtil.GetTeraShard(tera)]} {(quantity ? $"x{Amount}" : "")} {GetClientOrHostString()}"; return $"{itemnames[ItemID]} {(quantity ? $"x{Amount}" : "")} {GetClientOrHostString()}"; } - private string GetClientOrHostString() - { - return $"{(Aux == 0 ? "" : Aux == 1 ? "(H)" : Aux == 2 ? "(C)" : Aux == 3 ? "(Once)" : "")}"; - } + private string GetClientOrHostString() => + $"{(Aux == 0 ? "" : Aux == 1 ? "(Host)" : Aux == 2 ? "(Guests)" : Aux == 3 ? "(Once)" : "")}"; - public bool CompareItem(Reward item, bool greaterthan = false) + public bool CompareItem(Reward item) { - if (greaterthan && item.ItemID == ushort.MaxValue - 2) - { - if (ItemID == ushort.MaxValue-2 || (ItemID >= 1904 && ItemID <= 1908)) - if (Amount >= item.Amount) - return true; - - return false; - } - if (item.ItemID != ItemID) return false; - if (!greaterthan && item.Amount != Amount) - return false; - if(greaterthan && Amount < item.Amount) + if (item.Amount != Amount) return false; return true; } - public bool NeedAccurate() + public bool CompareEncounterItemID(Reward item) { - return ItemID switch - { - >= 1862 and <= 1879 => true, - >= 1956 and <= 2159 => true, - _ => false, - }; - } + if (item.ItemID == ushort.MaxValue - 2 && RewardUtil.IsHerbaMystica(ItemID)) + return true; - public bool IsHerba() => ItemID >= 1904 && ItemID <= 1908; + if (RewardUtil.IsTeraShard(item.ItemID) && RewardUtil.IsTeraShard(ItemID)) + return true; + + return item.ItemID == ItemID; + } } -public class RewardDetails : IRaidDetails +public struct RewardDetails : IRaidDetails { public uint Seed { get; set; } public List? Rewards {get; set;} public ushort Species { get; set; } public int Stars { get; set; } public TeraShiny Shiny { get; set; } + public byte TeraType { get; set; } public byte EventIndex { get; set; } - public ulong Calcs { get; set; } - public string[] GetStrings(string[] itemnames, string language) + public readonly string[] GetStrings(string[] itemnames, string language, MoveType tera) { var list = new string[25]; if(Rewards is not null) for(var i = 0; i < Rewards.Count; i++) - list[i] = Rewards[i].GetItemName(itemnames, language, true); + list[i] = Rewards[i].GetItemName(tera, itemnames, language, true); return list; } } -public class RewardGridEntry +public struct RewardGridEntry { public string? Seed { get; private set; } + public string? Info { get; private set; } public string? Item1 { get; private set; } public string? Item2 { get; private set; } public string? Item3 { get; private set; } @@ -110,13 +96,11 @@ public class RewardGridEntry public string? Item23 { get; private set; } public string? Item24 { get; private set; } public string? Item25 { get; private set; } - public string? ExtraInfo { get; private set; } public string? EventIndex { get; private set; } - public string? Calcs { get; private set; } - public RewardGridEntry(RewardDetails res, string[] itemnames, string[]speciesnames, string[] shinynames, string language) + public RewardGridEntry(RewardDetails res, string[] itemnames, string[]speciesnames, string[] shinynames, string[] typenames, string language) { - var str = res.GetStrings(itemnames, language); + var str = res.GetStrings(itemnames, language, (MoveType)res.TeraType); Seed = $"{res.Seed:X8}"; Item1 = str[0]; Item2 = str[1]; @@ -143,133 +127,101 @@ public RewardGridEntry(RewardDetails res, string[] itemnames, string[]speciesnam Item23 = str[22]; Item24 = str[23]; Item25 = str[24]; - ExtraInfo = $"{speciesnames[res.Species]} ({res.Stars}☆) {(res.Shiny > TeraShiny.No ? $"({shinynames[(int)res.Shiny]})" : "")}"; EventIndex = $"{res.EventIndex}"; - Calcs = $"{res.Calcs}"; - } - - public RewardGridEntry(string[] str) - { - Seed = str[0]; - Item1 = str[1]; - Item2 = str[2]; - Item3 = str[3]; - Item4 = str[4]; - Item5 = str[5]; - Item6 = str[6]; - Item7 = str[7]; - Item8 = str[8]; - Item9 = str[9]; - Item10 = str[10]; - Item11 = str[11]; - Item12 = str[12]; - Item13 = str[13]; - Item14 = str[14]; - Item15 = str[15]; - Item16 = str[16]; - Item17 = str[17]; - Item18 = str[18]; - Item19 = str[19]; - Item20 = str[20]; - Item21 = str[21]; - Item22 = str[22]; - Item23 = str[23]; - Item24 = str[24]; - Item25 = str[25]; - ExtraInfo = str[22]; - EventIndex = str[23]; - Calcs = str[24]; - } - - public string[] GetStrings() - { - var list = new List - { - Seed!, - Item1!, - Item2!, - Item3!, - Item4!, - Item5!, - Item6!, - Item7!, - Item8!, - Item9!, - Item10!, - Item11!, - Item12!, - Item13!, - Item14!, - Item15!, - Item16!, - Item17!, - Item18!, - Item19!, - Item20!, - Item21!, - Item22!, - Item23!, - Item24!, - Item25!, - ExtraInfo!, - EventIndex!, - Calcs!, - }; - return [.. list]; + Info = $"{speciesnames[res.Species]} {res.Stars}☆ ({typenames[res.TeraType]}) {(res.Shiny > TeraShiny.No ? $"({shinynames[(int)res.Shiny]})" : "")}"; } } /// -/// Toggles the marking at a given index. +/// Check if a RewardDetails matches the filter. /// /// check for Stars and Species. /// check for Any Herba Mystica. public class RewardFilter(bool isEncounterFilter, bool isAnyHerbaFilter) { - protected bool EncounterFilter { get; set; } = isEncounterFilter; - protected bool HerbaFilter { get; set; } = isAnyHerbaFilter; + public bool EncounterFilter { get; init; } = isEncounterFilter; + protected bool HerbaFilter { get; init; } = isAnyHerbaFilter; public Reward[]? FilterRewards { get; set; } - public ushort Species { get; set; } - public int Stars { get; set; } + public EncounterFilter? Encounter { get; set; } public TeraShiny Shiny { get; set; } public bool IsFilterMatch(RewardDetails res) { if (EncounterFilter) { - if (Species > 0) - if (Species != res.Species) + if (Encounter.Species > 0) + if (Encounter.Species != res.Species) return false; - if (Stars > 0) - if (Stars != res.Stars) + if (Encounter.Stars > 0) + if (Encounter.Stars != res.Stars) return false; } - if (Shiny > TeraShiny.No) - if (res.Shiny < TeraShiny.Yes) - return false; + if (Shiny > TeraShiny.Any) + { + if (Shiny is TeraShiny.Yes) + { + if (res.Shiny < TeraShiny.Yes) + return false; + } + else if (Shiny > TeraShiny.Yes) + { + if (Shiny != res.Shiny) + return false; + } + else if (Shiny is TeraShiny.No) + { + if (res.Shiny >= TeraShiny.Yes) + return false; + } + } - if (FilterRewards is not null && FilterRewards.Length > 0) + if (FilterRewards.Length > 0) { - var itemlist = new List(); - foreach (var item in res.Rewards!) + var itemlist = new Dictionary(); + foreach (var item in res.Rewards) { - var index = HerbaFilter && item.IsHerba() ? itemlist.FindIndex(i => i.ItemID == ushort.MaxValue-2) : itemlist.FindIndex(i => i.ItemID == item.ItemID); - if (index >= 0) - itemlist[index].Amount += item.Amount; + var itemId = HerbaFilter && RewardUtil.IsHerbaMystica(item.ItemID) ? ushort.MaxValue - 2 : + RewardUtil.IsTeraShard(item.ItemID) ? RewardUtil.GetTeraShard((MoveType)res.TeraType) : item.ItemID; + + if (itemlist.ContainsKey(itemId)) + itemlist[itemId] += item.Amount; else - itemlist.Add(new Reward { ItemID = HerbaFilter && item.IsHerba() ? ushort.MaxValue-2 : item.ItemID, Amount = item.Amount }); + itemlist[itemId] = item.Amount; } var match = 0; - foreach (var item in itemlist) - foreach (var filter in FilterRewards!) - if (item.CompareItem(filter, true)) - match++; + foreach (var filter in FilterRewards) + if (itemlist.TryGetValue(filter.ItemID, out var amount) && amount >= filter.Amount) + match++; - return match >= FilterRewards!.Length; + return match >= FilterRewards.Length; + } + + return true; + } + + public bool IsEncounterMatch(EncounterRaidTF9 encounter) + { + if (EncounterFilter) + { + if (Encounter.Species > 0) + if (Encounter.Species != encounter.Species) + return false; + + if (Encounter.Stars > 0) + if (Encounter.Stars != encounter.Stars) + return false; + } + + if (FilterRewards.Length > 0) + { + var encRewards = encounter.FixedRewards.Concat(encounter.LotteryRewards); + foreach (var reward in FilterRewards) + if (!encRewards.Any(r => r.CompareEncounterItemID(reward))) + return false; } return true; @@ -277,9 +229,9 @@ public bool IsFilterMatch(RewardDetails res) public bool IsFilterNull() { - if (FilterRewards is null && Species == 0 && Stars == 0 && Shiny is TeraShiny.Any) + if (FilterRewards is null && !EncounterFilter && Shiny is TeraShiny.Any) return true; - if(FilterRewards is not null && FilterRewards.Length <= 0 && Species == 0 && Stars == 0 && Shiny is TeraShiny.Any) + if(FilterRewards is not null && FilterRewards.Length <= 0 && !EncounterFilter && Shiny is TeraShiny.Any) return true; return false; @@ -297,29 +249,31 @@ public bool CompareFilter(RewardFilter res) return false; } - if (res.Species != Species) - return false; + if (EncounterFilter) + { + if (res.EncounterFilter) + { + if (res.Encounter!.Species != Encounter!.Species) + return false; - if (res.Stars != Stars) - return false; + if (res.Encounter.Stars != Encounter.Stars) + return false; + } + else + { + return false; + } + } if (res.Shiny != Shiny) return false; return true; } +} - public bool NeedAccurate() - { - if (!IsFilterNull()) - { - if (Shiny > TeraShiny.No) - return true; - - foreach (var f in FilterRewards!) - if (f.NeedAccurate()) - return true; - } - return false; - } +public class EncounterFilter(ushort species, byte stars) +{ + public ushort Species { get; init; } = species; + public byte Stars { get; init; } = stars; } diff --git a/TeraFinder.Core/Classes/TeraDetails.cs b/TeraFinder.Core/Classes/TeraDetails.cs index 2d78baa6..1d23b23c 100644 --- a/TeraFinder.Core/Classes/TeraDetails.cs +++ b/TeraFinder.Core/Classes/TeraDetails.cs @@ -2,7 +2,7 @@ namespace TeraFinder.Core; -public class TeraDetails : IRaidDetails +public struct TeraDetails() : IRaidDetails { public uint Seed { get; set; } public TeraShiny Shiny { get; set; } @@ -10,7 +10,7 @@ public class TeraDetails : IRaidDetails public ushort Species { get; set; } public byte Form { get; set; } public int Level { get; set; } - public sbyte TeraType { get; set; } + public byte TeraType { get; set; } public uint EC { get; set; } public uint PID { get; set; } public int HP { get; set; } @@ -20,7 +20,8 @@ public class TeraDetails : IRaidDetails public int SPD { get; set; } public int SPE { get; set; } public int Ability { get; set; } - public byte Nature { get; set; } + public int AbilityNumber { get; set; } + public Nature Nature { get; set; } public Gender Gender { get; set; } public byte Height { get; set; } public byte Weight { get; set; } @@ -30,23 +31,10 @@ public class TeraDetails : IRaidDetails public ushort Move3 { get; set; } public ushort Move4 { get; set; } public byte EventIndex { get; set; } - public ulong Calcs { get; set; } - public Nature StatNature { get; internal set; } - - public int GetAbilityNumber() - { - var entry = PersonalTable.SV.GetFormEntry(Species, Form); - if (Ability == entry.Ability1) - return 1; - else if (Ability == entry.Ability2) - return 2; - //else if (Ability == entry.AbilityH) - return 3; - } - public string[] GetStrings(string[] namelist, string[] abilitylist, string[] naturelist, string[] movelist, string[] typelist, string[] formlist, string[] genderlistascii, string[] genderlistunicode, string[] shinies) + public readonly string[] GetStrings(string[] namelist, string[] abilitylist, string[] naturelist, string[] movelist, string[] typelist, string[] formlist, string[] genderlistascii, string[] genderlistunicode, string[] shinies) { - var list = new string[26]; + var list = new string[25]; list[0] = ($"{Seed:X8}"); list[1] = ($"{GetShiny(shinies)}"); list[2] = ($"{Stars}"); @@ -62,7 +50,7 @@ public string[] GetStrings(string[] namelist, string[] abilitylist, string[] nat list[12] = ($"{SPD}"); list[13] = ($"{SPE}"); list[14] = ($"{GetAbilityName(abilitylist)}"); - list[15] = ($"{naturelist[Nature]}"); + list[15] = ($"{naturelist[(byte)Nature]}"); list[16] = ($"{genderlistunicode[(int)Gender]}"); list[17] = ($"{Height}"); list[18] = ($"{Weight}"); @@ -72,29 +60,27 @@ public string[] GetStrings(string[] namelist, string[] abilitylist, string[] nat list[22] = ($"{movelist[Move3]}"); list[23] = ($"{movelist[Move4]}"); list[24] = ($"{EventIndex}"); - list[25] = ($"{Calcs}"); return list; } - private string GetShiny(string[] shinies) + private readonly string GetShiny(string[] shinies) { return shinies[(int)Shiny]; } - public string GetName(string[] namelist, string[] typelist ,string[] formlist, string[] genderlist) + public readonly string GetName(string[] namelist, string[] typelist ,string[] formlist, string[] genderlist) { var forms = FormConverter.GetFormList(Species, typelist, formlist, genderlist, EntityContext.Gen9); return $"{namelist[Species]}{(forms.Length > 1 ? $"-{forms[Form]}" : "")}"; } - private string GetAbilityName(string[] abilitylist) + private readonly string GetAbilityName(string[] abilitylist) { - var num = GetAbilityNumber(); - return $"{abilitylist[Ability]} ({(num == 3 ? "H" : num)})"; + return $"{abilitylist[Ability]} ({(AbilityNumber == 4 ? "H" : AbilityNumber)})"; } } -public class GridEntry +public struct GridEntry { public string? Seed { get; private set; } public string? Shiny { get; private set; } @@ -121,7 +107,6 @@ public class GridEntry public string? Move3 { get; private set; } public string? Move4 { get; private set; } public string? EventIndex { get; private set; } - public string? Calcs { get; private set; } public GridEntry(TeraDetails res, string[] namelist, string[] abilitylist, string[] naturelist, string[] movelist, string[] typelist, string[] formlist, string[] genderlistascii, string[] genderlistunicode, string[] shinylist) { @@ -151,7 +136,6 @@ public GridEntry(TeraDetails res, string[] namelist, string[] abilitylist, strin Move3 = str[22]; Move4 = str[23]; EventIndex = str[24]; - Calcs = str[25]; } public GridEntry(string[] str) @@ -181,12 +165,11 @@ public GridEntry(string[] str) Move3 = str[22]; Move4 = str[23]; EventIndex = str[24]; - Calcs = str[25]; } - public string[] GetStrings() + public readonly string[] GetStrings() { - var list = new string[26]; + var list = new string[25]; list[0] = ($"{Seed}"); list[1] = ($"{Shiny}"); list[2] = ($"{Stars}"); @@ -212,13 +195,12 @@ public string[] GetStrings() list[22] = ($"{Move3}"); list[23] = ($"{Move4}"); list[24] = ($"{EventIndex}"); - list[25] = ($"{Calcs}"); return list; } } /// -/// Toggles the marking at a given index. +/// Check if a TeraDetails matches the filter. /// /// check for Stars and Species. /// check for IVs @@ -226,10 +208,10 @@ public string[] GetStrings() /// check for EC and Scale public class TeraFilter(bool isEncounterFilter, bool isIvFilter, bool isStatFilter, bool isAuxFilter) { - protected bool EncounterFilter { get; set; } = isEncounterFilter; - protected bool IVFilter { get; set; } = isIvFilter; - protected bool StatFilter { get; set; } = isStatFilter; - protected bool AuxFilter { get; set; } = isAuxFilter; + public bool EncounterFilter { get; init; } = isEncounterFilter; + protected bool IVFilter { get; init; } = isIvFilter; + protected bool StatFilter { get; init; } = isStatFilter; + protected bool AuxFilter { get; init; } = isAuxFilter; public bool IsFormFilter { get; set; } @@ -252,7 +234,7 @@ public class TeraFilter(bool isEncounterFilter, bool isIvFilter, bool isStatFilt public int Form { get; set; } public sbyte TeraType { get; set; } public int AbilityNumber { get; set; } - public byte Nature { get; set; } + public Nature Nature { get; set; } public Gender Gender { get; set; } public TeraShiny Shiny { get; set; } public bool AltEC { get; set; } @@ -297,10 +279,10 @@ public bool IsFilterMatch(TeraDetails res) return false; if (AbilityNumber != 0) - if (AbilityNumber != res.GetAbilityNumber()) + if (AbilityNumber != res.AbilityNumber) return false; - if (Nature != 25) + if (Nature is not Nature.Random) if (Nature != res.Nature) return false; @@ -309,14 +291,9 @@ public bool IsFilterMatch(TeraDetails res) return false; } - if (Shiny is > TeraShiny.Any) + if (Shiny > TeraShiny.Any) { - if (Shiny is TeraShiny.No) - { - if (res.Shiny >= TeraShiny.Yes) - return false; - } - else if (Shiny is TeraShiny.Yes) + if (Shiny is TeraShiny.Yes) { if (res.Shiny < TeraShiny.Yes) return false; @@ -326,6 +303,11 @@ public bool IsFilterMatch(TeraDetails res) if (Shiny != res.Shiny) return false; } + else if (Shiny is TeraShiny.No) + { + if (res.Shiny >= TeraShiny.Yes) + return false; + } } if (AuxFilter) @@ -341,7 +323,77 @@ public bool IsFilterMatch(TeraDetails res) return true; } - public bool IsFilterNull(bool isblack) + public bool IsEncounterMatch(EncounterRaidTF9 res) + { + if (EncounterFilter) + { + if (Species != 0) + if (Species != res.Species) + return false; + + if (Stars != 0) + if (Stars != res.Stars) + return false; + + if (IsFormFilter) + if (Form != res.Form) + return false; + } + + return true; + } + + public bool IsShinyMatch(TeraShiny res) + { + if (Shiny > TeraShiny.Any) + { + if (Shiny is TeraShiny.Yes && res < TeraShiny.Yes) + return false; + else if (Shiny > TeraShiny.Yes && Shiny != res) + return false; + } + return true; + } + + public bool IsIVMatch(ReadOnlySpan res) + { + if (IVFilter) + { + if (!(MinHP <= res[0] && res[0] <= MaxHP)) + return false; + if (!(MinAtk <= res[1] && res[1] <= MaxAtk)) + return false; + if (!(MinDef <= res[2] && res[2] <= MaxDef)) + return false; + if (!(MinSpa <= res[3] && res[3] <= MaxSpa)) + return false; + if (!(MinSpd <= res[4] && res[4] <= MaxSpd)) + return false; + if (!(MinSpe <= res[5] && res[5] <= MaxSpe)) + return false; + } + return true; + } + + public bool IsTeraMatch(byte res) => + TeraType == -1 || TeraType == res; + + public bool IsECMatch(uint res) => + !(AltEC && res % 100 != 0); + + public bool IsAbilityMatch(int res) => + AbilityNumber == 0 || AbilityNumber == res; + + public bool IsNatureMatch(Nature res) => + Nature is Nature.Random || Nature == res; + + public bool IsGenderMatch(Gender res) => + Gender == Gender.Random || Gender == res; + + public bool IsScaleMatch(int res) => + MinScale <= res && res <= MaxScale; + + public bool IsFilterNull() { if (!(MinHP == 0)) return false; @@ -367,7 +419,7 @@ public bool IsFilterNull(bool isblack) return false; if (!(MaxSpe == 31)) return false; - if (Stars != 0 && !isblack) + if (Stars != 0) return false; if (!(Species == 0)) return false; @@ -377,13 +429,13 @@ public bool IsFilterNull(bool isblack) return false; if (!(AbilityNumber == 0)) return false; - if (!(Nature == 25)) + if (Nature is not Nature.Random) return false; - if (!(Gender == Gender.Random)) + if (Gender is not Gender.Random) return false; - if (!(Shiny == TeraShiny.Any)) + if (Shiny is not TeraShiny.Any) return false; - if (!(AltEC == false)) + if (AltEC) return false; if (!(MinScale == 0)) return false; diff --git a/TeraFinder.Core/Utils/Enums.cs b/TeraFinder.Core/Enumerations/OutbreakSpecies.cs similarity index 83% rename from TeraFinder.Core/Utils/Enums.cs rename to TeraFinder.Core/Enumerations/OutbreakSpecies.cs index 5c1863d3..5e0b5052 100644 --- a/TeraFinder.Core/Utils/Enums.cs +++ b/TeraFinder.Core/Enumerations/OutbreakSpecies.cs @@ -1,770 +1,659 @@ namespace TeraFinder.Core; -public enum PaldeaSpeciesOb : ushort -{ - Pikachu = 25, - Raichu = 26, - Jigglypuff = 39, - Wigglytuff = 40, - Venonat = 48, - Venomoth = 49, - Diglett = 50, - Dugtrio = 51, - Meowth = 52, - Persian = 53, - Psyduck = 54, - Golduck = 55, - Mankey = 56, - Primeape = 57, - Growlithe = 58, - Arcanine = 59, - Slowpoke = 79, - Slowbro = 80, - Magnemite = 81, - Magneton = 82, - Grimer = 88, - Muk = 89, - Shellder = 90, - Cloyster = 91, - Gastly = 92, - Haunter = 93, - Drowzee = 96, - Hypno = 97, - Voltorb = 100, - Electrode = 101, - Chansey = 113, - Scyther = 123, - Tauros = 128, - Magikarp = 129, - Gyarados = 130, - Ditto = 132, - Eevee = 133, - Vaporeon = 134, - Jolteon = 135, - Flareon = 136, - Dratini = 147, - Dragonair = 148, - Pichu = 172, - Igglybuff = 174, - Mareep = 179, - Flaaffy = 180, - Ampharos = 181, - Marill = 183, - Azumarill = 184, - Sudowoodo = 185, - Hoppip = 187, - Skiploom = 188, - Jumpluff = 189, - Sunflora = 192, - Wooper = 194, - Espeon = 196, - Umbreon = 197, - Murkrow = 198, - Misdreavus = 200, - Girafarig = 203, - Pineco = 204, - Forretress = 205, - Dunsparce = 206, - Qwilfish = 211, - Heracross = 214, - Sneasel = 215, - Teddiursa = 216, - Ursaring = 217, - Delibird = 225, - Houndour = 228, - Houndoom = 229, - Phanpy = 231, - Donphan = 232, - Stantler = 234, - Blissey = 242, - Larvitar = 246, - Pupitar = 247, - Wingull = 278, - Pelipper = 279, - Ralts = 280, - Kirlia = 281, - Gardevoir = 282, - Surskit = 283, - Masquerain = 284, - Shroomish = 285, - Breloom = 286, - Slakoth = 287, - Vigoroth = 288, - Slaking = 289, - Makuhita = 296, - Hariyama = 297, - Azurill = 298, - Sableye = 302, - Meditite = 307, - Medicham = 308, - Gulpin = 316, - Swalot = 317, - Numel = 322, - Camerupt = 323, - Torkoal = 324, - Spoink = 325, - Grumpig = 326, - Cacnea = 331, - Cacturne = 332, - Swablu = 333, - Altaria = 334, - Zangoose = 335, - Seviper = 336, - Barboach = 339, - Whiscash = 340, - Shuppet = 353, - Banette = 354, - Tropius = 357, - Snorunt = 361, - Glalie = 362, - Luvdisc = 370, - Bagon = 371, - Shelgon = 372, - Starly = 396, - Staravia = 397, - Staraptor = 398, - Kricketot = 401, - Kricketune = 402, - Shinx = 403, - Luxio = 404, - Luxray = 405, - Combee = 415, - Vespiquen = 416, - Pachirisu = 417, - Buizel = 418, - Floatzel = 419, - Shellos = 422, - Gastrodon = 423, - Drifloon = 425, - Drifblim = 426, - Mismagius = 429, - Honchkrow = 430, - Stunky = 434, - Skuntank = 435, - Bronzor = 436, - Bronzong = 437, - Bonsly = 438, - Happiny = 440, - Gible = 443, - Gabite = 444, - Riolu = 447, - Lucario = 448, - Hippopotas = 449, - Hippowdon = 450, - Croagunk = 453, - Toxicroak = 454, - Finneon = 456, - Lumineon = 457, - Snover = 459, - Abomasnow = 460, - Weavile = 461, - Leafeon = 470, - Glaceon = 471, - Gallade = 475, - Froslass = 478, - Rotom = 479, - Petilil = 548, - Lilligant = 549, - Basculin = 550, - Sandile = 551, - Krokorok = 552, - Zorua = 570, - Zoroark = 571, - Gothita = 574, - Gothorita = 575, - Gothitelle = 576, - Deerling = 585, - Sawsbuck = 586, - Foongus = 590, - Amoonguss = 591, - Alomomola = 594, - Tynamo = 602, - Eelektrik = 603, - Axew = 610, - Fraxure = 611, - Cubchoo = 613, - Beartic = 614, - Cryogonal = 615, - Pawniard = 624, - Bisharp = 625, - Rufflet = 627, - Braviary = 628, - Deino = 633, - Zweilous = 634, - Larvesta = 636, - Volcarona = 637, - Fletchling = 661, - Fletchinder = 662, - Talonflame = 663, - Scatterbug = 664, - Spewpa = 665, - Vivillon = 666, - Litleo = 667, - Pyroar = 668, - Flabébé = 669, - Floette = 670, - Florges = 671, - Skiddo = 672, - Gogoat = 673, - Skrelp = 690, - Dragalge = 691, - Clauncher = 692, - Clawitzer = 693, - Sylveon = 700, - Hawlucha = 701, - Dedenne = 702, - Goomy = 704, - Sliggoo = 705, - Klefki = 707, - Bergmite = 712, - Avalugg = 713, - Noibat = 714, - Noivern = 715, - Yungoos = 734, - Gumshoos = 735, - Crabrawler = 739, - Crabominable = 740, - Oricorio = 741, - Rockruff = 744, - Lycanroc = 745, - Mareanie = 747, - Toxapex = 748, - Mudbray = 749, - Mudsdale = 750, - Fomantis = 753, - Lurantis = 754, - Salandit = 757, - Salazzle = 758, - Bounsweet = 761, - Steenee = 762, - Oranguru = 765, - Passimian = 766, - Sandygast = 769, - Palossand = 770, - Komala = 775, - Mimikyu = 778, - Skwovet = 819, - Greedent = 820, - Rookidee = 821, - Corvisquire = 822, - Chewtle = 833, - Drednaw = 834, - Rolycoly = 837, - Carkol = 838, - Applin = 840, - Silicobra = 843, - Sandaconda = 844, - Arrokuda = 846, - Barraskewda = 847, - Toxel = 848, - Toxtricity = 849, - Sinistea = 854, - Hatenna = 856, - Hattrem = 857, - Impidimp = 859, - Morgrem = 860, - Falinks = 870, - Pincurchin = 871, - Snom = 872, - Frosmoth = 873, - Stonjourner = 874, - Eiscue = 875, - Indeedee = 876, - Cufant = 878, - Copperajah = 879, - Dreepy = 885, - Drakloak = 886, - Lechonk = 915, - Oinkologne = 916, - Tarountula = 917, - Spidops = 918, - Nymble = 919, - Lokix = 920, - Pawmi = 921, - Pawmo = 922, - Tandemaus = 924, - Fidough = 926, - Dachsbun = 927, - Smoliv = 928, - Dolliv = 929, - Squawkabilly = 931, - Nacli = 932, - Naclstack = 933, - Charcadet = 935, - Tadbulb = 938, - Bellibolt = 939, - Wattrel = 940, - Kilowattrel = 941, - Maschiff = 942, - Mabosstiff = 943, - Shroodle = 944, - Grafaiai = 945, - Bramblin = 946, - Brambleghast = 947, - Toedscool = 948, - Toedscruel = 949, - Klawf = 950, - Capsakid = 951, - Scovillain = 952, - Rellor = 953, - Flittle = 955, - Espathra = 956, - Tinkatink = 957, - Tinkatuff = 958, - Wiglett = 960, - Wugtrio = 961, - Bombirdier = 962, - Finizen = 963, - Varoom = 965, - Revavroom = 966, - Cyclizar = 967, - Orthworm = 968, - Glimmet = 969, - Greavard = 971, - Houndstone = 972, - Flamigo = 973, - Cetoddle = 974, - Cetitan = 975, - Veluza = 976, - Dondozo = 977, - Tatsugiri = 978, - Clodsire = 980, - Frigibax = 996, - Arctibax = 997, -} - -public enum KitakamiSpeciesOb : ushort -{ - Ekans = 23, - Arbok = 24, - Pikachu = 25, - Sandshrew = 27, - Sandslash = 28, - Clefairy = 35, - Vulpix = 37, - Mankey = 56, - Primeape = 57, - Growlithe = 58, - Poliwag = 60, - Poliwhirl = 61, - Bellsprout = 69, - Weepinbell = 70, - Geodude = 74, - Graveler = 75, - Gastly = 92, - Haunter = 93, - Gengar = 94, - Koffing = 109, - Magikarp = 129, - Gyarados = 130, - Sentret = 161, - Furret = 162, - Hoothoot = 163, - Noctowl = 164, - Spinarak = 167, - Ariados = 168, - Pichu = 172, - Cleffa = 173, - Sudowoodo = 185, - Aipom = 190, - Yanma = 193, - Wooper = 194, - Quagsire = 195, - Dunsparce = 206, - Gligar = 207, - Heracross = 214, - Sneasel = 215, - Slugma = 218, - Swinub = 220, - Piloswine = 221, - Houndour = 228, - Houndoom = 229, - Stantler = 234, - Poochyena = 261, - Mightyena = 262, - Lotad = 270, - Lombre = 271, - Seedot = 273, - Nuzleaf = 274, - Ralts = 280, - Kirlia = 281, - Gardevoir = 282, - Surskit = 283, - Masquerain = 284, - Nosepass = 299, - Volbeat = 313, - Illumise = 314, - Spoink = 325, - Barboach = 339, - Whiscash = 340, - Corphish = 341, - Crawdaunt = 342, - Feebas = 349, - Duskull = 355, - Dusclops = 356, - Chimecho = 358, - Snorunt = 361, - Starly = 396, - Staravia = 397, - Staraptor = 398, - Kricketot = 401, - Kricketune = 402, - Shinx = 403, - Luxio = 404, - Luxray = 405, - Pachirisu = 417, - Chingling = 433, - Bronzor = 436, - Bronzong = 437, - Bonsly = 438, - Gible = 443, - Gabite = 444, - Munchlax = 446, - Riolu = 447, - Lucario = 448, - Gallade = 475, - Timburr = 532, - Gurdurr = 533, - Sewaddle = 540, - Swadloon = 541, - Leavanny = 542, - Petilil = 548, - Basculin = 550, - Ducklett = 580, - Tynamo = 602, - Eelektrik = 603, - Litwick = 607, - Lampent = 608, - Mienfoo = 619, - Pawniard = 624, - Bisharp = 625, - Vullaby = 629, - Carbink = 703, - Goomy = 704, - Sliggoo = 705, - Phantump = 708, - Trevenant = 709, - Noibat = 714, - Grubbin = 736, - Charjabug = 737, - Oricorio = 741, - Cutiefly = 742, - Ribombee = 743, - Rockruff = 744, - Lycanroc = 745, - Mudbray = 749, - Fomantis = 753, - Lurantis = 754, - Salandit = 757, - Mimikyu = 778, - Jangmoo = 782, - Hakamoo = 783, - Skwovet = 819, - Greedent = 820, - Chewtle = 833, - Drednaw = 834, - Applin = 840, - Flapple = 841, - Appletun = 842, - Cramorant = 845, - Arrokuda = 846, - Barraskewda = 847, - Hatenna = 856, - Hattrem = 857, - Hatterene = 858, - Impidimp = 859, - Morgrem = 860, - Grimmsnarl = 861, - Indeedee = 876, - Morpeko = 877, - Dudunsparce = 982, - Orthworm = 968, - Tandemaus = 924, - Bombirdier = 962, - Glimmet = 969, - Toedscool = 948, - Toedscruel = 949, - Kingambit = 983, - Annihilape = 979, - Poltchageist = 1012, -} - -public enum BlueberrySpeciesOb : ushort -{ - Bulbasaur = 1, - Charmander = 4, - Squirtle = 7, - Sandshrew = 27, - Vulpix = 37, - Oddish = 43, - Gloom = 44, - Vileplume = 45, - Venonat = 48, - Venomoth = 49, - Diglett = 50, - Dugtrio = 51, - Tentacool = 72, - Tentacruel = 73, - Geodude = 74, - Graveler = 75, - Slowpoke = 79, - Magnemite = 81, - Magneton = 82, - Doduo = 84, - Dodrio = 85, - Seel = 86, - Dewgong = 87, - Grimer = 88, - Muk = 89, - Exeggcute = 102, - Exeggutor = 103, - Hitmonlee = 106, - Hitmonchan = 107, - Rhyhorn = 111, - Rhydon = 112, - Chansey = 113, - Horsea = 116, - Seadra = 117, - Scyther = 123, - Electabuzz = 125, - Magmar = 126, - Tauros = 128, - Lapras = 131, - Porygon = 137, - Chikorita = 152, - Cyndaquil = 155, - Totodile = 158, - Chinchou = 170, - Lanturn = 171, - Bellossom = 182, - Girafarig = 203, - Snubbull = 209, - Granbull = 210, - Qwilfish = 211, - Scizor = 212, - Skarmory = 227, - Smeargle = 235, - Tyrogue = 236, - Hitmontop = 237, - Elekid = 239, - Magby = 240, - Blissey = 242, - Treecko = 252, - Torchic = 255, - Mudkip = 258, - Slakoth = 287, - Vigoroth = 288, - Slaking = 289, - Plusle = 311, - Minun = 312, - Numel = 322, - Camerupt = 323, - Torkoal = 324, - Trapinch = 328, - Vibrava = 329, - Flygon = 330, - Swablu = 333, - Altaria = 334, - Zangoose = 335, - Seviper = 336, - Luvdisc = 370, - Beldum = 374, - Metang = 375, - Turtwig = 387, - Chimchar = 390, - Piplup = 393, - Cranidos = 408, - Shieldon = 410, - Happiny = 440, - Finneon = 456, - Lumineon = 457, - Snover = 459, - Abomasnow = 460, - Rotom = 479, - Snivy = 495, - Tepig = 498, - Oshawott = 501, - Blitzle = 522, - Zebstrika = 523, - Drilbur = 529, - Excadrill = 530, - Cottonee = 546, - Whimsicott = 547, - Sandile = 551, - Krokorok = 552, - Krookodile = 553, - Scraggy = 559, - Scrafty = 560, - Minccino = 572, - Cinccino = 573, - Gothita = 574, - Gothorita = 575, - Gothitelle = 576, - Solosis = 577, - Duosion = 578, - Reuniclus = 579, - Deerling = 585, - Sawsbuck = 586, - Alomomola = 594, - Joltik = 595, - Galvantula = 596, - Tynamo = 602, - Eelektrik = 603, - Eelektross = 604, - Axew = 610, - Fraxure = 611, - Cubchoo = 613, - Beartic = 614, - Golett = 622, - Golurk = 623, - Rufflet = 627, - Braviary = 628, - Vullaby = 629, - Mandibuzz = 630, - Chespin = 650, - Fennekin = 653, - Froakie = 656, - Fletchling = 661, - Fletchinder = 662, - Talonflame = 663, - Litleo = 667, - Pyroar = 668, - Espurr = 677, - Meowstic = 678, - Inkay = 686, - Rowlet = 722, - Litten = 725, - Popplio = 728, - Pikipek = 731, - Trumbeak = 732, - Toucannon = 733, - Crabrawler = 739, - Crabominable = 740, - Oricorio = 741, - Dewpider = 751, - Araquanid = 752, - Comfey = 764, - Minior = 774, - Bruxish = 779, - Grookey = 810, - Scorbunny = 813, - Sobble = 816, - Sinistea = 854, - Milcery = 868, - Duraludon = 884, - Kleavor = 900, - Rellor = 953, - Rabsca = 954, - Farigiraf = 981, -} - -public enum ScarletExclusives : ushort +public enum PaldeaSpeciesOb : ushort { - Gligar = 207, + Pikachu = 25, + Raichu = 26, + Jigglypuff = 39, + Wigglytuff = 40, + Venonat = 48, + Venomoth = 49, + Diglett = 50, + Dugtrio = 51, + Meowth = 52, + Persian = 53, + Psyduck = 54, + Golduck = 55, + Mankey = 56, + Primeape = 57, + Growlithe = 58, + Arcanine = 59, + Slowpoke = 79, + Slowbro = 80, + Magnemite = 81, + Magneton = 82, + Grimer = 88, + Muk = 89, + Shellder = 90, + Cloyster = 91, + Gastly = 92, + Haunter = 93, + Drowzee = 96, + Hypno = 97, + Voltorb = 100, + Electrode = 101, + Chansey = 113, + Scyther = 123, + Tauros = 128, + Magikarp = 129, + Gyarados = 130, + Ditto = 132, + Eevee = 133, + Vaporeon = 134, + Jolteon = 135, + Flareon = 136, + Dratini = 147, + Dragonair = 148, + Pichu = 172, + Igglybuff = 174, + Mareep = 179, + Flaaffy = 180, + Ampharos = 181, + Marill = 183, + Azumarill = 184, + Sudowoodo = 185, + Hoppip = 187, + Skiploom = 188, + Jumpluff = 189, + Sunflora = 192, + Wooper = 194, + Espeon = 196, + Umbreon = 197, + Murkrow = 198, + Misdreavus = 200, + Girafarig = 203, + Pineco = 204, + Forretress = 205, + Dunsparce = 206, + Qwilfish = 211, + Heracross = 214, + Sneasel = 215, + Teddiursa = 216, + Ursaring = 217, + Delibird = 225, + Houndour = 228, + Houndoom = 229, + Phanpy = 231, + Donphan = 232, + Stantler = 234, + Blissey = 242, Larvitar = 246, Pupitar = 247, - Tyranitar = 248, - Cranidos = 408, - Rampardos = 409, + Wingull = 278, + Pelipper = 279, + Ralts = 280, + Kirlia = 281, + Gardevoir = 282, + Surskit = 283, + Masquerain = 284, + Shroomish = 285, + Breloom = 286, + Slakoth = 287, + Vigoroth = 288, + Slaking = 289, + Makuhita = 296, + Hariyama = 297, + Azurill = 298, + Sableye = 302, + Meditite = 307, + Medicham = 308, + Gulpin = 316, + Swalot = 317, + Numel = 322, + Camerupt = 323, + Torkoal = 324, + Spoink = 325, + Grumpig = 326, + Cacnea = 331, + Cacturne = 332, + Swablu = 333, + Altaria = 334, + Zangoose = 335, + Seviper = 336, + Barboach = 339, + Whiscash = 340, + Shuppet = 353, + Banette = 354, + Tropius = 357, + Snorunt = 361, + Glalie = 362, + Luvdisc = 370, + Bagon = 371, + Shelgon = 372, + Starly = 396, + Staravia = 397, + Staraptor = 398, + Kricketot = 401, + Kricketune = 402, + Shinx = 403, + Luxio = 404, + Luxray = 405, + Combee = 415, + Vespiquen = 416, + Pachirisu = 417, + Buizel = 418, + Floatzel = 419, + Shellos = 422, + Gastrodon = 423, Drifloon = 425, Drifblim = 426, + Mismagius = 429, + Honchkrow = 430, Stunky = 434, Skuntank = 435, - Gliscor = 472, + Bronzor = 436, + Bronzong = 437, + Bonsly = 438, + Happiny = 440, + Gible = 443, + Gabite = 444, + Riolu = 447, + Lucario = 448, + Hippopotas = 449, + Hippowdon = 450, + Croagunk = 453, + Toxicroak = 454, + Finneon = 456, + Lumineon = 457, + Snover = 459, + Abomasnow = 460, + Weavile = 461, + Leafeon = 470, + Glaceon = 471, + Gallade = 475, + Froslass = 478, + Rotom = 479, + Petilil = 548, + Lilligant = 549, + Basculin = 550, + Sandile = 551, + Krokorok = 552, + Zorua = 570, + Zoroark = 571, + Gothita = 574, + Gothorita = 575, + Gothitelle = 576, + Deerling = 585, + Sawsbuck = 586, + Foongus = 590, + Amoonguss = 591, + Alomomola = 594, + Tynamo = 602, + Eelektrik = 603, + Axew = 610, + Fraxure = 611, + Cubchoo = 613, + Beartic = 614, + Cryogonal = 615, + Pawniard = 624, + Bisharp = 625, + Rufflet = 627, + Braviary = 628, Deino = 633, Zweilous = 634, - Hydreigon = 635, + Larvesta = 636, + Volcarona = 637, + Fletchling = 661, + Fletchinder = 662, + Talonflame = 663, + Scatterbug = 664, + Spewpa = 665, + Vivillon = 666, + Litleo = 667, + Pyroar = 668, + Flabébé = 669, + Floette = 670, + Florges = 671, + Skiddo = 672, + Gogoat = 673, Skrelp = 690, Dragalge = 691, - Oranguru = 765, - Cramorant = 845, - Stonjourner = 874, - Armarouge = 936, - GreatTusk = 984, - ScreamTail = 985, - BruteBonnet = 986, - FlutterMane = 987, - SlitherWing = 988, - SandyShocks = 989, - RoaringMoon = 1005, - Koraidon = 1007, - WalkingWake = 1009, - GougingFire = 1020, - RagingBolt = 1021, -} - -public enum VioletExclusives : ushort -{ - Aipom = 190, - Misdreavus = 200, - Gulpin = 316, - Swalot = 317, - Bagon = 371, - Shelgon = 372, - Salamence = 373, - Shieldon = 410, - Bastiodon = 411, - Ambipom = 424, - Mismagius = 429, Clauncher = 692, Clawitzer = 693, + Sylveon = 700, + Hawlucha = 701, + Dedenne = 702, + Goomy = 704, + Sliggoo = 705, + Klefki = 707, + Bergmite = 712, + Avalugg = 713, + Noibat = 714, + Noivern = 715, + Yungoos = 734, + Gumshoos = 735, + Crabrawler = 739, + Crabominable = 740, + Oricorio = 741, + Rockruff = 744, + Lycanroc = 745, + Mareanie = 747, + Toxapex = 748, + Mudbray = 749, + Mudsdale = 750, + Fomantis = 753, + Lurantis = 754, + Salandit = 757, + Salazzle = 758, + Bounsweet = 761, + Steenee = 762, + Oranguru = 765, Passimian = 766, - Morpeko = 877, + Sandygast = 769, + Palossand = 770, + Komala = 775, + Mimikyu = 778, + Skwovet = 819, + Greedent = 820, + Rookidee = 821, + Corvisquire = 822, + Chewtle = 833, + Drednaw = 834, + Rolycoly = 837, + Carkol = 838, + Applin = 840, + Silicobra = 843, + Sandaconda = 844, + Arrokuda = 846, + Barraskewda = 847, + Toxel = 848, + Toxtricity = 849, + Sinistea = 854, + Hatenna = 856, + Hattrem = 857, + Impidimp = 859, + Morgrem = 860, + Falinks = 870, + Pincurchin = 871, + Snom = 872, + Frosmoth = 873, + Stonjourner = 874, + Eiscue = 875, + Indeedee = 876, + Cufant = 878, + Copperajah = 879, Dreepy = 885, Drakloak = 886, - Dragapult = 887, - Eiscue = 875, - Ceruledge = 937, - IronTreads = 990, - IronBundle = 991, - IronHands = 992, - IronJugulis = 993, - IronMoth = 994, - IronThorns = 995, - IronValiant = 1006, - Miraidon = 1008, - IronLeaves = 1010, - IronBoulder = 1022, - IronCrown = 1023, -} - -public enum TeraShiny : int -{ - Any = 0, - No = 1, - Yes = 2, - Star = 3, - Square = 4, + Lechonk = 915, + Oinkologne = 916, + Tarountula = 917, + Spidops = 918, + Nymble = 919, + Lokix = 920, + Pawmi = 921, + Pawmo = 922, + Tandemaus = 924, + Fidough = 926, + Dachsbun = 927, + Smoliv = 928, + Dolliv = 929, + Squawkabilly = 931, + Nacli = 932, + Naclstack = 933, + Charcadet = 935, + Tadbulb = 938, + Bellibolt = 939, + Wattrel = 940, + Kilowattrel = 941, + Maschiff = 942, + Mabosstiff = 943, + Shroodle = 944, + Grafaiai = 945, + Bramblin = 946, + Brambleghast = 947, + Toedscool = 948, + Toedscruel = 949, + Klawf = 950, + Capsakid = 951, + Scovillain = 952, + Rellor = 953, + Flittle = 955, + Espathra = 956, + Tinkatink = 957, + Tinkatuff = 958, + Wiglett = 960, + Wugtrio = 961, + Bombirdier = 962, + Finizen = 963, + Varoom = 965, + Revavroom = 966, + Cyclizar = 967, + Orthworm = 968, + Glimmet = 969, + Greavard = 971, + Houndstone = 972, + Flamigo = 973, + Cetoddle = 974, + Cetitan = 975, + Veluza = 976, + Dondozo = 977, + Tatsugiri = 978, + Clodsire = 980, + Frigibax = 996, + Arctibax = 997, } -public enum GameProgress : byte +public enum KitakamiSpeciesOb : ushort { - Beginning = 0, - UnlockedTeraRaids = 1, - Unlocked3Stars = 2, - Unlocked4Stars = 3, - Unlocked5Stars = 4, - Unlocked6Stars = 5, - None = 6, -} - -public enum RaidContent : byte -{ - Standard = 0, - Black = 1, - Event = 2, - Event_Mighty = 3, -} - -public enum RewardCategory : int -{ - ItemNone = 0, - Poke = 1, - Gem = 2, + Ekans = 23, + Arbok = 24, + Pikachu = 25, + Sandshrew = 27, + Sandslash = 28, + Clefairy = 35, + Vulpix = 37, + Mankey = 56, + Primeape = 57, + Growlithe = 58, + Poliwag = 60, + Poliwhirl = 61, + Bellsprout = 69, + Weepinbell = 70, + Geodude = 74, + Graveler = 75, + Gastly = 92, + Haunter = 93, + Gengar = 94, + Koffing = 109, + Magikarp = 129, + Gyarados = 130, + Sentret = 161, + Furret = 162, + Hoothoot = 163, + Noctowl = 164, + Spinarak = 167, + Ariados = 168, + Pichu = 172, + Cleffa = 173, + Sudowoodo = 185, + Aipom = 190, + Yanma = 193, + Wooper = 194, + Quagsire = 195, + Dunsparce = 206, + Gligar = 207, + Heracross = 214, + Sneasel = 215, + Slugma = 218, + Swinub = 220, + Piloswine = 221, + Houndour = 228, + Houndoom = 229, + Stantler = 234, + Poochyena = 261, + Mightyena = 262, + Lotad = 270, + Lombre = 271, + Seedot = 273, + Nuzleaf = 274, + Ralts = 280, + Kirlia = 281, + Gardevoir = 282, + Surskit = 283, + Masquerain = 284, + Nosepass = 299, + Volbeat = 313, + Illumise = 314, + Spoink = 325, + Barboach = 339, + Whiscash = 340, + Corphish = 341, + Crawdaunt = 342, + Feebas = 349, + Duskull = 355, + Dusclops = 356, + Chimecho = 358, + Snorunt = 361, + Starly = 396, + Staravia = 397, + Staraptor = 398, + Kricketot = 401, + Kricketune = 402, + Shinx = 403, + Luxio = 404, + Luxray = 405, + Pachirisu = 417, + Chingling = 433, + Bronzor = 436, + Bronzong = 437, + Bonsly = 438, + Gible = 443, + Gabite = 444, + Munchlax = 446, + Riolu = 447, + Lucario = 448, + Gallade = 475, + Timburr = 532, + Gurdurr = 533, + Sewaddle = 540, + Swadloon = 541, + Leavanny = 542, + Petilil = 548, + Basculin = 550, + Ducklett = 580, + Tynamo = 602, + Eelektrik = 603, + Litwick = 607, + Lampent = 608, + Mienfoo = 619, + Pawniard = 624, + Bisharp = 625, + Vullaby = 629, + Carbink = 703, + Goomy = 704, + Sliggoo = 705, + Phantump = 708, + Trevenant = 709, + Noibat = 714, + Grubbin = 736, + Charjabug = 737, + Oricorio = 741, + Cutiefly = 742, + Ribombee = 743, + Rockruff = 744, + Lycanroc = 745, + Mudbray = 749, + Fomantis = 753, + Lurantis = 754, + Salandit = 757, + Mimikyu = 778, + Jangmoo = 782, + Hakamoo = 783, + Skwovet = 819, + Greedent = 820, + Chewtle = 833, + Drednaw = 834, + Applin = 840, + Flapple = 841, + Appletun = 842, + Cramorant = 845, + Arrokuda = 846, + Barraskewda = 847, + Hatenna = 856, + Hattrem = 857, + Hatterene = 858, + Impidimp = 859, + Morgrem = 860, + Grimmsnarl = 861, + Indeedee = 876, + Morpeko = 877, + Dudunsparce = 982, + Orthworm = 968, + Tandemaus = 924, + Bombirdier = 962, + Glimmet = 969, + Toedscool = 948, + Toedscruel = 949, + Kingambit = 983, + Annihilape = 979, + Poltchageist = 1012, } -public enum RoutineType +public enum BlueberrySpeciesOb : ushort { - None, - ReadWrite, + Bulbasaur = 1, + Charmander = 4, + Squirtle = 7, + Sandshrew = 27, + Vulpix = 37, + Oddish = 43, + Gloom = 44, + Vileplume = 45, + Venonat = 48, + Venomoth = 49, + Diglett = 50, + Dugtrio = 51, + Tentacool = 72, + Tentacruel = 73, + Geodude = 74, + Graveler = 75, + Slowpoke = 79, + Magnemite = 81, + Magneton = 82, + Doduo = 84, + Dodrio = 85, + Seel = 86, + Dewgong = 87, + Grimer = 88, + Muk = 89, + Exeggcute = 102, + Exeggutor = 103, + Hitmonlee = 106, + Hitmonchan = 107, + Rhyhorn = 111, + Rhydon = 112, + Chansey = 113, + Horsea = 116, + Seadra = 117, + Scyther = 123, + Electabuzz = 125, + Magmar = 126, + Tauros = 128, + Lapras = 131, + Porygon = 137, + Chikorita = 152, + Cyndaquil = 155, + Totodile = 158, + Chinchou = 170, + Lanturn = 171, + Bellossom = 182, + Girafarig = 203, + Snubbull = 209, + Granbull = 210, + Qwilfish = 211, + Scizor = 212, + Skarmory = 227, + Smeargle = 235, + Tyrogue = 236, + Hitmontop = 237, + Elekid = 239, + Magby = 240, + Blissey = 242, + Treecko = 252, + Torchic = 255, + Mudkip = 258, + Slakoth = 287, + Vigoroth = 288, + Slaking = 289, + Plusle = 311, + Minun = 312, + Numel = 322, + Camerupt = 323, + Torkoal = 324, + Trapinch = 328, + Vibrava = 329, + Flygon = 330, + Swablu = 333, + Altaria = 334, + Zangoose = 335, + Seviper = 336, + Luvdisc = 370, + Beldum = 374, + Metang = 375, + Turtwig = 387, + Chimchar = 390, + Piplup = 393, + Cranidos = 408, + Shieldon = 410, + Happiny = 440, + Finneon = 456, + Lumineon = 457, + Snover = 459, + Abomasnow = 460, + Rotom = 479, + Snivy = 495, + Tepig = 498, + Oshawott = 501, + Blitzle = 522, + Zebstrika = 523, + Drilbur = 529, + Excadrill = 530, + Cottonee = 546, + Whimsicott = 547, + Sandile = 551, + Krokorok = 552, + Krookodile = 553, + Scraggy = 559, + Scrafty = 560, + Minccino = 572, + Cinccino = 573, + Gothita = 574, + Gothorita = 575, + Gothitelle = 576, + Solosis = 577, + Duosion = 578, + Reuniclus = 579, + Deerling = 585, + Sawsbuck = 586, + Alomomola = 594, + Joltik = 595, + Galvantula = 596, + Tynamo = 602, + Eelektrik = 603, + Eelektross = 604, + Axew = 610, + Fraxure = 611, + Cubchoo = 613, + Beartic = 614, + Golett = 622, + Golurk = 623, + Rufflet = 627, + Braviary = 628, + Vullaby = 629, + Mandibuzz = 630, + Chespin = 650, + Fennekin = 653, + Froakie = 656, + Fletchling = 661, + Fletchinder = 662, + Talonflame = 663, + Litleo = 667, + Pyroar = 668, + Espurr = 677, + Meowstic = 678, + Inkay = 686, + Rowlet = 722, + Litten = 725, + Popplio = 728, + Pikipek = 731, + Trumbeak = 732, + Toucannon = 733, + Crabrawler = 739, + Crabominable = 740, + Oricorio = 741, + Dewpider = 751, + Araquanid = 752, + Comfey = 764, + Minior = 774, + Bruxish = 779, + Grookey = 810, + Scorbunny = 813, + Sobble = 816, + Sinistea = 854, + Milcery = 868, + Duraludon = 884, + Kleavor = 900, + Rellor = 953, + Rabsca = 954, + Farigiraf = 981, } diff --git a/TeraFinder.Core/Enumerations/RaidEnums.cs b/TeraFinder.Core/Enumerations/RaidEnums.cs new file mode 100644 index 00000000..ab2e4c87 --- /dev/null +++ b/TeraFinder.Core/Enumerations/RaidEnums.cs @@ -0,0 +1,43 @@ +namespace TeraFinder.Core; + +public enum TeraShiny : int +{ + Any = 0, + No = 1, + Yes = 2, + Star = 3, + Square = 4, +} + +public enum GameProgress : byte +{ + Beginning = 0, + UnlockedTeraRaids = 1, + Unlocked3Stars = 2, + Unlocked4Stars = 3, + Unlocked5Stars = 4, + Unlocked6Stars = 5, +} + +public enum EventProgress : int +{ + Stage0 = 0, + Stage1 = 1, + Stage2 = 2, + Stage3 = 3, +} + +public enum RaidContent : byte +{ + Standard = 0, + Black = 1, + Event = 2, + Event_Mighty = 3, +} + +public enum RewardCategory : int +{ + ItemNone = 0, + Poke = 1, + Gem = 2, +} diff --git a/TeraFinder.Core/Enumerations/VersionExclusives.cs b/TeraFinder.Core/Enumerations/VersionExclusives.cs new file mode 100644 index 00000000..c5bb11c9 --- /dev/null +++ b/TeraFinder.Core/Enumerations/VersionExclusives.cs @@ -0,0 +1,71 @@ +namespace TeraFinder.Core; + +public enum ScarletExclusives : ushort +{ + Gligar = 207, + Larvitar = 246, + Pupitar = 247, + Tyranitar = 248, + Cranidos = 408, + Rampardos = 409, + Drifloon = 425, + Drifblim = 426, + Stunky = 434, + Skuntank = 435, + Gliscor = 472, + Deino = 633, + Zweilous = 634, + Hydreigon = 635, + Skrelp = 690, + Dragalge = 691, + Oranguru = 765, + Cramorant = 845, + Stonjourner = 874, + Armarouge = 936, + GreatTusk = 984, + ScreamTail = 985, + BruteBonnet = 986, + FlutterMane = 987, + SlitherWing = 988, + SandyShocks = 989, + RoaringMoon = 1005, + Koraidon = 1007, + WalkingWake = 1009, + GougingFire = 1020, + RagingBolt = 1021, +} + +public enum VioletExclusives : ushort +{ + Aipom = 190, + Misdreavus = 200, + Gulpin = 316, + Swalot = 317, + Bagon = 371, + Shelgon = 372, + Salamence = 373, + Shieldon = 410, + Bastiodon = 411, + Ambipom = 424, + Mismagius = 429, + Clauncher = 692, + Clawitzer = 693, + Passimian = 766, + Morpeko = 877, + Dreepy = 885, + Drakloak = 886, + Dragapult = 887, + Eiscue = 875, + Ceruledge = 937, + IronTreads = 990, + IronBundle = 991, + IronHands = 992, + IronJugulis = 993, + IronMoth = 994, + IronThorns = 995, + IronValiant = 1006, + Miraidon = 1008, + IronLeaves = 1010, + IronBoulder = 1022, + IronCrown = 1023, +} diff --git a/TeraFinder.Core/Interfaces/IEventRaid9.cs b/TeraFinder.Core/Interfaces/IEventRaid9.cs new file mode 100644 index 00000000..bfb7259f --- /dev/null +++ b/TeraFinder.Core/Interfaces/IEventRaid9.cs @@ -0,0 +1,35 @@ +namespace TeraFinder.Core; + +public interface IEventRaid9 +{ + ushort Species { get; } + byte Index { get; } + byte RandRate { get; } + + ushort RandRate0MinScarlet { get; } + ushort RandRate0MinViolet { get; } + ushort RandRate0TotalScarlet { get; } + ushort RandRate0TotalViolet { get; } + + ushort RandRate1MinScarlet { get; } + ushort RandRate1MinViolet { get; } + ushort RandRate1TotalScarlet { get; } + ushort RandRate1TotalViolet { get; } + + ushort RandRate2MinScarlet { get; } + ushort RandRate2MinViolet { get; } + ushort RandRate2TotalScarlet { get; } + ushort RandRate2TotalViolet { get; } + + ushort RandRate3MinScarlet { get; } + ushort RandRate3MinViolet { get; } + ushort RandRate3TotalScarlet { get; } + ushort RandRate3TotalViolet { get; } + + ushort GetRandRateTotalScarlet(EventProgress stage); + ushort GetRandRateTotalViolet(EventProgress stage); + ushort GetRandRateMinScarlet(EventProgress stage); + ushort GetRandRateMinViolet(EventProgress stage); + + EventProgress GetProgressMaximum(uint seed); +} diff --git a/TeraFinder.Core/Classes/IExtendedTeraRaid9.cs b/TeraFinder.Core/Interfaces/IExtendedTeraRaid9.cs similarity index 52% rename from TeraFinder.Core/Classes/IExtendedTeraRaid9.cs rename to TeraFinder.Core/Interfaces/IExtendedTeraRaid9.cs index fe769b9f..b90f5875 100644 --- a/TeraFinder.Core/Classes/IExtendedTeraRaid9.cs +++ b/TeraFinder.Core/Interfaces/IExtendedTeraRaid9.cs @@ -4,18 +4,13 @@ namespace TeraFinder.Core; public interface IExtendedTeraRaid9 : ITeraRaid9 { uint Identifier { get; } - ulong FixedRewardHash { get; } - ulong LotteryRewardHash { get; } - int Item { get; } + List FixedRewards { get; } + List LotteryRewards { get; } + int HeldItem { get; } ExtraMoves ExtraMoves { get; } byte Level { get; } Nature Nature { get; } SizeType9 ScaleType { get; } byte Scale { get; } IndividualValueSet IVs { get; } - - ushort GetRandRateTotalScarlet(int stage); - ushort GetRandRateTotalViolet(int stage); - ushort GetRandRateMinScarlet(int stage); - ushort GetRandRateMinViolet(int stage); } diff --git a/TeraFinder.Core/Classes/IRaidDetails.cs b/TeraFinder.Core/Interfaces/IRaidDetails.cs similarity index 87% rename from TeraFinder.Core/Classes/IRaidDetails.cs rename to TeraFinder.Core/Interfaces/IRaidDetails.cs index 0aed0314..820c16b1 100644 --- a/TeraFinder.Core/Classes/IRaidDetails.cs +++ b/TeraFinder.Core/Interfaces/IRaidDetails.cs @@ -6,5 +6,4 @@ public interface IRaidDetails ushort Species { get; } int Stars { get; } TeraShiny Shiny { get; } - ulong Calcs { get; } } diff --git a/TeraFinder.Core/Misc/AreaNames.cs b/TeraFinder.Core/Misc/AreaNames.cs new file mode 100644 index 00000000..172f9f0a --- /dev/null +++ b/TeraFinder.Core/Misc/AreaNames.cs @@ -0,0 +1,65 @@ +namespace TeraFinder.Core; + +public static class AreaNames +{ + //From https://github.com/LegoFigure11/RaidCrawler/blob/main/Structures/Areas.cs + //GPL v3 License + //Thanks LegoFigure11! + public static string[] AreaPaldea = [ + "", + "South Province (Area 1)", + "", // Unused + "", // Unused + "South Province (Area 2)", + "South Province (Area 4)", + "South Province (Area 6)", + "South Province (Area 5)", + "South Province (Area 3)", + "West Province (Area 1)", + "Asado Desert", + "West Province (Area 2)", + "West Province (Area 3)", + "Tagtree Thicket", + "East Province (Area 3)", + "East Province (Area 1)", + "East Province (Area 2)", + "Dalizapa Passage", + "Casseroya Lake", + "Glaseado Mountain", + "North Province (Area 3)", + "North Province (Area 1)", + "North Province (Area 2)", + ]; + + //Thanks santacrab2! + public static string[] AreaKitakami = [ + "", + "Kitakami Road", + "Apple Hills", + "Revelers Road", + "Oni Mountain", + "Infernal Pass", + "Crystal Pool", + "Wistful Fields", + "Mossfell Confluence", + "Fellhorn Gorge", + "Paradise Barrens", + "Kitakami Wilds", + ]; + + //From https://github.com/LegoFigure11/RaidCrawler/blob/main/Structures/Areas.cs + //GPL v3 License + //Thanks LegoFigure11! + public static string[] AreaBlueberry = + [ + "", + "Savannna Biome", + "Coastal Biome", + "Canyon Biome", + "Polar Biome", + "Savanna Biome", + "Coastal Biome", + "Canyon Biome", + "Polar Biome", + ]; +} diff --git a/TeraFinder.Core/Properties/Resources.Designer.cs b/TeraFinder.Core/Properties/Resources.Designer.cs index 169766f7..c283f42f 100644 --- a/TeraFinder.Core/Properties/Resources.Designer.cs +++ b/TeraFinder.Core/Properties/Resources.Designer.cs @@ -7693,9 +7693,9 @@ internal static byte[] dlc2_981 { /// /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] encounter_gem_blueberry { + internal static byte[] encounter_dist_paldea { get { - object obj = ResourceManager.GetObject("encounter_gem_blueberry", resourceCulture); + object obj = ResourceManager.GetObject("encounter_dist_paldea", resourceCulture); return ((byte[])(obj)); } } @@ -7703,9 +7703,9 @@ internal static byte[] encounter_gem_blueberry { /// /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] encounter_gem_kitakami { + internal static byte[] encounter_gem_blueberry_black { get { - object obj = ResourceManager.GetObject("encounter_gem_kitakami", resourceCulture); + object obj = ResourceManager.GetObject("encounter_gem_blueberry_black", resourceCulture); return ((byte[])(obj)); } } @@ -7713,9 +7713,59 @@ internal static byte[] encounter_gem_kitakami { /// /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] encounter_gem_paldea { + internal static byte[] encounter_gem_blueberry_standard { get { - object obj = ResourceManager.GetObject("encounter_gem_paldea", resourceCulture); + object obj = ResourceManager.GetObject("encounter_gem_blueberry_standard", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] encounter_gem_kitakami_black { + get { + object obj = ResourceManager.GetObject("encounter_gem_kitakami_black", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] encounter_gem_kitakami_standard { + get { + object obj = ResourceManager.GetObject("encounter_gem_kitakami_standard", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] encounter_gem_paldea_black { + get { + object obj = ResourceManager.GetObject("encounter_gem_paldea_black", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] encounter_gem_paldea_standard { + get { + object obj = ResourceManager.GetObject("encounter_gem_paldea_standard", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] encounter_might_paldea { + get { + object obj = ResourceManager.GetObject("encounter_might_paldea", resourceCulture); return ((byte[])(obj)); } } diff --git a/TeraFinder.Core/Properties/Resources.resx b/TeraFinder.Core/Properties/Resources.resx index 725efb0a..b3bc2204 100644 --- a/TeraFinder.Core/Properties/Resources.resx +++ b/TeraFinder.Core/Properties/Resources.resx @@ -1255,14 +1255,29 @@ ..\Resources\outbreaks_default\Blueberry\dlc2-981.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Resources\raid_default\encounter_gem_blueberry.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\raid_default\encounter_dist_paldea.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Resources\raid_default\encounter_gem_kitakami.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\raid_default\encounter_gem_blueberry_black.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Resources\raid_default\encounter_gem_paldea.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\raid_default\encounter_gem_blueberry_standard.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\raid_default\encounter_gem_kitakami_black.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\raid_default\encounter_gem_kitakami_standard.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\raid_default\encounter_gem_paldea_black.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\raid_default\encounter_gem_paldea_standard.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\raid_default\encounter_might_paldea.pkl;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ..\Resources\raid_default\kitakami_locations.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/TeraFinder.Core/Resources/raid_default/encounter_dist_paldea.pkl b/TeraFinder.Core/Resources/raid_default/encounter_dist_paldea.pkl new file mode 100644 index 00000000..ad2933f4 Binary files /dev/null and b/TeraFinder.Core/Resources/raid_default/encounter_dist_paldea.pkl differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_gem_blueberry.pkl b/TeraFinder.Core/Resources/raid_default/encounter_gem_blueberry.pkl deleted file mode 100644 index 4bc2e301..00000000 Binary files a/TeraFinder.Core/Resources/raid_default/encounter_gem_blueberry.pkl and /dev/null differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_gem_blueberry_black.pkl b/TeraFinder.Core/Resources/raid_default/encounter_gem_blueberry_black.pkl new file mode 100644 index 00000000..e2a5cb88 Binary files /dev/null and b/TeraFinder.Core/Resources/raid_default/encounter_gem_blueberry_black.pkl differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_gem_blueberry_standard.pkl b/TeraFinder.Core/Resources/raid_default/encounter_gem_blueberry_standard.pkl new file mode 100644 index 00000000..37cb50fc Binary files /dev/null and b/TeraFinder.Core/Resources/raid_default/encounter_gem_blueberry_standard.pkl differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_gem_kitakami.pkl b/TeraFinder.Core/Resources/raid_default/encounter_gem_kitakami.pkl deleted file mode 100644 index 3ad50f6d..00000000 Binary files a/TeraFinder.Core/Resources/raid_default/encounter_gem_kitakami.pkl and /dev/null differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_gem_kitakami_black.pkl b/TeraFinder.Core/Resources/raid_default/encounter_gem_kitakami_black.pkl new file mode 100644 index 00000000..d5e6c7fd Binary files /dev/null and b/TeraFinder.Core/Resources/raid_default/encounter_gem_kitakami_black.pkl differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_gem_kitakami_standard.pkl b/TeraFinder.Core/Resources/raid_default/encounter_gem_kitakami_standard.pkl new file mode 100644 index 00000000..24959a4b Binary files /dev/null and b/TeraFinder.Core/Resources/raid_default/encounter_gem_kitakami_standard.pkl differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_gem_paldea.pkl b/TeraFinder.Core/Resources/raid_default/encounter_gem_paldea.pkl deleted file mode 100644 index cccd7374..00000000 Binary files a/TeraFinder.Core/Resources/raid_default/encounter_gem_paldea.pkl and /dev/null differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_gem_paldea_black.pkl b/TeraFinder.Core/Resources/raid_default/encounter_gem_paldea_black.pkl new file mode 100644 index 00000000..57dba726 Binary files /dev/null and b/TeraFinder.Core/Resources/raid_default/encounter_gem_paldea_black.pkl differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_gem_paldea_standard.pkl b/TeraFinder.Core/Resources/raid_default/encounter_gem_paldea_standard.pkl new file mode 100644 index 00000000..a0fded4c Binary files /dev/null and b/TeraFinder.Core/Resources/raid_default/encounter_gem_paldea_standard.pkl differ diff --git a/TeraFinder.Core/Resources/raid_default/encounter_might_paldea.pkl b/TeraFinder.Core/Resources/raid_default/encounter_might_paldea.pkl new file mode 100644 index 00000000..fa0da048 Binary files /dev/null and b/TeraFinder.Core/Resources/raid_default/encounter_might_paldea.pkl differ diff --git a/TeraFinder.Core/Resources/translations/lang_de.txt b/TeraFinder.Core/Resources/translations/lang_de.txt index 7633d6fc..8342c207 100644 --- a/TeraFinder.Core/Resources/translations/lang_de.txt +++ b/TeraFinder.Core/Resources/translations/lang_de.txt @@ -8,6 +8,8 @@ Plugin.ImportNews=Import from files... Plugin.OutbreakNull=Import Empty (Null) Outbreak Event Plugin.RaidNull=Import Empty (Null) Raid Event Plugin.OutbreakViewer=Mass Outbreak Viewer/Editor +Plugin.RaidCalculator=Raid Calculator +Plugin.RewardCalculator=Reward Calculator Plugin.MapPaldea=Paldea Plugin.MapKitakami=Kitakami Plugin.MapBlueberry=Blueberry @@ -105,6 +107,7 @@ CalculatorForm.btnSendToEditor=Send Selected Result to Raid Editor CalculatorForm.lblEventct=Event Index: CalculatorForm.lblMap=Location: CalculatorForm.btnCopySeed=Copy Seed +CalculatorForm.lblTime=T: RewardCalcForm=Reward Calculator RewardCalcForm.grpFilters=Filters @@ -136,6 +139,8 @@ RewardCalcForm.btnSendSelectedRaid=Send Selected Result to Raid Editor RewardCalcForm.lblEventCt=Event Index: RewardCalcForm.lblMap=Location: RewardCalcForm.btnCopySeed=Copy Seed +RewardCalcForm.lblTime=T: +RewardCalcForm.lblShiny=Shiny: CheckerForm=Seed Checker CheckerForm.lblTID=TID: @@ -252,6 +257,7 @@ ActionSearch=Search ActionStop=Stop ToolTipAccurate=Force the calculator to determine Pokmon Tera Type and Shinyness from a given seed, in order to accurately determine Tera Shards types and Extra Infos. Makes the searches a little slower. ToolTipAllResults=Disabled - Stop each thread search at the first result that matches the filters. Enabled - Compute all possible results until Max Calcs number is reached. Ignored if no filter is set. +WarningNoEncounter=No encounter available for the Game Progress and Stars selection. ActionConnect=Connect ActionConnecting=Connecting... diff --git a/TeraFinder.Core/Resources/translations/lang_en.txt b/TeraFinder.Core/Resources/translations/lang_en.txt index 7633d6fc..8342c207 100644 --- a/TeraFinder.Core/Resources/translations/lang_en.txt +++ b/TeraFinder.Core/Resources/translations/lang_en.txt @@ -8,6 +8,8 @@ Plugin.ImportNews=Import from files... Plugin.OutbreakNull=Import Empty (Null) Outbreak Event Plugin.RaidNull=Import Empty (Null) Raid Event Plugin.OutbreakViewer=Mass Outbreak Viewer/Editor +Plugin.RaidCalculator=Raid Calculator +Plugin.RewardCalculator=Reward Calculator Plugin.MapPaldea=Paldea Plugin.MapKitakami=Kitakami Plugin.MapBlueberry=Blueberry @@ -105,6 +107,7 @@ CalculatorForm.btnSendToEditor=Send Selected Result to Raid Editor CalculatorForm.lblEventct=Event Index: CalculatorForm.lblMap=Location: CalculatorForm.btnCopySeed=Copy Seed +CalculatorForm.lblTime=T: RewardCalcForm=Reward Calculator RewardCalcForm.grpFilters=Filters @@ -136,6 +139,8 @@ RewardCalcForm.btnSendSelectedRaid=Send Selected Result to Raid Editor RewardCalcForm.lblEventCt=Event Index: RewardCalcForm.lblMap=Location: RewardCalcForm.btnCopySeed=Copy Seed +RewardCalcForm.lblTime=T: +RewardCalcForm.lblShiny=Shiny: CheckerForm=Seed Checker CheckerForm.lblTID=TID: @@ -252,6 +257,7 @@ ActionSearch=Search ActionStop=Stop ToolTipAccurate=Force the calculator to determine Pokmon Tera Type and Shinyness from a given seed, in order to accurately determine Tera Shards types and Extra Infos. Makes the searches a little slower. ToolTipAllResults=Disabled - Stop each thread search at the first result that matches the filters. Enabled - Compute all possible results until Max Calcs number is reached. Ignored if no filter is set. +WarningNoEncounter=No encounter available for the Game Progress and Stars selection. ActionConnect=Connect ActionConnecting=Connecting... diff --git a/TeraFinder.Core/Resources/translations/lang_es.txt b/TeraFinder.Core/Resources/translations/lang_es.txt index 6e45b971..c6e12c39 100644 --- a/TeraFinder.Core/Resources/translations/lang_es.txt +++ b/TeraFinder.Core/Resources/translations/lang_es.txt @@ -8,6 +8,8 @@ Plugin.ImportNews=Importar desde archivos... Plugin.OutbreakNull=Importar Apariciones Masivas Vacías (Evento Nulo) Plugin.RaidNull=Importar Teraincursión Vacía (Evento Nulo) Plugin.OutbreakViewer=Visor/Editor de Apariciones Masivas +Plugin.RaidCalculator=Calcular Teraincursión +Plugin.RewardCalculator=Calcular Recompensas Plugin.MapPaldea=Paldea Plugin.MapKitakami=Noroteo Plugin.MapBlueberry=Arándano @@ -105,6 +107,7 @@ CalculatorForm.btnSendToEditor=Enviar Resultado Seleccionado a Raid Editor CalculatorForm.lblEventct=Índice Evento: CalculatorForm.lblMap=Ubicación: CalculatorForm.btnCopySeed=Copiar Seed +CalculatorForm.lblTime=T: RewardCalcForm=Calculadora de Recompensas RewardCalcForm.grpFilters=Filtros @@ -136,6 +139,8 @@ RewardCalcForm.btnSendSelectedRaid=Enviar Resultado Seleccionado a Raid Editor RewardCalcForm.lblEventCt=Índice Evento: RewardCalcForm.lblMap=Ubicación: RewardCalcForm.btnCopySeed=Copiar Seed +RewardCalcForm.lblTime=T: +RewardCalcForm.lblShiny=Variocolor: CheckerForm=Inspector de Seeds CheckerForm.lblTID=TID: @@ -252,6 +257,7 @@ ActionSearch=Buscar ActionStop=Parar ToolTipAccurate=Forzar la calculadora a definir el Teratipo y variocolor de una seed dada, para así determinar con precisión el tipo de Teralitos e información extra. Esto hace las búsquedas un poco lentas. ToolTipAllResults=Deshabilitado - Detener cada hilo de búsqueda al primer resultado que coincida con los filtros. Habilitado - Computa todos los resultados posibles hasta que el número en Max Calc sea alcanzado. Se ignora si no hay ningún filtro establecido. +WarningNoEncounter=No encounter available for the Game Progress and Stars selection. ActionConnect=Conectar ActionConnecting=Conectando... @@ -344,4 +350,4 @@ GridUtil.MissingData=PKHeX Core no contiene datos de evento GridUtil.CheckWiki=Por favor, consulta wiki de Tera Finder para saber cómo actualizar la dependencia PKHeX.Core. GridUtil.Report=Por favor, reporta este error al autor de Tera Finder. GridUtil.RowsExceeded=Selección de filas superó el máximo permitido [1]. -GridUtil.MismatchGroupID=GroupID no coincide. La Teraincursión seleccionada sólo puede contener eventos con índice {editorIndex}. El resultado seleccionado tiene índice {resultIndex}. +GridUtil.MismatchGroupID=GroupID no coincide. La Teraincursión seleccionada sólo puede contener eventos con índice {editorIndex}. El resultado seleccionado tiene índice {resultIndex}. \ No newline at end of file diff --git a/TeraFinder.Core/Resources/translations/lang_fr.txt b/TeraFinder.Core/Resources/translations/lang_fr.txt index 8f35ce8e..9b229500 100644 --- a/TeraFinder.Core/Resources/translations/lang_fr.txt +++ b/TeraFinder.Core/Resources/translations/lang_fr.txt @@ -8,6 +8,8 @@ Plugin.ImportNews=Import from files... Plugin.OutbreakNull=Import Empty (Null) Outbreak Event Plugin.RaidNull=Import Empty (Null) Raid Event Plugin.OutbreakViewer=Mass Outbreak Viewer/Editor +Plugin.RaidCalculator=Raid Calculator +Plugin.RewardCalculator=Reward Calculator Plugin.MapPaldea=Paldea Plugin.MapKitakami=Septentria Plugin.MapBlueberry=Myrtille @@ -105,6 +107,7 @@ CalculatorForm.btnSendToEditor=Send Selected Result to Raid Editor CalculatorForm.lblEventct=Event Index: CalculatorForm.lblMap=Location: CalculatorForm.btnCopySeed=Copy Seed +CalculatorForm.lblTime=T: RewardCalcForm=Reward Calculator RewardCalcForm.grpFilters=Filters @@ -136,6 +139,8 @@ RewardCalcForm.btnSendSelectedRaid=Send Selected Result to Raid Editor RewardCalcForm.lblEventCt=Event Index: RewardCalcForm.lblMap=Location: RewardCalcForm.btnCopySeed=Copy Seed +RewardCalcForm.lblTime=T: +RewardCalcForm.lblShiny=Shiny: CheckerForm=Seed Checker CheckerForm.lblTID=TID: @@ -252,6 +257,7 @@ ActionSearch=Search ActionStop=Stop ToolTipAccurate=Force the calculator to determine Pokmon Tera Type and Shinyness from a given seed, in order to accurately determine Tera Shards types and Extra Infos. Makes the searches a little slower. ToolTipAllResults=Disabled - Stop each thread search at the first result that matches the filters. Enabled - Compute all possible results until Max Calcs number is reached. Ignored if no filter is set. +WarningNoEncounter=No encounter available for the Game Progress and Stars selection. ActionConnect=Connect ActionConnecting=Connecting... diff --git a/TeraFinder.Core/Resources/translations/lang_it.txt b/TeraFinder.Core/Resources/translations/lang_it.txt index 3208fa21..ee82923e 100644 --- a/TeraFinder.Core/Resources/translations/lang_it.txt +++ b/TeraFinder.Core/Resources/translations/lang_it.txt @@ -8,6 +8,8 @@ Plugin.ImportNews=Importa da file... Plugin.OutbreakNull=Importa l'evento vuoto (Null) per le Comparse Massicce Plugin.RaidNull=Importa l'evento vuoto (Null) per i Raid Plugin.OutbreakViewer=Visualizza e Modifica Comparse Massicce +Plugin.RaidCalculator=Calcolatore Raid +Plugin.RewardCalculator=Calcolatore Ricompense Plugin.MapPaldea=Paldea Plugin.MapKitakami=Nordivia Plugin.MapBlueberry=Mirtillo @@ -105,6 +107,7 @@ CalculatorForm.btnSendToEditor=Invia il risultato selezionato al Raid Editor CalculatorForm.lblEventct=Indice Evento: CalculatorForm.lblMap=Mappa: CalculatorForm.btnCopySeed=Copia Seed +CalculatorForm.lblTime=T: RewardCalcForm=Calcolatore Ricompense RewardCalcForm.grpFilters=Filtri @@ -136,6 +139,8 @@ RewardCalcForm.btnSendSelectedRaid=Invia il risultato selezionato al Raid Editor RewardCalcForm.lblEventCt=Indice Evento: RewardCalcForm.lblMap=Mappa: RewardCalcForm.btnCopySeed=Copia Seed +RewardCalcForm.lblTime=T: +RewardCalcForm.lblShiny=Shiny: CheckerForm=Controllo Seed CheckerForm.lblTID=TID: @@ -252,6 +257,7 @@ ActionSearch=Cerca ActionStop=Stop ToolTipAccurate=Forza il calcolatore a determinare Tera Tipo e Shinyness, in modo da poter determinare accuratamente il tipo di Teralite e le Extra Info. Le ricerche saranno un po' pi lente. ToolTipAllResults=Disabilitato - Ferma ogni thread al primo risultato trovato che corrisponda ai filtri. Abilitato - Calcola tutti i possibili risultati fino a che non si raggiunge la quantit di Max Calc. Ignorato se nessun filtro stato impostato. +WarningNoEncounter=Nessun incontro disponibile per il Progresso e le Stelle selezionate. ActionConnect=Connetti ActionConnecting=Connessione... diff --git a/TeraFinder.Core/Resources/translations/lang_ja.txt b/TeraFinder.Core/Resources/translations/lang_ja.txt index 7633d6fc..8342c207 100644 --- a/TeraFinder.Core/Resources/translations/lang_ja.txt +++ b/TeraFinder.Core/Resources/translations/lang_ja.txt @@ -8,6 +8,8 @@ Plugin.ImportNews=Import from files... Plugin.OutbreakNull=Import Empty (Null) Outbreak Event Plugin.RaidNull=Import Empty (Null) Raid Event Plugin.OutbreakViewer=Mass Outbreak Viewer/Editor +Plugin.RaidCalculator=Raid Calculator +Plugin.RewardCalculator=Reward Calculator Plugin.MapPaldea=Paldea Plugin.MapKitakami=Kitakami Plugin.MapBlueberry=Blueberry @@ -105,6 +107,7 @@ CalculatorForm.btnSendToEditor=Send Selected Result to Raid Editor CalculatorForm.lblEventct=Event Index: CalculatorForm.lblMap=Location: CalculatorForm.btnCopySeed=Copy Seed +CalculatorForm.lblTime=T: RewardCalcForm=Reward Calculator RewardCalcForm.grpFilters=Filters @@ -136,6 +139,8 @@ RewardCalcForm.btnSendSelectedRaid=Send Selected Result to Raid Editor RewardCalcForm.lblEventCt=Event Index: RewardCalcForm.lblMap=Location: RewardCalcForm.btnCopySeed=Copy Seed +RewardCalcForm.lblTime=T: +RewardCalcForm.lblShiny=Shiny: CheckerForm=Seed Checker CheckerForm.lblTID=TID: @@ -252,6 +257,7 @@ ActionSearch=Search ActionStop=Stop ToolTipAccurate=Force the calculator to determine Pokmon Tera Type and Shinyness from a given seed, in order to accurately determine Tera Shards types and Extra Infos. Makes the searches a little slower. ToolTipAllResults=Disabled - Stop each thread search at the first result that matches the filters. Enabled - Compute all possible results until Max Calcs number is reached. Ignored if no filter is set. +WarningNoEncounter=No encounter available for the Game Progress and Stars selection. ActionConnect=Connect ActionConnecting=Connecting... diff --git a/TeraFinder.Core/Resources/translations/lang_ko.txt b/TeraFinder.Core/Resources/translations/lang_ko.txt index 97f48e53..3a3c4971 100644 --- a/TeraFinder.Core/Resources/translations/lang_ko.txt +++ b/TeraFinder.Core/Resources/translations/lang_ko.txt @@ -8,6 +8,8 @@ Plugin.ImportNews=Import from files... Plugin.OutbreakNull=Import Empty (Null) Outbreak Event Plugin.RaidNull=Import Empty (Null) Raid Event Plugin.OutbreakViewer=대량발생 보기/편집 +Plugin.RaidCalculator=레이드 계산기 +Plugin.RewardCalculator=보상 계산기 Plugin.MapPaldea=Paldea Plugin.MapKitakami=Kitakami Plugin.MapBlueberry=Blueberry @@ -105,6 +107,7 @@ CalculatorForm.btnSendToEditor=레이드 편집기로 선택한 결과 보내기 CalculatorForm.lblEventct=이벤트 값: CalculatorForm.lblMap=Location: CalculatorForm.btnCopySeed=Copy Seed +CalculatorForm.lblTime=T: RewardCalcForm=보상 계산기 RewardCalcForm.grpFilters=필터 @@ -136,6 +139,8 @@ RewardCalcForm.btnSendSelectedRaid=레이드 편집기로 선택한 결과 보 RewardCalcForm.lblEventCt=이벤트 값: RewardCalcForm.lblMap=Location: RewardCalcForm.btnCopySeed=Copy Seed +RewardCalcForm.lblTime=T: +RewardCalcForm.lblShiny=이로치: CheckerForm=시드체크 CheckerForm.lblTID=TID: @@ -252,6 +257,7 @@ ActionSearch=검색 ActionStop=정지 ToolTipAccurate=포켓몬의 테라타입과 이로치여부를 결정하고, 이를 통해 테라피스의 타입과 추가 정보를 정확하게 판단하도록 합니다. 검색 속도가 약간 느려집니다. ToolTipAllResults=체크x - 필터와 일치하는 첫 번째 결과에서 검색을 중지합니다. 체크o - 최대 계산값에 도달할 때까지 가능한 모든 결과를 계산합니다. 필터가 설정되지 않은 경우 무시됩니다. +WarningNoEncounter=No encounter available for the Game Progress and Stars selection. ActionConnect=연결 ActionConnecting=연결중 diff --git a/TeraFinder.Core/Resources/translations/lang_zh.txt b/TeraFinder.Core/Resources/translations/lang_zh.txt index 3d6374fa..ffa3d263 100644 --- a/TeraFinder.Core/Resources/translations/lang_zh.txt +++ b/TeraFinder.Core/Resources/translations/lang_zh.txt @@ -8,6 +8,8 @@ Plugin.ImportNews=导入文件 Plugin.OutbreakNull=清除现有大量出现 Plugin.RaidNull=清除现有活动团战 Plugin.OutbreakViewer=大量出现查看/编辑 +Plugin.RaidCalculator=太晶洞窟计算器 +Plugin.RewardCalculator=奖励计算器 Plugin.MapPaldea=帕底亚 Plugin.MapKitakami=北上乡 Plugin.MapBlueberry=蓝莓学院 @@ -105,6 +107,7 @@ CalculatorForm.btnSendToEditor=将所选结果发送到Raid编辑器 CalculatorForm.lblEventct=活动索引: CalculatorForm.lblMap=地图: CalculatorForm.btnCopySeed=复制Seed +CalculatorForm.lblTime=T: RewardCalcForm=奖励计算器 RewardCalcForm.grpFilters=筛选器 @@ -136,6 +139,8 @@ RewardCalcForm.btnSendSelectedRaid=将所选结果发送到Raid编辑器 RewardCalcForm.lblEventCt=活动索引: RewardCalcForm.lblMap=地图: RewardCalcForm.btnCopySeed=复制Seed +RewardCalcForm.lblTime=T: +RewardCalcForm.lblShiny=闪光: CheckerForm=Seed检索器 CheckerForm.lblTID=表ID: @@ -252,6 +257,7 @@ ActionSearch=搜索 ActionStop=停止 ToolTipAccurate=从提供的Seed强制检索指定宝可梦的太晶属性和闪光,以便准确的指定太晶碎片种类和额外信息。 使搜索速度稍慢。 ToolTipAllResults=禁用 - 在找到一个结果后停止搜索。 启用 - 搜索所有可能的结果,直到达到最大搜索量。 如果未设置过滤器,则忽略。 +WarningNoEncounter=No encounter available for the Game Progress and Stars selection. ActionConnect=连接 ActionConnecting=正在连接... diff --git a/TeraFinder.Core/Resources/translations/lang_zh2.txt b/TeraFinder.Core/Resources/translations/lang_zh2.txt index f81f6f06..269a737f 100644 --- a/TeraFinder.Core/Resources/translations/lang_zh2.txt +++ b/TeraFinder.Core/Resources/translations/lang_zh2.txt @@ -8,6 +8,8 @@ Plugin.ImportNews=Import from files... Plugin.OutbreakNull=Import Empty (Null) Outbreak Event Plugin.RaidNull=Import Empty (Null) Raid Event Plugin.OutbreakViewer=大量出現查看/編輯 +Plugin.RaidCalculator=太晶洞窟計算器 +Plugin.RewardCalculator=獎勵計算器 Plugin.MapPaldea=Paldea Plugin.MapKitakami=Kitakami Plugin.MapBlueberry=Blueberry @@ -105,6 +107,7 @@ CalculatorForm.btnSendToEditor=將所選結果發送到Raid編輯器 CalculatorForm.lblEventct=活動索引: CalculatorForm.lblMap=地图: CalculatorForm.btnCopySeed=Copy Seed +CalculatorForm.lblTime=T: RewardCalcForm=獎勵計算器 RewardCalcForm.grpFilters=篩選器 @@ -136,6 +139,8 @@ RewardCalcForm.btnSendSelectedRaid=將所選結果發送到Raid編輯器 RewardCalcForm.lblEventCt=活動索引: RewardCalcForm.lblMap=地图: RewardCalcForm.btnCopySeed=Copy Seed +RewardCalcForm.lblTime=T: +RewardCalcForm.lblShiny=閃光: CheckerForm=Seed檢索器 CheckerForm.lblTID=表ID: @@ -252,6 +257,7 @@ ActionSearch=搜索 ActionStop=停止 ToolTipAccurate=從提供的Seed強製檢索指定寶可夢的太晶屬性和閃光,以便準確的指定太晶碎片種類和額外信息。 使搜索速度稍慢。 ToolTipAllResults=禁用 - 在找到一個結果後停止搜索。 啟用 - 搜索所有可能的結果,直到達到最大搜索量。 如果未設置過濾器,則忽略。 +WarningNoEncounter=No encounter available for the Game Progress and Stars selection. ActionConnect=連接 ActionConnecting=正在連接... diff --git a/TeraFinder.Core/TeraFinder.Core.csproj b/TeraFinder.Core/TeraFinder.Core.csproj index 02f0bf18..6fdcc6d3 100644 --- a/TeraFinder.Core/TeraFinder.Core.csproj +++ b/TeraFinder.Core/TeraFinder.Core.csproj @@ -17,16 +17,20 @@ embedded - 1701;1702;CA2211 + 1701,1702,CA2211,CS8604,CS8629,CS8602 False embedded - 1701;1702;CA2211 + 1701,1702,CA2211,CS8604,CS8629,CS8602 False + + $(DefineConstants);USE_PKHEX_MASTER + + True @@ -40,9 +44,6 @@ - - deps\SysBot.Base.dll - deps\pkNX.Structures.dll diff --git a/TeraFinder.Core/Utils/EventUtil.cs b/TeraFinder.Core/Utils/EventUtil.cs index b92e04af..f8f28a1f 100644 --- a/TeraFinder.Core/Utils/EventUtil.cs +++ b/TeraFinder.Core/Utils/EventUtil.cs @@ -1,45 +1,61 @@ using System.Data; +using System.Reflection; using System.Text; using System.Text.Json; +using PKHeX.Core; using pkNX.Structures; using pkNX.Structures.FlatBuffers.SV; -//Most of functions here are taken from pkNX -//https://github.com/kwsch/pkNX/blob/master/pkNX.WinForms/Dumping/TeraRaidRipper.cs -//GPL v3 Licence namespace TeraFinder.Core; public static class EventUtil { - public static string[] GetEventItemDataFromSAV(PKHeX.Core.SAV9SV sav) + public static EventProgress GetEventStageFromProgress(GameProgress progress) => progress switch { - //Read from save file block flatbuffer - var KBCATEventRaidIdentifier = sav.Accessor.FindOrDefault(Blocks.KBCATEventRaidIdentifier.Key); - if (KBCATEventRaidIdentifier.Type is not PKHeX.Core.SCTypeCode.None && BitConverter.ToUInt32(KBCATEventRaidIdentifier.Data) > 0) + GameProgress.Unlocked6Stars or GameProgress.Unlocked5Stars => EventProgress.Stage3, + GameProgress.Unlocked4Stars => EventProgress.Stage2, + GameProgress.Unlocked3Stars => EventProgress.Stage1, + _ => EventProgress.Stage0, + }; + + public static (EncounterEventTF9[] dist, EncounterEventTF9[] mighty) + GetCurrentEventEncounters(SAV9SV sav, (Dictionary> fixedRewards, Dictionary> lotteryRewards) rewards) + { + try + { + (var distData, var mightyData) = GetEventEncounterData(sav); + return (EncounterEventTF9.GetArray(distData, rewards.fixedRewards, rewards.lotteryRewards), EncounterEventTF9.GetArray(mightyData, rewards.fixedRewards, rewards.lotteryRewards)); + } + catch { } + return ([], []); + } + + public static (string distRewards, string mightyRewards) GetCurrentEventRewards(SAV9SV sav) + { + var KBCATEventRaidIdentifier = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATEventRaidIdentifier.Key); + if (KBCATEventRaidIdentifier.Type is not SCTypeCode.None && BitConverter.ToUInt32(KBCATEventRaidIdentifier.Data) > 0) { - var KBCATFixedRewardItemArray = sav.Accessor.FindOrDefault(Blocks.KBCATFixedRewardItemArray.Key).Data; - var KBCATLotteryRewardItemArray = sav.Accessor.FindOrDefault(Blocks.KBCATLotteryRewardItemArray.Key).Data; + var KBCATFixedRewardItemArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATFixedRewardItemArray.Key).Data; + var KBCATLotteryRewardItemArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATLotteryRewardItemArray.Key).Data; var tableDrops = pkNX.Structures.FlatBuffers.FlatBufferConverter.DeserializeFrom(KBCATFixedRewardItemArray); var tableBonus = pkNX.Structures.FlatBuffers.FlatBufferConverter.DeserializeFrom(KBCATLotteryRewardItemArray); var opt = new JsonSerializerOptions { WriteIndented = true }; var drops = JsonSerializer.Serialize(tableDrops, opt); var lottery = JsonSerializer.Serialize(tableBonus, opt); - return [drops, lottery]; + return (drops, lottery); } var drops_def = Encoding.UTF8.GetString(Properties.Resources.raid_fixed_reward_item_array); var lottery_def = Encoding.UTF8.GetString(Properties.Resources.raid_lottery_reward_item_array); - return [drops_def, lottery_def]; + return (drops_def, lottery_def); } - public static byte[][] GetEventEncounterDataFromSAV(PKHeX.Core.SAV9SV sav) + private static (byte[] distData, byte[] mightyData) GetEventEncounterData(SAV9SV sav) { - byte[][] res = null!; var type2list = new List(); var type3list = new List(); - var KBCATRaidEnemyArray = sav.Accessor.FindOrDefault(Blocks.KBCATRaidEnemyArray.Key).Data; - + var KBCATRaidEnemyArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATRaidEnemyArray.Key).Data; var tableEncounters = pkNX.Structures.FlatBuffers.FlatBufferConverter.DeserializeFrom(KBCATRaidEnemyArray); var byGroupID = tableEncounters.Table @@ -77,23 +93,16 @@ public static byte[][] GetEventEncounterDataFromSAV(PKHeX.Core.SAV9SV sav) AddToList(items, type2list, RaidSerializationFormat.Distribution); } - res = [[..type2list.SelectMany(z => z)], [..type3list.SelectMany(z => z)]]; - return res; + return ([..type2list.SelectMany(z => z)], [..type3list.SelectMany(z => z)]); } - public static DeliveryRaidPriority? GetDeliveryPriority(PKHeX.Core.SAV9SV sav) + public static DeliveryRaidPriority? GetEventDeliveryPriority(SAV9SV sav) { - var KBCATRaidPriorityArray = sav.Accessor.FindOrDefault(Blocks.KBCATRaidPriorityArray.Key); - if (KBCATRaidPriorityArray.Type is not PKHeX.Core.SCTypeCode.None && KBCATRaidPriorityArray.Data.Length > 0) + var KBCATRaidPriorityArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATRaidPriorityArray.Key); + if (KBCATRaidPriorityArray.Type is not SCTypeCode.None && KBCATRaidPriorityArray.Data.Length > 0) { - try - { - return pkNX.Structures.FlatBuffers.FlatBufferConverter.DeserializeFrom(KBCATRaidPriorityArray.Data).Table.First(); - } - catch (Exception) - { - return null; - } + try { return pkNX.Structures.FlatBuffers.FlatBufferConverter.DeserializeFrom(KBCATRaidPriorityArray.Data).Table.First(); } + catch { } } return null; } @@ -214,4 +223,54 @@ private static void TryAddToPickle(RaidEnemyInfo enc, List list, RaidSer [1, 2, 3, 4], [3, 4, 5, 6, 7], ]; + + public static byte GetDeliveryGroupID(IEventRaid9[] encounters, SAV9SV sav, EventProgress progress, RaidSpawnList9 raids, int currRaid) + { + var possibleGroups = new HashSet(); + + foreach (var enc in encounters) + if ((sav.Version is PKHeX.Core.GameVersion.SL && enc.GetRandRateTotalScarlet(progress) > 0) || + (sav.Version is PKHeX.Core.GameVersion.VL && enc.GetRandRateTotalViolet(progress) > 0)) + possibleGroups.Add(enc.Index); + + var eventCount = GetEventCount(raids, ++currRaid); + + var priority = GetEventDeliveryPriority(sav); + var groupid = priority is not null ? GetDeliveryGroupID(eventCount, priority.GroupID.Groups, possibleGroups) : (byte)0; + + return groupid; + } + + private static int GetEventCount(RaidSpawnList9 raids, int selected) + { + var count = 0; + for (var i = 0; i < selected; i++) + if (raids.GetRaid(i).Content >= TeraRaidContentType.Distribution) + count++; + return count; + } + + //From https://github.com/LegoFigure11/RaidCrawler/blob/7e764a9a5c0aa74270b3679083c813471abc55d6/Structures/TeraDistribution.cs#L145 + //GPL v3 License + //Thanks LegoFigure11 & architade! + private static byte GetDeliveryGroupID(int eventct, GroupSet ids, HashSet possible_groups) + { + if (eventct > -1 && possible_groups.Count > 0) + { + var cts = new int[10]; + for (var i = 0; i < ids.Groups_Length; i++) + cts[i] = GroupSet.Groups_Item(ref ids, i); + + for (int i = 0; i < cts.Length; i++) + { + var ct = cts[i]; + if (!possible_groups.Contains(i + 1)) + continue; + if (eventct <= ct) + return (byte)(i + 1); + eventct -= ct; + } + } + return 0; + } } \ No newline at end of file diff --git a/TeraFinder.Core/Utils/ResourcesUtil.cs b/TeraFinder.Core/Utils/ResourcesUtil.cs new file mode 100644 index 00000000..f6951f1c --- /dev/null +++ b/TeraFinder.Core/Utils/ResourcesUtil.cs @@ -0,0 +1,56 @@ +using PKHeX.Core; +using System.Text; + +namespace TeraFinder.Core; + +public static class ResourcesUtil +{ + public static byte[] GetDenLocations(TeraRaidMapParent map) => map switch + { + TeraRaidMapParent.Paldea => Properties.Resources.paldea_locations, + TeraRaidMapParent.Kitakami => Properties.Resources.kitakami_locations, + _ => Properties.Resources.blueberry_locations + }; + + public static byte[] GetFixedRewardsData() => Properties.Resources.raid_fixed_reward_item_array; + + public static byte[] GetLotteryRewardsData() => Properties.Resources.raid_lottery_reward_item_array; + + public static (EncounterTeraTF9[] standard, EncounterTeraTF9[] black) GetAllTeraEncounters(TeraRaidMapParent map) + { + var (fixedRewards, lotteryRewards) = RewardUtil.GetTeraRewardsTables(); + var standard = EncounterTeraTF9.GetArray(map switch + { + TeraRaidMapParent.Paldea => Properties.Resources.encounter_gem_paldea_standard, + TeraRaidMapParent.Kitakami => Properties.Resources.encounter_gem_kitakami_standard, + TeraRaidMapParent.Blueberry => Properties.Resources.encounter_gem_blueberry_standard, + _ => throw new ArgumentOutOfRangeException(nameof(map)) + }, fixedRewards, lotteryRewards, map); + + var black = EncounterTeraTF9.GetArray(map switch + { + TeraRaidMapParent.Paldea => Properties.Resources.encounter_gem_paldea_black, + TeraRaidMapParent.Kitakami => Properties.Resources.encounter_gem_kitakami_black, + TeraRaidMapParent.Blueberry => Properties.Resources.encounter_gem_blueberry_black, + _ => throw new ArgumentOutOfRangeException(nameof(map)) + }, fixedRewards, lotteryRewards, map); + + return (standard, black); + } + + public static (EncounterEventTF9[] dist, EncounterEventTF9[] might) GetAllEventEncounters() + { + var dist = EncounterEventTF9.GetArray(Properties.Resources.encounter_dist_paldea, [], []); + var might = EncounterEventTF9.GetArray(Properties.Resources.encounter_might_paldea, [], []); + return (dist, might); + } + + public static string? GetTextResource(string res) + { + var obj = Properties.Resources.ResourceManager.GetObject(res); + if (res.Contains("lang")) + return (string?)obj; + else if (obj is null) return null; + return Encoding.UTF8.GetString((byte[])obj); + } +} \ No newline at end of file diff --git a/TeraFinder.Core/Utils/RewardUtil.cs b/TeraFinder.Core/Utils/RewardUtil.cs index cf7fc8a0..0c7dec5d 100644 --- a/TeraFinder.Core/Utils/RewardUtil.cs +++ b/TeraFinder.Core/Utils/RewardUtil.cs @@ -5,26 +5,28 @@ namespace TeraFinder.Core; public static class RewardUtil { - public static readonly string[] TeraShard = ["テラピ", "Tera Shard", "Téra-Éclat", "Teralite", "Tera-Stück", "Teralito", "테라피스", "晶碎块", "晶碎塊"]; - public static readonly string[] Material = ["おとしもの", "Material", "Échantillons", "Materiali", "Materialentasche", "Materiales", "掉落物", "掉落物", "掉落物"]; + public static List GetCombinedRewardList(TeraDetails rng, List fixedRewards, List lotteryRewards, int boost = 0) + { + var lotteryrng = CalculateLotteryRNG(rng, lotteryRewards, boost); + var list = new List(); + list.AddRange(fixedRewards); + list.AddRange(lotteryrng); + return list; + } - public static Dictionary>[] GetTeraRewardsTables() + public static (Dictionary> fixedRewardTable, Dictionary> lotteryRewardTable) GetTeraRewardsTables() { - var drops = JsonSerializer.Deserialize(Properties.Resources.raid_fixed_reward_item_array)!; - var lottery = JsonSerializer.Deserialize(Properties.Resources.raid_lottery_reward_item_array)!; - var fixedTable = GetFixedTable(drops.Table); - var lotteryTable = GetLotteryTable(lottery.Table); - return [fixedTable, lotteryTable]; + var drops = JsonSerializer.Deserialize(ResourcesUtil.GetFixedRewardsData())!; + var lottery = JsonSerializer.Deserialize(ResourcesUtil.GetLotteryRewardsData())!; + return (GetFixedTable(drops.Table), GetLotteryTable(lottery.Table)); } - public static Dictionary>[] GetDistRewardsTables(SAV9SV sav) + public static (Dictionary> fixedDistRewardTable, Dictionary> lotteryDistRewardTable) GetDistRewardsTables(SAV9SV sav) { - var rewards = EventUtil.GetEventItemDataFromSAV(sav); - var drops = JsonSerializer.Deserialize(rewards[0])!; - var lottery = JsonSerializer.Deserialize(rewards[1])!; - var fixedTable = GetFixedTable(drops.Table); - var lotteryTable = GetLotteryTable(lottery.Table); - return [fixedTable, lotteryTable]; + var (distRewards, mightyRewards) = EventUtil.GetCurrentEventRewards(sav); + var drops = JsonSerializer.Deserialize(distRewards)!; + var lottery = JsonSerializer.Deserialize(mightyRewards)!; + return (GetFixedTable(drops.Table), GetLotteryTable(lottery.Table)); } public static bool IsTM(int item) => item switch @@ -48,7 +50,36 @@ public static string GetNameTM(int item, ReadOnlySpan items, ReadOnlySpa }; } - private static int GetTeraShard(MoveType type) + public static void ReplaceMaterialReward(this List rewards, Species species) + { + for (var i = 0; i < rewards.Count; i++) + { + switch (rewards[i].ItemID) + { + case ushort.MaxValue: + rewards[i].ItemID = GetMaterial(species); + break; + default: + break; + } + } + } + + public static bool IsHerbaMystica(int item) => item switch + { + ushort.MaxValue - 2 => true, + >= 1904 and <= 1908 => true, + _ => false, + }; + + public static bool IsTeraShard(int item) => item switch + { + ushort.MaxValue - 1 => true, + >= 1862 and <= 1879 => true, + _ => false, + }; + + public static int GetTeraShard(MoveType type) { return type switch { @@ -70,7 +101,7 @@ private static int GetTeraShard(MoveType type) MoveType.Dragon => 1876, MoveType.Dark => 1877, MoveType.Fairy => 1879, - _ => ushort.MaxValue - 1, + _ => throw new NotImplementedException(nameof(type)), }; } @@ -352,82 +383,29 @@ Species.GreatTusk or Species.ScreamTail or Species.BruteBonnet or Species.Flutte Species.IronTreads or Species.IronBundle or Species.IronHands or Species.IronJugulis or Species.IronMoth or Species.IronThorns or Species.IronValiant or Species.IronLeaves or Species.IronBoulder or Species.IronCrown => 0, - _ => ushort.MaxValue, + _ => 0, }; } - //Slightly modified from https://github.com/LegoFigure11/RaidCrawler/blob/06a7f4c17fca74297d6199f37a171f2b480d40f0/Structures/RaidRewards.cs#L10 //GPL v3 License //Thanks LegoFigure11 & Architdate! - public static List GetRewardList(TeraDetails pkm, ulong fixedhash, ulong lotteryhash, Dictionary>? fixedic = null, Dictionary>? lotterydic = null, int boost = 0) + private static List CalculateLotteryRNG(TeraDetails rng, List lotterylist, int boost = 0) { var rewardlist = new List(); - var fixedlist = new List(); - var lotterylist = new List(); - - var fixedexists = fixedic is not null && fixedic.TryGetValue(fixedhash, out fixedlist); - var lotteryexists = lotterydic is not null && lotterydic.TryGetValue(lotteryhash, out lotterylist); - - if (fixedexists) + var xoro = new Xoroshiro128Plus(rng.Seed); + var amount = GetRewardCount(xoro.NextInt(100), rng.Stars) + boost; + for (var i = 0; i < amount; i++) { - foreach (var reward in fixedlist!) + var treshold = (int)xoro.NextInt((ulong)lotterylist[0].Aux); + foreach (var reward in lotterylist) { - rewardlist.Add(reward.ItemID == ushort.MaxValue ? new Reward { ItemID = GetMaterial((Species)pkm.Species), Amount = reward.Amount, Aux = reward.Aux } : - reward.ItemID == ushort.MaxValue - 1 ? new Reward { ItemID = GetTeraShard((MoveType)pkm.TeraType), Amount = reward.Amount, Aux = reward.Aux } : reward); - } - } - if (lotteryexists) - { - var xoro = new Xoroshiro128Plus(pkm.Seed); - var amount = GetRewardCount(xoro.NextInt(100), pkm.Stars) + boost; - for (var i = 0; i < amount; i++) - { - var treshold = (int)xoro.NextInt((ulong)lotterylist!.ElementAt(0).Aux); - foreach (var reward in lotterylist!) - { - if (reward.Probability > treshold) - { - rewardlist.Add(reward.ItemID == ushort.MaxValue ? new Reward { ItemID = GetMaterial((Species)pkm.Species), Amount = reward.Amount } : - reward.ItemID == ushort.MaxValue - 1 ? new Reward { ItemID = GetTeraShard((MoveType)pkm.TeraType), Amount = reward.Amount } : reward); - break; - } - treshold -= reward.Probability; - } - } - } - return rewardlist; - } - - public static List GetRewardList(uint seed, ushort species, int stars, ulong fixedhash, ulong lotteryhash, Dictionary>? fixedic = null, Dictionary>? lotterydic = null, int boost = 0) - { - var rewardlist = new List(); - var fixedlist = new List(); - var lotterylist = new List(); - - var fixedexists = fixedic is not null && fixedic.TryGetValue(fixedhash, out fixedlist); - var lotteryexists = lotterydic is not null && lotterydic.TryGetValue(lotteryhash, out lotterylist); - - if (fixedexists) - foreach (var reward in fixedlist!) - rewardlist.Add(reward.ItemID == ushort.MaxValue ? new Reward { ItemID = GetMaterial((Species)species), Amount = reward.Amount, Aux = reward.Aux } : reward); - - if (lotteryexists) - { - var xoro = new Xoroshiro128Plus(seed); - var amount = GetRewardCount(xoro.NextInt(100), stars) + boost; - for (var i = 0; i < amount; i++) - { - var tres = (int)xoro.NextInt((ulong)lotterylist!.ElementAt(0).Aux); - foreach (var reward in lotterylist!) - { - if (reward.Probability > tres) - { - rewardlist.Add(reward.ItemID == ushort.MaxValue ? new Reward { ItemID = GetMaterial((Species)species), Amount = reward.Amount } : reward); - break; - } - tres -= reward.Probability; + if (reward.Probability > treshold) + { + rewardlist.Add(reward); + break; } + treshold -= reward.Probability; } } return rewardlist; diff --git a/TeraFinder.Core/Utils/SavUtil.cs b/TeraFinder.Core/Utils/SavUtil.cs new file mode 100644 index 00000000..73d5ec54 --- /dev/null +++ b/TeraFinder.Core/Utils/SavUtil.cs @@ -0,0 +1,36 @@ +using PKHeX.Core; + +namespace TeraFinder.Core; + +public static class SavUtil +{ + public static GameProgress GetProgress(SAV9SV sav) + { + var Unlocked6Stars = sav.Accessor.FindOrDefault(BlockDefinitions.KUnlockedRaidDifficulty6.Key).Type is SCTypeCode.Bool2; + + if (Unlocked6Stars) + return GameProgress.Unlocked6Stars; + + var Unlocked5Stars = sav.Accessor.FindOrDefault(BlockDefinitions.KUnlockedRaidDifficulty5.Key).Type is SCTypeCode.Bool2; + + if (Unlocked5Stars) + return GameProgress.Unlocked5Stars; + + var Unlocked4Stars = sav.Accessor.FindOrDefault(BlockDefinitions.KUnlockedRaidDifficulty4.Key).Type is SCTypeCode.Bool2; + + if (Unlocked4Stars) + return GameProgress.Unlocked4Stars; + + var Unlocked3Stars = sav.Accessor.FindOrDefault(BlockDefinitions.KUnlockedRaidDifficulty3.Key).Type is SCTypeCode.Bool2; + + if (Unlocked3Stars) + return GameProgress.Unlocked3Stars; + + var UnlockedTeraRaids = sav.Accessor.FindOrDefault(BlockDefinitions.KUnlockedTeraRaidBattles.Key).Type is SCTypeCode.Bool2; + + if (UnlockedTeraRaids) + return GameProgress.UnlockedTeraRaids; + + return GameProgress.Beginning; + } +} diff --git a/TeraFinder.Core/Utils/SeedCheckerUtil.cs b/TeraFinder.Core/Utils/SeedCheckerUtil.cs new file mode 100644 index 00000000..e70a602c --- /dev/null +++ b/TeraFinder.Core/Utils/SeedCheckerUtil.cs @@ -0,0 +1,7 @@ +namespace TeraFinder.Core; + +public static class SeedCheckerUtil +{ + public static Dictionary> GroupEventEncounters(EncounterEventTF9[] encounters) => + encounters.GroupBy(e => Convert.ToUInt32($"{e.Identifier}"[..^2], 10)).ToDictionary(g => g.Key, g => new HashSet(g)); +} diff --git a/TeraFinder.Core/Utils/TeraUtil.cs b/TeraFinder.Core/Utils/TeraUtil.cs deleted file mode 100644 index bd866d8a..00000000 --- a/TeraFinder.Core/Utils/TeraUtil.cs +++ /dev/null @@ -1,496 +0,0 @@ -using PKHeX.Core; -using System.Text; - -namespace TeraFinder.Core; - -public static class TeraUtil -{ - public static byte[] GetDenLocations(TeraRaidMapParent map) => map switch - { - TeraRaidMapParent.Paldea => Properties.Resources.paldea_locations, - TeraRaidMapParent.Kitakami => Properties.Resources.kitakami_locations, - _ => Properties.Resources.blueberry_locations - }; - - public static string? GetTextResource(string res) - { - var obj = Properties.Resources.ResourceManager.GetObject(res); - if (res.Contains("lang")) - return (string?)obj; - else if (obj is null) return null; - return Encoding.UTF8.GetString((byte[]) obj); - } - - public static uint GetID32(uint tid7, uint sid7) => (uint)(tid7 + ((ulong)sid7 * 1000000)); - public static ushort GetTID16(uint id32) => (ushort)(id32 & 0xFFFF); - public static ushort GetSID16(uint id32) => (ushort)(id32 >> 16); - - public static PK9 GenerateTeraEntity(SAV9SV sav, EncounterRaid9 encounter, RaidContent content, uint seed, uint id32, int groupid) - { - var template = new PK9(Properties.Resources.template); - var rngres = CalcRNG(seed, id32, content, encounter, groupid); - template.Species = rngres.Species; - template.Form = rngres.Form; - if (rngres.Stars == 7) template.RibbonMarkMightiest = true; - template.MetDate = DateOnly.FromDateTime(DateTime.Now); - template.MetLevel = (byte)rngres.Level; - template.CurrentLevel = (byte)rngres.Level; - template.Obedience_Level = (byte)rngres.Level; - template.TeraTypeOriginal = (MoveType)rngres.TeraType; - template.EncryptionConstant = rngres.EC; - template.ID32 = id32; - template.Version = sav.Version; - template.Language = (byte)sav.Language; - template.HandlingTrainerName = sav.OT; - template.HandlingTrainerLanguage = (byte)sav.Language; - template.OriginalTrainerName = sav.OT; - template.OriginalTrainerGender = sav.Gender; - template.PID = rngres.PID; - template.IV_HP = rngres.HP; - template.IV_ATK = rngres.ATK; - template.IV_DEF = rngres.DEF; - template.IV_SPA = rngres.SPA; - template.IV_SPD = rngres.SPD; - template.IV_SPE = rngres.SPE; - template.Ability = rngres.Ability; - template.AbilityNumber = rngres.GetAbilityNumber() == 3 ? 4 : rngres.GetAbilityNumber(); - template.Nature = (Nature)rngres.Nature; - template.StatNature = (Nature)rngres.Nature; - template.Gender = (byte)rngres.Gender; - template.HeightScalar = rngres.Height; - template.WeightScalar = rngres.Weight; - template.Scale = rngres.Scale; - template.Move1 = rngres.Move1; - template.Move2 = rngres.Move2; - template.Move3 = rngres.Move3; - template.Move4 = rngres.Move4; - if (encounter.Item > 0) template.HeldItem = encounter.Item; - - template.HealPP(); - template.ClearNickname(); - - try - { - var la = new LegalityAnalysis(template); - - if (!la.Valid) - { - var ability = la.Results.Where(l => l.Identifier is CheckIdentifier.Ability).FirstOrDefault(); - var la_ot = la.Results.Where(l => l.Identifier is CheckIdentifier.Trainer).FirstOrDefault(); - if (!ability.Valid) - { - for (var i = 0; i <= 4 && !la.Valid; i++) - { - template.AbilityNumber = i; - i++; - la = new LegalityAnalysis(template); - } - } - if ((LanguageID)template.Language is (LanguageID.ChineseS or LanguageID.ChineseT or LanguageID.Korean or LanguageID.Japanese) && !la_ot.Valid) - template.OriginalTrainerName = "TF"; - } - } - catch (Exception ex) - { - //PKHeX currently has a bug when analyzing the Mighty Mark ribbon if the encounter is not in the db, this is an hacky way to handle the exception - if (ex.ToString().Contains("RibbonMarkMightiest")) - template.RibbonMarkMightiest = false; - - return template; - } - - return template; - } - - public static GameProgress GetProgress(SAV9SV sav) - { - var Unlocked6Stars = sav.Accessor.FindOrDefault(Blocks.KUnlockedRaidDifficulty6.Key).Type is SCTypeCode.Bool2; - - if (Unlocked6Stars) - return GameProgress.Unlocked6Stars; - - var Unlocked5Stars = sav.Accessor.FindOrDefault(Blocks.KUnlockedRaidDifficulty5.Key).Type is SCTypeCode.Bool2; - - if (Unlocked5Stars) - return GameProgress.Unlocked5Stars; - - var Unlocked4Stars = sav.Accessor.FindOrDefault(Blocks.KUnlockedRaidDifficulty4.Key).Type is SCTypeCode.Bool2; - - if (Unlocked4Stars) - return GameProgress.Unlocked4Stars; - - var Unlocked3Stars = sav.Accessor.FindOrDefault(Blocks.KUnlockedRaidDifficulty3.Key).Type is SCTypeCode.Bool2; - - if (Unlocked3Stars) - return GameProgress.Unlocked3Stars; - - var UnlockedTeraRaids = sav.Accessor.FindOrDefault(Blocks.KUnlockedTeraRaidBattles.Key).Type is SCTypeCode.Bool2; - - if (UnlockedTeraRaids) - return GameProgress.UnlockedTeraRaids; - - return GameProgress.Beginning; - } - - public static int GetStars(uint seed, GameProgress progress) - { - if (progress is GameProgress.Beginning) - return 0; - - var xoro = new Xoroshiro128Plus(seed); - var stars = progress == (GameProgress)6 ? 6 : CalcStars(xoro, progress); - return stars; - } - - private static int CalcStars(Xoroshiro128Plus xoro, GameProgress progress) - { - var rand = xoro.NextInt(100); - - return progress switch - { - GameProgress.Unlocked6Stars => rand switch - { - > 70 => 5, - > 30 => 4, - _ => 3, - }, - GameProgress.Unlocked5Stars => rand switch - { - > 75 => 5, - > 40 => 4, - _ => 3, - }, - GameProgress.Unlocked4Stars => rand switch - { - > 70 => 4, - > 40 => 3, - > 20 => 2, - _ => 1, - }, - GameProgress.Unlocked3Stars => rand switch - { - > 70 => 3, - > 30 => 2, - _ => 1, - }, - _ => rand switch - { - > 80 => 2, - _ => 1, - }, - }; - } - - public static List GetAvailableSpecies(SAV9SV sav, string[] species, string[] forms, string[] types, Dictionary plugins, int stars, RaidContent content, TeraRaidMapParent map) - { - List list = []; - var game = (GameVersion)sav.Version; - - var encounters = content is RaidContent.Event ? GetSAVDistEncounters(sav)[0] : content is RaidContent.Event_Mighty ? GetSAVDistEncounters(sav)[1] : - EncounterRaid9.GetEncounters(EncounterTera9.GetArray(map switch - { - TeraRaidMapParent.Paldea => Properties.Resources.encounter_gem_paldea, - TeraRaidMapParent.Kitakami => Properties.Resources.encounter_gem_kitakami, - _ => Properties.Resources.encounter_gem_blueberry - }, map)); - - foreach (var encounter in encounters) - { - if (encounter.Species > 0 && (encounter.Version is GameVersion.SV || encounter.Version == game) && ((stars == 0 && encounter.Stars != 6) || encounter.Stars == stars)) - { - var formlist = FormConverter.GetFormList(encounter.Species, types, forms, GameInfo.GenderSymbolASCII, EntityContext.Gen9); - var str = $"{species[encounter.Species]}{(formlist.Length > 1 ? $"-{$"{formlist[encounter.Form]}"}" : "")}"; - - if (!encounter.CanBeEncounteredScarlet) - str += $" ({plugins["GameVersionVL"]})"; - - if (!encounter.CanBeEncounteredViolet) - str += $" ({plugins["GameVersionSL"]})"; - - if (!list.Contains(str)) - list.Add(str); - } - } - return list; - } - - public static EncounterRaid9[] GetAllTeraEncounters(TeraRaidMapParent map) => - EncounterRaid9.GetEncounters(EncounterTera9.GetArray(map switch - { - TeraRaidMapParent.Paldea => Properties.Resources.encounter_gem_paldea, - TeraRaidMapParent.Kitakami => Properties.Resources.encounter_gem_kitakami, - _ => Properties.Resources.encounter_gem_blueberry - }, map)); - - public static EncounterRaid9[] GetAllDistEncounters(RaidContent type) => - type switch - { - RaidContent.Event => EncounterRaid9.GetEncounters(PKHeX.Core.EncounterDist9.GetArray(Util.GetBinaryResource("encounter_dist_paldea.pkl"))), - RaidContent.Event_Mighty => EncounterRaid9.GetEncounters(PKHeX.Core.EncounterMight9.GetArray(Util.GetBinaryResource("encounter_might_paldea.pkl"))), - _ => throw new ArgumentException("Invalid RaidContent type"), - }; - - public static EncounterRaid9[][] GetSAVDistEncounters(SAV9SV sav) - { - try - { - var events = EventUtil.GetEventEncounterDataFromSAV(sav); - var dist = EncounterRaid9.GetEncounters(EncounterDist9.GetArray(events[0])); - var mighty = EncounterRaid9.GetEncounters(EncounterMight9.GetArray(events[1])); - return [dist, mighty]; - } - catch - { - const int encSize = EncounterDist9.SerializedSize; - var dist = EncounterRaid9.GetEncounters(EncounterDist9.GetArray(new byte[encSize])); - var might = EncounterRaid9.GetEncounters(EncounterMight9.GetArray(new byte[encSize])); - return [dist, might]; - } - } - - public static EncounterRaid9? GetTeraEncounter(uint seed, GameVersion game, int stars, EncounterRaid9[] encounters, TeraRaidMapParent map) - { - var xoro = new Xoroshiro128Plus(seed); - if (stars < 6) xoro.NextInt(100); - var max = game is GameVersion.SL ? EncounterTera9.GetRateTotalSL(stars, map) : EncounterTera9.GetRateTotalVL(stars, map); - var rateRand = (int)xoro.NextInt((uint)max); - foreach (var encounter in encounters) - { - var min = game is GameVersion.SL ? encounter.RandRateMinScarlet : encounter.RandRateMinViolet; - if (encounter.Stars == stars && min >= 0 && (uint)(rateRand - min) < encounter.RandRate) - return encounter; - } - return null; - } - - public static EncounterRaid9? GetDistEncounter(uint seed, GameVersion game, GameProgress progress, EncounterRaid9[] encounters, int groupid = -2) - { - var p = progress switch - { - GameProgress.Unlocked6Stars or GameProgress.Unlocked5Stars => 3, - GameProgress.Unlocked4Stars => 2, - GameProgress.Unlocked3Stars => 1, - _ => 0, - }; - - foreach (var encounter in encounters) - { - if (groupid != -2 && encounter.Index != groupid) - continue; - var max = game is GameVersion.SL ? encounter.GetRandRateTotalScarlet(p) : encounter.GetRandRateTotalViolet(p); - var min = game is GameVersion.SL ? encounter.GetRandRateMinScarlet(p) : encounter.GetRandRateMinViolet(p); - if (min >= 0 && max > 0) - { - var xoro = new Xoroshiro128Plus(seed); - xoro.NextInt(100); - var rateRand = xoro.NextInt(max); - if ((uint)(rateRand - min) < encounter.RandRate) - return encounter; - } - } - return null; - } - - public static EncounterRaid9[] FilterDistEncounters(uint seed, GameVersion version, GameProgress progress, EncounterRaid9[] encounters, int groupid, ushort species) - { - var res = new List(); - var p = progress switch - { - GameProgress.Unlocked6Stars or GameProgress.Unlocked5Stars => 3, - GameProgress.Unlocked4Stars => 2, - GameProgress.Unlocked3Stars => 1, - _ => 0, - }; - - foreach (var encounter in encounters) - { - if (encounter.Species != species || encounter.Index != groupid) - continue; - var max = version is GameVersion.SL ? encounter.GetRandRateTotalScarlet(p) : encounter.GetRandRateTotalViolet(p); - var min = version is GameVersion.SL ? encounter.GetRandRateMinScarlet(p) : encounter.GetRandRateMinViolet(p); - if (min >= 0 && max > 0) - { - var xoro = new Xoroshiro128Plus(seed); - xoro.NextInt(100); - var rateRand = xoro.NextInt(max); - if ((uint)(rateRand - min) < encounter.RandRate) - res.Add(encounter); - } - } - - return [..res]; - } - - private static byte GetGender(EncounterRaid9 enc, bool isMighty) - { - if (isMighty) - { - return enc.Gender switch - { - 0 => PersonalInfo.RatioMagicMale, - 1 => PersonalInfo.RatioMagicFemale, - 2 => PersonalInfo.RatioMagicGenderless, - _ => PersonalTable.SV.GetFormEntry(enc.Species, enc.Form).Gender, - }; - } - return PersonalTable.SV.GetFormEntry(enc.Species, enc.Form).Gender; - } - - public static TeraDetails CalcRNG(uint seed, uint id32, RaidContent content, EncounterRaid9 encounter, int groupid, ulong calc = 0) - { - var rngres = new TeraDetails - { - Seed = seed, - Stars = encounter.Stars, - Species = encounter.Species, - Level = encounter.Level, - Form = encounter.Form, - TeraType = (sbyte)Tera9RNG.GetTeraType(seed, encounter.TeraType, encounter.Species, encounter.Form), - Move1 = encounter.Moves.Move1, - Move2 = encounter.Moves.Move2, - Move3 = encounter.Moves.Move3, - Move4 = encounter.Moves.Move4, - EventIndex = (byte)groupid, - Calcs = calc, - }; - - var param = new GenerateParam9 - { - Species = encounter.Species, - GenderRatio = GetGender(encounter, content is RaidContent.Event_Mighty), - FlawlessIVs = encounter.FlawlessIVCount, - RollCount = 1, - Height = 0, - Weight = 0, - ScaleType = encounter.ScaleType, - Scale = encounter.Scale, - Ability = encounter.Ability, - Shiny = encounter.Shiny, - Nature = encounter.Nature, - IVs = encounter.IVs, - }; - - Encounter9RNG.GenerateData(rngres, param, id32, seed); - - return rngres; - } - - public static int GetDeliveryGroupID(SAV9SV sav, GameProgress progress, RaidContent content, EncounterRaid9[]? Dist, RaidSpawnList9 raids, int currRaid = -1) - { - var p = progress switch - { - GameProgress.Unlocked6Stars or GameProgress.Unlocked5Stars => 3, - GameProgress.Unlocked4Stars => 2, - GameProgress.Unlocked3Stars => 1, - _ => 0, - }; - - var possibleGroups = new HashSet(); - if (content is RaidContent.Event or RaidContent.Event_Mighty && Dist is not null) - foreach (var enc in Dist) - if (((GameVersion)sav.Version is GameVersion.SL && enc.GetRandRateTotalScarlet(p) > 0) || - ((GameVersion)sav.Version is GameVersion.VL && enc.GetRandRateTotalViolet(p) > 0)) - possibleGroups.Add(enc.Index); - - var eventCount = content >= RaidContent.Event ? GetEventCount(raids, currRaid+1) : 0; - - var priority = EventUtil.GetDeliveryPriority(sav); - var groupid = priority is not null ? GetDeliveryGroupID(eventCount, priority.GroupID.Groups, possibleGroups) : 0; - - return groupid; - } - - private static int GetEventCount(RaidSpawnList9 raids, int selected) - { - var count = 0; - for (var i = 0; i < selected; i++) - if ((RaidContent)raids.GetRaid(i).Content >= RaidContent.Event) - count++; - return count; - } - - //From https://github.com/LegoFigure11/RaidCrawler/blob/7e764a9a5c0aa74270b3679083c813471abc55d6/Structures/TeraDistribution.cs#L145 - //GPL v3 License - //Thanks LegoFigure11 & architade! - private static int GetDeliveryGroupID(int eventct, pkNX.Structures.FlatBuffers.SV.GroupSet ids, HashSet possible_groups) - { - if (eventct > -1 && possible_groups.Count > 0) - { - var cts = new int[10]; - for (var i = 0; i < ids.Groups_Length; i++) - cts[i] = pkNX.Structures.FlatBuffers.SV.GroupSet.Groups_Item(ref ids, i); - - for (int i = 0; i < cts.Length; i++) - { - var ct = cts[i]; - if (!possible_groups.Contains(i + 1)) - continue; - if (eventct <= ct) - return i + 1; - eventct -= ct; - } - } - return 0; - } - - //From https://github.com/LegoFigure11/RaidCrawler/blob/main/Structures/Areas.cs - //GPL v3 License - //Thanks LegoFigure11! - public static string[] AreaPaldea = [ - "", - "South Province (Area 1)", - "", // Unused - "", // Unused - "South Province (Area 2)", - "South Province (Area 4)", - "South Province (Area 6)", - "South Province (Area 5)", - "South Province (Area 3)", - "West Province (Area 1)", - "Asado Desert", - "West Province (Area 2)", - "West Province (Area 3)", - "Tagtree Thicket", - "East Province (Area 3)", - "East Province (Area 1)", - "East Province (Area 2)", - "Dalizapa Passage", - "Casseroya Lake", - "Glaseado Mountain", - "North Province (Area 3)", - "North Province (Area 1)", - "North Province (Area 2)", - ]; - - //Thanks santacrab2! - public static string[] AreaKitakami = [ - "", - "Kitakami Road", - "Apple Hills", - "Revelers Road", - "Oni Mountain", - "Infernal Pass", - "Crystal Pool", - "Wistful Fields", - "Mossfell Confluence", - "Fellhorn Gorge", - "Paradise Barrens", - "Kitakami Wilds", - ]; - - //From https://github.com/LegoFigure11/RaidCrawler/blob/main/Structures/Areas.cs - //GPL v3 License - //Thanks LegoFigure11! - public static string[] AreaBlueberry = - [ - "", - "Savannna Biome", - "Coastal Biome", - "Canyon Biome", - "Polar Biome", - "Savanna Biome", - "Coastal Biome", - "Canyon Biome", - "Polar Biome", - ]; -} diff --git a/TeraFinder.Core/Utils/TidUtil.cs b/TeraFinder.Core/Utils/TidUtil.cs new file mode 100644 index 00000000..9192e684 --- /dev/null +++ b/TeraFinder.Core/Utils/TidUtil.cs @@ -0,0 +1,10 @@ +namespace TeraFinder.Core; + +public static class TidUtil +{ + public static uint GetID32(uint tid7, uint sid7) => (uint)(tid7 + ((ulong)sid7 * 1000000)); + + public static ushort GetTID16(uint id32) => (ushort)(id32 & 0xFFFF); + + public static ushort GetSID16(uint id32) => (ushort)(id32 >> 16); +} diff --git a/TeraFinder.Launcher/Launcher.cs b/TeraFinder.Launcher/Launcher.cs index aa2d82e0..ce56a3c3 100644 --- a/TeraFinder.Launcher/Launcher.cs +++ b/TeraFinder.Launcher/Launcher.cs @@ -1,17 +1,20 @@ -namespace TeraFinder.Launcher +namespace TeraFinder.Launcher; + +internal static class Launcher { - internal static class Launcher + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main() - { - // To customize application configuration such as set high DPI settings or default font, - // see https://aka.ms/applicationconfiguration. - ApplicationConfiguration.Initialize(); - Application.Run(new TeraFinderForm()); - } + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + var splash = new SplashScreen(); + new Task(() => splash.ShowDialog()).Start(); + var TF = new TeraFinderForm(); + splash.Invoke(splash.Close); + Application.Run(TF); } } \ No newline at end of file diff --git a/TeraFinder.Launcher/Properties/Resources.Designer.cs b/TeraFinder.Launcher/Properties/Resources.Designer.cs index 22917db0..72c20e91 100644 --- a/TeraFinder.Launcher/Properties/Resources.Designer.cs +++ b/TeraFinder.Launcher/Properties/Resources.Designer.cs @@ -69,5 +69,15 @@ internal static System.Drawing.Icon icon { return ((System.Drawing.Icon)(obj)); } } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap splash { + get { + object obj = ResourceManager.GetObject("splash", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } } diff --git a/TeraFinder.Launcher/Properties/Resources.resx b/TeraFinder.Launcher/Properties/Resources.resx index 95ac60c0..ad8dd506 100644 --- a/TeraFinder.Launcher/Properties/Resources.resx +++ b/TeraFinder.Launcher/Properties/Resources.resx @@ -121,4 +121,7 @@ ..\Resources\icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\splash.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/TeraFinder.Launcher/Resources/splash.png b/TeraFinder.Launcher/Resources/splash.png new file mode 100644 index 00000000..ad665065 Binary files /dev/null and b/TeraFinder.Launcher/Resources/splash.png differ diff --git a/TeraFinder.Launcher/SplashScreen.Designer.cs b/TeraFinder.Launcher/SplashScreen.Designer.cs new file mode 100644 index 00000000..416f7606 --- /dev/null +++ b/TeraFinder.Launcher/SplashScreen.Designer.cs @@ -0,0 +1,92 @@ +namespace TeraFinder.Launcher +{ + partial class SplashScreen + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + pictureSplash = new PictureBox(); + lblName = new Label(); + lblInfo = new Label(); + ((System.ComponentModel.ISupportInitialize)pictureSplash).BeginInit(); + SuspendLayout(); + // + // pictureSplash + // + pictureSplash.BackgroundImage = Properties.Resources.splash; + pictureSplash.Location = new Point(8, 7); + pictureSplash.Name = "pictureSplash"; + pictureSplash.Size = new Size(106, 63); + pictureSplash.TabIndex = 0; + pictureSplash.TabStop = false; + // + // lblName + // + lblName.AutoSize = true; + lblName.Location = new Point(122, 14); + lblName.Name = "lblName"; + lblName.Size = new Size(178, 20); + lblName.TabIndex = 1; + lblName.Text = "Tera Finder is initializing..."; + // + // lblInfo + // + lblInfo.AutoSize = true; + lblInfo.Location = new Point(147, 43); + lblInfo.Name = "lblInfo"; + lblInfo.Size = new Size(118, 20); + lblInfo.TabIndex = 2; + lblInfo.Text = "www.manu.tools"; + // + // SplashScreen + // + AutoScaleDimensions = new SizeF(8F, 20F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(309, 77); + ControlBox = false; + Controls.Add(lblInfo); + Controls.Add(lblName); + Controls.Add(pictureSplash); + FormBorderStyle = FormBorderStyle.None; + MaximizeBox = false; + MdiChildrenMinimizedAnchorBottom = false; + MinimizeBox = false; + Name = "SplashScreen"; + ShowIcon = false; + StartPosition = FormStartPosition.CenterScreen; + Text = "Tera Finder"; + ((System.ComponentModel.ISupportInitialize)pictureSplash).EndInit(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private PictureBox pictureSplash; + private Label lblName; + private Label lblInfo; + } +} \ No newline at end of file diff --git a/TeraFinder.Launcher/SplashScreen.cs b/TeraFinder.Launcher/SplashScreen.cs new file mode 100644 index 00000000..80f5d3d4 --- /dev/null +++ b/TeraFinder.Launcher/SplashScreen.cs @@ -0,0 +1,10 @@ +namespace TeraFinder.Launcher +{ + public partial class SplashScreen : Form + { + public SplashScreen() + { + InitializeComponent(); + } + } +} diff --git a/TeraFinder.Launcher/SplashScreen.resx b/TeraFinder.Launcher/SplashScreen.resx new file mode 100644 index 00000000..af32865e --- /dev/null +++ b/TeraFinder.Launcher/SplashScreen.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TeraFinder.Launcher/TeraFinderForm.Designer.cs b/TeraFinder.Launcher/TeraFinderForm.Designer.cs index 907522e2..9d4f463a 100644 --- a/TeraFinder.Launcher/TeraFinderForm.Designer.cs +++ b/TeraFinder.Launcher/TeraFinderForm.Designer.cs @@ -152,7 +152,7 @@ private void InitializeComponent() btnStartFinder.TabIndex = 6; btnStartFinder.Text = "Seed Checker"; btnStartFinder.UseVisualStyleBackColor = true; - btnStartFinder.Click += btnStartFinder_Click; + btnStartFinder.Click += btnStartSeedChecker_Click; // // grpSavTools // @@ -289,6 +289,7 @@ private void InitializeComponent() MinimizeBox = false; Name = "TeraFinderForm"; RightToLeft = RightToLeft.No; + StartPosition = FormStartPosition.CenterScreen; Text = "Tera Finder "; EnabledChanged += FormEnabledChanged; DragDrop += FileDragDrop; diff --git a/TeraFinder.Launcher/TeraFinderForm.cs b/TeraFinder.Launcher/TeraFinderForm.cs index 5b6a644b..3d5433e8 100644 --- a/TeraFinder.Launcher/TeraFinderForm.cs +++ b/TeraFinder.Launcher/TeraFinderForm.cs @@ -202,9 +202,9 @@ private void btnStartCalculator_Click(object sender, EventArgs e) Plugin.LaunchCalculator(); } - private void btnStartFinder_Click(object sender, EventArgs e) + private void btnStartSeedChecker_Click(object sender, EventArgs e) { - Plugin.LaunchFinder(); + Plugin.LaunchSeedChecker(); } private void btnStartRewardCalc_Click(object sender, EventArgs e) diff --git a/TeraFinder.Plugins/Forms/CalculatorForm.Designer.cs b/TeraFinder.Plugins/Forms/CalculatorForm.Designer.cs index 2781ac3e..99d0273a 100644 --- a/TeraFinder.Plugins/Forms/CalculatorForm.Designer.cs +++ b/TeraFinder.Plugins/Forms/CalculatorForm.Designer.cs @@ -110,6 +110,7 @@ private void InitializeComponent() btnToPkmEditor = new ToolStripMenuItem(); btnSendToEditor = new ToolStripMenuItem(); btnCopySeed = new ToolStripMenuItem(); + lblTime = new Label(); grpRaidDetails.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)numFrames).BeginInit(); grpFilters.SuspendLayout(); @@ -266,16 +267,17 @@ private void InitializeComponent() // cmbProgress.FormattingEnabled = true; cmbProgress.Items.AddRange(new object[] { "Beginning", "UnlockedTeraRaids", "Unlocked3Stars", "Unlocked4Stars", "Unlocked5Stars", "Unlocked6Stars" }); - cmbProgress.Location = new Point(101, 79); + cmbProgress.Location = new Point(116, 80); cmbProgress.Margin = new Padding(3, 4, 3, 4); cmbProgress.Name = "cmbProgress"; - cmbProgress.Size = new Size(174, 28); + cmbProgress.Size = new Size(196, 28); cmbProgress.TabIndex = 7; + cmbProgress.SelectedIndexChanged += cmbProgress_IndexChanged; // // lblProgress // lblProgress.AutoSize = true; - lblProgress.Location = new Point(21, 84); + lblProgress.Location = new Point(36, 85); lblProgress.Name = "lblProgress"; lblProgress.Size = new Size(68, 20); lblProgress.TabIndex = 6; @@ -331,7 +333,7 @@ private void InitializeComponent() grpFilters.Controls.Add(nSpaMax); grpFilters.Controls.Add(nSpdMax); grpFilters.Controls.Add(nSpeMax); - grpFilters.Location = new Point(666, 12); + grpFilters.Location = new Point(713, 12); grpFilters.Margin = new Padding(3, 4, 3, 4); grpFilters.Name = "grpFilters"; grpFilters.Padding = new Padding(3, 4, 3, 4); @@ -440,7 +442,7 @@ private void InitializeComponent() // cmbStars // cmbStars.FormattingEnabled = true; - cmbStars.Items.AddRange(new object[] { "Any", "1S ☆", "2S ☆☆", "3S ☆☆☆", "4S ☆☆☆☆", "5S ☆☆☆☆☆", "6S ☆☆☆☆☆☆", "7S ☆☆☆☆☆☆☆" }); + cmbStars.Items.AddRange(new object[] { "1S ☆", "2S ☆☆", "3S ☆☆☆", "4S ☆☆☆☆", "5S ☆☆☆☆☆", "6S ☆☆☆☆☆☆", "7S ☆☆☆☆☆☆☆" }); cmbStars.Location = new Point(341, 35); cmbStars.Margin = new Padding(3, 4, 3, 4); cmbStars.Name = "cmbStars"; @@ -799,13 +801,13 @@ private void InitializeComponent() dataGrid.ReadOnly = true; dataGrid.RowHeadersVisible = false; dataGrid.RowHeadersWidth = 51; - dataGrid.RowTemplate.Height = 29; - dataGrid.Size = new Size(1466, 541); + dataGrid.Size = new Size(1513, 541); dataGrid.TabIndex = 34; dataGrid.MouseUp += dataGrid_MouseUp; // // grpGameInfo // + grpGameInfo.Controls.Add(lblTime); grpGameInfo.Controls.Add(lblFound); grpGameInfo.Controls.Add(txtSID); grpGameInfo.Controls.Add(lblSID); @@ -819,24 +821,24 @@ private void InitializeComponent() grpGameInfo.Margin = new Padding(3, 4, 3, 4); grpGameInfo.Name = "grpGameInfo"; grpGameInfo.Padding = new Padding(3, 4, 3, 4); - grpGameInfo.Size = new Size(307, 245); + grpGameInfo.Size = new Size(354, 245); grpGameInfo.TabIndex = 2; grpGameInfo.TabStop = false; grpGameInfo.Text = "Game Info"; // // txtSID // - txtSID.Location = new Point(101, 153); + txtSID.Location = new Point(116, 154); txtSID.Margin = new Padding(3, 4, 3, 4); txtSID.Name = "txtSID"; - txtSID.Size = new Size(174, 27); + txtSID.Size = new Size(196, 27); txtSID.TabIndex = 9; txtSID.KeyPress += txtID_KeyPress; // // lblSID // lblSID.AutoSize = true; - lblSID.Location = new Point(21, 156); + lblSID.Location = new Point(36, 157); lblSID.Name = "lblSID"; lblSID.Size = new Size(35, 20); lblSID.TabIndex = 10; @@ -844,17 +846,17 @@ private void InitializeComponent() // // txtTID // - txtTID.Location = new Point(101, 116); + txtTID.Location = new Point(116, 117); txtTID.Margin = new Padding(3, 4, 3, 4); txtTID.Name = "txtTID"; - txtTID.Size = new Size(174, 27); + txtTID.Size = new Size(196, 27); txtTID.TabIndex = 8; txtTID.KeyPress += txtID_KeyPress; // // lblTID // lblTID.AutoSize = true; - lblTID.Location = new Point(21, 119); + lblTID.Location = new Point(36, 120); lblTID.Name = "lblTID"; lblTID.Size = new Size(35, 20); lblTID.TabIndex = 8; @@ -863,7 +865,7 @@ private void InitializeComponent() // lblGame // lblGame.AutoSize = true; - lblGame.Location = new Point(21, 45); + lblGame.Location = new Point(36, 46); lblGame.Name = "lblGame"; lblGame.Size = new Size(51, 20); lblGame.TabIndex = 1; @@ -873,10 +875,10 @@ private void InitializeComponent() // cmbGame.FormattingEnabled = true; cmbGame.Items.AddRange(new object[] { "Scarlet", "Violet" }); - cmbGame.Location = new Point(101, 40); + cmbGame.Location = new Point(116, 41); cmbGame.Margin = new Padding(3, 4, 3, 4); cmbGame.Name = "cmbGame"; - cmbGame.Size = new Size(174, 28); + cmbGame.Size = new Size(196, 28); cmbGame.TabIndex = 6; // // toolTip @@ -893,7 +895,7 @@ private void InitializeComponent() contextMenuStrip.ImageScalingSize = new Size(20, 20); contextMenuStrip.Items.AddRange(new ToolStripItem[] { btnViewRewards, btnSaveAll, btnSave, btnSavePk9, btnToPkmEditor, btnSendToEditor, btnCopySeed }); contextMenuStrip.Name = "contextMenuStrip"; - contextMenuStrip.Size = new Size(313, 200); + contextMenuStrip.Size = new Size(313, 172); // // btnViewRewards // @@ -944,11 +946,21 @@ private void InitializeComponent() btnCopySeed.Text = "Copy Seed"; btnCopySeed.Click += btnCopySeed_Click; // + // lblTime + // + lblTime.AutoSize = true; + lblTime.Location = new Point(207, 213); + lblTime.Name = "lblTime"; + lblTime.Size = new Size(20, 20); + lblTime.TabIndex = 35; + lblTime.Text = "T:"; + lblTime.Visible = false; + // // CalculatorForm // AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1483, 811); + ClientSize = new Size(1530, 811); Controls.Add(grpGameInfo); Controls.Add(dataGrid); Controls.Add(grpFilters); @@ -1066,4 +1078,5 @@ private void InitializeComponent() private Label lblMap; private ComboBox cmbMap; private ToolStripMenuItem btnCopySeed; + private Label lblTime; } \ No newline at end of file diff --git a/TeraFinder.Plugins/Forms/CalculatorForm.cs b/TeraFinder.Plugins/Forms/CalculatorForm.cs index 1348cba2..1c6c9b76 100644 --- a/TeraFinder.Plugins/Forms/CalculatorForm.cs +++ b/TeraFinder.Plugins/Forms/CalculatorForm.cs @@ -1,4 +1,5 @@ using PKHeX.Core; +using System.Collections.Concurrent; using TeraFinder.Core; namespace TeraFinder.Plugins; @@ -6,10 +7,12 @@ namespace TeraFinder.Plugins; public partial class CalculatorForm : Form { public EditorForm Editor = null!; - private readonly List CalculatedList = []; - private TeraFilter? Filter = null; + private TeraFilter? Filter = null!; private CancellationTokenSource Token = new(); + private readonly ConcurrentBag CalculatedList = []; + private readonly ConcurrentList GridEntries = []; + private Dictionary Strings = null!; public string[] NameList = null!; @@ -22,9 +25,6 @@ public partial class CalculatorForm : Form public string[] GenderListUnicode = null!; public string[] ShinyList = null!; - public int CurrentViewedIndex = 0; - public bool NotLinkedSearch = true; - public CalculatorForm(EditorForm editor) { InitializeComponent(); @@ -49,7 +49,7 @@ public CalculatorForm(EditorForm editor) GenderListUnicode = [.. GameInfo.GenderSymbolUnicode]; ShinyList = [Strings["TeraShiny.Any"], Strings["TeraShiny.No"], Strings["TeraShiny.Yes"], Strings["TeraShiny.Star"], Strings["TeraShiny.Square"]]; - var progress = (int)(Editor.Progress == GameProgress.None ? 0 : Editor.Progress); + var progress = (int)Editor.Progress; cmbProgress.SelectedIndex = progress; cmbGame.SelectedIndex = Editor.SAV.Version == GameVersion.VL ? 1 : 0; txtTID.Text = $"{Editor.SAV.TrainerTID7}"; @@ -90,6 +90,13 @@ public CalculatorForm(EditorForm editor) nSpeMax.Value = 31; numScaleMax.Value = 255; + if (Editor.CurrEncount is { Stars: > 0 }) + { + var index = cmbStars.Items.Cast().ToList().FindIndex(stars => byte.TryParse($"{stars[0]}", out var res) && res == Editor.CurrEncount.Stars); + if (index != -1) + cmbStars.SelectedIndex = index; + } + TranslateCmbProgress(); TranslateCmbShiny(); TranslateCmbGame(); @@ -146,6 +153,8 @@ private void GenerateDictionary() { "Plugin.MapPaldea", "Paldea" }, { "Plugin.MapKitakami", "Kitakami" }, { "Plugin.MapBlueberry", "Blueberry" }, + { "CalculatorForm.lblTime", "T:" }, + { "WarningNoEncounter", "" } }; } @@ -197,30 +206,80 @@ private void TranslateCmbGame() private bool IsBlankSAV() { - if (Editor.Progress is GameProgress.Beginning or GameProgress.None) + if (Editor.Progress is GameProgress.Beginning) return true; return false; } + private EncounterRaidTF9[] GetCurrentEncounters() => (RaidContent)cmbContent.SelectedIndex switch + { + RaidContent.Standard => (TeraRaidMapParent)cmbMap.SelectedIndex switch + { + TeraRaidMapParent.Kitakami => Editor.Kitakami, + TeraRaidMapParent.Blueberry => Editor.Blueberry, + _ => Editor.Paldea, + }, + RaidContent.Black => (TeraRaidMapParent)cmbMap.SelectedIndex switch + { + TeraRaidMapParent.Kitakami => Editor.KitakamiBlack, + TeraRaidMapParent.Blueberry => Editor.BlueberryBlack, + _ => Editor.PaldeaBlack, + }, + RaidContent.Event => Editor.Dist, + RaidContent.Event_Mighty => Editor.Mighty, + _ => throw new NotImplementedException(nameof(cmbContent.SelectedIndex)), + }; + private void cmbMap_IndexChanged(object sender, EventArgs e) { - var species = TeraUtil.GetAvailableSpecies(Editor.SAV, NameList, FormList, TypeList, Strings, GetStars(), (RaidContent)cmbContent.SelectedIndex, (TeraRaidMapParent)cmbMap.SelectedIndex); + EncounterRaidTF9[] encs = GetCurrentEncounters(); + var species = EncounterRaidTF9.GetAvailableSpecies(encs, GetStars(), NameList, FormList, TypeList, Strings); cmbSpecies.Items.Clear(); cmbSpecies.Items.Add(Strings["Any"]); cmbSpecies.Items.AddRange([..species]); cmbSpecies.SelectedIndex = 0; } - private void cmbContent_IndexChanged(object sender, EventArgs e) + private void cmbContent_IndexChanged(object sender, EventArgs e) => UpdateCmbStars(sender, e); + private void cmbProgress_IndexChanged(object sender, EventArgs e) => UpdateCmbStars(sender, e); + + private void UpdateCmbStars(object sender, EventArgs e) { + if (cmbContent.SelectedIndex == -1 || cmbProgress.SelectedIndex == -1 || cmbGame.SelectedIndex == -1) + return; + var stars = TranslatedStars(); - if (cmbContent.SelectedIndex == 0) - stars = [stars[0], stars[1], stars[2], stars[3], stars[4], stars[5]]; - if (cmbContent.SelectedIndex == 1) + if (cmbContent.SelectedIndex == 0 && cmbProgress.SelectedIndex == 1) + stars = [stars[1], stars[2]]; + else if (cmbContent.SelectedIndex == 0 && cmbProgress.SelectedIndex == 2) + stars = [stars[1], stars[2], stars[3]]; + else if (cmbContent.SelectedIndex == 0 && cmbProgress.SelectedIndex == 3) + stars = [stars[1], stars[2], stars[3], stars[4]]; + else if (cmbContent.SelectedIndex == 0 && cmbProgress.SelectedIndex is 4 or 5) + stars = [stars[3], stars[4], stars[5]]; + + else if (cmbContent.SelectedIndex == 1) stars = [stars[6]]; - if (cmbContent.SelectedIndex == 2) - stars = [stars[0], stars[1], stars[2], stars[3], stars[4], stars[5]]; - if (cmbContent.SelectedIndex == 3) + + else if (cmbContent.SelectedIndex == 2) + { + var encounters = (EncounterEventTF9[])GetCurrentEncounters(); + var eventProgress = EventUtil.GetEventStageFromProgress((GameProgress)cmbProgress.SelectedIndex); + var version = cmbGame.SelectedIndex == 1 ? GameVersion.SL : GameVersion.VL; + + var possibleStars = EncounterEventTF9.GetPossibleEventStars(encounters, eventProgress, version); + var starsList = new List(); + + foreach (var s in possibleStars.OrderBy(star => star)) + starsList.Add(stars[s]); + + if (starsList.Count > 0) + stars = [.. starsList]; + else + stars = [stars[0]]; + } + + else if (cmbContent.SelectedIndex == 3) stars = [stars[7]]; cmbStars.Items.Clear(); @@ -232,11 +291,9 @@ private void cmbContent_IndexChanged(object sender, EventArgs e) private void cmbStars_IndexChanged(object sender, EventArgs e) { - var sav = Editor.SAV.Clone(); - sav.TrainerTID7 = Convert.ToUInt32(txtTID.Text, 10); - sav.TrainerSID7 = Convert.ToUInt32(txtSID.Text, 10); - sav.Version = (GameVersion)(cmbGame.SelectedIndex == 0 ? (int)GameVersion.SL : (int)GameVersion.SV); - var species = TeraUtil.GetAvailableSpecies((SAV9SV)sav, NameList, FormList, TypeList, Strings, GetStars(), (RaidContent)cmbContent.SelectedIndex, (TeraRaidMapParent)cmbMap.SelectedIndex); + EncounterRaidTF9[] encs = GetCurrentEncounters(); + var species = EncounterRaidTF9.GetAvailableSpecies(encs, GetStars(), NameList, FormList, TypeList, Strings); + cmbSpecies.Items.Clear(); cmbSpecies.Items.Add(Strings["Any"]); cmbSpecies.Items.AddRange([..species]); @@ -247,8 +304,8 @@ private void cmbSpecies_IndexChanged(object sender, EventArgs e) { if (cmbSpecies.SelectedIndex > 0) { - var entity = GetSpeciesAndForm(); - var entry = PersonalTable.SV.GetFormEntry(entity[0], (byte)entity[1]); + var entity = GetSpeciesFormIndex(); + var entry = PersonalTable.SV.GetFormEntry(entity.species, entity.form); cmbAbility.Items.Clear(); cmbAbility.Items.Add(Strings["Any"]); cmbAbility.Items.Add($"{AbilityList[entry.Ability1]} (1)"); @@ -282,7 +339,7 @@ private void txtID_KeyPress(object sender, KeyPressEventArgs e) private void btnReset_Click(object sender, EventArgs e) { - cmbStars.SelectedIndex = 0; + //cmbStars.SelectedIndex = 0; cmbSpecies.SelectedIndex = 0; cmbTeraType.SelectedIndex = 0; cmbAbility.SelectedIndex = 0; @@ -306,41 +363,45 @@ private void btnReset_Click(object sender, EventArgs e) numScaleMax.Value = 255; } - private int GetStars() + private byte GetStars() { if (cmbStars.Text.Equals(Strings["Any"])) return 0; else - return (int)char.GetNumericValue(cmbStars.Text[0]); + return (byte)char.GetNumericValue(cmbStars.Text[0]); } - private ushort[] GetSpeciesAndForm() => GetSpeciesAndForm(cmbSpecies.Text); + private (ushort species, byte form, byte index) GetSpeciesFormIndex() => GetSpeciesFormIndex(cmbSpecies.Text); - private ushort[] GetSpeciesAndForm(string str) + private (ushort species, byte form, byte index) GetSpeciesFormIndex(string str) { - var res = new ushort[2]; - + (ushort species, byte form, byte index) result = (0, 0, 0); str = str.Replace($" ({Strings["GameVersionSL"]})", string.Empty).Replace($" ({Strings["GameVersionVL"]})", string.Empty); if (!str.Equals(Strings["Any"])) { var formLocation = str.IndexOf('-'); var isForm = Array.IndexOf(NameList, str) == -1 && formLocation > 0; + if (byte.TryParse(str[^2].ToString(), out var index) && str[^1] == ')') + { + result.index = index; + str = str[..^4]; + } if (!isForm) { var species = Editor.Language.ToLower().Equals("en") ? str : GameInfo.GetStrings("en").specieslist[Array.IndexOf(NameList, str)]; - res[0] = (ushort)Enum.Parse(typeof(Species), species.Replace(" ", string.Empty).Replace("-", string.Empty)); + result.species = (ushort)Enum.Parse(typeof(Species), species.Replace(" ", string.Empty).Replace("-", string.Empty)); } else { var species = Editor.Language.ToLower().Equals("en") ? str[..formLocation] : GameInfo.GetStrings("en").specieslist[Array.IndexOf(NameList, str[..formLocation])]; - res[0] = (ushort)Enum.Parse(typeof(Species), species.Replace(" ", string.Empty).Replace("-", string.Empty)); - res[1] = ShowdownParsing.GetFormFromString(str.AsSpan()[(formLocation + 1)..], GameInfo.GetStrings(Editor.Language), res[0], EntityContext.Gen9); + result.species = (ushort)Enum.Parse(typeof(Species), species.Replace(" ", string.Empty).Replace("-", string.Empty)); + result.form = ShowdownParsing.GetFormFromString(str.AsSpan()[(formLocation + 1)..], GameInfo.GetStrings(Editor.Language), result.species, EntityContext.Gen9); } } - return res; + return result; } private Gender GetGender() @@ -353,32 +414,40 @@ private Gender GetGender() }; } - private void btnApply_Click(object sender, EventArgs e) + private async void btnApply_Click(object sender, EventArgs e) { lblFound.Visible = false; CreateFilter(); - if (dataGrid.Rows.Count > 0) + if (!CalculatedList.IsEmpty) { - DialogResult d = MessageBox.Show(Strings["FiltersPopup"], Strings["FiltersApply"], MessageBoxButtons.YesNo); - if (d == DialogResult.Yes) + DialogResult dialogue = MessageBox.Show(Strings["FiltersPopup"], Strings["FiltersApply"], MessageBoxButtons.YesNo); + if (dialogue is DialogResult.Yes) { - var list = new List(); - foreach (var c in CalculatedList) - if (Filter is null || Filter.IsFilterMatch(c)) - list.Add(new GridEntry(c, NameList, AbilityList, NatureList, MoveList, TypeList, FormList, GenderListAscii, GenderListUnicode, ShinyList)); - dataGrid.DataSource = list; + dataGrid.DataSource = null; + GridEntries.Clear(); + await Task.Run(() => + { + Parallel.ForEach(CalculatedList, el => + { + if (Filter is null || Filter.IsFilterMatch(el)) + GridEntries.Add(new GridEntry(el, NameList, AbilityList, NatureList, MoveList, TypeList, FormList, GenderListAscii, GenderListUnicode, ShinyList)); + }); + }); + GridEntries.FinalizeElements(); + dataGrid.DataSource = GridEntries; } } + UpdateFoundLabel(); } private void CreateFilter() { var stars = GetStars(); - var speciesForm = GetSpeciesAndForm(); + var entity = GetSpeciesFormIndex(); var teraType = (sbyte)(cmbTeraType.SelectedIndex - 1); var gender = GetGender(); - var encounterFilter = speciesForm[0] > 0 || stars > 0; + var encounterFilter = entity.species > 0 || stars > 0; var ivFilter = nHpMin.Value > 0 || nAtkMin.Value > 0 || nDefMin.Value > 0 || nSpaMin.Value > 0 || nSpdMin.Value > 0 || nSpeMin.Value > 0 || numScaleMin.Value > 0 || nHpMax.Value < 31 || nAtkMax.Value < 31 || nDefMax.Value < 31 || nSpaMax.Value < 31 || nSpdMax.Value < 31 || nSpeMax.Value < 31; var statFilter = teraType != -1 || cmbAbility.SelectedIndex != 0 || cmbNature.SelectedIndex != 25 || gender is not Gender.Random; @@ -401,27 +470,25 @@ private void CreateFilter() MinScale = (int)numScaleMin.Value, MaxScale = (int)numScaleMax.Value, Stars = stars, - Species = speciesForm[0], - Form = speciesForm[1], + Species = entity.species, + Form = entity.form, TeraType = teraType, - AbilityNumber = cmbAbility.SelectedIndex, - Nature = (byte)cmbNature.SelectedIndex, + AbilityNumber = cmbAbility.SelectedIndex == 3 ? 4 : cmbAbility.SelectedIndex, + Nature = (Nature)cmbNature.SelectedIndex, Gender = gender, Shiny = (TeraShiny)cmbShiny.SelectedIndex, AltEC = cmbEC.SelectedIndex == 1, - IsFormFilter = speciesForm[1] > 0, + IsFormFilter = entity.form > 0, }; - var isblack = (RaidContent)cmbContent.SelectedIndex is RaidContent.Black or RaidContent.Event_Mighty; - - if (Filter is null && filter.IsFilterNull(isblack)) + if (Filter is null && filter.IsFilterNull()) return; if (Filter is not null && Filter.CompareFilter(filter)) return; - if (filter.IsFilterNull(isblack)) + if (filter.IsFilterNull()) Filter = null; else Filter = filter; @@ -443,6 +510,7 @@ private void DisableControls() txtSeed.Enabled = false; numFrames.Enabled = false; cmbMap.Enabled = false; + SetTimeText(false); } private void EnableControls(bool enableProfile = false) @@ -456,37 +524,41 @@ private void EnableControls(bool enableProfile = false) cmbMap.Enabled = true; } - private void UpdateLabel() + private void UpdateFoundLabel() { - var isblack = (RaidContent)cmbContent.SelectedIndex is RaidContent.Black or RaidContent.Event_Mighty; - if (Filter is not null && !Filter.IsFilterNull(isblack)) + if (Filter is not null && !Filter.IsFilterNull()) { if (showresults.Checked) try { - lblFound.Text = $"{Strings["Found"]} {CalculatedList.Count}"; + lblFound.Text = $"{Strings["Found"]}: {GridEntries.Count}"; } catch (Exception) { - lblFound.Text = $"{Strings["Found"]} {CalculatedList.Count}"; + lblFound.Text = $"{Strings["Found"]}: {GridEntries.LongCount()}"; } else - lblFound.Text = $"{Strings["Found"]} {(CalculatedList.Count > 0 ? Strings["True"] : Strings["False"])}"; + lblFound.Text = $"{Strings["Found"]}: {(!GridEntries.IsEmpty ? Strings["True"] : Strings["False"])}"; lblFound.Visible = true; } else lblFound.Visible = false; } + private void SetTimeText(bool visible, string time = "") + { + lblTime.Text = $"{Strings["CalculatorForm.lblTime"]} {time}"; + lblTime.Visible = visible; + } + public async void btnSearch_Click(object sender, EventArgs e) { - ushort species; - byte form; + (ushort species, byte form, byte index) entity; if (btnSearch.Text.Equals(Strings["ActionSearch"])) { Token = new(); - if (cmbProgress.SelectedIndex is (int)GameProgress.Beginning or (int)GameProgress.None) + if (cmbProgress.SelectedIndex is (int)GameProgress.Beginning) { cmbProgress.Focus(); return; @@ -509,9 +581,7 @@ public async void btnSearch_Click(object sender, EventArgs e) } try { - var f = GetSpeciesAndForm(); - species = f[0]; - form = (byte)f[1]; + entity = GetSpeciesFormIndex(); } catch (Exception) { @@ -519,49 +589,58 @@ public async void btnSearch_Click(object sender, EventArgs e) return; } - if (CalculatedList.Count > 0) + CreateFilter(); + if (Filter is null || !Filter.EncounterFilter || Filter.Stars == 0 || GetCurrentEncounters().Length == 0) + { + MessageBox.Show(Strings["WarningNoEncounter"]); + cmbStars.Focus(); + return; + } + + if (!CalculatedList.IsEmpty) { + dataGrid.DataSource = null; CalculatedList.Clear(); - dataGrid.DataSource = new List(); + GridEntries.Clear(); } btnSearch.Text = Strings["ActionStop"]; DisableControls(); - ActiveForm!.Update(); + //ActiveForm.Update(); - CreateFilter(); var sav = (SAV9SV)Editor.SAV.Clone(); sav.TrainerTID7 = Convert.ToUInt32(txtTID.Text, 10); sav.TrainerSID7 = Convert.ToUInt32(txtSID.Text, 10); - sav.Version = (GameVersion)(cmbGame.SelectedIndex == 0 ? (int)GameVersion.SL : (int)GameVersion.SV); - var progress = (RaidContent)cmbContent.SelectedIndex is RaidContent.Black ? GameProgress.None : (GameProgress)cmbProgress.SelectedIndex; + sav.Version = cmbGame.SelectedIndex == 0 ? GameVersion.SL : GameVersion.SV; + var progress = (GameProgress)cmbProgress.SelectedIndex; var content = (RaidContent)cmbContent.SelectedIndex; - var index = (byte)CurrentViewedIndex; - if (content >= RaidContent.Event && cmbSpecies.SelectedIndex != 0) + try { - foreach (var enc in content is RaidContent.Event ? Editor.Dist! : Editor.Mighty!) + var stopwatch = new System.Diagnostics.Stopwatch(); + stopwatch.Start(); + await StartSearch(sav, progress, content, entity.index, (TeraRaidMapParent)cmbMap.SelectedIndex, Token); +#if DEBUG + if (!GridEntries.IsFinalized) + MessageBox.Show("Something went wrong: Result list isn't finalized."); +#endif + while (dataGrid.RowCount < GridEntries.Count) { - if (enc.Species != species || enc.Form != form) - continue; - - index = enc.Index; - break; + dataGrid.DataSource = null; + dataGrid.DataSource = GridEntries; } - } - try - { - var griddata = await StartSearch(sav, progress, content, index, (TeraRaidMapParent)cmbMap.SelectedIndex, Token); - dataGrid.DataSource = griddata; + stopwatch.Stop(); + SetTimeText(true, $"{stopwatch.Elapsed}"); + btnSearch.Text = Strings["ActionSearch"]; EnableControls(IsBlankSAV()); - UpdateLabel(); + UpdateFoundLabel(); } catch (OperationCanceledException) { btnSearch.Text = Strings["ActionSearch"]; EnableControls(IsBlankSAV()); - UpdateLabel(); + UpdateFoundLabel(); } } else @@ -569,120 +648,59 @@ public async void btnSearch_Click(object sender, EventArgs e) Token.Cancel(); btnSearch.Text = Strings["ActionSearch"]; EnableControls(IsBlankSAV()); - UpdateLabel(); + UpdateFoundLabel(); return; } } - private async Task> StartSearch(SAV9SV sav, GameProgress progress, RaidContent content, byte index, TeraRaidMapParent map, CancellationTokenSource token) + private async Task StartSearch(SAV9SV sav, GameProgress progress, RaidContent content, byte index, TeraRaidMapParent map, CancellationTokenSource token) { - var gridList = new List(); - var seed = txtSeed.Text.Equals("") ? 0 : Convert.ToUInt32(txtSeed.Text, 16); + var encounters = GetCurrentEncounters(); - var indexSpecific = index != 0; - var eventSpecific = content is RaidContent.Event or RaidContent.Event_Mighty; - - var possibleGroups = new HashSet(); - if (!indexSpecific && eventSpecific) - foreach (var enc in content is RaidContent.Event ? Editor.Dist! : Editor.Mighty!) + var possibleGroups = new HashSet(); + if (index == 0 && content is RaidContent.Event or RaidContent.Event_Mighty) + foreach (var enc in encounters.Where(Filter.IsEncounterMatch)) possibleGroups.Add(enc.Index); else possibleGroups.Add(index); - foreach (var group in possibleGroups) + await Task.Run(() => { - if (token.IsCancellationRequested) - break; - - await Task.Run(async () => + foreach (var group in possibleGroups) { - var nthreads = (uint)numFrames.Value < 1000 ? 1 : Environment.ProcessorCount; - var gridresults = new List[nthreads]; - var calcresults = new List[nthreads]; - var resetEvent = new ManualResetEvent(false); - var toProcess = nthreads; - var maxcalcs = (uint)numFrames.Value; - var calcsperthread = maxcalcs / (uint)nthreads; - - for (uint j = 0; j < nthreads; j++) + EncounterRaidTF9[] effective_encounters = content switch { - var n = j; - var tseed = seed; + RaidContent.Standard or RaidContent.Black => ((EncounterTeraTF9[])encounters).Where(e => e.Index == group && Filter.IsEncounterMatch(e)).ToArray(), + RaidContent.Event or RaidContent.Event_Mighty => ((EncounterEventTF9[])encounters).Where(e => e.Index == group && Filter.IsEncounterMatch(e)).ToArray(), + _ => throw new NotImplementedException(nameof(content)), + }; - new Thread(delegate () - { - var tmpgridlist = new List(); - var tmpcalclist = new List(); - - var initialFrame = calcsperthread * n; - var maxframe = n < nthreads - 1 ? calcsperthread * (n + 1) : maxcalcs; - tseed += initialFrame; + var romMaxRate = sav.Version is GameVersion.VL ? EncounterTera9.GetRateTotalVL(Filter.Stars, map) : EncounterTera9.GetRateTotalSL(Filter.Stars, map); + var eventProgress = EventUtil.GetEventStageFromProgress(progress); - for (ulong i = initialFrame; i <= maxframe && !token.IsCancellationRequested; i++) - { - var res = CalcResult(tseed, progress, sav, content, i, group, map); - if (Filter is not null && res is not null && Filter.IsFilterMatch(res)) - { - tmpgridlist.Add(new GridEntry(res, NameList, AbilityList, NatureList, MoveList, TypeList, FormList, GenderListAscii, GenderListUnicode, ShinyList)); - tmpcalclist.Add(res); - if (!showresults.Checked) - { - if (NotLinkedSearch || (!eventSpecific || (eventSpecific && indexSpecific))) - { - token.Cancel(); - break; - } - } - } - else if (Filter is null && res is not null) - { - tmpgridlist.Add(new GridEntry(res, NameList, AbilityList, NatureList, MoveList, TypeList, FormList, GenderListAscii, GenderListUnicode, ShinyList)); - tmpcalclist.Add(res); - } - - if (token.IsCancellationRequested) - break; - - tseed++; - } - - gridresults[n] = tmpgridlist; - calcresults[n] = tmpcalclist; - - if (Interlocked.Decrement(ref toProcess) == 0 || token.IsCancellationRequested) - resetEvent.Set(); - }).Start(); - } - - resetEvent.WaitOne(); - - await Task.Delay(0_300).ConfigureAwait(false); - - for (var i = 0; i < nthreads; i++) + if (effective_encounters.Length > 0) { - if (gridresults[i] is not null && gridresults[i].Count > 0) - gridList.AddRange(gridresults[i]); - if (calcresults[i] is not null && calcresults[i].Count > 0) - CalculatedList.AddRange(calcresults[i]); - } - }, token.Token); - } + var initialValue = txtSeed.Text.Equals("") ? 0 : Convert.ToUInt32(txtSeed.Text, 16); + var maxValue = (long)initialValue + (uint)numFrames.Value; - return gridList; - } - - private TeraDetails? CalcResult(ulong Seed, GameProgress progress, SAV9SV sav, RaidContent content, ulong calc, int groupid, TeraRaidMapParent map) - { - var seed = (uint)(Seed & 0xFFFFFFFF); - var encounter = content is RaidContent.Standard or RaidContent.Black ? TeraUtil.GetTeraEncounter(seed, sav.Version, - TeraUtil.GetStars(seed, progress), map switch { TeraRaidMapParent.Paldea => Editor.Paldea!, TeraRaidMapParent.Kitakami => Editor.Kitakami!, _ => Editor.Blueberry! }, map) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, sav.Version, progress, Editor.Mighty!, groupid) : - TeraUtil.GetDistEncounter(seed, sav.Version, progress, Editor.Dist!, groupid); + Parallel.For(initialValue, maxValue, (seed, iterator) => + { + if (token.IsCancellationRequested) + iterator.Break(); - if (encounter is null) - return null; + if (EncounterRaidTF9.TryGenerateTeraDetails((uint)seed, effective_encounters, Filter, romMaxRate, sav.Version, progress, eventProgress, content, sav.ID32, group, out _, out var result)) + { + CalculatedList.Add(result.Value); + GridEntries.Add(new GridEntry(result.Value, NameList, AbilityList, NatureList, MoveList, TypeList, FormList, GenderListAscii, GenderListUnicode, ShinyList)); - return TeraUtil.CalcRNG(seed, sav.ID32, content, encounter, groupid, calc); + if (!showresults.Checked) + token.Cancel(); + } + }); + } + } + GridEntries.FinalizeElements(); + }); } private void dataGrid_MouseUp(object sender, MouseEventArgs e) @@ -723,7 +741,7 @@ private string[] TranslatedStars() private void btnToPkmEditor_Click(object sender, EventArgs e) => dataGrid.SendSelectedPk9Editor(this, Editor.Language, (TeraRaidMapParent)cmbMap.SelectedIndex); - private void btnSendToEditor_Click(object sender, EventArgs e) => dataGrid.SendSelectedRaidEditor(this, Editor.Language, (TeraRaidMapParent)cmbMap.SelectedIndex); + private void btnSendToEditor_Click(object sender, EventArgs e) => dataGrid.SendSelectedRaidEditor(this, Editor.Language); private void btnSavePk9_Click(object sender, EventArgs e) => dataGrid.SaveSelectedPk9(this, Editor.Language, (TeraRaidMapParent)cmbMap.SelectedIndex); diff --git a/TeraFinder.Plugins/Forms/CalculatorForm.resx b/TeraFinder.Plugins/Forms/CalculatorForm.resx index 5c0d75ff..5f620d83 100644 --- a/TeraFinder.Plugins/Forms/CalculatorForm.resx +++ b/TeraFinder.Plugins/Forms/CalculatorForm.resx @@ -18,7 +18,7 @@ System.Resources.ResXResourceReader, System.Windows.Forms, ... System.Resources.ResXResourceWriter, System.Windows.Forms, ... this is my long stringthis is a comment - Blue + Blue [base64 mime encoded serialized .NET Framework object] diff --git a/TeraFinder.Plugins/Forms/CheckerForm.cs b/TeraFinder.Plugins/Forms/CheckerForm.cs index 978f744b..fa8c50c5 100644 --- a/TeraFinder.Plugins/Forms/CheckerForm.cs +++ b/TeraFinder.Plugins/Forms/CheckerForm.cs @@ -8,7 +8,25 @@ public partial class CheckerForm : Form private readonly PK9 PKM = null!; private Dictionary Strings = null!; - public CheckerForm(PKM pk, string language) + private readonly EncounterTeraTF9[] Paldea = null!; + private readonly EncounterTeraTF9[] PaldeaBlack = null!; + private readonly EncounterTeraTF9[] Kitakami = null!; + private readonly EncounterTeraTF9[] KitakamiBlack = null!; + private readonly EncounterTeraTF9[] Blueberry = null!; + private readonly EncounterTeraTF9[] BlueberryBlack = null!; + + private readonly Dictionary> Dist = null!; + private readonly Dictionary> Mighty = null!; + + public CheckerForm(PKM pk, string language, + EncounterTeraTF9[] paldea, + EncounterTeraTF9[] paldeablack, + EncounterTeraTF9[] kitakami, + EncounterTeraTF9[] kitakamiblack, + EncounterTeraTF9[] blueberry, + EncounterTeraTF9[] blueberryblack, + Dictionary> dist, + Dictionary> mighty) { InitializeComponent(); GenerateDictionary(); @@ -42,6 +60,15 @@ public CheckerForm(PKM pk, string language) numHeight.Value = PKM.HeightScalar; numWeight.Value = PKM.WeightScalar; numScale.Value = PKM.Scale; + + Paldea = paldea; + PaldeaBlack = paldeablack; + Kitakami = kitakami; + KitakamiBlack = kitakamiblack; + Blueberry = blueberry; + BlueberryBlack = blueberryblack; + Dist = dist; + Mighty = mighty; } private void GenerateDictionary() @@ -85,7 +112,7 @@ private void btnCalc_Click(object sender, EventArgs e) var spa = (int)numSpA.Value; var spd = (int)numSpD.Value; var spe = (int)numSpe.Value; - var nature = cmbNature.SelectedIndex; + var nature = (Nature)cmbNature.SelectedIndex; var tera = cmbTera.SelectedIndex; var height = (byte)numHeight.Value; var weight = (byte)numWeight.Value; @@ -104,7 +131,7 @@ private void btnCalc_Click(object sender, EventArgs e) IV_SPA = spa, IV_SPD = spd, IV_SPE = spe, - Nature = (Nature)nature, + Nature = nature, TeraTypeOriginal = (MoveType)tera, HeightScalar = height, WeightScalar = weight, @@ -113,21 +140,23 @@ private void btnCalc_Click(object sender, EventArgs e) var seed = Tera9RNG.GetOriginalSeed(pk); - //Standard & Black Raids Check + //Standard Raids Check for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) { - var encounters = TeraUtil.GetAllTeraEncounters(map); - for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.None; progress++) + for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.Unlocked6Stars; progress++) { for (var version = GameVersion.SL; version <= GameVersion.VL; version++) { - var encounter = TeraUtil.GetTeraEncounter(seed, version, TeraUtil.GetStars(seed, progress), encounters, map); - if (encounter is not null) + var encounters = map switch { - var rng = TeraUtil.CalcRNG(seed, pk.ID32, progress is not GameProgress.None ? - RaidContent.Standard : RaidContent.Black, encounter, 0); - - if (CompareResult(pk, rng)) + TeraRaidMapParent.Paldea => Paldea, + TeraRaidMapParent.Kitakami => Kitakami, + TeraRaidMapParent.Blueberry => Blueberry, + _ => throw new NotImplementedException(nameof(map)), + }; + if (EncounterRaidTF9.TryGenerateTeraDetails(seed, encounters, version, progress, EventProgress.Stage0, RaidContent.Standard, map, pk.ID32, 0, out var encounter, out var result)) + { + if (CompareResult(pk, result!.Value)) { SetReultText(seed, encounter); return; @@ -137,23 +166,46 @@ private void btnCalc_Click(object sender, EventArgs e) } } - //Events & Events Mighty Raids Check + //Black Raids Check + for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) + { + for (var version = GameVersion.SL; version <= GameVersion.VL; version++) + { + var encounters = map switch + { + TeraRaidMapParent.Paldea => PaldeaBlack, + TeraRaidMapParent.Kitakami => KitakamiBlack, + TeraRaidMapParent.Blueberry => BlueberryBlack, + _ => throw new NotImplementedException(nameof(map)) + }; + if (EncounterRaidTF9.TryGenerateTeraDetails(seed, encounters, version, GameProgress.Unlocked6Stars, EventProgress.Stage0, RaidContent.Black, map, pk.ID32, 0, out var encounter, out var result)) + { + if (CompareResult(pk, result!.Value)) + { + SetReultText(seed, encounter); + return; + } + } + } + } + + //Events Raids Check for (var content = RaidContent.Event; content <= RaidContent.Event_Mighty; content++) { - var dist = TeraUtil.GetAllDistEncounters(content); - for (var progress = GameProgress.UnlockedTeraRaids; progress < GameProgress.None; progress++) + foreach (var group in content is RaidContent.Event ? Dist : Mighty) { - for (var version = GameVersion.SL; version <= GameVersion.VL; version++) { - for (var groupid = 0; groupid < 10; groupid++) + foreach (var index in new HashSet(group.Value.Select(enc => enc.Index))) + { + for (var game = GameVersion.SL; game <= GameVersion.VL; ++game) { - var encounters = TeraUtil.FilterDistEncounters(seed, version, progress, dist, groupid, species); - foreach (var encounter in encounters) { + var possibleStages = new HashSet(Enum.GetValues(typeof(EventProgress)).Cast() + .Where(progress => group.Value.Any(enc => enc.Index == index && enc.CanBeEncounteredFromStage(progress, game)))); - if (encounter is not null) + foreach (var stage in possibleStages) + { + if (EncounterRaidTF9.TryGenerateTeraDetails(seed, group.Value.ToArray(), game, GameProgress.UnlockedTeraRaids, stage, RaidContent.Event, TeraRaidMapParent.Paldea, pk.ID32, index, out var encounter, out var result)) { - var rng = TeraUtil.CalcRNG(seed, pk.ID32, content, encounter, groupid); - - if (CompareResult(pk, rng)) + if (CompareResult(pk, result!.Value)) { SetReultText(seed, encounter); return; @@ -161,9 +213,10 @@ private void btnCalc_Click(object sender, EventArgs e) } } } - } + } } } + SetReultText(seed); } @@ -187,7 +240,7 @@ private static bool CompareResult (PK9 pkm, TeraDetails rng) return false; if (pkm.IV_SPE != rng.SPE) return false; - if ((int)pkm.Nature != rng.Nature) + if (pkm.Nature != rng.Nature) return false; if ((sbyte)pkm.TeraTypeOriginal != rng.TeraType) return false; @@ -202,20 +255,17 @@ private static bool CompareResult (PK9 pkm, TeraDetails rng) return true; } - private void SetReultText (uint seed, EncounterRaid9? enc = null) + private void SetReultText (uint seed, EncounterRaidTF9? encounter = null) { - if (enc is not null) + if (encounter is not null) { - var type = enc.GetEncounterType(); - var isBlack = enc.Stars >= 6; - - if (type == typeof(Core.EncounterTera9) && !isBlack) + if (encounter.ContentType is RaidContent.Standard) txtSeed.Text = $"{seed:X8} ({Strings["RaidContent.Standard"]})"; - else if (type == typeof(Core.EncounterTera9) && isBlack) + else if (encounter.ContentType is RaidContent.Black) txtSeed.Text = $"{seed:X8} ({Strings["RaidContent.Black"]})"; - else if (type == typeof(PKHeX.Core.EncounterDist9)) + else if (encounter.ContentType is RaidContent.Event) txtSeed.Text = $"{seed:X8} ({Strings["RaidContent.Event"]})"; - else if (type == typeof(PKHeX.Core.EncounterMight9)) + else if (encounter.ContentType is RaidContent.Event_Mighty) txtSeed.Text = $"{seed:X8} ({Strings["RaidContent.Event_Mighty"]})"; return; diff --git a/TeraFinder.Plugins/Forms/ConnectionForm.cs b/TeraFinder.Plugins/Forms/ConnectionForm.cs index 05266bb2..132706af 100644 --- a/TeraFinder.Plugins/Forms/ConnectionForm.cs +++ b/TeraFinder.Plugins/Forms/ConnectionForm.cs @@ -1,6 +1,7 @@ using PKHeX.Core; -using TeraFinder.Core; using SysBot.Base; +using TeraFinder.Core; +using TeraFinder.RemoteExecutor; using TeraFinder.Plugins.Properties; using System.Buffers.Binary; @@ -126,21 +127,21 @@ private async void btnConnect_Click(object sender, EventArgs e) UpdateProgress(CurrentProgress++, MaxProgress); var version = await Executor.ReadGame(token).ConfigureAwait(false); UpdateProgress(CurrentProgress++, MaxProgress); - SAV.Version = (GameVersion)(int)version; - var mystatusblock = SAV.Accessor.FindOrDefault(Blocks.KMyStatus.Key); - mystatusblock.ChangeData((byte[]?)await Executor.ReadBlock(Blocks.KMyStatus, token).ConfigureAwait(false)); + SAV.Version = version; + var mystatusblock = SAV.Accessor.FindOrDefault(BlockDefinitions.KMyStatus.Key); + mystatusblock.ChangeData((byte[]?)await Executor.ReadBlock(BlockDefinitions.KMyStatus, token).ConfigureAwait(false)); UpdateProgress(CurrentProgress++, MaxProgress); - var raidpaldeablock = SAV.Accessor.FindOrDefault(Blocks.KTeraRaidPaldea.Key); - raidpaldeablock.ChangeData((byte[]?)await Executor.ReadBlock(Blocks.KTeraRaidPaldea, token).ConfigureAwait(false)); - var raidkitakamiblock = SAV.Accessor.FindOrDefault(Blocks.KTeraRaidDLC.Key); - raidkitakamiblock.ChangeData((byte[]?)await Executor.ReadBlock(Blocks.KTeraRaidDLC, token).ConfigureAwait(false)); + var raidpaldeablock = SAV.Accessor.FindOrDefault(BlockDefinitions.KTeraRaidPaldea.Key); + raidpaldeablock.ChangeData((byte[]?)await Executor.ReadBlock(BlockDefinitions.KTeraRaidPaldea, token).ConfigureAwait(false)); + var raidkitakamiblock = SAV.Accessor.FindOrDefault(BlockDefinitions.KTeraRaidDLC.Key); + raidkitakamiblock.ChangeData((byte[]?)await Executor.ReadBlock(BlockDefinitions.KTeraRaidDLC, token).ConfigureAwait(false)); UpdateProgress(CurrentProgress++, MaxProgress); var progress = await Executor.ReadGameProgress(token).ConfigureAwait(false); UpdateProgress(CurrentProgress++, MaxProgress); ProgressForm.EditProgress(SAV, progress); await DownloadEventData(token).ConfigureAwait(false); - var raidSevenStar = SAV.Accessor.FindOrDefault(Blocks.KSevenStarRaidsCapture.Key); - raidSevenStar.ChangeData((byte[]?)await Executor.ReadBlock(Blocks.KSevenStarRaidsCapture, token).ConfigureAwait(false)); + var raidSevenStar = SAV.Accessor.FindOrDefault(BlockDefinitions.KSevenStarRaidsCapture.Key); + raidSevenStar.ChangeData((byte[]?)await Executor.ReadBlock(BlockDefinitions.KSevenStarRaidsCapture, token).ConfigureAwait(false)); UpdateProgress(CurrentProgress++, MaxProgress); if (chkOutbreaksMain.Checked) await DownloadOutbreaksMainData(token).ConfigureAwait(false); if (chkOutbreaksDLC.Checked) await DownloadOutbreaksDLCData(token).ConfigureAwait(false); @@ -165,8 +166,8 @@ private async void btnConnect_Click(object sender, EventArgs e) private async Task DownloadEventData(CancellationToken token) { - var KBCATEventRaidIdentifier = SAV.Accessor.FindOrDefault(Blocks.KBCATEventRaidIdentifier.Key); - var raidIdentifierBlock = (byte[]?)await Executor.ReadBlock(Blocks.KBCATEventRaidIdentifier, token).ConfigureAwait(false); + var KBCATEventRaidIdentifier = SAV.Accessor.FindOrDefault(BlockDefinitions.KBCATEventRaidIdentifier.Key); + var raidIdentifierBlock = (byte[]?)await Executor.ReadBlock(BlockDefinitions.KBCATEventRaidIdentifier, token).ConfigureAwait(false); var identifier = BinaryPrimitives.ReadUInt32LittleEndian(raidIdentifierBlock); if (KBCATEventRaidIdentifier.Type is not SCTypeCode.None) @@ -179,8 +180,8 @@ private async Task DownloadEventData(CancellationToken token) if (identifier > 0) { - var KBCATFixedRewardItemArray = SAV.Accessor.FindOrDefault(Blocks.KBCATFixedRewardItemArray.Key); - var rewardItemBlock = (byte[]?)await Executor.ReadBlock(Blocks.KBCATFixedRewardItemArray, token).ConfigureAwait(false); + var KBCATFixedRewardItemArray = SAV.Accessor.FindOrDefault(BlockDefinitions.KBCATFixedRewardItemArray.Key); + var rewardItemBlock = (byte[]?)await Executor.ReadBlock(BlockDefinitions.KBCATFixedRewardItemArray, token).ConfigureAwait(false); if (KBCATFixedRewardItemArray.Type is not SCTypeCode.None) KBCATFixedRewardItemArray.ChangeData(rewardItemBlock); @@ -192,8 +193,8 @@ private async Task DownloadEventData(CancellationToken token) if (identifier > 0) { - var KBCATLotteryRewardItemArray = SAV.Accessor.FindOrDefault(Blocks.KBCATLotteryRewardItemArray.Key); - var lotteryItemBlock = (byte[]?)await Executor.ReadBlock(Blocks.KBCATLotteryRewardItemArray, token).ConfigureAwait(false); + var KBCATLotteryRewardItemArray = SAV.Accessor.FindOrDefault(BlockDefinitions.KBCATLotteryRewardItemArray.Key); + var lotteryItemBlock = (byte[]?)await Executor.ReadBlock(BlockDefinitions.KBCATLotteryRewardItemArray, token).ConfigureAwait(false); if (KBCATLotteryRewardItemArray.Type is not SCTypeCode.None) KBCATLotteryRewardItemArray.ChangeData(lotteryItemBlock); @@ -205,8 +206,8 @@ private async Task DownloadEventData(CancellationToken token) if (identifier > 0) { - var KBCATRaidEnemyArray = SAV.Accessor.FindOrDefault(Blocks.KBCATRaidEnemyArray.Key); - var raidEnemyBlock = (byte[]?)await Executor.ReadBlock(Blocks.KBCATRaidEnemyArray, token).ConfigureAwait(false); + var KBCATRaidEnemyArray = SAV.Accessor.FindOrDefault(BlockDefinitions.KBCATRaidEnemyArray.Key); + var raidEnemyBlock = (byte[]?)await Executor.ReadBlock(BlockDefinitions.KBCATRaidEnemyArray, token).ConfigureAwait(false); if (KBCATRaidEnemyArray.Type is not SCTypeCode.None) KBCATRaidEnemyArray.ChangeData(raidEnemyBlock); @@ -218,8 +219,8 @@ private async Task DownloadEventData(CancellationToken token) if (identifier > 0) { - var KBCATRaidPriorityArray = SAV.Accessor.FindOrDefault(Blocks.KBCATRaidPriorityArray.Key); - var raidPriorityBlock = (byte[]?)await Executor.ReadBlock(Blocks.KBCATRaidPriorityArray, token).ConfigureAwait(false); + var KBCATRaidPriorityArray = SAV.Accessor.FindOrDefault(BlockDefinitions.KBCATRaidPriorityArray.Key); + var raidPriorityBlock = (byte[]?)await Executor.ReadBlock(BlockDefinitions.KBCATRaidPriorityArray, token).ConfigureAwait(false); if (KBCATRaidPriorityArray.Type is not SCTypeCode.None) KBCATRaidPriorityArray.ChangeData(raidPriorityBlock); @@ -233,19 +234,19 @@ private async Task DownloadEventData(CancellationToken token) private async Task DownloadOutbreaksMainData(CancellationToken token) { - var KMassOutbreakAmount = SAV.Accessor.FindOrDefault(Blocks.KOutbreakMainNumActive.Key); - var KMassOutbreakAmountData = (byte?)await Executor.ReadBlock(Blocks.KOutbreakMainNumActive, token).ConfigureAwait(false); + var KMassOutbreakAmount = SAV.Accessor.FindOrDefault(BlockDefinitions.KOutbreakMainNumActive.Key); + var KMassOutbreakAmountData = (byte?)await Executor.ReadBlock(BlockDefinitions.KOutbreakMainNumActive, token).ConfigureAwait(false); if (KMassOutbreakAmount.Type is not SCTypeCode.None) KMassOutbreakAmount.ChangeData((new byte[] { (byte)KMassOutbreakAmountData! }).AsSpan()); else - BlockUtil.EditBlock(KMassOutbreakAmount, Blocks.KOutbreakMainNumActive.Type, (new byte[] { (byte)KMassOutbreakAmountData! }).AsSpan()); + BlockUtil.EditBlock(KMassOutbreakAmount, BlockDefinitions.KOutbreakMainNumActive.Type, (new byte[] { (byte)KMassOutbreakAmountData! }).AsSpan()); UpdateProgress(CurrentProgress++, MaxProgress); for (var i = 1; i <= 8; i++) { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}MainCenterPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}MainCenterPos")!.GetValue(new BlockDefinition())!; var KMassOutbreakCenterPos = SAV.Accessor.FindOrDefault(blockInfo.Key); var KMassOutbreakCenterPosData = (byte[]?)await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false); @@ -256,7 +257,7 @@ private async Task DownloadOutbreaksMainData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}MainDummyPos")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}MainDummyPos")!.GetValue(new BlockDefinition())!; var KMassOutbreakDummyPos = SAV.Accessor.FindOrDefault(blockInfo.Key); var KMassOutbreakDummyPosData = (byte[]?)await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false); @@ -267,7 +268,7 @@ private async Task DownloadOutbreaksMainData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}MainSpecies")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}MainSpecies")!.GetValue(new BlockDefinition())!; var KMassOutbreakSpecies = SAV.Accessor.FindOrDefault(blockInfo.Key); var KMassOutbreakSpeciesData = (uint)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; @@ -278,7 +279,7 @@ private async Task DownloadOutbreaksMainData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}MainForm")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}MainForm")!.GetValue(new BlockDefinition())!; var KMassOutbreakForm = SAV.Accessor.FindOrDefault(blockInfo.Key); var KMassOutbreakFormData = (byte)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; @@ -289,7 +290,7 @@ private async Task DownloadOutbreaksMainData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}MainFound")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}MainFound")!.GetValue(new BlockDefinition())!; var KMassOutbreakFound = SAV.Accessor.FindOrDefault(blockInfo.Key); var KMassOutbreakFoundData = (bool)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; @@ -303,7 +304,7 @@ private async Task DownloadOutbreaksMainData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}MainNumKOed")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}MainNumKOed")!.GetValue(new BlockDefinition())!; var KMassOutbreakNumKOed = SAV.Accessor.FindOrDefault(blockInfo.Key); var KMassOutbreakNumKOedData = (int)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; @@ -314,7 +315,7 @@ private async Task DownloadOutbreaksMainData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}MainTotalSpawns")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}MainTotalSpawns")!.GetValue(new BlockDefinition())!; var KMassOutbreakTotalSpawns = SAV.Accessor.FindOrDefault(blockInfo.Key); var KMassOutbreakTotalSpawnsData = (int)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; @@ -329,21 +330,21 @@ private async Task DownloadOutbreaksMainData(CancellationToken token) private async Task DownloadOutbreaksDLCData(CancellationToken token) { - var KMassOutbreakAmount = SAV.Accessor.FindOrDefault(Blocks.KOutbreakDLC1NumActive.Key); + var KMassOutbreakAmount = SAV.Accessor.FindOrDefault(BlockDefinitions.KOutbreakDLC1NumActive.Key); byte? KMassOutbreakAmountData; - try { KMassOutbreakAmountData = (byte?)await Executor.ReadBlock(Blocks.KOutbreakDLC1NumActive, token).ConfigureAwait(false); } + try { KMassOutbreakAmountData = (byte?)await Executor.ReadBlock(BlockDefinitions.KOutbreakDLC1NumActive, token).ConfigureAwait(false); } catch (ArgumentOutOfRangeException) { KMassOutbreakAmountData = 0; } if (KMassOutbreakAmount.Type is not SCTypeCode.None) KMassOutbreakAmount.ChangeData((new byte[] { (byte)KMassOutbreakAmountData! }).AsSpan()); else - BlockUtil.EditBlock(KMassOutbreakAmount, Blocks.KOutbreakDLC1NumActive.Type, (new byte[] { (byte)KMassOutbreakAmountData! }).AsSpan()); + BlockUtil.EditBlock(KMassOutbreakAmount, BlockDefinitions.KOutbreakDLC1NumActive.Type, (new byte[] { (byte)KMassOutbreakAmountData! }).AsSpan()); UpdateProgress(CurrentProgress++, MaxProgress); for (var i = 1; i <= 4; i++) { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC1CenterPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC1CenterPos")!.GetValue(new BlockDefinition())!; var KMassOutbreakCenterPos = SAV.Accessor.FindOrDefault(blockInfo.Key); byte[]? KMassOutbreakCenterPosData; try { KMassOutbreakCenterPosData = (byte[]?)await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false); } @@ -356,7 +357,7 @@ private async Task DownloadOutbreaksDLCData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC1DummyPos")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC1DummyPos")!.GetValue(new BlockDefinition())!; var KMassOutbreakDummyPos = SAV.Accessor.FindOrDefault(blockInfo.Key); byte[]? KMassOutbreakDummyPosData; try { KMassOutbreakDummyPosData = (byte[]?)await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false); } @@ -369,7 +370,7 @@ private async Task DownloadOutbreaksDLCData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC1Species")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC1Species")!.GetValue(new BlockDefinition())!; var KMassOutbreakSpecies = SAV.Accessor.FindOrDefault(blockInfo.Key); uint KMassOutbreakSpeciesData; try { KMassOutbreakSpeciesData = (uint)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } @@ -382,7 +383,7 @@ private async Task DownloadOutbreaksDLCData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC1Form")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC1Form")!.GetValue(new BlockDefinition())!; var KMassOutbreakForm = SAV.Accessor.FindOrDefault(blockInfo.Key); byte KMassOutbreakFormData; try { KMassOutbreakFormData = (byte)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } @@ -395,7 +396,7 @@ private async Task DownloadOutbreaksDLCData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC1Found")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC1Found")!.GetValue(new BlockDefinition())!; var KMassOutbreakFound = SAV.Accessor.FindOrDefault(blockInfo.Key); bool KMassOutbreakFoundData; try { KMassOutbreakFoundData = (bool)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } @@ -411,7 +412,7 @@ private async Task DownloadOutbreaksDLCData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC1NumKOed")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC1NumKOed")!.GetValue(new BlockDefinition())!; var KMassOutbreakNumKOed = SAV.Accessor.FindOrDefault(blockInfo.Key); int KMassOutbreakNumKOedData; try { KMassOutbreakNumKOedData = (int)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } @@ -424,7 +425,7 @@ private async Task DownloadOutbreaksDLCData(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC1TotalSpawns")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC1TotalSpawns")!.GetValue(new BlockDefinition())!; var KMassOutbreakTotalSpawns = SAV.Accessor.FindOrDefault(blockInfo.Key); int KMassOutbreakTotalSpawnsData; try { KMassOutbreakTotalSpawnsData = (int)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } @@ -441,21 +442,21 @@ private async Task DownloadOutbreaksDLCData(CancellationToken token) private async Task DownloadOutbreaksDLC2Data(CancellationToken token) { - var KMassOutbreakAmount = SAV.Accessor.FindOrDefault(Blocks.KOutbreakDLC2NumActive.Key); + var KMassOutbreakAmount = SAV.Accessor.FindOrDefault(BlockDefinitions.KOutbreakDLC2NumActive.Key); byte? KMassOutbreakAmountData; - try { KMassOutbreakAmountData = (byte?)await Executor.ReadBlock(Blocks.KOutbreakDLC2NumActive, token).ConfigureAwait(false); } + try { KMassOutbreakAmountData = (byte?)await Executor.ReadBlock(BlockDefinitions.KOutbreakDLC2NumActive, token).ConfigureAwait(false); } catch (ArgumentOutOfRangeException) { KMassOutbreakAmountData = 0; } if (KMassOutbreakAmount.Type is not SCTypeCode.None) KMassOutbreakAmount.ChangeData((new byte[] { (byte)KMassOutbreakAmountData! }).AsSpan()); else - BlockUtil.EditBlock(KMassOutbreakAmount, Blocks.KOutbreakDLC2NumActive.Type, (new byte[] { (byte)KMassOutbreakAmountData! }).AsSpan()); + BlockUtil.EditBlock(KMassOutbreakAmount, BlockDefinitions.KOutbreakDLC2NumActive.Type, (new byte[] { (byte)KMassOutbreakAmountData! }).AsSpan()); UpdateProgress(CurrentProgress++, MaxProgress); for (var i = 1; i <= 5; i++) { - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC2CenterPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC2CenterPos")!.GetValue(new BlockDefinition())!; var KMassOutbreakCenterPos = SAV.Accessor.FindOrDefault(blockInfo.Key); byte[]? KMassOutbreakCenterPosData; try { KMassOutbreakCenterPosData = (byte[]?)await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false); } @@ -468,7 +469,7 @@ private async Task DownloadOutbreaksDLC2Data(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC2DummyPos")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC2DummyPos")!.GetValue(new BlockDefinition())!; var KMassOutbreakDummyPos = SAV.Accessor.FindOrDefault(blockInfo.Key); byte[]? KMassOutbreakDummyPosData; try { KMassOutbreakDummyPosData = (byte[]?)await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false); } @@ -481,7 +482,7 @@ private async Task DownloadOutbreaksDLC2Data(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC2Species")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC2Species")!.GetValue(new BlockDefinition())!; var KMassOutbreakSpecies = SAV.Accessor.FindOrDefault(blockInfo.Key); uint KMassOutbreakSpeciesData; try { KMassOutbreakSpeciesData = (uint)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } @@ -494,7 +495,7 @@ private async Task DownloadOutbreaksDLC2Data(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC2Form")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC2Form")!.GetValue(new BlockDefinition())!; var KMassOutbreakForm = SAV.Accessor.FindOrDefault(blockInfo.Key); byte KMassOutbreakFormData; try { KMassOutbreakFormData = (byte)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } @@ -507,7 +508,7 @@ private async Task DownloadOutbreaksDLC2Data(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC2Found")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC2Found")!.GetValue(new BlockDefinition())!; var KMassOutbreakFound = SAV.Accessor.FindOrDefault(blockInfo.Key); bool KMassOutbreakFoundData; try { KMassOutbreakFoundData = (bool)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } @@ -523,7 +524,7 @@ private async Task DownloadOutbreaksDLC2Data(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC2NumKOed")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC2NumKOed")!.GetValue(new BlockDefinition())!; var KMassOutbreakNumKOed = SAV.Accessor.FindOrDefault(blockInfo.Key); int KMassOutbreakNumKOedData; try { KMassOutbreakNumKOedData = (int)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } @@ -536,7 +537,7 @@ private async Task DownloadOutbreaksDLC2Data(CancellationToken token) UpdateProgress(CurrentProgress++, MaxProgress); - blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{i}DLC2TotalSpawns")!.GetValue(new DataBlock())!; + blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{i}DLC2TotalSpawns")!.GetValue(new BlockDefinition())!; var KMassOutbreakTotalSpawns = SAV.Accessor.FindOrDefault(blockInfo.Key); int KMassOutbreakTotalSpawnsData; try { KMassOutbreakTotalSpawnsData = (int)(await Executor.ReadBlock(blockInfo, token).ConfigureAwait(false))!; } diff --git a/TeraFinder.Plugins/Forms/EditorForm.cs b/TeraFinder.Plugins/Forms/EditorForm.cs index 89c3b99f..1c7ca45d 100644 --- a/TeraFinder.Plugins/Forms/EditorForm.cs +++ b/TeraFinder.Plugins/Forms/EditorForm.cs @@ -11,7 +11,6 @@ public partial class EditorForm : Form public SAV9SV SAV { get; set; } = null!; public IPKMView? PKMEditor { get; private set; } = null!; private Dictionary DenLocations = null!; - public GameProgress Progress { get; set; } = GameProgress.None; private readonly Image DefBackground = null!; private Size DefSize = new(0, 0); private bool Loaded = false; @@ -20,36 +19,35 @@ public partial class EditorForm : Form private string[] KitakamiLocations = null!; private string[] BlueberryLocations = null!; + public string Language = null!; private ConnectionForm? Connection = null; - + public GameProgress Progress { get; set; } = GameProgress.Beginning; public TeraRaidMapParent CurrMap = TeraRaidMapParent.Paldea; - public string Language = null!; - public EncounterRaid9[]? Paldea = null; - public EncounterRaid9[]? Kitakami = null; - public EncounterRaid9[]? Blueberry = null; - public EncounterRaid9[]? Dist = null; - public EncounterRaid9[]? Mighty = null; - public Dictionary>? TeraFixedRewards = null; - public Dictionary>? TeraLotteryRewards = null; - public Dictionary>? DistFixedRewards = null; - public Dictionary>? DistLotteryRewards = null; - - public EncounterRaid9? CurrEncount = null; + public EncounterTeraTF9[] Paldea = null!; + public EncounterTeraTF9[] PaldeaBlack = null!; + public EncounterTeraTF9[] Kitakami = null!; + public EncounterTeraTF9[] KitakamiBlack = null!; + public EncounterTeraTF9[] Blueberry = null!; + public EncounterTeraTF9[] BlueberryBlack = null!; + + public EncounterEventTF9[] Dist = null!; + public EncounterEventTF9[] Mighty = null!; + + public EncounterRaidTF9? CurrEncount = null; public TeraDetails? CurrTera = null; public EditorForm(SAV9SV sav, IPKMView? editor, string language, - EncounterRaid9[]? paldea, - EncounterRaid9[]? kitakami, - EncounterRaid9[]? blueberry, - EncounterRaid9[]? dist, - EncounterRaid9[]? mighty, - Dictionary>? terafixed, - Dictionary>? teralottery, - Dictionary>? distfixed, - Dictionary>? distlottery, + EncounterTeraTF9[]? paldea, + EncounterTeraTF9[]? paldeablack, + EncounterTeraTF9[]? kitakami, + EncounterTeraTF9[]? kitakamiblack, + EncounterTeraTF9[]? blueberry, + EncounterTeraTF9[]? blueberryblack, + EncounterEventTF9[]? dist, + EncounterEventTF9[]? mighty, ConnectionForm? connection) { InitializeComponent(); @@ -64,39 +62,14 @@ public EditorForm(SAV9SV sav, InitLocationNames(); GenerateDenLocations(); - if (dist is null) - { - var events = TeraUtil.GetSAVDistEncounters(SAV); - var eventsrewards = RewardUtil.GetDistRewardsTables(SAV); - Dist = events[0]; - Mighty = events[1]; - DistFixedRewards = eventsrewards[0]; - DistLotteryRewards = eventsrewards[1]; - } - else - { - Dist = dist; - Mighty = mighty; - DistFixedRewards = distfixed; - DistLotteryRewards = distlottery; - } - if (terafixed is null) - { - var terarewards = RewardUtil.GetTeraRewardsTables(); - TeraFixedRewards = terarewards[0]; - TeraLotteryRewards = terarewards[1]; - } - else - { - TeraFixedRewards = terafixed; - TeraLotteryRewards = teralottery; - } - Paldea = paldea is null ? TeraUtil.GetAllTeraEncounters(TeraRaidMapParent.Paldea) : paldea; - Kitakami = kitakami is null ? TeraUtil.GetAllTeraEncounters(TeraRaidMapParent.Kitakami) : kitakami; - Blueberry = blueberry is null ? TeraUtil.GetAllTeraEncounters(TeraRaidMapParent.Blueberry) : blueberry; + (Paldea, PaldeaBlack) = paldea is null || paldeablack is null ? ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Paldea) : (paldea, paldeablack); + (Kitakami, KitakamiBlack) = kitakami is null || kitakamiblack is null ? ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Kitakami) : (kitakami, kitakamiblack); + (Blueberry, BlueberryBlack) = blueberry is null || blueberryblack is null ? ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Blueberry) : (blueberry, blueberryblack); + (Dist, Mighty) = dist is null || mighty is null ? EventUtil.GetCurrentEventEncounters(SAV, RewardUtil.GetDistRewardsTables(SAV)) : (dist, mighty); + DefBackground = pictureBox.BackgroundImage!; DefSize = pictureBox.Size; - Progress = TeraUtil.GetProgress(SAV); + Progress = SavUtil.GetProgress(SAV); foreach (var name in UpdateRaidNameList()) cmbDens.Items.Add(name); cmbMap.Items.Add($"{Strings["Plugin.MapPaldea"]} ({Strings["Plugin.Main"]})"); @@ -112,7 +85,7 @@ public EditorForm(SAV9SV sav, } private void GenerateDenLocations() => - DenLocations = JsonSerializer.Deserialize>(TeraUtil.GetDenLocations(CurrMap))!; + DenLocations = JsonSerializer.Deserialize>(ResourcesUtil.GetDenLocations(CurrMap))!; private void GenerateDictionary() { @@ -199,7 +172,7 @@ private void TranslateCmbContent() private void InitLocationNames() { - PaldeaLocations = TeraUtil.AreaPaldea; + PaldeaLocations = AreaNames.AreaPaldea; PaldeaLocations[1] = Strings["AREASPA1"]; PaldeaLocations[4] = Strings["AREASPA2"]; PaldeaLocations[5] = Strings["AREASPA4"]; @@ -221,7 +194,7 @@ private void InitLocationNames() PaldeaLocations[21] = Strings["AREANPA1"]; PaldeaLocations[22] = Strings["AREANPA2"]; - KitakamiLocations = TeraUtil.AreaKitakami; + KitakamiLocations = AreaNames.AreaKitakami; KitakamiLocations[1] = Strings["AREA1KR"]; KitakamiLocations[2] = Strings["AREA1AH"]; KitakamiLocations[3] = Strings["AREA1RR"]; @@ -234,7 +207,7 @@ private void InitLocationNames() KitakamiLocations[10] = Strings["AREA1PB"]; KitakamiLocations[11] = Strings["AREA1KW"]; - BlueberryLocations = TeraUtil.AreaBlueberry; + BlueberryLocations = AreaNames.AreaBlueberry; BlueberryLocations[1] = Strings["AREA2SV"]; BlueberryLocations[2] = Strings["AREA2CO"]; BlueberryLocations[3] = Strings["AREA2CA"]; @@ -406,7 +379,7 @@ private async Task UpdateRemote() { if (Connection is not null && Connection.IsConnected()) { - var block = CurrMap is TeraRaidMapParent.Paldea ? Blocks.KTeraRaidPaldea : Blocks.KTeraRaidDLC; + var block = CurrMap is TeraRaidMapParent.Paldea ? BlockDefinitions.KTeraRaidPaldea : BlockDefinitions.KTeraRaidDLC; var savBlock = SAV.Accessor.FindOrDefault(block.Key)!; await Connection.Executor.WriteBlock(savBlock.Data, block, new CancellationToken()).ConfigureAwait(false); } @@ -427,18 +400,30 @@ private void UpdatePKMInfo(TeraRaidDetail raid) if (Progress is not GameProgress.Beginning && ((raid.Seed == 0 && raid.IsEnabled) || raid.Seed > 0)) { var content = (RaidContent)cmbContent.SelectedIndex; - var groupid = TeraUtil.GetDeliveryGroupID(SAV, Progress, content, content is RaidContent.Event_Mighty ? Mighty : Dist, - CurrMap switch { TeraRaidMapParent.Paldea => SAV.RaidPaldea, TeraRaidMapParent.Kitakami => SAV.RaidKitakami, _ => SAV.RaidBlueberry }, cmbDens.SelectedIndex); - var progress = raid.Content is TeraRaidContentType.Black6 ? GameProgress.None : Progress; - var encounter = cmbContent.SelectedIndex < 2 ? TeraUtil.GetTeraEncounter(raid.Seed, SAV.Version, - TeraUtil.GetStars(raid.Seed, progress), CurrMap switch { TeraRaidMapParent.Paldea => Paldea!, TeraRaidMapParent.Kitakami => Kitakami!, _ => Blueberry! }, CurrMap) : - raid.Content is TeraRaidContentType.Might7 ? TeraUtil.GetDistEncounter(raid.Seed, SAV.Version, progress, Mighty!, groupid) : - TeraUtil.GetDistEncounter(raid.Seed, SAV.Version, progress, Dist!, groupid); - - if (encounter is not null) + var groupid = content switch { - var rngres = TeraUtil.CalcRNG(raid.Seed, SAV.ID32, (RaidContent)raid.Content, encounter, groupid); + RaidContent.Event or RaidContent.Event_Mighty => EventUtil.GetDeliveryGroupID([.. Dist, .. Mighty], + SAV, EventUtil.GetEventStageFromProgress(Progress), CurrMap switch + { + TeraRaidMapParent.Paldea => SAV.RaidPaldea, + TeraRaidMapParent.Kitakami => SAV.RaidKitakami, + TeraRaidMapParent.Blueberry => SAV.RaidBlueberry, + _ => throw new NotImplementedException(nameof(CurrMap)) + }, cmbDens.SelectedIndex), + _ => (byte)0, + }; + var success = EncounterRaidTF9.TryGenerateTeraDetails(raid.Seed, content switch + { + RaidContent.Standard => CurrMap switch { TeraRaidMapParent.Paldea => Paldea, TeraRaidMapParent.Kitakami => Kitakami, _ => Blueberry }, + RaidContent.Black => CurrMap switch { TeraRaidMapParent.Paldea => PaldeaBlack, TeraRaidMapParent.Kitakami => KitakamiBlack, _ => BlueberryBlack }, + RaidContent.Event => Dist, + RaidContent.Event_Mighty => Mighty, + _ => throw new NotImplementedException(nameof(content)), + }, SAV.Version, Progress, EventUtil.GetEventStageFromProgress(Progress), content, CurrMap, SAV.ID32, groupid, out var encounter, out var result); + + if (success && encounter is not null && result is not null) + { var species = GameInfo.GetStrings(Language).specieslist; var types = GameInfo.GetStrings(Language).types; var forms = GameInfo.GetStrings(Language).forms; @@ -447,28 +432,28 @@ private void UpdatePKMInfo(TeraRaidDetail raid) var genders = GameInfo.GenderSymbolUnicode.ToArray(); var moves = GameInfo.GetStrings(Language).movelist; - lblSpecies.Text = $"{Strings["EditorForm.lblSpecies"]} {rngres.GetName(species, types, forms, genders)}"; - lblTera.Text = $"{Strings["EditorForm.lblTera"]} {types[rngres.TeraType]}"; - lblNature.Text = $"{Strings["EditorForm.lblNature"]} {natures[rngres.Nature]}"; - lblAbility.Text = $"{Strings["EditorForm.lblAbility"]} {abilities[rngres.Ability]}"; - lblShiny.Text = $"{Strings["EditorForm.lblShiny"]} {rngres.Shiny}"; - lblGender.Text = $"{Strings["EditorForm.lblGender"]} {genders[(int)rngres.Gender]}"; + lblSpecies.Text = $"{Strings["EditorForm.lblSpecies"]} {result.Value.GetName(species, types, forms, genders)}"; + lblTera.Text = $"{Strings["EditorForm.lblTera"]} {types[result.Value.TeraType]}"; + lblNature.Text = $"{Strings["EditorForm.lblNature"]} {natures[(byte)result.Value.Nature]}"; + lblAbility.Text = $"{Strings["EditorForm.lblAbility"]} {abilities[result.Value.Ability]}"; + lblShiny.Text = $"{Strings["EditorForm.lblShiny"]} {result.Value.Shiny}"; + lblGender.Text = $"{Strings["EditorForm.lblGender"]} {genders[(int)result.Value.Gender]}"; lblIndex.Text = $"{Strings["EditorForm.lblIndex"]} {groupid}"; lblIndex.Visible = groupid != 0; - txtHP.Text = $"{rngres.HP}"; - txtAtk.Text = $"{rngres.ATK}"; - txtDef.Text = $"{rngres.DEF}"; - txtSpA.Text = $"{rngres.SPA}"; - txtSpD.Text = $"{rngres.SPD}"; - txtSpe.Text = $"{rngres.SPE}"; - txtScale.Text = $"{rngres.Scale}"; - txtMove1.Text = $"{moves[rngres.Move1]}"; - txtMove2.Text = $"{moves[rngres.Move2]}"; - txtMove3.Text = $"{moves[rngres.Move3]}"; - txtMove4.Text = $"{moves[rngres.Move4]}"; + txtHP.Text = $"{result.Value.HP}"; + txtAtk.Text = $"{result.Value.ATK}"; + txtDef.Text = $"{result.Value.DEF}"; + txtSpA.Text = $"{result.Value.SPA}"; + txtSpD.Text = $"{result.Value.SPD}"; + txtSpe.Text = $"{result.Value.SPE}"; + txtScale.Text = $"{result.Value.Scale}"; + txtMove1.Text = $"{moves[result.Value.Move1]}"; + txtMove2.Text = $"{moves[result.Value.Move2]}"; + txtMove3.Text = $"{moves[result.Value.Move3]}"; + txtMove4.Text = $"{moves[result.Value.Move4]}"; pictureBox.BackgroundImage = null; - pictureBox.Image = GetRaidResultSprite(rngres, raid.IsEnabled, encounter.Item); + pictureBox.Image = GetRaidResultSprite(result.Value, raid.IsEnabled, encounter.HeldItem); if (pictureBox.Image is not null) pictureBox.Size = pictureBox.Image.Size; else @@ -477,16 +462,16 @@ private void UpdatePKMInfo(TeraRaidDetail raid) pictureBox.Size = DefSize; } - imgMap.SetMapPoint((MoveType)rngres.TeraType, (int)raid.AreaID, (int)raid.LotteryGroup, (int)raid.SpawnPointID, CurrMap, DenLocations); + imgMap.SetMapPoint((MoveType)result.Value.TeraType, (int)raid.AreaID, (int)raid.LotteryGroup, (int)raid.SpawnPointID, CurrMap, DenLocations); btnRewards.Width = pictureBox.Image is not null ? pictureBox.Image.Width : pictureBox.BackgroundImage!.Width; btnRewards.Visible = true; CurrEncount = encounter; - CurrTera = rngres; + CurrTera = result; - SetStarSymbols(rngres.Stars); - SetLevelLabel(rngres.Level); + SetStarSymbols(result.Value.Stars); + SetLevelLabel(result.Value.Level); var movestring = $"{Strings["EditorForm.toolTipMoves"]}"; if (encounter.ExtraMoves.ExtraMoveList.Count > 0) @@ -573,31 +558,8 @@ private string[] UpdateRaidNameList() return names; } - private void btnOpenCalculator_Click(object sender, EventArgs e) - { - var calcform = new CalculatorForm(this); - - if (CurrEncount is not null && CurrEncount.IsDistribution) - { - calcform.CurrentViewedIndex = CurrEncount.Index; - calcform.NotLinkedSearch = false; - } - - calcform.Show(); - } - - private void btnOpenRewardCalculator_Click(object sender, EventArgs e) - { - var calcform = new RewardCalcForm(this); - - if (CurrEncount is not null && CurrEncount.IsDistribution) - { - calcform.CurrentViewedIndex = CurrEncount.Index; - calcform.NotLinkedSearch = false; - } - - calcform.Show(); - } + private void btnOpenCalculator_Click(object sender, EventArgs e) => new CalculatorForm(this).Show(); + private void btnOpenRewardCalculator_Click(object sender, EventArgs e) => new RewardCalcForm(this).Show(); private void btnDx_Click(object sender, EventArgs e) { @@ -620,327 +582,156 @@ private void btnRewards_Click(object sender, EventArgs e) { if (CurrEncount is not null && CurrTera is not null) { - var lvl0 = RewardUtil.GetRewardList(CurrTera, CurrEncount.FixedRewardHash, CurrEncount.LotteryRewardHash, - CurrEncount.IsDistribution ? DistFixedRewards : TeraFixedRewards, CurrEncount.IsDistribution ? DistLotteryRewards : TeraLotteryRewards, 0); - var lvl1 = RewardUtil.GetRewardList(CurrTera, CurrEncount.FixedRewardHash, CurrEncount.LotteryRewardHash, - CurrEncount.IsDistribution ? DistFixedRewards : TeraFixedRewards, CurrEncount.IsDistribution ? DistLotteryRewards : TeraLotteryRewards, 1); - var lvl2 = RewardUtil.GetRewardList(CurrTera, CurrEncount.FixedRewardHash, CurrEncount.LotteryRewardHash, - CurrEncount.IsDistribution ? DistFixedRewards : TeraFixedRewards, CurrEncount.IsDistribution ? DistLotteryRewards : TeraLotteryRewards, 2); - var lvl3 = RewardUtil.GetRewardList(CurrTera, CurrEncount.FixedRewardHash, CurrEncount.LotteryRewardHash, - CurrEncount.IsDistribution ? DistFixedRewards : TeraFixedRewards, CurrEncount.IsDistribution ? DistLotteryRewards : TeraLotteryRewards, 3); - - var form = new RewardListForm(Language, lvl0, lvl1, lvl2, lvl3); + var lvl0 = RewardUtil.GetCombinedRewardList(CurrTera.Value, CurrEncount.FixedRewards, CurrEncount.LotteryRewards, 0); + var lvl1 = RewardUtil.GetCombinedRewardList(CurrTera.Value, CurrEncount.FixedRewards, CurrEncount.LotteryRewards, 1); + var lvl2 = RewardUtil.GetCombinedRewardList(CurrTera.Value, CurrEncount.FixedRewards, CurrEncount.LotteryRewards, 2); + var lvl3 = RewardUtil.GetCombinedRewardList(CurrTera.Value, CurrEncount.FixedRewards, CurrEncount.LotteryRewards, 3); + + var form = new RewardListForm(Language, (MoveType)CurrTera.Value.TeraType, lvl0, lvl1, lvl2, lvl3); form.ShowDialog(); } } - private void btnShinifyCurrent_Click(object sender, EventArgs e) + public EncounterRaidTF9[] GetCurrentEncounters(RaidContent content, TeraRaidMapParent map) => content switch { - var spawnList = CurrMap switch + RaidContent.Standard => map switch { - TeraRaidMapParent.Paldea => SAV.RaidPaldea, - TeraRaidMapParent.Kitakami => SAV.RaidKitakami, - _ => SAV.RaidBlueberry - }; - var raid = spawnList.GetAllRaids().Length > 1 ? spawnList.GetRaid(cmbDens.SelectedIndex) : new TeraRaidDetail(new byte[TeraRaidDetail.SIZE]); - - var seed = raid.Seed; - var content = (RaidContent)raid.Content; - var groupid = TeraUtil.GetDeliveryGroupID(SAV, Progress, content, content is RaidContent.Event_Mighty ? Mighty : Dist, spawnList, cmbDens.SelectedIndex); - var progress = content is RaidContent.Black ? (GameProgress)6 : Progress; - var originalEncounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(seed, SAV.Version, - TeraUtil.GetStars(seed, progress), CurrMap switch { TeraRaidMapParent.Paldea => Paldea!, TeraRaidMapParent.Kitakami => Kitakami!, _ => Blueberry! }, CurrMap) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Mighty!, groupid) : TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Dist!, groupid); - - if (originalEncounter is null) - return; - - if (originalEncounter.IsDistribution) + TeraRaidMapParent.Paldea => Paldea, + TeraRaidMapParent.Kitakami => Kitakami, + TeraRaidMapParent.Blueberry => Blueberry, + _ => throw new NotImplementedException(nameof(cmbMap.SelectedIndex)), + }, + RaidContent.Black => map switch { - var canBeShiny = false; - foreach (var enc in content is RaidContent.Event ? Dist! : Mighty!) - { - if (enc.Index != groupid) - continue; - - if (enc.Species != originalEncounter.Species || enc.Form != originalEncounter.Form) - continue; - - if (enc.Shiny is not Shiny.Never) - { - canBeShiny = true; - break; - } - } - - if (!canBeShiny) - return; - } - - for (uint i = 0; i <= 0xFFFFFFFF; i++) - { - var encounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(seed, SAV.Version, - TeraUtil.GetStars(seed, progress), CurrMap switch - { - TeraRaidMapParent.Paldea => Paldea!, - TeraRaidMapParent.Kitakami => Kitakami!, - _ => Blueberry! - }, CurrMap) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Mighty!, groupid) : TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Dist!, groupid); - var rngres = encounter is not null && (encounter.Species == originalEncounter.Species && encounter.Form == originalEncounter.Form) ? - TeraUtil.CalcRNG(seed, SAV.ID32, content, encounter, groupid) : null; - - var isShiny = rngres is not null && rngres.Shiny >= TeraShiny.Yes; - - if (!isShiny) - seed++; - else - { - seed = rngres!.Seed; - break; - } - } - - raid.Seed = seed; - raid.IsEnabled = true; - raid.IsClaimedLeaguePoints = false; - cmbDens_IndexChanged(this, new EventArgs()); - Task.Run(UpdateRemote).Wait(); - SystemSounds.Asterisk.Play(); - } - - private void btnRandomizeCurrent_Click(object sender, EventArgs e) + TeraRaidMapParent.Paldea => PaldeaBlack, + TeraRaidMapParent.Kitakami => KitakamiBlack, + TeraRaidMapParent.Blueberry => BlueberryBlack, + _ => throw new NotImplementedException(nameof(cmbMap.SelectedIndex)), + }, + RaidContent.Event => Dist, + RaidContent.Event_Mighty => Mighty, + _ => throw new NotImplementedException(nameof(cmbContent.SelectedIndex)), + }; + + private void btnShinifyCurrent_Click(object sender, EventArgs e) => EditCurrentRaid(true, true); + private void btnRandomizeCurrent_Click(object sender, EventArgs e) => EditCurrentRaid(false, false); + + private void btnRandomizeAll_Click(object sender, EventArgs e) => EditAllRaids(false, false); + private void BtnShinifyAllRaids_Click(object sender, EventArgs e) => EditAllRaids(false, true); + private void BtnShinyAllEncounters_Click(object sender, EventArgs e) => EditAllRaids(true, true); + + private void EditCurrentRaid(bool forceEncounter, bool forceShiny) { - var spawnList = CurrMap switch + if (CurrEncount is null || CurrTera is null) + return; + + var spawns = CurrMap switch { TeraRaidMapParent.Paldea => SAV.RaidPaldea, TeraRaidMapParent.Kitakami => SAV.RaidKitakami, _ => SAV.RaidBlueberry }; - var raid = spawnList.GetAllRaids().Length > 1 ? spawnList.GetRaid(cmbDens.SelectedIndex) : new TeraRaidDetail(new byte[TeraRaidDetail.SIZE]); - - var seed = raid.Seed; - var content = (RaidContent)raid.Content; - var groupid = TeraUtil.GetDeliveryGroupID(SAV, Progress, content, content is RaidContent.Event_Mighty ? Mighty : Dist, spawnList, cmbDens.SelectedIndex); - var progress = content is RaidContent.Black ? (GameProgress)6 : Progress; - var originalEncounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(seed, SAV.Version, - TeraUtil.GetStars(seed, progress), CurrMap switch - { - TeraRaidMapParent.Paldea => Paldea!, - TeraRaidMapParent.Kitakami => Kitakami!, - _ => Blueberry! - }, CurrMap) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Mighty!, groupid) : TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Dist!, groupid); - if (originalEncounter is null) + if (!spawns.GetAllRaids().Any(raid => raid.IsEnabled)) return; - var xoro = new Xoroshiro128Plus(seed); - seed = (uint)(xoro.Next() & 0xFFFFFFFF); - - raid.Seed = seed; - raid.IsEnabled = true; - raid.IsClaimedLeaguePoints = false; + ShinifyRaid(CurrEncount, CurrTera.Value, spawns.GetRaid(cmbDens.SelectedIndex), forceEncounter, forceShiny); cmbDens_IndexChanged(this, new EventArgs()); Task.Run(UpdateRemote).Wait(); SystemSounds.Asterisk.Play(); } - private void btnRandomizeAll_Click(object sender, EventArgs e) + private void EditAllRaids(bool forceEncouner, bool forceShiny) { - var spawnList = CurrMap switch + var spawns = CurrMap switch { TeraRaidMapParent.Paldea => SAV.RaidPaldea, TeraRaidMapParent.Kitakami => SAV.RaidKitakami, _ => SAV.RaidBlueberry }; - foreach (var raid in spawnList.GetAllRaids()) + if (!spawns.GetAllRaids().Any(raid => raid.IsEnabled)) + return; + + Parallel.For(0, spawns.GetAllRaids().Length, i => { - var seed = raid.Seed; + var raid = spawns.GetRaid(i); var content = (RaidContent)raid.Content; - var groupid = TeraUtil.GetDeliveryGroupID(SAV, Progress, content, content is RaidContent.Event_Mighty ? Mighty : Dist, spawnList, cmbDens.SelectedIndex); - var progress = content is RaidContent.Black ? (GameProgress)6 : Progress; - var originalEncounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(seed, SAV.Version, - TeraUtil.GetStars(seed, progress), CurrMap switch - { - TeraRaidMapParent.Paldea => Paldea!, - TeraRaidMapParent.Kitakami => Kitakami!, - _ => Blueberry! - }, CurrMap) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Mighty!, groupid) : TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Dist!, groupid); + var encounters = GetCurrentEncounters(content, CurrMap); + var eventProgress = EventUtil.GetEventStageFromProgress(Progress); + var groupid = content >= RaidContent.Event ? EventUtil.GetDeliveryGroupID(content is RaidContent.Event ? + (EncounterEventTF9[])encounters : (EncounterEventTF9[])encounters, SAV, eventProgress, spawns, i) : (byte)0; - if (originalEncounter is null) - continue; + if (!EncounterRaidTF9.TryGenerateTeraDetails(raid.Seed, encounters, SAV.Version, Progress, eventProgress, content, CurrMap, SAV.ID32, groupid, out var encounter, out var detail)) + return; - var xoro = new Xoroshiro128Plus(seed); - seed = (uint)(xoro.Next() & 0xFFFFFFFF); - - raid.Seed = seed; - raid.IsEnabled = true; - raid.IsClaimedLeaguePoints = false; - } + ShinifyRaid(encounter, detail!.Value, raid, forceEncouner, forceShiny); + }); cmbDens_IndexChanged(this, new EventArgs()); Task.Run(UpdateRemote).Wait(); SystemSounds.Asterisk.Play(); } - private void BtnShinifyAllRaids_Click(object sender, EventArgs e) => ShinifyRaids(false); - private void BtnShinyAllEncounters_Click(object sender, EventArgs e) => ShinifyRaids(true); - - private void ShinifyRaids(bool keepEncounter) + private void ShinifyRaid(EncounterRaidTF9? encounter, TeraDetails details, TeraRaidDetail raid, bool forceEncounter, bool forceShiny) { - var progressWindow = new ShinifyForm(0, Strings["ShinifyForm.lblValue"]); + if (encounter is null) + return; - var spawnList = CurrMap switch + var filter = new TeraFilter(forceEncounter, false, false, false) { - TeraRaidMapParent.Paldea => SAV.RaidPaldea, - TeraRaidMapParent.Kitakami => SAV.RaidKitakami, - _ => SAV.RaidBlueberry + IsFormFilter = forceEncounter, + MinHP = 0, + MaxHP = 31, + MinAtk = 0, + MaxAtk = 31, + MinDef = 0, + MaxDef = 31, + MinSpa = 0, + MaxSpa = 31, + MinSpd = 0, + MaxSpd = 31, + MinSpe = 0, + MaxSpe = 31, + MinScale = 0, + MaxScale = 255, + Stars = encounter.Stars, + Species = encounter.Species, + Form = encounter.Form, + TeraType = -1, + AbilityNumber = 0, + Nature = Nature.Random, + Gender = Gender.Random, + Shiny = forceShiny ? TeraShiny.Yes : TeraShiny.Any, + AltEC = details.EC % 100 == 0, }; - var raidList = spawnList.GetAllRaids(); - var raidCount = raidList.Count(raid => raid.IsEnabled == true); - foreach (var iterator in raidList.Select((value, i) => new { i, value })) - { - var raid = iterator.value; - var index = iterator.i; - - if (index > raidCount) - break; - - if (raid.AreaID == 0) - continue; - - var currProgress = (index * 100) / raidCount; - progressWindow.UpdateComputedValue(currProgress); - - var seed = raid.Seed; - var content = (RaidContent)raid.Content; - var groupid = TeraUtil.GetDeliveryGroupID(SAV, Progress, content, content is RaidContent.Event_Mighty ? Mighty : Dist, spawnList, index); - var progress = content is RaidContent.Black ? (GameProgress)6 : Progress; - var originalEncounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(seed, SAV.Version, - TeraUtil.GetStars(seed, progress), CurrMap switch - { - TeraRaidMapParent.Paldea => Paldea!, - TeraRaidMapParent.Kitakami => Kitakami!, - _ => Blueberry! - }, CurrMap) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Mighty!, groupid) : TeraUtil.GetDistEncounter(seed, SAV.Version, progress, Dist!, groupid); - - if (originalEncounter is null) - continue; - - if (originalEncounter.IsDistribution) - { - var canBeShiny = false; - foreach (var enc in content is RaidContent.Event ? Dist! : Mighty!) - { - if (enc.Index != groupid) - continue; - - if (keepEncounter && (enc.Species != originalEncounter.Species || enc.Form != originalEncounter.Form)) - continue; - - if (enc.Shiny is not Shiny.Never) - { - canBeShiny = true; - break; - } - } - - if (!canBeShiny) - continue; - } - var token = new CancellationTokenSource(); - var nthreads = Environment.ProcessorCount; - var resetEvent = new ManualResetEvent(false); - var toProcess = nthreads; - var calcsperthread = 0xFFFFFFFF / (uint)nthreads; - - for (uint i = 0; i < nthreads; i++) - { - var n = i; - var tseed = seed; - - new Thread(delegate () - { - var initialFrame = calcsperthread * n; - var maxFrame = n < nthreads - 1 ? calcsperthread * (n + 1) : 0xFFFFFFFF; - tseed += initialFrame; + if (filter.Shiny >= TeraShiny.Yes) + { + if (encounter.Shiny is Shiny.Never) + return; - for (ulong j = initialFrame; j <= maxFrame && !token.IsCancellationRequested; j++) - { - var encounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(tseed, SAV.Version, - TeraUtil.GetStars(tseed, progress), CurrMap switch - { - TeraRaidMapParent.Paldea => Paldea!, - TeraRaidMapParent.Kitakami => Kitakami!, - _ => Blueberry! - }, CurrMap) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(tseed, SAV.Version, progress, Mighty!, groupid) : TeraUtil.GetDistEncounter(tseed, SAV.Version, progress, Dist!, groupid); - - var rngres = encounter is not null && (!keepEncounter || (encounter.Species == originalEncounter.Species && encounter.Form == originalEncounter.Form)) ? - TeraUtil.CalcRNG(tseed, SAV.ID32, content, encounter, groupid) : null; - - var isShiny = rngres is not null && rngres.Shiny >= TeraShiny.Yes; - - if (!isShiny) - tseed++; - else - { - seed = rngres!.Seed; - token.Cancel(); - break; - } - } - - if (Interlocked.Decrement(ref toProcess) == 0 || token.IsCancellationRequested) - resetEvent.Set(); - - }).Start(); - - resetEvent.WaitOne(); - - raid.Seed = seed; - raid.IsEnabled = true; - raid.IsClaimedLeaguePoints = false; - } + if (details.Shiny >= TeraShiny.Yes) + return; } - progressWindow.Close(); - cmbDens_IndexChanged(this, new EventArgs()); - Task.Run(UpdateRemote).Wait(); - SystemSounds.Asterisk.Play(); - MessageBox.Show(Strings["ShinifiedAll"]); - } - - public class ShinifyForm : Form - { - private readonly Label lblValue; - private readonly string Progress; - - public ShinifyForm(int computedValue, string progress) + TeraDetails? res = null; + EncounterRaidTF9[] encounters = filter.EncounterFilter is true ? encounter.ContentType switch { - MaximizeBox = false; - MinimizeBox = false; - FormBorderStyle = FormBorderStyle.FixedDialog; - Size = new Size(200, 75); - StartPosition = FormStartPosition.CenterParent; - - Progress = progress; - lblValue = new Label { Text = $"{Progress} {computedValue}%", TextAlign = ContentAlignment.TopCenter }; - lblValue.Location = new Point((Width - lblValue.Width) / 2, lblValue.Location.Y); - - Controls.Add(lblValue); - Show(); - } + RaidContent.Standard or RaidContent.Black => ((EncounterTeraTF9[])GetCurrentEncounters(encounter.ContentType, encounter.Map)).Where(filter.IsEncounterMatch).ToArray(), + RaidContent.Event or RaidContent.Event_Mighty => ((EncounterEventTF9[])GetCurrentEncounters(encounter.ContentType, encounter.Map)).Where(filter.IsEncounterMatch).ToArray(), + _ => throw new NotImplementedException(nameof(encounter.ContentType)), + } : GetCurrentEncounters(encounter.ContentType, encounter.Map); + + var xoro = new Xoroshiro128Plus(details.Seed); + for (var i = details.Seed + 1; i != details.Seed + uint.MaxValue; i++) + if (EncounterRaidTF9.TryGenerateTeraDetails((uint)(xoro.Next() & uint.MaxValue), encounters, SAV.Version, Progress, + EventUtil.GetEventStageFromProgress(Progress), encounter.ContentType, encounter.Map, SAV.ID32, encounter.Index, out _, out res)) + if (filter.IsFilterMatch(res.Value)) + break; - public void UpdateComputedValue(int computed) - { - lblValue.Text = $"{Progress} {computed}%"; - lblValue.Location = new Point((Width - lblValue.Width) / 2, lblValue.Location.Y); - } + raid.Seed = res is not null ? res.Value.Seed : raid.Seed; + raid.IsEnabled = true; + raid.IsClaimedLeaguePoints = false; } } diff --git a/TeraFinder.Plugins/Forms/OutbreakForm.cs b/TeraFinder.Plugins/Forms/OutbreakForm.cs index 3b5b1ed9..4abbd920 100644 --- a/TeraFinder.Plugins/Forms/OutbreakForm.cs +++ b/TeraFinder.Plugins/Forms/OutbreakForm.cs @@ -229,7 +229,7 @@ private void cmbSpecies_IndexChanged(object sender, EventArgs e) if (!isExclusive) { var resourceName = $"{CurrMap switch { TeraRaidMapParent.Kitakami => "dlc1", TeraRaidMapParent.Blueberry => "dlc2", _ => "" }}_{species}"; - json = TeraUtil.GetTextResource(resourceName); + json = ResourcesUtil.GetTextResource(resourceName); if (json is not null && json.Length > 0) { var message = Strings["OutbreakForm.LoadDefault"].Replace("{species}", SpeciesList[species]); @@ -273,7 +273,7 @@ private void cmbSpecies_IndexChanged(object sender, EventArgs e) { var success = false; var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}Species")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}Species")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(outbreak.Species, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -312,7 +312,7 @@ private void cmbForm_IndexChanged(object sender, EventArgs e) var species = SpeciesConverter.GetNational9((ushort)outbreak.Species); var resourceName = $"{CurrMap switch { TeraRaidMapParent.Kitakami => "dlc1", TeraRaidMapParent.Blueberry => "dlc2", _ => "" }}_{species}_{cmbForm.SelectedIndex}"; - var json = TeraUtil.GetTextResource(resourceName); + var json = ResourcesUtil.GetTextResource(resourceName); if (!Importing && json is not null) { if (json is not null && json.Length > 0) @@ -351,7 +351,7 @@ private void cmbForm_IndexChanged(object sender, EventArgs e) { var success = false; var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}Form")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}Form")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(outbreak.Form, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -376,7 +376,7 @@ private void numMaxSpawn_ValueChanged(object sender, EventArgs e) { var success = false; var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}TotalSpawns")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}TotalSpawns")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(outbreak.MaxSpawns, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -401,7 +401,7 @@ private void numKO_ValueChanged(object sender, EventArgs e) { var success = false; var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}NumKOed")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}NumKOed")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(outbreak.NumKO, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -430,7 +430,7 @@ private void chkFound_CheckedChanged(object sender, EventArgs e) { var success = false; var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}Found")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}Found")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(outbreak.Found, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -472,7 +472,12 @@ private void chkEnabled_CheckChanged(object sender, EventArgs e) { var success = false; var value = (byte)outbreak.GetAmountAvailable(); - var blockInfo = CurrMap switch { TeraRaidMapParent.Kitakami => Blocks.KOutbreakDLC1NumActive, TeraRaidMapParent.Blueberry => Blocks.KOutbreakDLC2NumActive, _ => Blocks.KOutbreakMainNumActive }; + var blockInfo = CurrMap switch + { + TeraRaidMapParent.Kitakami => BlockDefinitions.KOutbreakDLC1NumActive, + TeraRaidMapParent.Blueberry => BlockDefinitions.KOutbreakDLC2NumActive, + _ => BlockDefinitions.KOutbreakMainNumActive, + }; Task.Run(async () => { success = await Connection.Executor.WriteBlock(value, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -503,7 +508,7 @@ private void txtCenterX_TextChanged(object sender, EventArgs e) var success = false; var toInject = outbreak.LocationCenter.GetCoordinates().ToArray(); var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}CenterPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}CenterPos")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(toInject, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -538,7 +543,7 @@ private void txtCenterY_TextChanged(object sender, EventArgs e) var success = false; var toInject = outbreak.LocationCenter.GetCoordinates().ToArray(); var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}CenterPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}CenterPos")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(toInject, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -572,7 +577,7 @@ private void txtCenterZ_TextChanged(object sender, EventArgs e) var success = false; var toInject = outbreak.LocationCenter.GetCoordinates().ToArray(); var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}CenterPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}CenterPos")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(toInject, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -607,7 +612,7 @@ private void txtDummyX_TextChanged(object sender, EventArgs e) var success = false; var toInject = outbreak.LocationDummy.GetCoordinates().ToArray(); var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}DummyPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}DummyPos")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(toInject, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -639,7 +644,7 @@ private void txtDummyY_TextChanged(object sender, EventArgs e) var success = false; var toInject = outbreak.LocationDummy.GetCoordinates().ToArray(); var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}DummyPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}DummyPos")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(toInject, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) @@ -671,7 +676,7 @@ private void txtDummyZ_TextChanged(object sender, EventArgs e) var success = false; var toInject = outbreak.LocationDummy.GetCoordinates().ToArray(); var locationMap = CurrMap switch { TeraRaidMapParent.Kitakami => "DLC1", TeraRaidMapParent.Blueberry => "DLC2", _ => "Main" }; - var blockInfo = (DataBlock)typeof(Blocks).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}DummyPos")!.GetValue(new DataBlock())!; + var blockInfo = (BlockDefinition)typeof(BlockDefinitions).GetField($"KOutbreak0{cmbOutbreaks.SelectedIndex + 1}{locationMap}DummyPos")!.GetValue(new BlockDefinition())!; Task.Run(async () => { success = await Connection.Executor.WriteBlock(toInject, blockInfo, new CancellationToken(), toExpect).ConfigureAwait(false); }).Wait(); if (!success) diff --git a/TeraFinder.Plugins/Forms/ProgressForm.cs b/TeraFinder.Plugins/Forms/ProgressForm.cs index 8ddf1f9d..3bc201cb 100644 --- a/TeraFinder.Plugins/Forms/ProgressForm.cs +++ b/TeraFinder.Plugins/Forms/ProgressForm.cs @@ -21,7 +21,7 @@ public ProgressForm(SAV9SV sav, string language, ConnectionForm? connection) SAV = sav; Raids = []; - cmbProgress.SelectedIndex = (int)TeraUtil.GetProgress(sav); + cmbProgress.SelectedIndex = (int)SavUtil.GetProgress(sav); var raid7 = sav.RaidSevenStar.GetAllRaids(); foreach (var raid in raid7) { @@ -106,46 +106,46 @@ private async Task WriteProgressLive(GameProgress progress) if (progress >= GameProgress.Unlocked3Stars) { - var toexpect = (bool?)await Connection.Executor.ReadBlock(Blocks.KUnlockedRaidDifficulty3, CancellationToken.None); - await Connection.Executor.WriteBlock(true, Blocks.KUnlockedRaidDifficulty3, CancellationToken.None, toexpect); + var toexpect = (bool?)await Connection.Executor.ReadBlock(BlockDefinitions.KUnlockedRaidDifficulty3, CancellationToken.None); + await Connection.Executor.WriteBlock(true, BlockDefinitions.KUnlockedRaidDifficulty3, CancellationToken.None, toexpect); } else { - var toexpect = (bool?)await Connection.Executor.ReadBlock(Blocks.KUnlockedRaidDifficulty3, CancellationToken.None); - await Connection.Executor.WriteBlock(false, Blocks.KUnlockedRaidDifficulty3, CancellationToken.None, toexpect); + var toexpect = (bool?)await Connection.Executor.ReadBlock(BlockDefinitions.KUnlockedRaidDifficulty3, CancellationToken.None); + await Connection.Executor.WriteBlock(false, BlockDefinitions.KUnlockedRaidDifficulty3, CancellationToken.None, toexpect); } if (progress >= GameProgress.Unlocked4Stars) { - var toexpect = (bool?)await Connection.Executor.ReadBlock(Blocks.KUnlockedRaidDifficulty4, CancellationToken.None); - await Connection.Executor.WriteBlock(true, Blocks.KUnlockedRaidDifficulty4, CancellationToken.None, toexpect); + var toexpect = (bool?)await Connection.Executor.ReadBlock(BlockDefinitions.KUnlockedRaidDifficulty4, CancellationToken.None); + await Connection.Executor.WriteBlock(true, BlockDefinitions.KUnlockedRaidDifficulty4, CancellationToken.None, toexpect); } else { - var toexpect = (bool?)await Connection.Executor.ReadBlock(Blocks.KUnlockedRaidDifficulty4, CancellationToken.None); - await Connection.Executor.WriteBlock(false, Blocks.KUnlockedRaidDifficulty4, CancellationToken.None, toexpect); + var toexpect = (bool?)await Connection.Executor.ReadBlock(BlockDefinitions.KUnlockedRaidDifficulty4, CancellationToken.None); + await Connection.Executor.WriteBlock(false, BlockDefinitions.KUnlockedRaidDifficulty4, CancellationToken.None, toexpect); } if (progress >= GameProgress.Unlocked5Stars) { - var toexpect = (bool?)await Connection.Executor.ReadBlock(Blocks.KUnlockedRaidDifficulty5, CancellationToken.None); - await Connection.Executor.WriteBlock(true, Blocks.KUnlockedRaidDifficulty5, CancellationToken.None, toexpect); + var toexpect = (bool?)await Connection.Executor.ReadBlock(BlockDefinitions.KUnlockedRaidDifficulty5, CancellationToken.None); + await Connection.Executor.WriteBlock(true, BlockDefinitions.KUnlockedRaidDifficulty5, CancellationToken.None, toexpect); } else { - var toexpect = (bool?)await Connection.Executor.ReadBlock(Blocks.KUnlockedRaidDifficulty5, CancellationToken.None); - await Connection.Executor.WriteBlock(false, Blocks.KUnlockedRaidDifficulty5, CancellationToken.None, toexpect); + var toexpect = (bool?)await Connection.Executor.ReadBlock(BlockDefinitions.KUnlockedRaidDifficulty5, CancellationToken.None); + await Connection.Executor.WriteBlock(false, BlockDefinitions.KUnlockedRaidDifficulty5, CancellationToken.None, toexpect); } if (progress >= GameProgress.Unlocked6Stars) { - var toexpect = (bool?)await Connection.Executor.ReadBlock(Blocks.KUnlockedRaidDifficulty6, CancellationToken.None); - await Connection.Executor.WriteBlock(true, Blocks.KUnlockedRaidDifficulty6, CancellationToken.None, toexpect); + var toexpect = (bool?)await Connection.Executor.ReadBlock(BlockDefinitions.KUnlockedRaidDifficulty6, CancellationToken.None); + await Connection.Executor.WriteBlock(true, BlockDefinitions.KUnlockedRaidDifficulty6, CancellationToken.None, toexpect); } else { - var toexpect = (bool?)await Connection.Executor.ReadBlock(Blocks.KUnlockedRaidDifficulty6, CancellationToken.None); - await Connection.Executor.WriteBlock(false, Blocks.KUnlockedRaidDifficulty6, CancellationToken.None, toexpect); + var toexpect = (bool?)await Connection.Executor.ReadBlock(BlockDefinitions.KUnlockedRaidDifficulty6, CancellationToken.None); + await Connection.Executor.WriteBlock(false, BlockDefinitions.KUnlockedRaidDifficulty6, CancellationToken.None, toexpect); } } @@ -153,7 +153,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) { if (progress >= GameProgress.UnlockedTeraRaids) { - var dummy = Blocks.KUnlockedTeraRaidBattles; + var dummy = BlockDefinitions.KUnlockedTeraRaidBattles; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -164,7 +164,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) } else { - var dummy = Blocks.KUnlockedTeraRaidBattles; + var dummy = BlockDefinitions.KUnlockedTeraRaidBattles; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -176,7 +176,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) if (progress >= GameProgress.Unlocked3Stars) { - var dummy = Blocks.KUnlockedRaidDifficulty3; + var dummy = BlockDefinitions.KUnlockedRaidDifficulty3; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -187,7 +187,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) } else { - var dummy = Blocks.KUnlockedRaidDifficulty3; + var dummy = BlockDefinitions.KUnlockedRaidDifficulty3; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -199,7 +199,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) if (progress >= GameProgress.Unlocked4Stars) { - var dummy = Blocks.KUnlockedRaidDifficulty4; + var dummy = BlockDefinitions.KUnlockedRaidDifficulty4; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -210,7 +210,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) } else { - var dummy = Blocks.KUnlockedRaidDifficulty4; + var dummy = BlockDefinitions.KUnlockedRaidDifficulty4; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -222,7 +222,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) if (progress >= GameProgress.Unlocked5Stars) { - var dummy = Blocks.KUnlockedRaidDifficulty5; + var dummy = BlockDefinitions.KUnlockedRaidDifficulty5; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -233,7 +233,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) } else { - var dummy = Blocks.KUnlockedRaidDifficulty5; + var dummy = BlockDefinitions.KUnlockedRaidDifficulty5; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -245,7 +245,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) if (progress >= GameProgress.Unlocked6Stars) { - var dummy = Blocks.KUnlockedRaidDifficulty6; + var dummy = BlockDefinitions.KUnlockedRaidDifficulty6; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -256,7 +256,7 @@ public static void EditProgress(SAV9SV sav, GameProgress progress) } else { - var dummy = Blocks.KUnlockedRaidDifficulty6; + var dummy = BlockDefinitions.KUnlockedRaidDifficulty6; var block = sav.Accessor.FindOrDefault(dummy.Key); if (block.Type is SCTypeCode.None) { @@ -279,7 +279,7 @@ private async void btnApplyRaid7_Click(object sender, EventArgs e) { try { - await Connection.Executor.WriteBlock(SAV.RaidSevenStar.Captured.Data.ToArray(), Blocks.KSevenStarRaidsCapture, CancellationToken.None).ConfigureAwait(false); + await Connection.Executor.WriteBlock(SAV.RaidSevenStar.Captured.Data.ToArray(), BlockDefinitions.KSevenStarRaidsCapture, CancellationToken.None).ConfigureAwait(false); } catch { diff --git a/TeraFinder.Plugins/Forms/RewardCalcForm.Designer.cs b/TeraFinder.Plugins/Forms/RewardCalcForm.Designer.cs index 5e61df9b..2ee523ed 100644 --- a/TeraFinder.Plugins/Forms/RewardCalcForm.Designer.cs +++ b/TeraFinder.Plugins/Forms/RewardCalcForm.Designer.cs @@ -46,19 +46,15 @@ private void InitializeComponent() comboBox14 = new ComboBox(); comboBox15 = new ComboBox(); comboBox16 = new ComboBox(); - comboBox17 = new ComboBox(); - comboBox18 = new ComboBox(); - comboBox19 = new ComboBox(); - comboBox20 = new ComboBox(); grpFilters = new GroupBox(); grpEncounter = new GroupBox(); - chkShiny = new CheckBox(); + cmbShiny = new ComboBox(); + lblShiny = new Label(); cmbStars = new ComboBox(); lblStars = new Label(); cmbSpecies = new ComboBox(); lblSpecies = new Label(); btnApply = new Button(); - chkAccurateSearch = new CheckBox(); grpItems = new GroupBox(); label1 = new Label(); label2 = new Label(); @@ -76,14 +72,6 @@ private void InitializeComponent() label14 = new Label(); label15 = new Label(); label16 = new Label(); - label17 = new Label(); - label18 = new Label(); - label19 = new Label(); - label20 = new Label(); - numericUpDown20 = new NumericUpDown(); - numericUpDown19 = new NumericUpDown(); - numericUpDown18 = new NumericUpDown(); - numericUpDown17 = new NumericUpDown(); numericUpDown16 = new NumericUpDown(); numericUpDown15 = new NumericUpDown(); numericUpDown14 = new NumericUpDown(); @@ -123,6 +111,7 @@ private void InitializeComponent() lblCalcs = new Label(); txtSeed = new TextBox(); grpSearch = new GroupBox(); + lblTime = new Label(); lblFound = new Label(); chkAllResults = new CheckBox(); btnSearch = new Button(); @@ -136,10 +125,6 @@ private void InitializeComponent() grpFilters.SuspendLayout(); grpEncounter.SuspendLayout(); grpItems.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)numericUpDown20).BeginInit(); - ((System.ComponentModel.ISupportInitialize)numericUpDown19).BeginInit(); - ((System.ComponentModel.ISupportInitialize)numericUpDown18).BeginInit(); - ((System.ComponentModel.ISupportInitialize)numericUpDown17).BeginInit(); ((System.ComponentModel.ISupportInitialize)numericUpDown16).BeginInit(); ((System.ComponentModel.ISupportInitialize)numericUpDown15).BeginInit(); ((System.ComponentModel.ISupportInitialize)numericUpDown14).BeginInit(); @@ -167,7 +152,7 @@ private void InitializeComponent() // comboBox1 // comboBox1.FormattingEnabled = true; - comboBox1.Location = new Point(7, 24); + comboBox1.Location = new Point(10, 24); comboBox1.Margin = new Padding(3, 4, 3, 4); comboBox1.Name = "comboBox1"; comboBox1.Size = new Size(219, 28); @@ -176,7 +161,7 @@ private void InitializeComponent() // comboBox2 // comboBox2.FormattingEnabled = true; - comboBox2.Location = new Point(7, 60); + comboBox2.Location = new Point(10, 60); comboBox2.Margin = new Padding(3, 4, 3, 4); comboBox2.Name = "comboBox2"; comboBox2.Size = new Size(219, 28); @@ -185,7 +170,7 @@ private void InitializeComponent() // comboBox3 // comboBox3.FormattingEnabled = true; - comboBox3.Location = new Point(7, 96); + comboBox3.Location = new Point(10, 96); comboBox3.Margin = new Padding(3, 4, 3, 4); comboBox3.Name = "comboBox3"; comboBox3.Size = new Size(219, 28); @@ -194,7 +179,7 @@ private void InitializeComponent() // comboBox4 // comboBox4.FormattingEnabled = true; - comboBox4.Location = new Point(7, 132); + comboBox4.Location = new Point(10, 132); comboBox4.Margin = new Padding(3, 4, 3, 4); comboBox4.Name = "comboBox4"; comboBox4.Size = new Size(219, 28); @@ -203,7 +188,7 @@ private void InitializeComponent() // comboBox5 // comboBox5.FormattingEnabled = true; - comboBox5.Location = new Point(7, 168); + comboBox5.Location = new Point(10, 168); comboBox5.Margin = new Padding(3, 4, 3, 4); comboBox5.Name = "comboBox5"; comboBox5.Size = new Size(219, 28); @@ -212,7 +197,7 @@ private void InitializeComponent() // comboBox6 // comboBox6.FormattingEnabled = true; - comboBox6.Location = new Point(7, 204); + comboBox6.Location = new Point(10, 204); comboBox6.Margin = new Padding(3, 4, 3, 4); comboBox6.Name = "comboBox6"; comboBox6.Size = new Size(219, 28); @@ -221,7 +206,7 @@ private void InitializeComponent() // comboBox7 // comboBox7.FormattingEnabled = true; - comboBox7.Location = new Point(7, 240); + comboBox7.Location = new Point(10, 240); comboBox7.Margin = new Padding(3, 4, 3, 4); comboBox7.Name = "comboBox7"; comboBox7.Size = new Size(219, 28); @@ -230,7 +215,7 @@ private void InitializeComponent() // comboBox8 // comboBox8.FormattingEnabled = true; - comboBox8.Location = new Point(7, 276); + comboBox8.Location = new Point(10, 276); comboBox8.Margin = new Padding(3, 4, 3, 4); comboBox8.Name = "comboBox8"; comboBox8.Size = new Size(219, 28); @@ -239,7 +224,7 @@ private void InitializeComponent() // comboBox9 // comboBox9.FormattingEnabled = true; - comboBox9.Location = new Point(7, 312); + comboBox9.Location = new Point(10, 312); comboBox9.Margin = new Padding(3, 4, 3, 4); comboBox9.Name = "comboBox9"; comboBox9.Size = new Size(219, 28); @@ -248,7 +233,7 @@ private void InitializeComponent() // comboBox10 // comboBox10.FormattingEnabled = true; - comboBox10.Location = new Point(7, 348); + comboBox10.Location = new Point(10, 348); comboBox10.Margin = new Padding(3, 4, 3, 4); comboBox10.Name = "comboBox10"; comboBox10.Size = new Size(219, 28); @@ -257,7 +242,7 @@ private void InitializeComponent() // comboBox11 // comboBox11.FormattingEnabled = true; - comboBox11.Location = new Point(7, 384); + comboBox11.Location = new Point(10, 384); comboBox11.Margin = new Padding(3, 4, 3, 4); comboBox11.Name = "comboBox11"; comboBox11.Size = new Size(219, 28); @@ -266,7 +251,7 @@ private void InitializeComponent() // comboBox12 // comboBox12.FormattingEnabled = true; - comboBox12.Location = new Point(7, 420); + comboBox12.Location = new Point(10, 420); comboBox12.Margin = new Padding(3, 4, 3, 4); comboBox12.Name = "comboBox12"; comboBox12.Size = new Size(219, 28); @@ -275,7 +260,7 @@ private void InitializeComponent() // comboBox13 // comboBox13.FormattingEnabled = true; - comboBox13.Location = new Point(7, 456); + comboBox13.Location = new Point(10, 456); comboBox13.Margin = new Padding(3, 4, 3, 4); comboBox13.Name = "comboBox13"; comboBox13.Size = new Size(219, 28); @@ -284,7 +269,7 @@ private void InitializeComponent() // comboBox14 // comboBox14.FormattingEnabled = true; - comboBox14.Location = new Point(7, 492); + comboBox14.Location = new Point(10, 492); comboBox14.Margin = new Padding(3, 4, 3, 4); comboBox14.Name = "comboBox14"; comboBox14.Size = new Size(219, 28); @@ -293,7 +278,7 @@ private void InitializeComponent() // comboBox15 // comboBox15.FormattingEnabled = true; - comboBox15.Location = new Point(7, 528); + comboBox15.Location = new Point(10, 528); comboBox15.Margin = new Padding(3, 4, 3, 4); comboBox15.Name = "comboBox15"; comboBox15.Size = new Size(219, 28); @@ -302,106 +287,78 @@ private void InitializeComponent() // comboBox16 // comboBox16.FormattingEnabled = true; - comboBox16.Location = new Point(7, 564); + comboBox16.Location = new Point(10, 564); comboBox16.Margin = new Padding(3, 4, 3, 4); comboBox16.Name = "comboBox16"; comboBox16.Size = new Size(219, 28); comboBox16.TabIndex = 15; // - // comboBox17 - // - comboBox17.FormattingEnabled = true; - comboBox17.Location = new Point(7, 600); - comboBox17.Margin = new Padding(3, 4, 3, 4); - comboBox17.Name = "comboBox17"; - comboBox17.Size = new Size(219, 28); - comboBox17.TabIndex = 16; - // - // comboBox18 - // - comboBox18.FormattingEnabled = true; - comboBox18.Location = new Point(7, 636); - comboBox18.Margin = new Padding(3, 4, 3, 4); - comboBox18.Name = "comboBox18"; - comboBox18.Size = new Size(219, 28); - comboBox18.TabIndex = 17; - // - // comboBox19 - // - comboBox19.FormattingEnabled = true; - comboBox19.Location = new Point(7, 672); - comboBox19.Margin = new Padding(3, 4, 3, 4); - comboBox19.Name = "comboBox19"; - comboBox19.Size = new Size(219, 28); - comboBox19.TabIndex = 18; - // - // comboBox20 - // - comboBox20.FormattingEnabled = true; - comboBox20.Location = new Point(7, 708); - comboBox20.Margin = new Padding(3, 4, 3, 4); - comboBox20.Name = "comboBox20"; - comboBox20.Size = new Size(219, 28); - comboBox20.TabIndex = 19; - // // grpFilters // grpFilters.Controls.Add(grpEncounter); grpFilters.Controls.Add(btnApply); - grpFilters.Controls.Add(chkAccurateSearch); grpFilters.Controls.Add(grpItems); grpFilters.Controls.Add(btnReset); grpFilters.Location = new Point(14, 12); grpFilters.Margin = new Padding(3, 4, 3, 4); grpFilters.Name = "grpFilters"; grpFilters.Padding = new Padding(3, 4, 3, 4); - grpFilters.Size = new Size(343, 949); + grpFilters.Size = new Size(343, 905); grpFilters.TabIndex = 20; grpFilters.TabStop = false; grpFilters.Text = "Filters"; // // grpEncounter // - grpEncounter.Controls.Add(chkShiny); + grpEncounter.Controls.Add(cmbShiny); + grpEncounter.Controls.Add(lblShiny); grpEncounter.Controls.Add(cmbStars); grpEncounter.Controls.Add(lblStars); grpEncounter.Controls.Add(cmbSpecies); grpEncounter.Controls.Add(lblSpecies); - grpEncounter.Location = new Point(7, 60); + grpEncounter.Location = new Point(7, 28); grpEncounter.Margin = new Padding(3, 4, 3, 4); grpEncounter.Name = "grpEncounter"; grpEncounter.Padding = new Padding(3, 4, 3, 4); - grpEncounter.Size = new Size(330, 96); + grpEncounter.Size = new Size(330, 201); grpEncounter.TabIndex = 25; grpEncounter.TabStop = false; grpEncounter.Text = "Encounter"; // - // chkShiny + // cmbShiny // - chkShiny.AutoSize = true; - chkShiny.Location = new Point(191, 64); - chkShiny.Margin = new Padding(3, 4, 3, 4); - chkShiny.Name = "chkShiny"; - chkShiny.Size = new Size(100, 24); - chkShiny.TabIndex = 24; - chkShiny.Text = "Only Shiny"; - chkShiny.UseVisualStyleBackColor = true; + cmbShiny.FormattingEnabled = true; + cmbShiny.Items.AddRange(new object[] { "Any", "No", "Yes", "Star", "Square" }); + cmbShiny.Location = new Point(111, 130); + cmbShiny.Name = "cmbShiny"; + cmbShiny.Size = new Size(187, 28); + cmbShiny.TabIndex = 5; + // + // lblShiny + // + lblShiny.AutoSize = true; + lblShiny.Location = new Point(26, 133); + lblShiny.Name = "lblShiny"; + lblShiny.Size = new Size(47, 20); + lblShiny.TabIndex = 4; + lblShiny.Text = "Shiny:"; // // cmbStars // cmbStars.FormattingEnabled = true; cmbStars.Items.AddRange(new object[] { "Any", "1☆", "2☆", "3☆", "4☆", "5☆", "6☆", "7☆" }); - cmbStars.Location = new Point(104, 60); + cmbStars.Location = new Point(111, 59); cmbStars.Margin = new Padding(3, 4, 3, 4); cmbStars.Name = "cmbStars"; - cmbStars.Size = new Size(65, 28); + cmbStars.Size = new Size(187, 28); cmbStars.TabIndex = 3; + cmbStars.SelectedIndexChanged += cmbStars_IndexChanged; // // lblStars // lblStars.AutoSize = true; - lblStars.Font = new Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point); - lblStars.Location = new Point(19, 63); + lblStars.Font = new Font("Segoe UI", 9F); + lblStars.Location = new Point(26, 62); lblStars.Name = "lblStars"; lblStars.Size = new Size(44, 20); lblStars.TabIndex = 2; @@ -411,7 +368,7 @@ private void InitializeComponent() // cmbSpecies.FormattingEnabled = true; cmbSpecies.Items.AddRange(new object[] { "Any" }); - cmbSpecies.Location = new Point(104, 26); + cmbSpecies.Location = new Point(111, 95); cmbSpecies.Margin = new Padding(3, 4, 3, 4); cmbSpecies.Name = "cmbSpecies"; cmbSpecies.Size = new Size(187, 28); @@ -420,7 +377,7 @@ private void InitializeComponent() // lblSpecies // lblSpecies.AutoSize = true; - lblSpecies.Location = new Point(19, 29); + lblSpecies.Location = new Point(26, 98); lblSpecies.Name = "lblSpecies"; lblSpecies.Size = new Size(62, 20); lblSpecies.TabIndex = 0; @@ -428,26 +385,15 @@ private void InitializeComponent() // // btnApply // - btnApply.Location = new Point(181, 900); + btnApply.Location = new Point(180, 850); btnApply.Margin = new Padding(3, 4, 3, 4); btnApply.Name = "btnApply"; - btnApply.Size = new Size(157, 41); + btnApply.Size = new Size(156, 41); btnApply.TabIndex = 24; btnApply.Text = "Apply Filters"; btnApply.UseVisualStyleBackColor = true; btnApply.Click += btnApply_Click; // - // chkAccurateSearch - // - chkAccurateSearch.AutoSize = true; - chkAccurateSearch.Location = new Point(75, 31); - chkAccurateSearch.Margin = new Padding(3, 4, 3, 4); - chkAccurateSearch.Name = "chkAccurateSearch"; - chkAccurateSearch.Size = new Size(158, 24); - chkAccurateSearch.TabIndex = 21; - chkAccurateSearch.Text = "Accurate Search (?)"; - chkAccurateSearch.UseVisualStyleBackColor = true; - // // grpItems // grpItems.Controls.Add(label1); @@ -466,14 +412,6 @@ private void InitializeComponent() grpItems.Controls.Add(label14); grpItems.Controls.Add(label15); grpItems.Controls.Add(label16); - grpItems.Controls.Add(label17); - grpItems.Controls.Add(label18); - grpItems.Controls.Add(label19); - grpItems.Controls.Add(label20); - grpItems.Controls.Add(numericUpDown20); - grpItems.Controls.Add(numericUpDown19); - grpItems.Controls.Add(numericUpDown18); - grpItems.Controls.Add(numericUpDown17); grpItems.Controls.Add(numericUpDown16); grpItems.Controls.Add(numericUpDown15); grpItems.Controls.Add(numericUpDown14); @@ -490,18 +428,14 @@ private void InitializeComponent() grpItems.Controls.Add(numericUpDown3); grpItems.Controls.Add(numericUpDown2); grpItems.Controls.Add(numericUpDown1); - grpItems.Controls.Add(comboBox20); grpItems.Controls.Add(comboBox1); grpItems.Controls.Add(comboBox10); - grpItems.Controls.Add(comboBox19); grpItems.Controls.Add(comboBox11); grpItems.Controls.Add(comboBox2); grpItems.Controls.Add(comboBox9); - grpItems.Controls.Add(comboBox18); grpItems.Controls.Add(comboBox12); grpItems.Controls.Add(comboBox3); grpItems.Controls.Add(comboBox8); - grpItems.Controls.Add(comboBox17); grpItems.Controls.Add(comboBox13); grpItems.Controls.Add(comboBox4); grpItems.Controls.Add(comboBox7); @@ -510,11 +444,11 @@ private void InitializeComponent() grpItems.Controls.Add(comboBox5); grpItems.Controls.Add(comboBox6); grpItems.Controls.Add(comboBox15); - grpItems.Location = new Point(7, 156); + grpItems.Location = new Point(6, 237); grpItems.Margin = new Padding(3, 4, 3, 4); grpItems.Name = "grpItems"; grpItems.Padding = new Padding(3, 4, 3, 4); - grpItems.Size = new Size(331, 741); + grpItems.Size = new Size(330, 599); grpItems.TabIndex = 21; grpItems.TabStop = false; grpItems.Text = "Items"; @@ -522,7 +456,7 @@ private void InitializeComponent() // label1 // label1.AutoSize = true; - label1.Location = new Point(235, 28); + label1.Location = new Point(238, 28); label1.Name = "label1"; label1.Size = new Size(29, 20); label1.TabIndex = 21; @@ -531,7 +465,7 @@ private void InitializeComponent() // label2 // label2.AutoSize = true; - label2.Location = new Point(235, 64); + label2.Location = new Point(238, 64); label2.Name = "label2"; label2.Size = new Size(29, 20); label2.TabIndex = 22; @@ -540,7 +474,7 @@ private void InitializeComponent() // label3 // label3.AutoSize = true; - label3.Location = new Point(235, 100); + label3.Location = new Point(238, 100); label3.Name = "label3"; label3.Size = new Size(29, 20); label3.TabIndex = 23; @@ -549,7 +483,7 @@ private void InitializeComponent() // label4 // label4.AutoSize = true; - label4.Location = new Point(235, 136); + label4.Location = new Point(238, 136); label4.Name = "label4"; label4.Size = new Size(29, 20); label4.TabIndex = 24; @@ -558,7 +492,7 @@ private void InitializeComponent() // label5 // label5.AutoSize = true; - label5.Location = new Point(235, 171); + label5.Location = new Point(238, 171); label5.Name = "label5"; label5.Size = new Size(29, 20); label5.TabIndex = 25; @@ -567,7 +501,7 @@ private void InitializeComponent() // label6 // label6.AutoSize = true; - label6.Location = new Point(235, 208); + label6.Location = new Point(238, 208); label6.Name = "label6"; label6.Size = new Size(29, 20); label6.TabIndex = 26; @@ -576,7 +510,7 @@ private void InitializeComponent() // label7 // label7.AutoSize = true; - label7.Location = new Point(235, 244); + label7.Location = new Point(238, 244); label7.Name = "label7"; label7.Size = new Size(29, 20); label7.TabIndex = 27; @@ -585,7 +519,7 @@ private void InitializeComponent() // label8 // label8.AutoSize = true; - label8.Location = new Point(235, 280); + label8.Location = new Point(238, 280); label8.Name = "label8"; label8.Size = new Size(29, 20); label8.TabIndex = 28; @@ -594,7 +528,7 @@ private void InitializeComponent() // label9 // label9.AutoSize = true; - label9.Location = new Point(235, 316); + label9.Location = new Point(238, 316); label9.Name = "label9"; label9.Size = new Size(29, 20); label9.TabIndex = 29; @@ -603,7 +537,7 @@ private void InitializeComponent() // label10 // label10.AutoSize = true; - label10.Location = new Point(235, 352); + label10.Location = new Point(238, 352); label10.Name = "label10"; label10.Size = new Size(29, 20); label10.TabIndex = 30; @@ -612,7 +546,7 @@ private void InitializeComponent() // label11 // label11.AutoSize = true; - label11.Location = new Point(235, 388); + label11.Location = new Point(238, 388); label11.Name = "label11"; label11.Size = new Size(29, 20); label11.TabIndex = 31; @@ -621,7 +555,7 @@ private void InitializeComponent() // label12 // label12.AutoSize = true; - label12.Location = new Point(235, 424); + label12.Location = new Point(238, 424); label12.Name = "label12"; label12.Size = new Size(29, 20); label12.TabIndex = 32; @@ -630,7 +564,7 @@ private void InitializeComponent() // label13 // label13.AutoSize = true; - label13.Location = new Point(235, 460); + label13.Location = new Point(238, 460); label13.Name = "label13"; label13.Size = new Size(29, 20); label13.TabIndex = 33; @@ -639,7 +573,7 @@ private void InitializeComponent() // label14 // label14.AutoSize = true; - label14.Location = new Point(235, 496); + label14.Location = new Point(238, 496); label14.Name = "label14"; label14.Size = new Size(29, 20); label14.TabIndex = 34; @@ -648,7 +582,7 @@ private void InitializeComponent() // label15 // label15.AutoSize = true; - label15.Location = new Point(235, 532); + label15.Location = new Point(238, 532); label15.Name = "label15"; label15.Size = new Size(29, 20); label15.TabIndex = 35; @@ -657,87 +591,15 @@ private void InitializeComponent() // label16 // label16.AutoSize = true; - label16.Location = new Point(235, 568); + label16.Location = new Point(238, 568); label16.Name = "label16"; label16.Size = new Size(29, 20); label16.TabIndex = 36; label16.Text = ">="; // - // label17 - // - label17.AutoSize = true; - label17.Location = new Point(235, 604); - label17.Name = "label17"; - label17.Size = new Size(29, 20); - label17.TabIndex = 37; - label17.Text = ">="; - // - // label18 - // - label18.AutoSize = true; - label18.Location = new Point(235, 640); - label18.Name = "label18"; - label18.Size = new Size(29, 20); - label18.TabIndex = 38; - label18.Text = ">="; - // - // label19 - // - label19.AutoSize = true; - label19.Location = new Point(235, 675); - label19.Name = "label19"; - label19.Size = new Size(29, 20); - label19.TabIndex = 39; - label19.Text = ">="; - // - // label20 - // - label20.AutoSize = true; - label20.Location = new Point(235, 712); - label20.Name = "label20"; - label20.Size = new Size(29, 20); - label20.TabIndex = 40; - label20.Text = ">="; - // - // numericUpDown20 - // - numericUpDown20.Location = new Point(264, 708); - numericUpDown20.Margin = new Padding(3, 4, 3, 4); - numericUpDown20.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); - numericUpDown20.Name = "numericUpDown20"; - numericUpDown20.Size = new Size(51, 27); - numericUpDown20.TabIndex = 39; - // - // numericUpDown19 - // - numericUpDown19.Location = new Point(264, 672); - numericUpDown19.Margin = new Padding(3, 4, 3, 4); - numericUpDown19.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); - numericUpDown19.Name = "numericUpDown19"; - numericUpDown19.Size = new Size(51, 27); - numericUpDown19.TabIndex = 38; - // - // numericUpDown18 - // - numericUpDown18.Location = new Point(264, 636); - numericUpDown18.Margin = new Padding(3, 4, 3, 4); - numericUpDown18.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); - numericUpDown18.Name = "numericUpDown18"; - numericUpDown18.Size = new Size(51, 27); - numericUpDown18.TabIndex = 37; - // - // numericUpDown17 - // - numericUpDown17.Location = new Point(264, 600); - numericUpDown17.Margin = new Padding(3, 4, 3, 4); - numericUpDown17.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); - numericUpDown17.Name = "numericUpDown17"; - numericUpDown17.Size = new Size(51, 27); - numericUpDown17.TabIndex = 36; - // // numericUpDown16 // - numericUpDown16.Location = new Point(264, 564); + numericUpDown16.Location = new Point(267, 564); numericUpDown16.Margin = new Padding(3, 4, 3, 4); numericUpDown16.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown16.Name = "numericUpDown16"; @@ -746,7 +608,7 @@ private void InitializeComponent() // // numericUpDown15 // - numericUpDown15.Location = new Point(264, 528); + numericUpDown15.Location = new Point(267, 528); numericUpDown15.Margin = new Padding(3, 4, 3, 4); numericUpDown15.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown15.Name = "numericUpDown15"; @@ -755,7 +617,7 @@ private void InitializeComponent() // // numericUpDown14 // - numericUpDown14.Location = new Point(264, 492); + numericUpDown14.Location = new Point(267, 492); numericUpDown14.Margin = new Padding(3, 4, 3, 4); numericUpDown14.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown14.Name = "numericUpDown14"; @@ -764,7 +626,7 @@ private void InitializeComponent() // // numericUpDown13 // - numericUpDown13.Location = new Point(264, 456); + numericUpDown13.Location = new Point(267, 456); numericUpDown13.Margin = new Padding(3, 4, 3, 4); numericUpDown13.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown13.Name = "numericUpDown13"; @@ -773,7 +635,7 @@ private void InitializeComponent() // // numericUpDown12 // - numericUpDown12.Location = new Point(264, 420); + numericUpDown12.Location = new Point(267, 420); numericUpDown12.Margin = new Padding(3, 4, 3, 4); numericUpDown12.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown12.Name = "numericUpDown12"; @@ -782,7 +644,7 @@ private void InitializeComponent() // // numericUpDown11 // - numericUpDown11.Location = new Point(264, 384); + numericUpDown11.Location = new Point(267, 384); numericUpDown11.Margin = new Padding(3, 4, 3, 4); numericUpDown11.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown11.Name = "numericUpDown11"; @@ -791,7 +653,7 @@ private void InitializeComponent() // // numericUpDown10 // - numericUpDown10.Location = new Point(264, 348); + numericUpDown10.Location = new Point(267, 348); numericUpDown10.Margin = new Padding(3, 4, 3, 4); numericUpDown10.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown10.Name = "numericUpDown10"; @@ -800,7 +662,7 @@ private void InitializeComponent() // // numericUpDown9 // - numericUpDown9.Location = new Point(264, 312); + numericUpDown9.Location = new Point(267, 312); numericUpDown9.Margin = new Padding(3, 4, 3, 4); numericUpDown9.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown9.Name = "numericUpDown9"; @@ -809,7 +671,7 @@ private void InitializeComponent() // // numericUpDown8 // - numericUpDown8.Location = new Point(264, 276); + numericUpDown8.Location = new Point(267, 276); numericUpDown8.Margin = new Padding(3, 4, 3, 4); numericUpDown8.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown8.Name = "numericUpDown8"; @@ -818,7 +680,7 @@ private void InitializeComponent() // // numericUpDown7 // - numericUpDown7.Location = new Point(264, 240); + numericUpDown7.Location = new Point(267, 240); numericUpDown7.Margin = new Padding(3, 4, 3, 4); numericUpDown7.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown7.Name = "numericUpDown7"; @@ -827,7 +689,7 @@ private void InitializeComponent() // // numericUpDown6 // - numericUpDown6.Location = new Point(264, 204); + numericUpDown6.Location = new Point(267, 204); numericUpDown6.Margin = new Padding(3, 4, 3, 4); numericUpDown6.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown6.Name = "numericUpDown6"; @@ -836,7 +698,7 @@ private void InitializeComponent() // // numericUpDown5 // - numericUpDown5.Location = new Point(264, 168); + numericUpDown5.Location = new Point(267, 168); numericUpDown5.Margin = new Padding(3, 4, 3, 4); numericUpDown5.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown5.Name = "numericUpDown5"; @@ -845,7 +707,7 @@ private void InitializeComponent() // // numericUpDown4 // - numericUpDown4.Location = new Point(264, 132); + numericUpDown4.Location = new Point(267, 132); numericUpDown4.Margin = new Padding(3, 4, 3, 4); numericUpDown4.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown4.Name = "numericUpDown4"; @@ -854,7 +716,7 @@ private void InitializeComponent() // // numericUpDown3 // - numericUpDown3.Location = new Point(264, 96); + numericUpDown3.Location = new Point(267, 96); numericUpDown3.Margin = new Padding(3, 4, 3, 4); numericUpDown3.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown3.Name = "numericUpDown3"; @@ -863,7 +725,7 @@ private void InitializeComponent() // // numericUpDown2 // - numericUpDown2.Location = new Point(264, 60); + numericUpDown2.Location = new Point(267, 60); numericUpDown2.Margin = new Padding(3, 4, 3, 4); numericUpDown2.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown2.Name = "numericUpDown2"; @@ -872,7 +734,7 @@ private void InitializeComponent() // // numericUpDown1 // - numericUpDown1.Location = new Point(264, 24); + numericUpDown1.Location = new Point(267, 24); numericUpDown1.Margin = new Padding(3, 4, 3, 4); numericUpDown1.Maximum = new decimal(new int[] { 999, 0, 0, 0 }); numericUpDown1.Name = "numericUpDown1"; @@ -881,10 +743,10 @@ private void InitializeComponent() // // btnReset // - btnReset.Location = new Point(7, 900); + btnReset.Location = new Point(7, 850); btnReset.Margin = new Padding(3, 4, 3, 4); btnReset.Name = "btnReset"; - btnReset.Size = new Size(157, 41); + btnReset.Size = new Size(156, 41); btnReset.TabIndex = 23; btnReset.Text = "Reset Filters"; btnReset.UseVisualStyleBackColor = true; @@ -955,6 +817,7 @@ private void InitializeComponent() cmbProgress.Name = "cmbProgress"; cmbProgress.Size = new Size(138, 28); cmbProgress.TabIndex = 22; + cmbProgress.SelectedIndexChanged += cmbProgress_IndexChanged; // // lblTID // @@ -1042,6 +905,7 @@ private void InitializeComponent() cmbContent.Name = "cmbContent"; cmbContent.Size = new Size(129, 28); cmbContent.TabIndex = 24; + cmbContent.SelectedIndexChanged += cmbContent_IndexChanged; // // cmbMap // @@ -1050,6 +914,7 @@ private void InitializeComponent() cmbMap.Name = "cmbMap"; cmbMap.Size = new Size(129, 28); cmbMap.TabIndex = 28; + cmbMap.SelectedIndexChanged += cmbMap_IndexChanged; // // numMaxCalc // @@ -1110,6 +975,7 @@ private void InitializeComponent() // // grpSearch // + grpSearch.Controls.Add(lblTime); grpSearch.Controls.Add(lblFound); grpSearch.Controls.Add(chkAllResults); grpSearch.Controls.Add(btnSearch); @@ -1122,6 +988,16 @@ private void InitializeComponent() grpSearch.TabStop = false; grpSearch.Text = "Search"; // + // lblTime + // + lblTime.AutoSize = true; + lblTime.Location = new Point(1001, 35); + lblTime.Name = "lblTime"; + lblTime.Size = new Size(20, 20); + lblTime.TabIndex = 25; + lblTime.Text = "T:"; + lblTime.Visible = false; + // // lblFound // lblFound.AutoSize = true; @@ -1167,7 +1043,7 @@ private void InitializeComponent() dataGrid.ReadOnly = true; dataGrid.RowHeadersWidth = 51; dataGrid.RowTemplate.Height = 25; - dataGrid.Size = new Size(1165, 716); + dataGrid.Size = new Size(1165, 672); dataGrid.TabIndex = 23; dataGrid.MouseUp += dataGrid_MouseUp; // @@ -1184,7 +1060,7 @@ private void InitializeComponent() contextMenuStrip.ImageScalingSize = new Size(20, 20); contextMenuStrip.Items.AddRange(new ToolStripItem[] { btnSaveAllTxt, btnSaveSelectedTxt, btnSendSelectedRaid, btnCopySeed }); contextMenuStrip.Name = "contextMenuStrip"; - contextMenuStrip.Size = new Size(313, 128); + contextMenuStrip.Size = new Size(313, 100); // // btnSaveAllTxt // @@ -1218,7 +1094,7 @@ private void InitializeComponent() // AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1540, 964); + ClientSize = new Size(1540, 922); Controls.Add(dataGrid); Controls.Add(grpSearch); Controls.Add(grpSettings); @@ -1230,15 +1106,10 @@ private void InitializeComponent() Text = "Reward Calculator"; FormClosing += Form_FormClosing; grpFilters.ResumeLayout(false); - grpFilters.PerformLayout(); grpEncounter.ResumeLayout(false); grpEncounter.PerformLayout(); grpItems.ResumeLayout(false); grpItems.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)numericUpDown20).EndInit(); - ((System.ComponentModel.ISupportInitialize)numericUpDown19).EndInit(); - ((System.ComponentModel.ISupportInitialize)numericUpDown18).EndInit(); - ((System.ComponentModel.ISupportInitialize)numericUpDown17).EndInit(); ((System.ComponentModel.ISupportInitialize)numericUpDown16).EndInit(); ((System.ComponentModel.ISupportInitialize)numericUpDown15).EndInit(); ((System.ComponentModel.ISupportInitialize)numericUpDown14).EndInit(); @@ -1285,10 +1156,6 @@ private void InitializeComponent() private ComboBox comboBox14; private ComboBox comboBox15; private ComboBox comboBox16; - private ComboBox comboBox17; - private ComboBox comboBox18; - private ComboBox comboBox19; - private ComboBox comboBox20; private GroupBox grpFilters; private GroupBox grpItems; private ToolTip toolTip; @@ -1308,14 +1175,6 @@ private void InitializeComponent() private Label label14; private Label label15; private Label label16; - private Label label17; - private Label label18; - private Label label19; - private Label label20; - private NumericUpDown numericUpDown20; - private NumericUpDown numericUpDown19; - private NumericUpDown numericUpDown18; - private NumericUpDown numericUpDown17; private NumericUpDown numericUpDown16; private NumericUpDown numericUpDown15; private NumericUpDown numericUpDown14; @@ -1360,16 +1219,17 @@ private void InitializeComponent() private ToolStripMenuItem btnSendSelectedRaid; public TextBox txtSID; public TextBox txtTID; - public CheckBox chkAccurateSearch; public ComboBox cmbContent; private GroupBox grpEncounter; private ComboBox cmbStars; private Label lblStars; private ComboBox cmbSpecies; private Label lblSpecies; - private CheckBox chkShiny; private Label lblFound; private Label lblMap; private ComboBox cmbMap; private ToolStripMenuItem btnCopySeed; + private Label lblTime; + private ComboBox cmbShiny; + private Label lblShiny; } \ No newline at end of file diff --git a/TeraFinder.Plugins/Forms/RewardCalcForm.cs b/TeraFinder.Plugins/Forms/RewardCalcForm.cs index bec06c71..6f045536 100644 --- a/TeraFinder.Plugins/Forms/RewardCalcForm.cs +++ b/TeraFinder.Plugins/Forms/RewardCalcForm.cs @@ -1,4 +1,5 @@ using PKHeX.Core; +using System.Collections.Concurrent; using TeraFinder.Core; namespace TeraFinder.Plugins; @@ -6,18 +7,21 @@ namespace TeraFinder.Plugins; public partial class RewardCalcForm : Form { public EditorForm Editor = null!; - private readonly List CalculatedList = []; private RewardFilter? Filter = null; public string[] SpeciesNames = null!; + public string[] FormNames = null!; + public string[] TypeNames = null!; public string[] ShinyNames = null!; public string[] Items = null!; + public string[] GenderListAscii = null!; + public string[] GenderListUnicode = null!; + private CancellationTokenSource Token = new(); + private readonly ConcurrentBag CalculatedList = []; + private readonly ConcurrentList GridEntries = []; private Dictionary Strings = null!; - public int CurrentViewedIndex = 0; - public bool NotLinkedSearch = true; - public RewardCalcForm(EditorForm editor) { InitializeComponent(); @@ -32,6 +36,11 @@ public RewardCalcForm(EditorForm editor) ShinyNames = [Strings["TeraShiny.Any"], Strings["TeraShiny.No"], Strings["TeraShiny.Yes"], Strings["TeraShiny.Star"], Strings["TeraShiny.Square"]]; SpeciesNames = GameInfo.GetStrings(editor.Language).specieslist; + FormNames = GameInfo.GetStrings(Editor.Language).forms; + TypeNames = GameInfo.GetStrings(Editor.Language).types; + GenderListAscii = [.. GameInfo.GenderSymbolASCII]; + GenderListUnicode = [.. GameInfo.GenderSymbolUnicode]; + cmbSpecies.Items[0] = Strings["Any"]; cmbSpecies.Items.AddRange(SpeciesNames[1..]); cmbSpecies.SelectedIndex = 0; @@ -46,10 +55,9 @@ public RewardCalcForm(EditorForm editor) }; cbitems.AddRange(Items[1..]); - var items = cbitems.ToArray(); foreach (var cb in grpItems.Controls.OfType()) { - cb.Items.AddRange(items); + cb.Items.AddRange(cbitems.ToArray()); cb.SelectedIndex = 0; } @@ -59,12 +67,13 @@ public RewardCalcForm(EditorForm editor) num.Minimum = 1; } - var progress = (int)(Editor.Progress == GameProgress.None ? 0 : Editor.Progress); + var progress = (int)editor.Progress; cmbProgress.SelectedIndex = progress; cmbGame.SelectedIndex = Editor.SAV.Version == GameVersion.VL ? 1 : 0; txtTID.Text = $"{Editor.SAV.TrainerTID7}"; txtSID.Text = $"{Editor.SAV.TrainerSID7}"; if (!IsBlankSAV()) grpProfile.Enabled = false; + txtSeed.Text = Editor.txtSeed.Text; cmbContent.SelectedIndex = Editor.cmbContent.SelectedIndex; cmbBoost.SelectedIndex = 0; @@ -73,12 +82,23 @@ public RewardCalcForm(EditorForm editor) cmbMap.Items.Add(Strings["Plugin.MapPaldea"]); cmbMap.Items.Add(Strings["Plugin.MapKitakami"]); cmbMap.Items.Add(Strings["Plugin.MapBlueberry"]); + cmbMap.SelectedIndex = (int)Editor.CurrMap; + cmbSpecies.SelectedIndex = 0; + cmbShiny.SelectedIndex = 0; + + if (Editor.CurrEncount is { Stars: > 0 }) + { + var index = cmbStars.Items.Cast().ToList().FindIndex(stars => byte.TryParse($"{stars[0]}", out var res) && res == Editor.CurrEncount.Stars); + if (index != -1) + cmbStars.SelectedIndex = index; + } + - toolTip.SetToolTip(chkAccurateSearch, Strings["ToolTipAccurate"]); toolTip1.SetToolTip(chkAllResults, Strings["ToolTipAllResults"]); TranslateCmbProgress(); + TranslateCmbShiny(); TranslateCmbGame(); TranslateCmbContent(); TranslateCmbBoost(); @@ -92,6 +112,7 @@ private void GenerateDictionary() Strings = new Dictionary { { "Any", "Any" }, + { "StarsAbbreviation", "S" }, { "AnyHerba", "Any Herba Mystica" }, { "Found", "Found" }, { "True", "True" }, @@ -132,11 +153,22 @@ private void GenerateDictionary() { "Plugin.MapPaldea", "Paldea" }, { "Plugin.MapKitakami", "Kitakami" }, { "Plugin.MapBlueberry", "Blueberry" }, + { "CalculatorForm.lblTime", "T:" }, + { "WarningNoEncounter", "" }, }; } private void TranslateDictionary(string language) => Strings = Strings.TranslateInnerStrings(language); + private void TranslateCmbShiny() + { + cmbShiny.Items[0] = Strings["TeraShiny.Any"]; + cmbShiny.Items[1] = Strings["TeraShiny.No"]; + cmbShiny.Items[2] = Strings["TeraShiny.Yes"]; + cmbShiny.Items[3] = Strings["TeraShiny.Star"]; + cmbShiny.Items[4] = Strings["TeraShiny.Square"]; + } + private void TranslateCmbProgress() { cmbProgress.Items[0] = Strings["GameProgress.Beginning"]; @@ -193,37 +225,177 @@ private void txtID_KeyPress(object sender, KeyPressEventArgs e) private bool IsBlankSAV() { - if (Editor.Progress is GameProgress.Beginning or GameProgress.None) + if (Editor.Progress is GameProgress.Beginning) return true; return false; } - private void btnApply_Click(object sender, EventArgs e) + private void cmbMap_IndexChanged(object sender, EventArgs e) + { + EncounterRaidTF9[] encs = GetCurrentEncounters(); + var species = EncounterRaidTF9.GetAvailableSpecies(encs, GetStars(), SpeciesNames, FormNames, TypeNames, Strings); + cmbSpecies.Items.Clear(); + cmbSpecies.Items.Add(Strings["Any"]); + cmbSpecies.Items.AddRange([.. species]); + cmbSpecies.SelectedIndex = 0; + } + + private void cmbContent_IndexChanged(object sender, EventArgs e) => UpdateCmbStars(sender, e); + private void cmbProgress_IndexChanged(object sender, EventArgs e) => UpdateCmbStars(sender, e); + + private void UpdateCmbStars(object sender, EventArgs e) + { + if (cmbContent.SelectedIndex == -1 || cmbProgress.SelectedIndex == -1 || cmbGame.SelectedIndex == -1) + return; + + var stars = TranslatedStars(); + if (cmbContent.SelectedIndex == 0 && cmbProgress.SelectedIndex == 1) + stars = [stars[1], stars[2]]; + else if (cmbContent.SelectedIndex == 0 && cmbProgress.SelectedIndex == 2) + stars = [stars[1], stars[2], stars[3]]; + else if (cmbContent.SelectedIndex == 0 && cmbProgress.SelectedIndex == 3) + stars = [stars[1], stars[2], stars[3], stars[4]]; + else if (cmbContent.SelectedIndex == 0 && cmbProgress.SelectedIndex is 4 or 5) + stars = [stars[3], stars[4], stars[5]]; + + else if (cmbContent.SelectedIndex == 1) + stars = [stars[6]]; + + else if (cmbContent.SelectedIndex == 2) + { + var encounters = (EncounterEventTF9[])GetCurrentEncounters(); + var eventProgress = EventUtil.GetEventStageFromProgress((GameProgress)cmbProgress.SelectedIndex); + var version = cmbGame.SelectedIndex == 1 ? GameVersion.SL : GameVersion.VL; + + var possibleStars = EncounterEventTF9.GetPossibleEventStars(encounters, eventProgress, version); + var starsList = new List(); + + foreach (var s in possibleStars.OrderBy(star => star)) + starsList.Add(stars[s]); + + if (starsList.Count > 0) + stars = [.. starsList]; + else + stars = [stars[0]]; + } + + else if (cmbContent.SelectedIndex == 3) + stars = [stars[7]]; + + cmbStars.Items.Clear(); + cmbStars.Items.AddRange(stars); + if (cmbStars.SelectedIndex == 0) + cmbStars_IndexChanged(sender, e); + cmbStars.SelectedIndex = 0; + } + + private void cmbStars_IndexChanged(object sender, EventArgs e) + { + if (cmbContent.SelectedIndex != -1 && cmbMap.SelectedIndex != -1) + { + EncounterRaidTF9[] encs = GetCurrentEncounters(); + var species = EncounterRaidTF9.GetAvailableSpecies(encs, GetStars(), SpeciesNames, FormNames, TypeNames, Strings); + + cmbSpecies.Items.Clear(); + cmbSpecies.Items.Add(Strings["Any"]); + cmbSpecies.Items.AddRange([.. species]); + cmbSpecies.SelectedIndex = 0; + } + } + + private byte GetStars() + { + if (cmbStars.Text.Equals(Strings["Any"])) + return 0; + else + return (byte)char.GetNumericValue(cmbStars.Text[0]); + } + + private (ushort species, byte form, byte index) GetSpeciesFormIndex() => GetSpeciesFormIndex(cmbSpecies.Text); + + private (ushort species, byte form, byte index) GetSpeciesFormIndex(string str) + { + (ushort species, byte form, byte index) result = (0, 0, 0); + str = str.Replace($" ({Strings["GameVersionSL"]})", string.Empty).Replace($" ({Strings["GameVersionVL"]})", string.Empty); + if (!str.Equals(Strings["Any"])) + { + var formLocation = str.IndexOf('-'); + var isForm = Array.IndexOf(SpeciesNames, str) == -1 && formLocation > 0; + + if (byte.TryParse(str[^2].ToString(), out var index) && str[^1] == ')') + { + result.index = index; + str = str[..^4]; + } + if (!isForm) + { + var species = Editor.Language.ToLower().Equals("en") ? str : + GameInfo.GetStrings("en").specieslist[Array.IndexOf(SpeciesNames, str)]; + result.species = (ushort)Enum.Parse(typeof(Species), species.Replace(" ", string.Empty).Replace("-", string.Empty)); + } + else + { + var species = Editor.Language.ToLower().Equals("en") ? str[..formLocation] : + GameInfo.GetStrings("en").specieslist[Array.IndexOf(SpeciesNames, str[..formLocation])]; + result.species = (ushort)Enum.Parse(typeof(Species), species.Replace(" ", string.Empty).Replace("-", string.Empty)); + result.form = ShowdownParsing.GetFormFromString(str.AsSpan()[(formLocation + 1)..], GameInfo.GetStrings(Editor.Language), result.species, EntityContext.Gen9); + } + } + return result; + } + + private EncounterRaidTF9[] GetCurrentEncounters() => (RaidContent)cmbContent.SelectedIndex switch + { + RaidContent.Standard => (TeraRaidMapParent)cmbMap.SelectedIndex switch + { + TeraRaidMapParent.Paldea => Editor.Paldea, + TeraRaidMapParent.Kitakami => Editor.Kitakami, + TeraRaidMapParent.Blueberry => Editor.Blueberry, + _ => throw new NotImplementedException(nameof(cmbMap.SelectedIndex)), + }, + RaidContent.Black => (TeraRaidMapParent)cmbMap.SelectedIndex switch + { + TeraRaidMapParent.Paldea => Editor.PaldeaBlack, + TeraRaidMapParent.Kitakami => Editor.KitakamiBlack, + TeraRaidMapParent.Blueberry => Editor.BlueberryBlack, + _ => throw new NotImplementedException(nameof(cmbMap.SelectedIndex)), + }, + RaidContent.Event => Editor.Dist, + RaidContent.Event_Mighty => Editor.Mighty, + _ => throw new NotImplementedException(nameof(cmbContent.SelectedIndex)), + }; + + private async void btnApply_Click(object sender, EventArgs e) { lblFound.Visible = false; CreateFilter(); - if (Filter is not null && Filter.NeedAccurate()) - chkAccurateSearch.Checked = true; - if (dataGrid.Rows.Count > 0) + if (!CalculatedList.IsEmpty) { - DialogResult d = MessageBox.Show(Strings["FiltersPopup"], Strings["FiltersApply"], MessageBoxButtons.YesNo); - if (d == DialogResult.Yes) + DialogResult dialogue = MessageBox.Show(Strings["FiltersPopup"], Strings["FiltersApply"], MessageBoxButtons.YesNo); + if (dialogue is DialogResult.Yes) { - var list = new List(); - foreach (var c in CalculatedList) - if (Filter is null || Filter.IsFilterMatch(c)) - list.Add(new RewardGridEntry(c, Items, SpeciesNames, ShinyNames, Editor.Language)); - dataGrid.DataSource = list; + dataGrid.DataSource = null; + GridEntries.Clear(); + await Task.Run(() => + { + Parallel.ForEach(CalculatedList, el => + { + if (Filter is null || Filter.IsFilterMatch(el)) + GridEntries.Add(new RewardGridEntry(el, Items, SpeciesNames, ShinyNames, TypeNames, Editor.Language)); + }); + }); + GridEntries.FinalizeElements(); + dataGrid.DataSource = GridEntries; } } + UpdateFoundLabel(); } private void btnReset_Click(object sender, EventArgs e) { - chkAccurateSearch.Checked = false; - chkShiny.Checked = false; + cmbShiny.SelectedIndex = 0; cmbSpecies.SelectedIndex = 0; - cmbStars.SelectedIndex = 0; + //cmbStars.SelectedIndex = 0; foreach (var cb in grpItems.Controls.OfType()) cb.SelectedIndex = 0; foreach (var num in grpItems.Controls.OfType()) @@ -233,10 +405,13 @@ private void btnReset_Click(object sender, EventArgs e) private void CreateFilter() { var items = new List(); - items.Clear(); + var stars = GetStars(); + var entity = GetSpeciesFormIndex(); + var encounterFilter = entity.species > 0 || stars > 0; var anyherba = false; var nums = grpItems.Controls.OfType(); + foreach (var cb in grpItems.Controls.OfType()) { if (cb.SelectedIndex > 0) @@ -249,8 +424,6 @@ private void CreateFilter() } } - var encounterFilter = cmbSpecies.SelectedIndex > 0 || cmbStars.SelectedIndex > 0; - var itemlist = new List(); foreach (var item in items) { @@ -262,9 +435,8 @@ private void CreateFilter() var filter = new RewardFilter(encounterFilter, anyherba) { FilterRewards = [.. itemlist], - Species = (ushort)cmbSpecies.SelectedIndex, - Stars = cmbStars.SelectedIndex, - Shiny = chkShiny.Checked ? TeraShiny.Yes : TeraShiny.Any, + Shiny = (TeraShiny)cmbShiny.SelectedIndex, + Encounter = new EncounterFilter(entity.species, stars), }; if (Filter is null && filter.IsFilterNull()) @@ -296,6 +468,7 @@ private void DisableControls() txtSeed.Enabled = false; numMaxCalc.Enabled = false; cmbMap.Enabled = false; + SetTimeText(false); } private void EnableControls(bool enableProfile = false) @@ -310,34 +483,41 @@ private void EnableControls(bool enableProfile = false) cmbMap.Enabled = true; } - private void UpdateLabel() + private void UpdateFoundLabel() { if (Filter is not null && !Filter.IsFilterNull()) { if (chkAllResults.Checked) try { - lblFound.Text = $"{Strings["Found"]}: {CalculatedList.Count}"; + lblFound.Text = $"{Strings["Found"]}: {GridEntries.Count}"; } catch (Exception) { - lblFound.Text = $"{Strings["Found"]}: {CalculatedList.Count}"; + lblFound.Text = $"{Strings["Found"]}: {GridEntries.LongCount()}"; } else - lblFound.Text = $"{Strings["Found"]} : {(CalculatedList.Count > 0 ? Strings["True"] : Strings["False"])}"; + lblFound.Text = $"{Strings["Found"]}: {(!GridEntries.IsEmpty ? Strings["True"] : Strings["False"])}"; lblFound.Visible = true; } else lblFound.Visible = false; } + private void SetTimeText(bool visible, string time = "") + { + lblTime.Text = $"{Strings["CalculatorForm.lblTime"]} {time}"; + lblTime.Visible = visible; + } + private async void btnSearch_Click(object sender, EventArgs e) { - var species = (ushort)cmbSpecies.SelectedIndex; + (ushort species, byte form, byte index) entity; + if (btnSearch.Text.Equals(Strings["ActionSearch"])) { Token = new(); - if (cmbProgress.SelectedIndex is (int)GameProgress.Beginning or (int)GameProgress.None) + if (cmbProgress.SelectedIndex is (int)GameProgress.Beginning) { cmbProgress.Focus(); return; @@ -352,54 +532,75 @@ private async void btnSearch_Click(object sender, EventArgs e) txtSID.Focus(); return; } + if ((cmbSpecies.Text.Contains(Strings["GameVersionSL"]) && cmbGame.SelectedIndex == 1) || + (cmbSpecies.Text.Contains(Strings["GameVersionVL"]) && cmbGame.SelectedIndex == 0)) + { + cmbSpecies.Focus(); + return; + } + try + { + entity = GetSpeciesFormIndex(); + } + catch (Exception) + { + cmbSpecies.Focus(); + return; + } - if (CalculatedList.Count > 0) + CreateFilter(); + if (Filter is null || Filter.Encounter is null || !Filter.EncounterFilter || Filter.Encounter.Stars == 0) + { + MessageBox.Show(Strings["WarningNoEncounter"]); + cmbStars.Focus(); + return; + } + + if (!CalculatedList.IsEmpty) { + dataGrid.DataSource = null; CalculatedList.Clear(); - dataGrid.DataSource = new List(); + GridEntries.Clear(); } btnSearch.Text = Strings["ActionStop"]; DisableControls(); - ActiveForm!.Update(); - - CreateFilter(); - if (Filter is not null && Filter.NeedAccurate()) - chkAccurateSearch.Checked = true; + //ActiveForm.Update(); var sav = (SAV9SV)Editor.SAV.Clone(); sav.TrainerTID7 = Convert.ToUInt32(txtTID.Text, 10); sav.TrainerSID7 = Convert.ToUInt32(txtSID.Text, 10); - sav.Version = (GameVersion)(cmbGame.SelectedIndex == 0 ? (int)GameVersion.SL : (int)GameVersion.SV); - var progress = (RaidContent)cmbContent.SelectedIndex is RaidContent.Black ? GameProgress.None : (GameProgress)cmbProgress.SelectedIndex; + sav.Version = cmbGame.SelectedIndex == 0 ? GameVersion.SL : GameVersion.SV; + var progress = (GameProgress)cmbProgress.SelectedIndex; var content = (RaidContent)cmbContent.SelectedIndex; var boost = cmbBoost.SelectedIndex; - var index = (byte)CurrentViewedIndex; - if (content >= RaidContent.Event && cmbSpecies.SelectedIndex != 0) + try { - foreach (var enc in content is RaidContent.Event ? Editor.Dist! : Editor.Mighty!) + var stopwatch = new System.Diagnostics.Stopwatch(); + stopwatch.Start(); + await StartSearch(sav, progress, content, boost, entity.index, (TeraRaidMapParent)cmbMap.SelectedIndex, Token); +#if DEBUG + if (!GridEntries.IsFinalized) + MessageBox.Show("Something went wrong: Result list isn't finalized."); +#endif + while (dataGrid.RowCount < GridEntries.Count) { - if (enc.Species != species) - continue; - - index = enc.Index; - break; + dataGrid.DataSource = null; + dataGrid.DataSource = GridEntries; } - } - try - { - var griddata = await StartSearch(sav, progress, content, boost, index, (TeraRaidMapParent)cmbMap.SelectedIndex, Token); - dataGrid.DataSource = griddata; + stopwatch.Stop(); + SetTimeText(true, $"{stopwatch.Elapsed}"); + btnSearch.Text = Strings["ActionSearch"]; EnableControls(IsBlankSAV()); - UpdateLabel(); + UpdateFoundLabel(); } catch (OperationCanceledException) { btnSearch.Text = Strings["ActionSearch"]; EnableControls(IsBlankSAV()); - UpdateLabel(); + UpdateFoundLabel(); } } else @@ -407,137 +608,60 @@ private async void btnSearch_Click(object sender, EventArgs e) Token.Cancel(); btnSearch.Text = Strings["ActionSearch"]; EnableControls(IsBlankSAV()); - UpdateLabel(); + UpdateFoundLabel(); return; } } - private async Task> StartSearch(SAV9SV sav, GameProgress progress, RaidContent content, int boost, int index, TeraRaidMapParent map, CancellationTokenSource token) + private async Task StartSearch(SAV9SV sav, GameProgress progress, RaidContent content, int boost, byte index, TeraRaidMapParent map, CancellationTokenSource token) { - var gridList = new List(); - var seed = txtSeed.Text.Equals("") ? 0 : Convert.ToUInt32(txtSeed.Text, 16); var lang = (LanguageID)Editor.SAV.Language; + var encounters = GetCurrentEncounters(); - var indexSpecific = index != 0; - var eventSpecific = content is RaidContent.Event or RaidContent.Event_Mighty; - - var possibleGroups = new HashSet(); - if (!indexSpecific && eventSpecific) - foreach (var enc in content is RaidContent.Event ? Editor.Dist! : Editor.Mighty!) + var possibleGroups = new HashSet(); + if (index == 0 && content is RaidContent.Event or RaidContent.Event_Mighty) + foreach (var enc in encounters.Where(Filter.IsEncounterMatch)) possibleGroups.Add(enc.Index); else possibleGroups.Add(index); - foreach (var group in possibleGroups) + await Task.Run(() => { - if (token.IsCancellationRequested) - break; - - await Task.Run(async () => + foreach (var group in possibleGroups) { - var nthreads = (uint)numMaxCalc.Value < 1000 ? 1 : Environment.ProcessorCount; - var gridresults = new List[nthreads]; - var calcresults = new List[nthreads]; - var resetEvent = new ManualResetEvent(false); - var toProcess = nthreads; - var maxcalcs = (uint)numMaxCalc.Value; - var calcsperthread = maxcalcs / (uint)nthreads; - - for (uint j = 0; j < nthreads; j++) + EncounterRaidTF9[] effective_encounters = content switch { - var n = j; - var tseed = seed; + RaidContent.Standard or RaidContent.Black => ((EncounterTeraTF9[])encounters).Where(e => e.Index == group && Filter.IsEncounterMatch(e)).ToArray(), + RaidContent.Event or RaidContent.Event_Mighty => ((EncounterEventTF9[])encounters).Where(e => e.Index == group && Filter.IsEncounterMatch(e)).ToArray(), + _ => throw new NotImplementedException(nameof(content)), + }; - new Thread(delegate () - { - var tmpgridlist = new List(); - var tmpcalclist = new List(); + var romMaxRate = sav.Version is GameVersion.VL ? EncounterTera9.GetRateTotalVL(Filter.Encounter.Stars, map) : EncounterTera9.GetRateTotalSL(Filter.Encounter.Stars, map); + var eventProgress = EventUtil.GetEventStageFromProgress(progress); - var initialFrame = calcsperthread * n; - var maxframe = n < nthreads - 1 ? calcsperthread * (n + 1) : maxcalcs; - tseed += initialFrame; - - for (ulong i = initialFrame; i <= maxframe && !token.IsCancellationRequested; i++) - { - var res = CalcResult(tseed, progress, sav, content, i, chkAccurateSearch.Checked, boost, group, map); - if (Filter is not null && res is not null && Filter.IsFilterMatch(res)) - { - tmpgridlist.Add(new RewardGridEntry(res, Items, SpeciesNames, ShinyNames, Editor.Language)); - tmpcalclist.Add(res); - if (!chkAllResults.Checked) - { - if (NotLinkedSearch || (!eventSpecific || (eventSpecific && indexSpecific))) - { - token.Cancel(); - break; - } - } - } - else if (Filter is null && res is not null) - { - tmpgridlist.Add(new RewardGridEntry(res, Items, SpeciesNames, ShinyNames, Editor.Language)); - tmpcalclist.Add(res); - } - - if (token.IsCancellationRequested) - break; - - tseed++; - } - - gridresults[n] = tmpgridlist; - calcresults[n] = tmpcalclist; - - if (Interlocked.Decrement(ref toProcess) == 0 || token.IsCancellationRequested) - resetEvent.Set(); - }).Start(); - } - - resetEvent.WaitOne(); - - await Task.Delay(0_300).ConfigureAwait(false); - - for (var i = 0; i < nthreads; i++) + if (effective_encounters.Length > 0) { - if (gridresults[i] is not null && gridresults[i].Count > 0) - gridList.AddRange(gridresults[i]); - if (calcresults[i] is not null && calcresults[i].Count > 0) - CalculatedList.AddRange(calcresults[i]); - } - }, token.Token); - } - - return gridList; - } - - private RewardDetails? CalcResult(ulong Seed, GameProgress progress, SAV9SV sav, RaidContent content, ulong calc, bool accuratesearch, int boost, int groupid, TeraRaidMapParent map) - { - var seed = (uint)(Seed & 0xFFFFFFFF); - var encounter = content is RaidContent.Standard or RaidContent.Black ? TeraUtil.GetTeraEncounter(seed, sav.Version, - TeraUtil.GetStars(seed, progress), map switch { TeraRaidMapParent.Paldea => Editor.Paldea!, TeraRaidMapParent.Kitakami => Editor.Kitakami!, _ => Editor.Blueberry! }, map) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, sav.Version, progress, Editor.Mighty!, groupid) : TeraUtil.GetDistEncounter(seed, sav.Version, progress, Editor.Dist!, groupid); - - if (encounter is null) - return null; + var initialValue = txtSeed.Text.Equals("") ? 0 : Convert.ToUInt32(txtSeed.Text, 16); + var maxValue = (long)initialValue + (uint)numMaxCalc.Value; - var fixedlist = encounter.IsDistribution ? Editor.DistFixedRewards : Editor.TeraFixedRewards; - var lotterylist = encounter.IsDistribution ? Editor.DistLotteryRewards : Editor.TeraLotteryRewards; - - List list; - TeraShiny shiny = TeraShiny.No; + Parallel.For(initialValue, maxValue, (seed, iterator) => + { + if (token.IsCancellationRequested) + iterator.Break(); - if (accuratesearch) - { - var det = TeraUtil.CalcRNG(seed, sav.ID32, content, encounter, groupid, calc); - list = RewardUtil.GetRewardList(det, encounter.FixedRewardHash, encounter.LotteryRewardHash, fixedlist, lotterylist, boost); - shiny = det.Shiny; - } - else - { - list = RewardUtil.GetRewardList(seed, encounter.Species, encounter.Stars, encounter.FixedRewardHash, encounter.LotteryRewardHash, fixedlist, lotterylist, boost); - } + if (EncounterRaidTF9.TryGenerateRewardDetails((uint)seed, effective_encounters, Filter, romMaxRate, sav.Version, progress, eventProgress, content, sav.ID32, group, boost, out _, out var result)) + { + CalculatedList.Add(result.Value); + GridEntries.Add(new RewardGridEntry(result.Value, Items, SpeciesNames, ShinyNames, TypeNames, Editor.Language)); - return new RewardDetails { Seed = seed, Rewards = list, Species = encounter.Species, Stars = encounter.Stars, Shiny = shiny, EventIndex = (byte)groupid, Calcs = calc }; + if (!chkAllResults.Checked) + token.Cancel(); + } + }); + } + } + GridEntries.FinalizeElements(); + }); } private void dataGrid_MouseUp(object sender, MouseEventArgs e) @@ -552,11 +676,31 @@ private void dataGrid_MouseUp(object sender, MouseEventArgs e) } } + private string[] TranslatedStars() + { + var res = TeraStars; + res[0] = Strings["Any"]; + for (var i = 0; i < res.Length; i++) + res[i] = res[i].Replace("S", Strings["StarsAbbreviation"]); + return res; + } + + private readonly static string[] TeraStars = [ + "Any", + "1S ☆", + "2S ☆☆", + "3S ☆☆☆", + "4S ☆☆☆☆", + "5S ☆☆☆☆☆", + "6S ☆☆☆☆☆☆", + "7S ☆☆☆☆☆☆☆", + ]; + private void btnSaveAllTxt_Click(object sender, EventArgs e) => dataGrid.SaveAllTxt(Editor.Language); private void btnSaveSelectedTxt_Click(object sender, EventArgs e) => dataGrid.SaveSelectedTxt(Editor.Language); - private void btnSendSelectedRaid_Click(object sender, EventArgs e) => dataGrid.SendSelectedRaidEditor(this, Editor.Language, (TeraRaidMapParent)cmbMap.SelectedIndex); + private void btnSendSelectedRaid_Click(object sender, EventArgs e) => dataGrid.SendSelectedRaidEditor(this, Editor.Language); private void btnCopySeed_Click(object sender, EventArgs e) => dataGrid.CopySeed(Editor.Language); } diff --git a/TeraFinder.Plugins/Forms/RewardCalcForm.resx b/TeraFinder.Plugins/Forms/RewardCalcForm.resx index ea653b29..a6ecbfd2 100644 --- a/TeraFinder.Plugins/Forms/RewardCalcForm.resx +++ b/TeraFinder.Plugins/Forms/RewardCalcForm.resx @@ -18,7 +18,7 @@ System.Resources.ResXResourceReader, System.Windows.Forms, ... System.Resources.ResXResourceWriter, System.Windows.Forms, ... this is my long stringthis is a comment - Blue + Blue [base64 mime encoded serialized .NET Framework object] @@ -127,7 +127,7 @@ 235, 17 - 53 + 43 diff --git a/TeraFinder.Plugins/Forms/RewardListForm.cs b/TeraFinder.Plugins/Forms/RewardListForm.cs index 6d480bdd..5d59692e 100644 --- a/TeraFinder.Plugins/Forms/RewardListForm.cs +++ b/TeraFinder.Plugins/Forms/RewardListForm.cs @@ -5,79 +5,25 @@ namespace TeraFinder.Plugins; public partial class RewardListForm : Form { - public RewardListForm(string language, List? lvl0 = null, List? lvl1 = null, List? lvl2 = null, List? lvl3 = null) + public RewardListForm(string language, MoveType tera, List? lvl0 = null, List? lvl1 = null, List? lvl2 = null, List? lvl3 = null) { InitializeComponent(); this.TranslateInterface(language); - var items = GameInfo.GetStrings(language).itemlist; - var lang = GameLanguage.GetLanguageIndex(language); - if(lvl0 is not null) - { - foreach(var item in lvl0) - { - if (item.ItemID == ushort.MaxValue) - gridNoBoost.Rows.Add($"{RewardUtil.Material[lang]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (item.ItemID == ushort.MaxValue - 1) - gridNoBoost.Rows.Add($"{RewardUtil.TeraShard[lang]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (RewardUtil.IsTM(item.ItemID)) - gridNoBoost.Rows.Add($"{RewardUtil.GetNameTM(item.ItemID, items, GameInfo.GetStrings(language).movelist)} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (item.ItemID < items.Length) - gridNoBoost.Rows.Add($"{items[item.ItemID]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else - gridNoBoost.Rows.Add($"{item.ItemID} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - } - } + if (lvl0 is not null) + foreach (var item in lvl0) + gridNoBoost.Rows.Add([item.GetItemName(tera, language: language, quantity: false), $"{item.Amount}"]); if (lvl1 is not null) - { foreach (var item in lvl1) - { - if (item.ItemID == ushort.MaxValue) - grid1Boost.Rows.Add($"{RewardUtil.Material[lang]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (item.ItemID == ushort.MaxValue - 1) - grid1Boost.Rows.Add($"{RewardUtil.TeraShard[lang]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (RewardUtil.IsTM(item.ItemID)) - grid1Boost.Rows.Add($"{RewardUtil.GetNameTM(item.ItemID, items, GameInfo.GetStrings(language).movelist)} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (item.ItemID < items.Length) - grid1Boost.Rows.Add($"{items[item.ItemID]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else - grid1Boost.Rows.Add($"{item.ItemID} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - } - } + grid1Boost.Rows.Add([item.GetItemName(tera, language: language, quantity: false), $"{item.Amount}"]); if (lvl2 is not null) - { foreach (var item in lvl2) - { - if (item.ItemID == ushort.MaxValue) - grid2Boost.Rows.Add($"{RewardUtil.Material[lang]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (item.ItemID == ushort.MaxValue - 1) - grid2Boost.Rows.Add($"{RewardUtil.TeraShard[lang]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (RewardUtil.IsTM(item.ItemID)) - grid2Boost.Rows.Add($"{RewardUtil.GetNameTM(item.ItemID, items, GameInfo.GetStrings(language).movelist)} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (item.ItemID < items.Length) - grid2Boost.Rows.Add($"{items[item.ItemID]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else - grid2Boost.Rows.Add($"{item.ItemID} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - } - } + grid2Boost.Rows.Add([item.GetItemName(tera, language: language, quantity: false), $"{item.Amount}"]); if (lvl3 is not null) - { foreach (var item in lvl3) - { - if (item.ItemID == ushort.MaxValue) - grid3Boost.Rows.Add($"{RewardUtil.Material[lang]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (item.ItemID == ushort.MaxValue - 1) - grid3Boost.Rows.Add($"{RewardUtil.TeraShard[lang]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (RewardUtil.IsTM(item.ItemID)) - grid3Boost.Rows.Add($"{RewardUtil.GetNameTM(item.ItemID, items, GameInfo.GetStrings(language).movelist)} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else if (item.ItemID < items.Length) - grid3Boost.Rows.Add($"{items[item.ItemID]} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - else - grid3Boost.Rows.Add($"{item.ItemID} {(item.Aux == 1 ? "(H)" : item.Aux == 2 ? "(C)" : item.Aux == 3 ? "(Once)" : "")}", $"{item.Amount}"); - } - } + grid3Boost.Rows.Add([item.GetItemName(tera, language: language, quantity: false), $"{item.Amount}"]); } } diff --git a/TeraFinder.Plugins/Resources/deps/PKHeX.Drawing.PokeSprite.dll b/TeraFinder.Plugins/Resources/deps/PKHeX.Drawing.PokeSprite.dll index 7628d51f..f7695bf6 100644 Binary files a/TeraFinder.Plugins/Resources/deps/PKHeX.Drawing.PokeSprite.dll and b/TeraFinder.Plugins/Resources/deps/PKHeX.Drawing.PokeSprite.dll differ diff --git a/TeraFinder.Plugins/Resources/deps/PKHeX.Drawing.dll b/TeraFinder.Plugins/Resources/deps/PKHeX.Drawing.dll index b167d16f..e95e04ca 100644 Binary files a/TeraFinder.Plugins/Resources/deps/PKHeX.Drawing.dll and b/TeraFinder.Plugins/Resources/deps/PKHeX.Drawing.dll differ diff --git a/TeraFinder.Plugins/TeraFinder.Plugins.csproj b/TeraFinder.Plugins/TeraFinder.Plugins.csproj index 93a28c1b..43454b7c 100644 --- a/TeraFinder.Plugins/TeraFinder.Plugins.csproj +++ b/TeraFinder.Plugins/TeraFinder.Plugins.csproj @@ -22,12 +22,12 @@ embedded - 1701;1702;IDE1006 + 1701,1702,IDE1006,IDE0042,CA1829,CA2211,CS8629,CS8602 embedded - 1701;1702;IDE1006 + 1701,1702,IDE1006,IDE0042,CA1829,CA2211,CS8629,CS8602 @@ -64,7 +64,7 @@ Resources\deps\PKHeX.Drawing.PokeSprite.dll - ..\TeraFinder.Core\deps\SysBot.Base.dll + ..\TeraFinder.RemoteExecutor\deps\SysBot.Base.dll ..\TeraFinder.Core\deps\pkNX.Structures.dll @@ -111,6 +111,7 @@ True True + diff --git a/TeraFinder.Plugins/TeraPlugin.cs b/TeraFinder.Plugins/TeraPlugin.cs index 5fa67332..d44c4582 100644 --- a/TeraFinder.Plugins/TeraPlugin.cs +++ b/TeraFinder.Plugins/TeraPlugin.cs @@ -9,7 +9,7 @@ namespace TeraFinder.Plugins; public class TeraPlugin : IPlugin { - public const string Version = "3.1.0"; + public const string Version = "4.0.0"; private bool UpdatePrompted = false; public string Name => nameof(TeraFinder); @@ -22,19 +22,23 @@ public class TeraPlugin : IPlugin public ConnectionForm? Connection = null; public string Language = Properties.Settings.Default.def_language; - public EncounterRaid9[]? Paldea = null; - public EncounterRaid9[]? Kitakami = null; - public EncounterRaid9[]? Blueberry = null; - public EncounterRaid9[]? Dist = null; - public EncounterRaid9[]? Mighty = null; - public Dictionary>? TeraFixedRewards = null; - public Dictionary>? TeraLotteryRewards = null; - public Dictionary>? DistFixedRewards = null; - public Dictionary>? DistLotteryRewards = null; + public EncounterTeraTF9[]? Paldea = null; + public EncounterTeraTF9[]? PaldeaBlack = null; + public EncounterTeraTF9[]? Kitakami = null; + public EncounterTeraTF9[]? KitakamiBlack = null; + public EncounterTeraTF9[]? Blueberry = null; + public EncounterTeraTF9[]? BlueberryBlack = null; + public EncounterEventTF9[]? Dist = null; + public EncounterEventTF9[]? Mighty = null; + + public Dictionary>? AllDist = null; + public Dictionary>? AllMighty = null; private readonly ToolStripMenuItem Plugin = new("Tera Finder Plugins"); private readonly ToolStripMenuItem Connect = new("Connect to Remote Device"); private readonly ToolStripMenuItem Editor = new("Tera Raid Viewer/Editor"); + private readonly ToolStripMenuItem RaidCalculator = new("Raid Calculator"); + private readonly ToolStripMenuItem RewardCalculator = new("Reward Calculator"); private readonly ToolStripMenuItem Finder = new("Tera Raid Seed Checker"); private readonly ToolStripMenuItem Flags = new("Edit Game Flags"); private readonly ToolStripMenuItem Outbreaks = new("Mass Outbreak Viewer/Editor"); @@ -62,17 +66,35 @@ public void Initialize(params object[] args) private void AddCheckerToList() { + const ushort TeraLocation = 30024; + + if (Paldea is null || PaldeaBlack is null) + (Paldea, PaldeaBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Paldea); + + if (Kitakami is null || KitakamiBlack is null) + (Kitakami, KitakamiBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Kitakami); + + if (Blueberry is null || BlueberryBlack is null) + (Blueberry, BlueberryBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Blueberry); + + if (AllDist is null || AllMighty is null) + { + var (dist, mighty) = ResourcesUtil.GetAllEventEncounters(); + AllDist = SeedCheckerUtil.GroupEventEncounters(dist); + AllMighty = SeedCheckerUtil.GroupEventEncounters(mighty); + } + var menuVSD = (ContextMenuStrip)((dynamic)SaveFileEditor).menu.mnuVSD; menuVSD.Opening += (s, e) => { if (SaveFileEditor.SAV is SAV9SV sav) { var info = GetSenderInfo(ref s!); var pk = info.Slot.Read(sav); - if (pk is PK9 pk9 && pk9.MetLocation == 30024) + if (pk is PK9 pk9 && pk9.MetLocation == TeraLocation) { var dic = new Dictionary { { "CheckerForm", "" } }.TranslateInnerStrings(Language); var calcSeed = new ToolStripMenuItem(dic["CheckerForm"]) { Image = Properties.Resources.icon.ToBitmap() }; menuVSD.Items.Insert(menuVSD.Items.Count, calcSeed); - calcSeed.Click += (s, e) => new CheckerForm(pk, Language).ShowDialog(); + calcSeed.Click += (s, e) => new CheckerForm(pk, Language, Paldea, PaldeaBlack, Kitakami, KitakamiBlack, Blueberry, BlueberryBlack, AllDist, AllMighty).ShowDialog(); menuVSD.Closing += (s, e) => menuVSD.Items.Remove(calcSeed); } } @@ -86,23 +108,16 @@ public void StandaloneInitialize(string defaultOT, ReadOnlySpan data = def else SAV = new SAV9SV { - Version = (GameVersion)(int)GameVersion.SL, + Version = GameVersion.SL, OT = defaultOT, Language = (int)GetLanguageID(language is not null ? language : Language), }; - var events = TeraUtil.GetSAVDistEncounters(SAV); - var terarewards = RewardUtil.GetTeraRewardsTables(); - var eventsrewards = RewardUtil.GetDistRewardsTables(SAV); - Paldea = TeraUtil.GetAllTeraEncounters(TeraRaidMapParent.Paldea); - Kitakami = TeraUtil.GetAllTeraEncounters(TeraRaidMapParent.Kitakami); - Blueberry = TeraUtil.GetAllTeraEncounters(TeraRaidMapParent.Blueberry); - Dist = events[0]; - Mighty = events[1]; - TeraFixedRewards = terarewards[0]; - TeraLotteryRewards = terarewards[1]; - DistFixedRewards = eventsrewards[0]; - DistLotteryRewards = eventsrewards[1]; + (Paldea, PaldeaBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Paldea); + (Kitakami, KitakamiBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Kitakami); + (Blueberry, BlueberryBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Blueberry); + (Dist, Mighty) = EventUtil.GetCurrentEventEncounters(SAV, RewardUtil.GetDistRewardsTables(SAV)); + Language = GetStringLanguage((LanguageID)SAV.Language); if (!UpdatePrompted) @@ -172,6 +187,8 @@ private void AddPluginControl(ToolStripDropDownItem tools) { Plugin.DropDownItems.Add(Connect); Plugin.DropDownItems.Add(Editor); + Plugin.DropDownItems.Add(RaidCalculator); + Plugin.DropDownItems.Add(RewardCalculator); Plugin.DropDownItems.Add(Outbreaks); Plugin.DropDownItems.Add(Finder); Plugin.DropDownItems.Add(Flags); @@ -180,16 +197,39 @@ private void AddPluginControl(ToolStripDropDownItem tools) Events.DropDownItems.Add(NullOutbreak); Plugin.DropDownItems.Add(Events); Connect.Click += (s, e) => LaunchConnector(); - Editor.Click += (s, e) => new EditorForm(SAV, PKMEditor, Language, Paldea, Kitakami, Blueberry, Dist, Mighty, TeraFixedRewards, TeraLotteryRewards, DistFixedRewards, DistLotteryRewards, Connection).Show(); - ImportNews.Click += (s, e) => ImportUtil.ImportNews(SAV, ref Dist, ref Mighty, ref DistFixedRewards, ref DistLotteryRewards, language: Language, plugin: true); + Editor.Click += (s, e) => new EditorForm(SAV, PKMEditor, Language, Paldea, PaldeaBlack, Kitakami, KitakamiBlack, Blueberry, BlueberryBlack, Dist, Mighty, Connection).Show(); + RaidCalculator.Click += (s, e) => LaunchCalculator(true); + RewardCalculator.Click += (s, e) => LaunchRewardCalculator(true); + ImportNews.Click += (s, e) => ImportUtil.ImportNews(SAV, ref Dist, ref Mighty, language: Language, plugin: true); NullRaid.Click += (s, e) => LaunchRaidNullImporter(); NullOutbreak.Click += (s, e) => LaunchOutbreakNullImporter(); Flags.Click += (s, e) => new ProgressForm(SAV, Language,Connection).ShowDialog(); - Finder.Click += (s, e) => new CheckerForm(PKMEditor!.PreparePKM(), Language).ShowDialog(); + Finder.Click += (s, e) => AddSeedCheckerPluginControl(); Outbreaks.Click += (s, e) => new OutbreakForm(SAV, Language, Connection).ShowDialog(); tools.DropDownItems.Add(Plugin); } + private void AddSeedCheckerPluginControl() + { + if (Paldea is null || PaldeaBlack is null) + (Paldea, PaldeaBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Paldea); + + if (Kitakami is null || KitakamiBlack is null) + (Kitakami, KitakamiBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Kitakami); + + if (Blueberry is null || BlueberryBlack is null) + (Blueberry, BlueberryBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Blueberry); + + if (AllDist is null || AllMighty is null) + { + var (dist, mighty) = ResourcesUtil.GetAllEventEncounters(); + AllDist = SeedCheckerUtil.GroupEventEncounters(dist); + AllMighty = SeedCheckerUtil.GroupEventEncounters(mighty); + } + + new CheckerForm(PKMEditor!.PreparePKM(), Language, Paldea, PaldeaBlack, Kitakami, KitakamiBlack, Blueberry, BlueberryBlack, AllDist, AllMighty).ShowDialog(); + } + private void TranslatePlugins() { var dic = new Dictionary @@ -204,11 +244,15 @@ private void TranslatePlugins() { "Plugin.ImportNews", "Import from files..." }, { "Plugin.OutbreakNull", "Import Empty (Null) Outbreak Event" }, { "Plugin.RaidNull", "Import Empty (Null) Raid Event" }, + { "Plugin.RaidCalculator", "Raid Calculator" }, + { "Plugin.RewardCalculator", "Reward Calculator" }, }.TranslateInnerStrings(Language); Plugin.Text = dic["Plugin.TeraFinderPlugin"]; Connect.Text = dic["Plugin.ConnectRemote"]; Editor.Text = dic["Plugin.TeraViewer"]; + RaidCalculator.Text = dic["Plugin.RaidCalculator"]; + RewardCalculator.Text = dic["Plugin.RewardCalculator"]; Finder.Text = dic["Plugin.SeedChecker"]; Flags.Text = dic["Plugin.FlagEditor"]; Events.Text = dic["Plugin.NewsImporter"]; @@ -220,31 +264,37 @@ private void TranslatePlugins() public void LaunchEditor() { - new EditorForm(SAV, PKMEditor, Language, Paldea, Kitakami, Blueberry, Dist, Mighty, TeraFixedRewards, TeraLotteryRewards, DistFixedRewards, DistLotteryRewards, Connection).ShowDialog(); + new EditorForm(SAV, PKMEditor, Language, Paldea, PaldeaBlack, Kitakami, KitakamiBlack, Blueberry, BlueberryBlack, Dist, Mighty, Connection).ShowDialog(); } - public void LaunchCalculator() + public void LaunchCalculator(bool plugin = false) { - var editor = new EditorForm(SAV, PKMEditor, Language, Paldea, Kitakami, Blueberry, Dist, Mighty, TeraFixedRewards, TeraLotteryRewards, DistFixedRewards, DistLotteryRewards, Connection); - new CalculatorForm(editor).ShowDialog(); + var editor = new EditorForm(SAV, PKMEditor, Language, Paldea, PaldeaBlack, Kitakami, KitakamiBlack, Blueberry, BlueberryBlack, Dist, Mighty, Connection); + if (plugin) + new CalculatorForm(editor).Show(); + else + new CalculatorForm(editor).ShowDialog(); } - public void LaunchRewardCalculator() + public void LaunchRewardCalculator(bool plugin = false) { - var editor = new EditorForm(SAV, PKMEditor, Language, Paldea, Kitakami, Blueberry, Dist, Mighty, TeraFixedRewards, TeraLotteryRewards, DistFixedRewards, DistLotteryRewards, Connection); - new RewardCalcForm(editor).ShowDialog(); + var editor = new EditorForm(SAV, PKMEditor, Language, Paldea, PaldeaBlack, Kitakami, KitakamiBlack, Blueberry, BlueberryBlack, Dist, Mighty, Connection); + if (plugin) + new RewardCalcForm(editor).Show(); + else + new RewardCalcForm(editor).ShowDialog(); } public void LaunchImporter() { - ImportUtil.ImportNews(SAV, ref Dist, ref Mighty, ref DistFixedRewards, ref DistLotteryRewards, language: Language, plugin: true); + ImportUtil.ImportNews(SAV, ref Dist, ref Mighty, language: Language, plugin: true); } public void LaunchRaidNullImporter() { ImportUtil.FinalizeImportRaid(SAV, Properties.Resources.event_raid_identifier, Properties.Resources.fixed_reward_item_array, Properties.Resources.lottery_reward_item_array, Properties.Resources.raid_enemy_array, Properties.Resources.raid_priority_array, "0", - ref Dist, ref Mighty, ref DistFixedRewards, ref DistLotteryRewards, ImportUtil.GenerateDictionary().TranslateInnerStrings(Language)); + ref Dist, ref Mighty, ImportUtil.GenerateDictionary().TranslateInnerStrings(Language)); } public void LaunchOutbreakNullImporter() @@ -258,9 +308,26 @@ public void LaunchGameEditor() new ProgressForm(SAV, Language,Connection).ShowDialog(); } - public void LaunchFinder() + public void LaunchSeedChecker() { - new CheckerForm(new PK9 { TrainerTID7 = SAV.TrainerTID7, TrainerSID7 = SAV.TrainerSID7 }, Language).ShowDialog(); + if (Paldea is null || PaldeaBlack is null) + (Paldea, PaldeaBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Paldea); + + if (Kitakami is null || KitakamiBlack is null) + (Kitakami, KitakamiBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Kitakami); + + if (Blueberry is null || BlueberryBlack is null) + (Blueberry, BlueberryBlack) = ResourcesUtil.GetAllTeraEncounters(TeraRaidMapParent.Blueberry); + + if (AllDist is null || AllMighty is null) + { + var (dist, mighty) = ResourcesUtil.GetAllEventEncounters(); + AllDist = SeedCheckerUtil.GroupEventEncounters(dist); + AllMighty = SeedCheckerUtil.GroupEventEncounters(mighty); + } + + new CheckerForm(new PK9 { TrainerTID7 = SAV.TrainerTID7, TrainerSID7 = SAV.TrainerSID7 }, + Language, Paldea, PaldeaBlack, Kitakami, KitakamiBlack, Blueberry, BlueberryBlack, AllDist, AllMighty).ShowDialog(); } public void LaunchMassOutbreakEditor() @@ -286,13 +353,7 @@ public ConnectionForm LaunchConnector(Form? parent = null) con.TranslateInterface(Language); con.FormClosing += (s, e) => { - var events = TeraUtil.GetSAVDistEncounters(SAV); - var eventsrewards = RewardUtil.GetDistRewardsTables(SAV); - Dist = events[0]; - Mighty = events[1]; - DistFixedRewards = eventsrewards[0]; - DistLotteryRewards = eventsrewards[1]; - + (Dist, Mighty) = EventUtil.GetCurrentEventEncounters(SAV, RewardUtil.GetDistRewardsTables(SAV)); if (parent is not null) { Language = GetStringLanguage((LanguageID)SAV.Language); @@ -330,14 +391,14 @@ public void NotifyDisplayLanguageChanged(string language) public string GetSavName() { var ot = SAV.OT; - var game = (GameVersion)SAV.Version; + var game = SAV.Version; var tid = (int)SAV.TrainerTID7; return $"{game} - {ot} ({tid}) - {Language.ToUpper()}"; } public uint GetRaidEventIdentifier() { - var block = SAV.Accessor.FindOrDefault(Blocks.KBCATEventRaidIdentifier.Key); + var block = SAV.Accessor.FindOrDefault(BlockDefinitions.KBCATEventRaidIdentifier.Key); var data = block.Data; if (data.Length > 0) return BinaryPrimitives.ReadUInt32LittleEndian(data); @@ -347,15 +408,15 @@ public uint GetRaidEventIdentifier() public uint GetOutbreakEventIdentifier() { - var enableBlock = SAV.Accessor.FindOrDefault(Blocks.KBCATOutbreakEnabled.Key); + var enableBlock = SAV.Accessor.FindOrDefault(BlockDefinitions.KBCATOutbreakEnabled.Key); if (enableBlock.Type == SCTypeCode.None || enableBlock.Type == SCTypeCode.Bool1) return 0; - var pokeDataBlock = SAV.Accessor.FindOrDefault(Blocks.KBCATOutbreakPokeData.Key); + var pokeDataBlock = SAV.Accessor.FindOrDefault(BlockDefinitions.KBCATOutbreakPokeData.Key); var tablePokeData = FlatBufferConverter.DeserializeFrom(pokeDataBlock.Data); return tablePokeData.Table[0].ID > 0 ? uint.Parse($"{tablePokeData.Table[0].ID}"[..8]) : 0; } - public bool TryLoadFile(string filePath) => ImportUtil.ImportNews(SAV, ref Dist, ref Mighty, ref DistFixedRewards, ref DistLotteryRewards, language: Language, path:filePath); + public bool TryLoadFile(string filePath) => ImportUtil.ImportNews(SAV, ref Dist, ref Mighty, language: Language, path:filePath); private void EnablePlugins() => Plugin.Enabled = true; @@ -368,7 +429,7 @@ private SlotViewInfo GetSenderInfo(ref object sender) Type contextMenuSAVType = ((dynamic)SaveFileEditor).menu.GetType(); MethodInfo? getSenderInfoMethod = contextMenuSAVType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static) .SingleOrDefault(m => m.Name.Contains("GetSenderInfo")); - return (SlotViewInfo)getSenderInfoMethod?.Invoke(null, [sender])!; + return (SlotViewInfo)getSenderInfoMethod?.Invoke(null, new object[] { sender })!; } public bool ExportSAVDialog(int currentBox = 0) diff --git a/TeraFinder.Plugins/Utils/GridUtil.cs b/TeraFinder.Plugins/Utils/GridUtil.cs index 5a13b5af..e05c4470 100644 --- a/TeraFinder.Plugins/Utils/GridUtil.cs +++ b/TeraFinder.Plugins/Utils/GridUtil.cs @@ -1,7 +1,4 @@ -using NLog; -using Octokit; -using PKHeX.Core; -using System.Runtime.CompilerServices; +using PKHeX.Core; using System.Text; using TeraFinder.Core; @@ -156,59 +153,48 @@ public static void SaveSelectedPk9(this DataGridView dataGrid, CalculatorForm f, try { var seed = Convert.ToUInt32(selectedRows.ElementAt(0).Cells[0].Value.ToString()!, 16); - var groupid = Convert.ToInt32(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 2].Value.ToString()!, 10); - var content = GetContent(seed, groupid, selectedRows.ElementAt(0), f, map); - var progress = GetProgress(seed, groupid, selectedRows.ElementAt(0), f, map); - var tid = Convert.ToUInt32(f.txtTID.Text, 10); - var sid = Convert.ToUInt32(f.txtSID.Text, 10); - - var sav = (SAV9SV)f.Editor.SAV.Clone(); - sav.Version = (GameVersion)(int)GetGameVersion(seed, groupid, selectedRows.ElementAt(0), f, map); - - var encounter = (int)content < 2 ? TeraUtil.GetTeraEncounter(seed, sav.Version, TeraUtil.GetStars(seed, progress), - map switch - { - TeraRaidMapParent.Paldea => f.Editor.Paldea!, - TeraRaidMapParent.Kitakami => f.Editor.Kitakami!, - _ => f.Editor.Blueberry! - }, map) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Mighty!, groupid) : - TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Dist!, groupid); - - var res = TeraUtil.GenerateTeraEntity(sav, encounter!, content, seed, TeraUtil.GetID32(tid, sid), groupid); - var la = new LegalityAnalysis(res); - - if (!la.Valid) + var groupid = Convert.ToByte(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 1].Value.ToString()!, 10); + var content = (RaidContent)f.cmbContent.SelectedIndex; + var progress = (GameProgress)f.cmbProgress.SelectedIndex; + var eventProgress = EventUtil.GetEventStageFromProgress(progress); + var version = f.cmbGame.SelectedIndex == 0 ? GameVersion.SL : GameVersion.VL; + var id32 = TidUtil.GetID32(Convert.ToUInt32(f.txtTID.Text, 10), Convert.ToUInt32(f.txtSID.Text, 10)); + + var encounters = f.Editor.GetCurrentEncounters(content, map); + if (EncounterRaidTF9.TryGenerateTeraDetails(seed, encounters, version, progress, eventProgress, content, map, id32, groupid, out var enc, out var result)) { - var la_encounter = la.Results.Where(l => l.Identifier is CheckIdentifier.Encounter).FirstOrDefault(); - if (content is RaidContent.Event or RaidContent.Event_Mighty) - MessageBox.Show($"{strings["GridUtil.ErrorParsing"]}\n{strings["GridUtil.MissingData"]} [{encounter!.Identifier}].\n{strings["GridUtil.CheckWiki"]}"); - else - MessageBox.Show($"{strings["GridUtil.ErrorParsing"]} {strings["GridUtil.Report"]}\n{la.Report()}"); - return; - } + if (!enc.GeneratePK9(result.Value, id32, version, f.Editor.SAV.OT, f.Editor.SAV.Language, f.Editor.SAV.Gender, out var pk9, out var la)) + { + var la_encounter = la.Results.Where(l => l.Identifier is CheckIdentifier.Encounter).FirstOrDefault(); + if (content is RaidContent.Event or RaidContent.Event_Mighty) + MessageBox.Show($"{strings["GridUtil.ErrorParsing"]}\n{strings["GridUtil.MissingData"]} [{enc.Identifier}].\n{strings["GridUtil.CheckWiki"]}"); + else + MessageBox.Show($"{strings["GridUtil.ErrorParsing"]} {strings["GridUtil.Report"]}\n{la.Report()}"); + return; + } - var sfd = new SaveFileDialog - { - Filter = "PK9 (*.pk9)|*.pk9", - FileName = $"{res.FileName}", - }; + var sfd = new SaveFileDialog + { + Filter = "PK9 (*.pk9)|*.pk9", + FileName = $"{pk9!.FileName}", + }; - if (sfd.ShowDialog() == DialogResult.OK) - { - if (File.Exists(sfd.FileName)) + if (sfd.ShowDialog() is DialogResult.OK) { - try + if (File.Exists(sfd.FileName)) { - File.Delete(sfd.FileName); - } - catch (IOException ex) - { - MessageBox.Show(ex.Message); + try + { + File.Delete(sfd.FileName); + } + catch (IOException ex) + { + MessageBox.Show(ex.Message); + } } + File.WriteAllBytes(sfd.FileName, pk9.Data); + MessageBox.Show($"{strings["GridUtil.Exported"]} {sfd.FileName}"); } - File.WriteAllBytes(sfd.FileName, res.Data); - MessageBox.Show($"{strings["GridUtil.Exported"]} {sfd.FileName}"); } } catch (Exception ex) @@ -240,36 +226,21 @@ public static void ViewRewards(this DataGridView dataGrid, CalculatorForm f, str try { var seed = Convert.ToUInt32(selectedRows.ElementAt(0).Cells[0].Value.ToString()!, 16); - var groupid = Convert.ToInt32(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 2].Value.ToString()!, 10); - var content = GetContent(seed, groupid, selectedRows.ElementAt(0), f, map); - var progress = GetProgress(seed, groupid, selectedRows.ElementAt(0), f, map); - - var sav = (SAV9SV)f.Editor.SAV.Clone(); - sav.Version = (GameVersion)(int)GetGameVersion(seed, groupid, selectedRows.ElementAt(0), f, map); - - var encounter = (int)content < 2 ? TeraUtil.GetTeraEncounter(seed, sav.Version, TeraUtil.GetStars(seed, progress), - map switch - { - TeraRaidMapParent.Paldea => f.Editor.Paldea!, - TeraRaidMapParent.Kitakami => f.Editor.Kitakami!, - _ => f.Editor.Blueberry! - }, map) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Mighty!) : - TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Dist!); - - var rngres = TeraUtil.CalcRNG(seed, TeraUtil.GetID32(Convert.ToUInt32(f.txtTID.Text, 10), Convert.ToUInt32(f.txtSID.Text, 10)), content, encounter!, groupid); - - var lvl0 = RewardUtil.GetRewardList(rngres, encounter!.FixedRewardHash, encounter!.LotteryRewardHash, - encounter!.IsDistribution ? f.Editor.DistFixedRewards : f.Editor.TeraFixedRewards, encounter!.IsDistribution ? f.Editor.DistLotteryRewards : f.Editor.TeraLotteryRewards, 0); - var lvl1 = RewardUtil.GetRewardList(rngres, encounter!.FixedRewardHash, encounter!.LotteryRewardHash, - encounter!.IsDistribution ? f.Editor.DistFixedRewards : f.Editor.TeraFixedRewards, encounter!.IsDistribution ? f.Editor.DistLotteryRewards : f.Editor.TeraLotteryRewards, 1); - var lvl2 = RewardUtil.GetRewardList(rngres, encounter!.FixedRewardHash, encounter!.LotteryRewardHash, - encounter!.IsDistribution ? f.Editor.DistFixedRewards : f.Editor.TeraFixedRewards, encounter!.IsDistribution ? f.Editor.DistLotteryRewards : f.Editor.TeraLotteryRewards, 2); - var lvl3 = RewardUtil.GetRewardList(rngres, encounter!.FixedRewardHash, encounter!.LotteryRewardHash, - encounter!.IsDistribution ? f.Editor.DistFixedRewards : f.Editor.TeraFixedRewards, encounter!.IsDistribution ? f.Editor.DistLotteryRewards : f.Editor.TeraLotteryRewards, 3); - - var form = new RewardListForm(f.Editor.Language, lvl0, lvl1, lvl2, lvl3); - form.ShowDialog(); + var groupid = Convert.ToByte(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 1].Value.ToString()!, 10); + var content = (RaidContent)f.cmbContent.SelectedIndex; + var progress = (GameProgress)f.cmbProgress.SelectedIndex; + var eventProgress = EventUtil.GetEventStageFromProgress(progress); + var id32 = TidUtil.GetID32(Convert.ToUInt32(f.txtTID.Text, 10), Convert.ToUInt32(f.txtSID.Text, 10)); + var version = f.cmbGame.SelectedIndex == 0 ? GameVersion.SL : GameVersion.VL; + + var encounters = f.Editor.GetCurrentEncounters(content, map); + + EncounterRaidTF9.TryGenerateRewardDetails(seed, encounters, version, progress, eventProgress, content, map, id32, groupid, 0, out var rng, out var lvl0); + EncounterRaidTF9.TryGenerateRewardDetails(seed, encounters, version, progress, eventProgress, content, map, id32, groupid, 1, out _, out var lvl1); + EncounterRaidTF9.TryGenerateRewardDetails(seed, encounters, version, progress, eventProgress, content, map, id32, groupid, 2, out _, out var lvl2); + EncounterRaidTF9.TryGenerateRewardDetails(seed, encounters, version, progress, eventProgress, content, map, id32, groupid, 3, out _, out var lvl3); + + new RewardListForm(f.Editor.Language, (MoveType)rng.Value.TeraType, lvl0.Value.Rewards, lvl1.Value.Rewards, lvl2.Value.Rewards, lvl3.Value.Rewards).ShowDialog(); } catch (Exception ex) { @@ -287,7 +258,7 @@ public static void ViewRewards(this DataGridView dataGrid, CalculatorForm f, str } } - public static void SendSelectedRaidEditor(this DataGridView dataGrid, CalculatorForm f, string language, TeraRaidMapParent map) + public static void SendSelectedRaidEditor(this DataGridView dataGrid, CalculatorForm f, string language) { var strings = GenerateDictionary(language); if (dataGrid.SelectedCells.Count > 0) @@ -299,16 +270,21 @@ public static void SendSelectedRaidEditor(this DataGridView dataGrid, Calculator try { var seed = Convert.ToUInt32(selectedRows.ElementAt(0).Cells[0].Value.ToString()!, 16); - var groupid = Convert.ToInt32(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 2].Value.ToString()!, 10); - var content = GetContent(seed, groupid, selectedRows.ElementAt(0), f, map); + var groupid = Convert.ToByte(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 1].Value.ToString()!, 10); + var content = (RaidContent)f.cmbContent.SelectedIndex; if (content is RaidContent.Event or RaidContent.Event_Mighty) { - if (f.Editor.CurrTera!.EventIndex != groupid) + if (f.Editor.CurrTera is not null) { - MessageBox.Show($"{strings["GridUtil.MismatchGroupID"].Replace("{editorIndex}", $"{f.Editor.CurrTera!.EventIndex}").Replace("{resultIndex}", $"{groupid}")}"); - return; + var tera = f.Editor.CurrTera; + if (tera.Value.EventIndex != groupid) + { + MessageBox.Show($"{strings["GridUtil.MismatchGroupID"].Replace("{editorIndex}", $"{tera.Value.EventIndex}").Replace("{resultIndex}", $"{groupid}")}"); + return; + } } + } f.Editor.txtSeed.Text = $"{seed:X8}"; @@ -330,7 +306,7 @@ public static void SendSelectedRaidEditor(this DataGridView dataGrid, Calculator } } - public static void SendSelectedRaidEditor(this DataGridView dataGrid, RewardCalcForm f, string language, TeraRaidMapParent map) + public static void SendSelectedRaidEditor(this DataGridView dataGrid, RewardCalcForm f, string language) { var strings = GenerateDictionary(language); if (dataGrid.SelectedCells.Count > 0) @@ -342,15 +318,19 @@ public static void SendSelectedRaidEditor(this DataGridView dataGrid, RewardCalc try { var seed = Convert.ToUInt32(selectedRows.ElementAt(0).Cells[0].Value.ToString()!, 16); - var groupid = Convert.ToInt32(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 2].Value.ToString()!, 10); - var content = GetContent(seed, groupid, selectedRows.ElementAt(0), f, map); + var groupid = Convert.ToInt32(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 1].Value.ToString()!, 10); + var content = (RaidContent)f.cmbContent.SelectedIndex; if (content is RaidContent.Event or RaidContent.Event_Mighty) { - if (f.Editor.CurrTera!.EventIndex != groupid) + if (f.Editor.CurrTera is not null) { - MessageBox.Show($"{strings["GridUtil.MismatchGroupID"].Replace("{editorIndex}", $"{f.Editor.CurrTera!.EventIndex}").Replace("{resultIndex}", $"{groupid}")}"); - return; + var tera = f.Editor.CurrTera; + if (tera.Value.EventIndex != groupid) + { + MessageBox.Show($"{strings["GridUtil.MismatchGroupID"].Replace("{editorIndex}", $"{tera.Value.EventIndex}").Replace("{resultIndex}", $"{groupid}")}"); + return; + } } } @@ -385,39 +365,28 @@ public static void SendSelectedPk9Editor(this DataGridView dataGrid, CalculatorF try { var seed = Convert.ToUInt32(selectedRows.ElementAt(0).Cells[0].Value.ToString()!, 16); - var groupid = Convert.ToInt32(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 2].Value.ToString()!, 10); - var content = GetContent(seed, groupid, selectedRows.ElementAt(0), f, map); - var progress = GetProgress(seed, groupid, selectedRows.ElementAt(0), f, map); - var tid = Convert.ToUInt32(f.txtTID.Text, 10); - var sid = Convert.ToUInt32(f.txtSID.Text, 10); - - var sav = (SAV9SV)f.Editor.SAV.Clone(); - sav.Version = (GameVersion)(int)GetGameVersion(seed, groupid, selectedRows.ElementAt(0), f, map); - - var encounter = (int)content < 2 ? TeraUtil.GetTeraEncounter(seed, sav.Version, TeraUtil.GetStars(seed, progress), - map switch + var groupid = Convert.ToByte(selectedRows.ElementAt(0).Cells[selectedRows.ElementAt(0).Cells.Count - 1].Value.ToString()!, 10); + var content = (RaidContent)f.cmbContent.SelectedIndex; + var progress = (GameProgress)f.cmbProgress.SelectedIndex; + var eventProgress = EventUtil.GetEventStageFromProgress(progress); + var version = f.cmbGame.SelectedIndex == 0 ? GameVersion.SL : GameVersion.VL; + var id32 = TidUtil.GetID32(Convert.ToUInt32(f.txtTID.Text, 10), Convert.ToUInt32(f.txtSID.Text, 10)); + + var encounters = f.Editor.GetCurrentEncounters(content, map); + if (EncounterRaidTF9.TryGenerateTeraDetails(seed, encounters, version, progress, eventProgress, content, map, id32, groupid, out var enc, out var result)) + { + if (!enc.GeneratePK9(result.Value, id32, version, f.Editor.SAV.OT, f.Editor.SAV.Language, f.Editor.SAV.Gender, out var pk9, out var la)) { - TeraRaidMapParent.Paldea => f.Editor.Paldea!, - TeraRaidMapParent.Kitakami => f.Editor.Kitakami!, - _ => f.Editor.Blueberry! - }, map) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Mighty!, groupid) : - TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Dist!, groupid); - - var res = TeraUtil.GenerateTeraEntity(sav, encounter!, content, seed, TeraUtil.GetID32(tid, sid), groupid); - var la = new LegalityAnalysis(res); + var la_encounter = la.Results.Where(l => l.Identifier is CheckIdentifier.Encounter).FirstOrDefault(); + if (content is RaidContent.Event or RaidContent.Event_Mighty) + MessageBox.Show($"{strings["GridUtil.ErrorParsing"]}\n{strings["GridUtil.MissingData"]} [{enc.Identifier}].\n{strings["GridUtil.CheckWiki"]}"); + else + MessageBox.Show($"{strings["GridUtil.ErrorParsing"]} {strings["GridUtil.Report"]}\n{la.Report()}"); + return; + } - if (!la.Valid) - { - var la_encounter = la.Results.Where(l => l.Identifier is CheckIdentifier.Encounter).FirstOrDefault(); - if (content is RaidContent.Event or RaidContent.Event_Mighty) - MessageBox.Show($"{strings["GridUtil.ErrorParsing"]}\n{strings["GridUtil.MissingData"]} [{encounter!.Identifier}].\n{strings["GridUtil.CheckWiki"]}"); - else - MessageBox.Show($"{strings["GridUtil.ErrorParsing"]} {strings["GridUtil.Report"]}\n{la.Report()}"); - return; + f.Editor.PKMEditor!.PopulateFields(pk9!, true); } - - f.Editor.PKMEditor!.PopulateFields(res, true); } catch (Exception ex) { @@ -449,221 +418,4 @@ public static void CopySeed(this DataGridView dataGrid, string language) else MessageBox.Show(strings["GridUtil.RowsExceeded"]); } - - private static GameProgress GetProgress(uint seed, int groupid, DataGridViewRow row, CalculatorForm f, TeraRaidMapParent map) - { - for (var content = RaidContent.Standard; content <= RaidContent.Event_Mighty; content++) - { - for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.None; progress++) - { - for (var game = GameVersion.SL; game <= GameVersion.VL; game++) - { - var sav = (SAV9SV)f.Editor.SAV.Clone(); - sav.Version = (GameVersion)(int)game; - var encounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(seed, sav.Version, TeraUtil.GetStars(seed, progress), - map switch - { - TeraRaidMapParent.Paldea => f.Editor.Paldea!, - TeraRaidMapParent.Kitakami => f.Editor.Kitakami!, - _ => f.Editor.Blueberry! - }, map) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Mighty!) : - TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Dist!); - - if (encounter is not null) - { - var rngres = TeraUtil.CalcRNG(seed, TeraUtil.GetID32(Convert.ToUInt32(f.txtTID.Text, 10), Convert.ToUInt32(f.txtSID.Text, 10)), content, encounter, groupid); - var success = true; - - if (rngres != null) - { - var entry = rngres.GetStrings(f.NameList, f.AbilityList, f.NatureList, f.MoveList, f.TypeList, f.FormList, f.GenderListAscii, f.GenderListUnicode, f.ShinyList); - var grid = new GridEntry(row.ConvertToString()).GetStrings(); - for (var i = 0; i < entry.Length - 1; i++) - if (!entry[i].Equals(grid[i])) - success = false; - } - - if (success) - return progress; - } - } - } - } - return (GameProgress)f.cmbProgress.SelectedIndex; - } - - private static RaidContent GetContent(uint seed, int groupid, DataGridViewRow row, CalculatorForm f, TeraRaidMapParent map) - { - for (var content = RaidContent.Standard; content <= RaidContent.Event_Mighty; content++) - { - for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.None; progress++) - { - for (var game = GameVersion.SL; game <= GameVersion.VL; game++) - { - var sav = (SAV9SV)f.Editor.SAV.Clone(); - sav.Version = (GameVersion)(int)game; - - var encounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(seed, sav.Version, TeraUtil.GetStars(seed, progress), - map switch - { - TeraRaidMapParent.Paldea => f.Editor.Paldea!, - TeraRaidMapParent.Kitakami => f.Editor.Kitakami!, - _ => f.Editor.Blueberry! - }, map) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Mighty!) : - TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Dist!); - - if (encounter is not null) - { - var rngres = TeraUtil.CalcRNG(seed, TeraUtil.GetID32(Convert.ToUInt32(f.txtTID.Text, 10), Convert.ToUInt32(f.txtSID.Text, 10)), content, encounter, groupid); - var success = true; - - if (rngres != null) - { - var entry = rngres.GetStrings(f.NameList, f.AbilityList, f.NatureList, f.MoveList, f.TypeList, f.FormList, f.GenderListAscii, f.GenderListUnicode, f.ShinyList); - var grid = new GridEntry(row.ConvertToString()).GetStrings(); - for (var i = 0; i < entry.Length - 1; i++) - if (!entry[i].Equals(grid[i])) - success = false; - } - - if (success) - { - var type = content; - if (progress is GameProgress.None) - type = RaidContent.Black; - return type; - } - } - } - } - } - return (RaidContent)f.cmbContent.SelectedIndex; - } - - private static RaidContent GetContent(uint seed, int groupid, DataGridViewRow row, RewardCalcForm f, TeraRaidMapParent map) - { - foreach (var accuratesearch in new[] { true, false }) - { - for (var content = RaidContent.Standard; content <= RaidContent.Event_Mighty; content++) - { - for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.None; progress++) - { - for (var game = GameVersion.SL; game <= GameVersion.VL; game++) - { - var sav = (SAV9SV)f.Editor.SAV.Clone(); - sav.Version = (GameVersion)(int)game; - - var encounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(seed, sav.Version, TeraUtil.GetStars(seed, progress), - map switch - { - TeraRaidMapParent.Paldea => f.Editor.Paldea!, - TeraRaidMapParent.Kitakami => f.Editor.Kitakami!, - _ => f.Editor.Blueberry! - }, map) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Mighty!) : - TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Dist!); - - if (encounter is not null) - { - var fixedlist = encounter.IsDistribution ? f.Editor.DistFixedRewards : f.Editor.TeraFixedRewards; - var lotterylist = encounter.IsDistribution ? f.Editor.DistLotteryRewards : f.Editor.TeraLotteryRewards; - - List list; - TeraShiny shiny = TeraShiny.No; - - if (accuratesearch) - { - var det = TeraUtil.CalcRNG(seed, sav.ID32, content, encounter, groupid); - list = RewardUtil.GetRewardList(det, encounter.FixedRewardHash, encounter.LotteryRewardHash, fixedlist, lotterylist); - shiny = det.Shiny; - } - else - { - list = RewardUtil.GetRewardList(seed, encounter.Species, encounter.Stars, encounter.FixedRewardHash, encounter.LotteryRewardHash, fixedlist, lotterylist); - } - - var rngres = new RewardDetails { Seed = seed, Rewards = list, Species = encounter.Species, Stars = encounter.Stars, Shiny = shiny, Calcs = 0 }; - var success = true; - - if (rngres != null) - { - var strlist = new List { $"{seed:X8}" }; - foreach (var item in rngres.Rewards) - strlist.Add(item.GetItemName(f.Items, f.Editor.Language, true)); - - var entry = strlist.ToArray(); - var grid = new RewardGridEntry(row.ConvertToString()).GetStrings(); - for (var i = 0; i < entry.Length - 1; i++) - if (!entry[i].Equals(grid[i])) - success = false; - } - - if (success) - { - var type = content; - if (progress is GameProgress.None) - type = RaidContent.Black; - return type; - } - } - } - } - } - } - return (RaidContent)f.cmbContent.SelectedIndex; - } - - private static GameVersion GetGameVersion(uint seed, int groupid, DataGridViewRow row, CalculatorForm f, TeraRaidMapParent map) - { - for (var content = RaidContent.Standard; content <= RaidContent.Event_Mighty; content++) - { - for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.None; progress++) - { - for (var game = GameVersion.SL; game <= GameVersion.VL; game++) - { - var sav = (SAV9SV)f.Editor.SAV.Clone(); - sav.Version = (GameVersion)(int)game; - var encounter = content < RaidContent.Event ? TeraUtil.GetTeraEncounter(seed, sav.Version, TeraUtil.GetStars(seed, progress), - map switch - { - TeraRaidMapParent.Paldea => f.Editor.Paldea!, - TeraRaidMapParent.Kitakami => f.Editor.Kitakami!, - _ => f.Editor.Blueberry! - }, map) : - content is RaidContent.Event_Mighty ? TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Mighty!) : - TeraUtil.GetDistEncounter(seed, sav.Version, progress, f.Editor.Dist!); - - if (encounter is not null) - { - var rngres = TeraUtil.CalcRNG(seed, TeraUtil.GetID32(Convert.ToUInt32(f.txtTID.Text, 10), Convert.ToUInt32(f.txtSID.Text, 10)), content, encounter, groupid); - var success = true; - - if (rngres != null) - { - var entry = rngres.GetStrings(f.NameList, f.AbilityList, f.NatureList, f.MoveList, f.TypeList, f.FormList, f.GenderListAscii, f.GenderListUnicode, f.ShinyList); - var grid = new GridEntry(row.ConvertToString()).GetStrings(); - for (var i = 0; i < entry.Length - 1; i++) - if (!entry[i].Equals(grid[i])) - success = false; - } - - if (success) - return game; - } - } - } - } - return f.cmbGame.SelectedIndex == 0 ? GameVersion.SL : GameVersion.VL; - } - - private static string[] ConvertToString(this DataGridViewRow row) - { - var cellcount = row.Cells.Count; - var output = new string[cellcount]; - for (var i = 0; i < cellcount; i++) - output[i] = Convert.ToString(row.Cells[i].Value)!; - return output; - } } diff --git a/TeraFinder.Plugins/Utils/ImagesUtil.cs b/TeraFinder.Plugins/Utils/ImagesUtil.cs index 96584338..fb65f0b9 100644 --- a/TeraFinder.Plugins/Utils/ImagesUtil.cs +++ b/TeraFinder.Plugins/Utils/ImagesUtil.cs @@ -31,7 +31,7 @@ public static class ImagesUtil if (!active && sprite is not null) sprite = ImageUtil.ToGrayscale(sprite); if(sprite is not null) - ImageUtil.BlendTransparentTo(sprite, TypeColor.GetTypeSpriteColor((byte)pkm.TeraType), 0xAF, 0x3740); + ImageUtil.BlendTransparentTo(sprite, TypeColor.GetTypeSpriteColor(pkm.TeraType), 0xAF, 0x3740); return sprite; } diff --git a/TeraFinder.Plugins/Utils/ImportUtil.cs b/TeraFinder.Plugins/Utils/ImportUtil.cs index 921a01f2..869ed287 100644 --- a/TeraFinder.Plugins/Utils/ImportUtil.cs +++ b/TeraFinder.Plugins/Utils/ImportUtil.cs @@ -7,10 +7,8 @@ namespace TeraFinder.Plugins; internal static class ImportUtil { public static bool ImportNews(SAV9SV sav, - ref EncounterRaid9[]? dist, - ref EncounterRaid9[]? mighty, - ref Dictionary>? distFixedRewards, - ref Dictionary>? distLotteryRewards, + ref EncounterEventTF9[]? dist, + ref EncounterEventTF9[]? mighty, string language, string path = "", bool plugin = false) @@ -60,7 +58,7 @@ public static bool ImportNews(SAV9SV sav, isOutbreak = true; if (isRaid) - return ImportRaidFiles(path, sav, zip, ref dist, ref mighty, ref distFixedRewards, ref distLotteryRewards, strings); + return ImportRaidFiles(path, sav, zip, ref dist, ref mighty, strings); if (isOutbreak) return ImportOutbreakFiles(path, sav, zip, strings); @@ -149,10 +147,8 @@ private static void DeleteFilesAndDirectory(string targetDir) private static bool ImportRaidFiles(string path, SAV9SV sav, bool zip, - ref EncounterRaid9[]? dist, - ref EncounterRaid9[]? mighty, - ref Dictionary>? distFixedRewards, - ref Dictionary>? distLotteryRewards, + ref EncounterEventTF9[]? dist, + ref EncounterEventTF9[]? mighty, Dictionary strings) { string index; @@ -215,11 +211,11 @@ private static bool ImportRaidFiles(string path, if (zip) DeleteFilesAndDirectory(path); - var KBCATEventRaidIdentifier = sav.Accessor.FindOrDefault(Blocks.KBCATEventRaidIdentifier.Key); - var KBCATFixedRewardItemArray = sav.Accessor.FindOrDefault(Blocks.KBCATFixedRewardItemArray.Key); - var KBCATLotteryRewardItemArray = sav.Accessor.FindOrDefault(Blocks.KBCATLotteryRewardItemArray.Key); - var KBCATRaidEnemyArray = sav.Accessor.FindOrDefault(Blocks.KBCATRaidEnemyArray.Key); - var KBCATRaidPriorityArray = sav.Accessor.FindOrDefault(Blocks.KBCATRaidPriorityArray.Key); + var KBCATEventRaidIdentifier = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATEventRaidIdentifier.Key); + var KBCATFixedRewardItemArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATFixedRewardItemArray.Key); + var KBCATLotteryRewardItemArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATLotteryRewardItemArray.Key); + var KBCATRaidEnemyArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATRaidEnemyArray.Key); + var KBCATRaidPriorityArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATRaidPriorityArray.Key); } catch (Exception ex) { @@ -227,7 +223,7 @@ private static bool ImportRaidFiles(string path, return false; } - return FinalizeImportRaid(sav, identifierBlock, rewardItemBlock, lotteryItemBlock, raidEnemyBlock, raidPriorityBlock, index, ref dist, ref mighty, ref distFixedRewards, ref distLotteryRewards, strings); + return FinalizeImportRaid(sav, identifierBlock, rewardItemBlock, lotteryItemBlock, raidEnemyBlock, raidPriorityBlock, index, ref dist, ref mighty, strings); } @@ -238,19 +234,17 @@ public static bool FinalizeImportRaid(SAV9SV sav, byte[] raidEnemyBlock, byte[] raidPriorityBlock, string index, - ref EncounterRaid9[]? dist, - ref EncounterRaid9[]? mighty, - ref Dictionary>? distFixedRewards, - ref Dictionary>? distLotteryRewards, + ref EncounterEventTF9[]? dist, + ref EncounterEventTF9[]? mighty, Dictionary strings) { try { - var KBCATEventRaidIdentifier = sav.Accessor.FindOrDefault(Blocks.KBCATEventRaidIdentifier.Key); - var KBCATFixedRewardItemArray = sav.Accessor.FindOrDefault(Blocks.KBCATFixedRewardItemArray.Key); - var KBCATLotteryRewardItemArray = sav.Accessor.FindOrDefault(Blocks.KBCATLotteryRewardItemArray.Key); - var KBCATRaidEnemyArray = sav.Accessor.FindOrDefault(Blocks.KBCATRaidEnemyArray.Key); - var KBCATRaidPriorityArray = sav.Accessor.FindOrDefault(Blocks.KBCATRaidPriorityArray.Key); + var KBCATEventRaidIdentifier = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATEventRaidIdentifier.Key); + var KBCATFixedRewardItemArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATFixedRewardItemArray.Key); + var KBCATLotteryRewardItemArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATLotteryRewardItemArray.Key); + var KBCATRaidEnemyArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATRaidEnemyArray.Key); + var KBCATRaidPriorityArray = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATRaidPriorityArray.Key); if (KBCATEventRaidIdentifier.Type is not SCTypeCode.None) KBCATEventRaidIdentifier.ChangeData(identifierBlock); @@ -277,12 +271,7 @@ public static bool FinalizeImportRaid(SAV9SV sav, else BlockUtil.EditBlock(KBCATRaidPriorityArray, SCTypeCode.Object, raidPriorityBlock); - var events = TeraUtil.GetSAVDistEncounters(sav); - var eventsrewards = RewardUtil.GetDistRewardsTables(sav); - dist = events[0]; - mighty = events[1]; - distFixedRewards = eventsrewards[0]; - distLotteryRewards = eventsrewards[1]; + (dist, mighty) = EventUtil.GetCurrentEventEncounters(sav, RewardUtil.GetDistRewardsTables(sav)); if (KBCATRaidEnemyArray is not null) MessageBox.Show($"{strings["ImportNews.Success"]} [{index}]!"); @@ -355,11 +344,11 @@ public static bool FinalizeImportOutbreak(SAV9SV sav, { try { - var KBCATOutbreakPokeData = sav.Accessor.FindOrDefault(Blocks.KBCATOutbreakPokeData.Key); - var KBCATOutbreakZonesPaldea = sav.Accessor.FindOrDefault(Blocks.KBCATOutbreakZonesPaldea.Key); - var KBCATOutbreakZonesKitakami = sav.Accessor.FindOrDefault(Blocks.KBCATOutbreakZonesKitakami.Key); - var KBCATOutbreakZonesBlueberry = sav.Accessor.FindOrDefault(Blocks.KBCATOutbreakZonesBlueberry.Key); - var KBCATOutbreakEnabled = sav.Accessor.FindOrDefault(Blocks.KBCATOutbreakEnabled.Key); + var KBCATOutbreakPokeData = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATOutbreakPokeData.Key); + var KBCATOutbreakZonesPaldea = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATOutbreakZonesPaldea.Key); + var KBCATOutbreakZonesKitakami = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATOutbreakZonesKitakami.Key); + var KBCATOutbreakZonesBlueberry = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATOutbreakZonesBlueberry.Key); + var KBCATOutbreakEnabled = sav.Accessor.FindOrDefault(BlockDefinitions.KBCATOutbreakEnabled.Key); if (KBCATOutbreakPokeData.Type is not SCTypeCode.None) KBCATOutbreakPokeData.ChangeData(pokeDataBlock); diff --git a/TeraFinder.Plugins/Utils/WinFormsTranslator.cs b/TeraFinder.Plugins/Utils/WinFormsTranslator.cs index 309785b8..990f3268 100644 --- a/TeraFinder.Plugins/Utils/WinFormsTranslator.cs +++ b/TeraFinder.Plugins/Utils/WinFormsTranslator.cs @@ -102,7 +102,7 @@ private static ReadOnlySpan GetTranslationFile(string lang) catch { /* In use? Just return the internal resource. */ } } - var txt = Core.TeraUtil.GetTextResource(file); + var txt = Core.ResourcesUtil.GetTextResource(file); return Util.LoadStringList(file, txt); } diff --git a/TeraFinder.Core/Classes/DeviceExecutor.cs b/TeraFinder.RemoteExecutor/DeviceExecutor.cs similarity index 87% rename from TeraFinder.Core/Classes/DeviceExecutor.cs rename to TeraFinder.RemoteExecutor/DeviceExecutor.cs index f9230c07..c6559369 100644 --- a/TeraFinder.Core/Classes/DeviceExecutor.cs +++ b/TeraFinder.RemoteExecutor/DeviceExecutor.cs @@ -1,9 +1,16 @@ using PKHeX.Core; +using TeraFinder.Core; using SysBot.Base; using System.Globalization; using static System.Buffers.Binary.BinaryPrimitives; -namespace TeraFinder.Core; +namespace TeraFinder.RemoteExecutor; + +public enum RoutineType +{ + None, + ReadWrite, +} public class DeviceState : BotState { @@ -120,22 +127,22 @@ public async Task ReadGameProgress(CancellationToken token) if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); - var Unlocked6Stars = await ReadEncryptedBlockBool(Blocks.KUnlockedRaidDifficulty6, token).ConfigureAwait(false); + var Unlocked6Stars = await ReadEncryptedBlockBool(BlockDefinitions.KUnlockedRaidDifficulty6, token).ConfigureAwait(false); if (Unlocked6Stars) return GameProgress.Unlocked6Stars; - var Unlocked5Stars = await ReadEncryptedBlockBool(Blocks.KUnlockedRaidDifficulty5, token).ConfigureAwait(false); + var Unlocked5Stars = await ReadEncryptedBlockBool(BlockDefinitions.KUnlockedRaidDifficulty5, token).ConfigureAwait(false); if (Unlocked5Stars) return GameProgress.Unlocked5Stars; - var Unlocked4Stars = await ReadEncryptedBlockBool(Blocks.KUnlockedRaidDifficulty4, token).ConfigureAwait(false); + var Unlocked4Stars = await ReadEncryptedBlockBool(BlockDefinitions.KUnlockedRaidDifficulty4, token).ConfigureAwait(false); if (Unlocked4Stars) return GameProgress.Unlocked4Stars; - var Unlocked3Stars = await ReadEncryptedBlockBool(Blocks.KUnlockedRaidDifficulty3, token).ConfigureAwait(false); + var Unlocked3Stars = await ReadEncryptedBlockBool(BlockDefinitions.KUnlockedRaidDifficulty3, token).ConfigureAwait(false); if (Unlocked3Stars) return GameProgress.Unlocked3Stars; @@ -143,7 +150,7 @@ public async Task ReadGameProgress(CancellationToken token) return GameProgress.UnlockedTeraRaids; } - public async Task WriteBlock(object data, DataBlock block, CancellationToken token, object? toExpect = default) + public async Task WriteBlock(object data, BlockDefinition block, CancellationToken token, object? toExpect = default) { if (block.IsEncrypted) return await WriteEncryptedBlockSafe(block, toExpect, data, token).ConfigureAwait(false); @@ -152,7 +159,7 @@ public async Task WriteBlock(object data, DataBlock block, CancellationTok } //Thanks santacrab2 & Zyro670 for the help with the following code - public async Task ReadBlock(DataBlock block, CancellationToken token) + public async Task ReadBlock(BlockDefinition block, CancellationToken token) { if (block.IsEncrypted) return await ReadEncryptedBlock(block, token).ConfigureAwait(false); @@ -160,7 +167,7 @@ public async Task WriteBlock(object data, DataBlock block, CancellationTok return await ReadDecryptedBlock(block, token).ConfigureAwait(false); } - private async Task WriteDecryptedBlock(byte[] data, DataBlock block, CancellationToken token) + private async Task WriteDecryptedBlock(byte[] data, BlockDefinition block, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -173,7 +180,7 @@ private async Task WriteDecryptedBlock(byte[] data, DataBlock block, Cance return true; } - private async Task ReadDecryptedBlock(DataBlock block, CancellationToken token) + private async Task ReadDecryptedBlock(BlockDefinition block, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -184,7 +191,7 @@ private async Task ReadDecryptedBlock(DataBlock block, CancellationToken return data; } - private async Task WriteEncryptedBlockSafe(DataBlock block, object? toExpect, object toWrite, CancellationToken token) + private async Task WriteEncryptedBlockSafe(BlockDefinition block, object? toExpect, object toWrite, CancellationToken token) { if (toExpect == default || toWrite == default) return false; @@ -201,7 +208,7 @@ private async Task WriteEncryptedBlockSafe(DataBlock block, object? toExpe }; } - private async Task ReadEncryptedBlock(DataBlock block, CancellationToken token) + private async Task ReadEncryptedBlock(BlockDefinition block, CancellationToken token) { return block.Type switch { @@ -215,7 +222,7 @@ private async Task WriteEncryptedBlockSafe(DataBlock block, object? toExpe }; } - private async Task WriteEncryptedBlockUint(DataBlock block, uint valueToExpect ,uint valueToInject, CancellationToken token) + private async Task WriteEncryptedBlockUint(BlockDefinition block, uint valueToExpect ,uint valueToInject, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -239,13 +246,13 @@ private async Task WriteEncryptedBlockUint(DataBlock block, uint valueToEx return true; } - private async Task ReadEncryptedBlockUint(DataBlock block, CancellationToken token) + private async Task ReadEncryptedBlockUint(BlockDefinition block, CancellationToken token) { var header = await ReadEncryptedBlockHeader(block, token).ConfigureAwait(false); return ReadUInt32LittleEndian(header.AsSpan()[1..]); } - private async Task WriteEncryptedBlockInt32(DataBlock block, int valueToExpect, int valueToInject, CancellationToken token) + private async Task WriteEncryptedBlockInt32(BlockDefinition block, int valueToExpect, int valueToInject, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -269,13 +276,13 @@ private async Task WriteEncryptedBlockInt32(DataBlock block, int valueToEx return true; } - private async Task ReadEncryptedBlockInt32(DataBlock block, CancellationToken token) + private async Task ReadEncryptedBlockInt32(BlockDefinition block, CancellationToken token) { var header = await ReadEncryptedBlockHeader(block, token).ConfigureAwait(false); return ReadInt32LittleEndian(header.AsSpan()[1..]); } - private async Task WriteEncryptedBlockByte(DataBlock block, byte valueToExpect, byte valueToInject, CancellationToken token) + private async Task WriteEncryptedBlockByte(BlockDefinition block, byte valueToExpect, byte valueToInject, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -299,13 +306,13 @@ private async Task WriteEncryptedBlockByte(DataBlock block, byte valueToEx return true; } - private async Task ReadEncryptedBlockByte(DataBlock block, CancellationToken token) + private async Task ReadEncryptedBlockByte(BlockDefinition block, CancellationToken token) { var header = await ReadEncryptedBlockHeader(block, token).ConfigureAwait(false); return header[1]; } - private async Task WriteEncryptedBlockArray(DataBlock block, byte[] arrayToExpect, byte[] arrayToInject, CancellationToken token) + private async Task WriteEncryptedBlockArray(BlockDefinition block, byte[] arrayToExpect, byte[] arrayToInject, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -329,7 +336,7 @@ private async Task WriteEncryptedBlockArray(DataBlock block, byte[] arrayT return true; } - private async Task ReadEncryptedBlockArray(DataBlock block, CancellationToken token) + private async Task ReadEncryptedBlockArray(BlockDefinition block, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -342,7 +349,7 @@ private async Task WriteEncryptedBlockArray(DataBlock block, byte[] arrayT return data[6..]; } - private async Task ReadEncryptedBlockHeader(DataBlock block, CancellationToken token) + private async Task ReadEncryptedBlockHeader(BlockDefinition block, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -355,7 +362,7 @@ private async Task ReadEncryptedBlockHeader(DataBlock block, Cancellatio return header; } - private async Task WriteEncryptedBlockBool(DataBlock block, bool valueToExpect, bool valueToInject, CancellationToken token) + private async Task WriteEncryptedBlockBool(BlockDefinition block, bool valueToExpect, bool valueToInject, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -382,7 +389,7 @@ private async Task WriteEncryptedBlockBool(DataBlock block, bool valueToEx //Thanks to Lincoln-LM (original scblock code) and Architdate (ported C# reference code)!! //https://github.com/Lincoln-LM/sv-live-map/blob/e0f4a30c72ef81f1dc175dae74e2fd3d63b0e881/sv_live_map_core/nxreader/raid_reader.py#L168 //https://github.com/LegoFigure11/RaidCrawler/blob/2e1832ae89e5ac39dcc25ccf2ae911ef0f634580/MainWindow.cs#L199 - private async Task ReadEncryptedBlockObject(DataBlock block, CancellationToken token) + private async Task ReadEncryptedBlockObject(BlockDefinition block, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -398,7 +405,7 @@ private async Task WriteEncryptedBlockBool(DataBlock block, bool valueToEx return res; } - public async Task WriteEncryptedBlockObject(DataBlock block, byte[] valueToExpect, byte[] valueToInject, CancellationToken token) + public async Task WriteEncryptedBlockObject(BlockDefinition block, byte[] valueToExpect, byte[] valueToInject, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -422,7 +429,7 @@ public async Task WriteEncryptedBlockObject(DataBlock block, byte[] valueT return true; } - private async Task ReadEncryptedBlockBool(DataBlock block, CancellationToken token) + private async Task ReadEncryptedBlockBool(BlockDefinition block, CancellationToken token) { if (Config.Connection.Protocol is SwitchProtocol.WiFi && !Connection.Connected) throw new InvalidOperationException("No remote connection"); @@ -437,7 +444,7 @@ private async Task ReadEncryptedBlockBool(DataBlock block, CancellationTok //Thanks Architdate & Santacrab2! //https://github.com/LegoFigure11/RaidCrawler/blob/f8e996aac4b134e6eb6231d539c345748fead490/RaidCrawler.Core/Connection/ConnectionWrapper.cs#L126 - private async Task GetBlockAddress(DataBlock block, CancellationToken token, bool prepareAddress = true) + private async Task GetBlockAddress(BlockDefinition block, CancellationToken token, bool prepareAddress = true) { if (KeyBlockAddress == 0) KeyBlockAddress = await SwitchConnection.PointerAll(block.Pointer!, token).ConfigureAwait(false); diff --git a/TeraFinder.RemoteExecutor/TeraFinder.RemoteExecutor.csproj b/TeraFinder.RemoteExecutor/TeraFinder.RemoteExecutor.csproj new file mode 100644 index 00000000..163538b5 --- /dev/null +++ b/TeraFinder.RemoteExecutor/TeraFinder.RemoteExecutor.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + deps\SysBot.Base.dll + + + + diff --git a/TeraFinder.Core/deps/SysBot.Base.dll b/TeraFinder.RemoteExecutor/deps/SysBot.Base.dll similarity index 100% rename from TeraFinder.Core/deps/SysBot.Base.dll rename to TeraFinder.RemoteExecutor/deps/SysBot.Base.dll diff --git a/TeraFinder.Tests/GenerateEntities.cs b/TeraFinder.Tests/GenerateEntities.cs new file mode 100644 index 00000000..792f0513 --- /dev/null +++ b/TeraFinder.Tests/GenerateEntities.cs @@ -0,0 +1,65 @@ +using Xunit; +using PKHeX.Core; +using TeraFinder.Core; + +#pragma warning disable CS8602 // Dereference of a possibly null reference. +#pragma warning disable CS8629 // Nullable value type may be null. +namespace TeraFinder.Tests +{ + public class GenerateEntities + { + private const uint MaxTests = 0xFFFF; + + [Fact] + public void TestEncounterTeraTF9Standard() + { + for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) + { + var encounters = ResourcesUtil.GetAllTeraEncounters(map).standard; + for (var game = GameVersion.SL; game <= GameVersion.VL; game++) + for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.Unlocked6Stars; progress++) + ParallelizeGeneration(encounters, game, RaidContent.Standard, map, progress); + } + } + + [Fact] + public void TestEncounterTeraTF9Black() + { + for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) + { + var encounters = ResourcesUtil.GetAllTeraEncounters(map).black; + for (var game = GameVersion.SL; game <= GameVersion.VL; game++) + ParallelizeGeneration(encounters, game, RaidContent.Black, map, GameProgress.Unlocked6Stars); + } + } + + [Fact] + public void TestEncounterEventTF9() + { + var (eventsData, mightyData) = ResourcesUtil.GetAllEventEncounters(); + var events = SeedCheckerUtil.GroupEventEncounters(eventsData); + var mighty = SeedCheckerUtil.GroupEventEncounters(mightyData); + + for (var content = RaidContent.Event; content <= RaidContent.Event_Mighty; content++) + foreach (var group in content is RaidContent.Event ? events : mighty) + foreach (var index in new HashSet(group.Value.Select(enc => enc.Index))) + for (var game = GameVersion.SL; game <= GameVersion.VL; ++game) + { + var possibleStages = new HashSet(Enum.GetValues(typeof(EventProgress)).Cast() + .Where(progress => group.Value.Any(enc => enc.Index == index && enc.CanBeEncounteredFromStage(progress, game)))); + + foreach (var stage in possibleStages) + ParallelizeGeneration(group.Value.ToArray(), game, content, eventProgress: stage, groupid: index); + } + } + + private static void ParallelizeGeneration(EncounterRaidTF9[] encounters, GameVersion version, RaidContent content, TeraRaidMapParent map = TeraRaidMapParent.Paldea, GameProgress progress = GameProgress.UnlockedTeraRaids, EventProgress eventProgress = EventProgress.Stage0, byte groupid = 0) => + Parallel.For(0L, MaxTests, (seed, state) => + { + Assert.True(EncounterRaidTF9.TryGenerateTeraDetails((uint)seed, encounters, version, progress, eventProgress, content, map, 0, groupid, out var encounter, out var result)); + Assert.True(encounter.GeneratePK9(result.Value, 0, version, "test", 2, 0, out _, out _)); + }); + } +} +#pragma warning restore CS8629 // Nullable value type may be null. +#pragma warning restore CS8602 // Dereference of a possibly null reference. \ No newline at end of file diff --git a/TeraFinder.Tests/GenerateEntitiesWithFilters.cs b/TeraFinder.Tests/GenerateEntitiesWithFilters.cs new file mode 100644 index 00000000..a74830e7 --- /dev/null +++ b/TeraFinder.Tests/GenerateEntitiesWithFilters.cs @@ -0,0 +1,86 @@ +using Xunit; +using PKHeX.Core; +using TeraFinder.Core; + +#pragma warning disable CS8602 // Dereference of a possibly null reference. +#pragma warning disable CS8629 // Nullable value type may be null. +namespace TeraFinder.Tests +{ + public class GenerateEntitiesWithFilters + { + private const uint MaxTests = 0xFFFF; + + [Fact] + public void TestEncounterTeraTF9StandardFilter() + { + for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) + for (var stars = 1; stars <= 5; stars++) + { + var encounters = ResourcesUtil.GetAllTeraEncounters(map).standard; + for (var game = GameVersion.SL; game <= GameVersion.VL; game++) + { + var romTotal = game is GameVersion.VL ? EncounterTera9.GetRateTotalVL(stars, map) : EncounterTera9.GetRateTotalSL(stars, map); + var filter = new TeraFilter(true, false, false, false) { Stars = stars }; + var effective_encounters = encounters.Where(filter.IsEncounterMatch).ToArray(); + + for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.Unlocked6Stars; progress++) + ParallelizeGeneration(effective_encounters, filter, game, RaidContent.Standard, romTotal, progress); + } + } + } + + [Fact] + public void TestEncounterTeraTF9BlackFilter() + { + for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) + { + var encounters = ResourcesUtil.GetAllTeraEncounters(map).black; + for (var game = GameVersion.SL; game <= GameVersion.VL; game++) + { + var romTotal = game is GameVersion.VL ? EncounterTera9.GetRateTotalVL(6, map) : EncounterTera9.GetRateTotalSL(6, map); + var filter = new TeraFilter(true, false, false, false) { Stars = 6 }; + var effective_encounters = encounters.Where(filter.IsEncounterMatch).ToArray(); + + ParallelizeGeneration(effective_encounters, filter, game, RaidContent.Black, romTotal, GameProgress.Unlocked6Stars); + } + } + } + + [Fact] + public void TestEncounterEventTF9Filter() + { + var (eventsData, mightyData) = ResourcesUtil.GetAllEventEncounters(); + var events = SeedCheckerUtil.GroupEventEncounters(eventsData); + var mighty = SeedCheckerUtil.GroupEventEncounters(mightyData); + + for (var content = RaidContent.Event; content <= RaidContent.Event_Mighty; content++) + foreach (var group in content is RaidContent.Event ? events : mighty) + foreach (var index in new HashSet(group.Value.Select(enc => enc.Index))) + for (var game = GameVersion.SL; game <= GameVersion.VL; ++game) + { + var possibleStages = new HashSet(Enum.GetValues(typeof(EventProgress)).Cast() + .Where(progress => group.Value.Any(enc => enc.Index == index && enc.CanBeEncounteredFromStage(progress, game)))); + + foreach (var stage in possibleStages) + { + foreach (var stars in new HashSet(group.Value.Select(encounter => encounter.Stars))) + { + var filter = new TeraFilter(true, false, false, false) { Stars = stars }; + var encounters = group.Value.Where(filter.IsEncounterMatch).ToArray(); + + ParallelizeGeneration(encounters, filter, game, content, eventProgress: stage, groupid: index); + } + } + } + } + + private static void ParallelizeGeneration(EncounterRaidTF9[] encounters, TeraFilter filter, GameVersion version, RaidContent content, short rateTotal = 0, GameProgress progress = GameProgress.UnlockedTeraRaids, EventProgress eventProgress = EventProgress.Stage0, byte groupid = 0) => + Parallel.For(0L, MaxTests, (seed, state) => + { + if (EncounterRaidTF9.TryGenerateTeraDetails((uint)seed, encounters, filter, rateTotal, version, progress, eventProgress, content, 0, groupid, out var encounter, out var result)) + Assert.True(encounter.GeneratePK9(result.Value, 0, version, "test", 2, 0, out _, out _)); + }); + } +} +#pragma warning restore CS8629 // Nullable value type may be null. +#pragma warning restore CS8602 // Dereference of a possibly null reference. \ No newline at end of file diff --git a/TeraFinder.Tests/GenerateRewards.cs b/TeraFinder.Tests/GenerateRewards.cs new file mode 100644 index 00000000..58dd90d7 --- /dev/null +++ b/TeraFinder.Tests/GenerateRewards.cs @@ -0,0 +1,47 @@ +using Xunit; +using PKHeX.Core; +using TeraFinder.Core; + +#pragma warning disable CS8604 // Dereference of a possibly null reference. +#pragma warning disable CS8629 // Nullable value type may be null. +namespace TeraFinder.Tests +{ + public class GenerateRewards + { + private const uint MaxTests = 0xFFFF; + + [Fact] + public void TestEncounterTeraTF9Standard() + { + for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) + { + var encounters = ResourcesUtil.GetAllTeraEncounters(map).standard; + for (var game = GameVersion.SL; game <= GameVersion.VL; game++) + for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.Unlocked6Stars; progress++) + ParallelizeGeneration(encounters, game, RaidContent.Standard, map, progress); + } + } + + [Fact] + public void TestEncounterTeraTF9Black() + { + for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) + { + var encounters = ResourcesUtil.GetAllTeraEncounters(map).black; + for (var game = GameVersion.SL; game <= GameVersion.VL; game++) + ParallelizeGeneration(encounters, game, RaidContent.Black, map, GameProgress.Unlocked6Stars); + } + } + + private static void ParallelizeGeneration(EncounterRaidTF9[] encounters, GameVersion version, RaidContent content, TeraRaidMapParent map = TeraRaidMapParent.Paldea, GameProgress progress = GameProgress.UnlockedTeraRaids, EventProgress eventProgress = EventProgress.Stage0, byte groupid = 0) + { + Parallel.For(0L, MaxTests, (seed, state) => + { + Assert.True(EncounterRaidTF9.TryGenerateRewardDetails((uint)seed, encounters, version, progress, eventProgress, content, map, 0, groupid, 1, out _, out var result)); + Assert.NotEmpty(result.Value.Rewards); + }); + } + } +} +#pragma warning restore CS8629 // Nullable value type may be null. +#pragma warning restore CS8604 // Dereference of a possibly null reference. \ No newline at end of file diff --git a/TeraFinder.Tests/GenerateRewardsWithFilters.cs b/TeraFinder.Tests/GenerateRewardsWithFilters.cs new file mode 100644 index 00000000..a89f006f --- /dev/null +++ b/TeraFinder.Tests/GenerateRewardsWithFilters.cs @@ -0,0 +1,60 @@ +using Xunit; +using PKHeX.Core; +using TeraFinder.Core; + +#pragma warning disable CS8604 // Dereference of a possibly null reference. +#pragma warning disable CS8629 // Nullable value type may be null. +namespace TeraFinder.Tests +{ + public class GenerateRewardsWithFilters + { + private const uint MaxTests = 0xFFFF; + + [Fact] + public void TestEncounterTeraTF9StandardFilter() + { + for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) + for (byte stars = 1; stars <= 5; stars++) + { + var encounters = ResourcesUtil.GetAllTeraEncounters(map).standard; + for (var game = GameVersion.SL; game <= GameVersion.VL; game++) + { + var romTotal = game is GameVersion.VL ? EncounterTera9.GetRateTotalVL(stars, map) : EncounterTera9.GetRateTotalSL(stars, map); + var filter = new RewardFilter(true, false) { Encounter = new EncounterFilter(0, stars), FilterRewards = [] }; + var effective_encounters = encounters.Where(filter.IsEncounterMatch).ToArray(); + + for (var progress = GameProgress.UnlockedTeraRaids; progress <= GameProgress.Unlocked6Stars; progress++) + ParallelizeGeneration(effective_encounters, filter, game, RaidContent.Standard, romTotal, progress); + } + } + } + + [Fact] + public void TestEncounterTeraTF9BlackFilter() + { + for (var map = TeraRaidMapParent.Paldea; map <= TeraRaidMapParent.Blueberry; map++) + { + var encounters = ResourcesUtil.GetAllTeraEncounters(map).black; + for (var game = GameVersion.SL; game <= GameVersion.VL; game++) + { + var romTotal = game is GameVersion.VL ? EncounterTera9.GetRateTotalVL(6, map) : EncounterTera9.GetRateTotalSL(6, map); + var filter = new RewardFilter(true, false) { Encounter = new EncounterFilter(0, 6), FilterRewards = [] }; + var effective_encounters = encounters.Where(filter.IsEncounterMatch).ToArray(); + + ParallelizeGeneration(effective_encounters, filter, game, RaidContent.Black, romTotal, GameProgress.Unlocked6Stars); + } + } + } + + private static void ParallelizeGeneration(EncounterRaidTF9[] encounters, RewardFilter filter, GameVersion version, RaidContent content, short rateTotal = 0, GameProgress progress = GameProgress.UnlockedTeraRaids, EventProgress eventProgress = EventProgress.Stage0, byte groupid = 0) + { + Parallel.For(0L, MaxTests, (seed, state) => + { + if (EncounterRaidTF9.TryGenerateRewardDetails((uint)seed, encounters, filter, rateTotal, version, progress, eventProgress, content, 0, groupid, 1, out var encounter, out var result)) + Assert.NotEmpty(result.Value.Rewards); + }); + } + } +} +#pragma warning restore CS8629 // Nullable value type may be null. +#pragma warning restore CS8604 // Dereference of a possibly null reference. \ No newline at end of file diff --git a/TeraFinder.Tests/TeraFinder.Tests.csproj b/TeraFinder.Tests/TeraFinder.Tests.csproj new file mode 100644 index 00000000..4ecc1247 --- /dev/null +++ b/TeraFinder.Tests/TeraFinder.Tests.csproj @@ -0,0 +1,31 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/TeraFinder.sln b/TeraFinder.sln index bc6b4397..00ed1078 100644 --- a/TeraFinder.sln +++ b/TeraFinder.sln @@ -6,12 +6,22 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TeraFinder.Core", "TeraFinder.Core\TeraFinder.Core.csproj", "{34B925D5-E9EE-45CD-95C2-133D632D5DFD}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TeraFinder.Plugins", "TeraFinder.Plugins\TeraFinder.Plugins.csproj", "{4E369721-CF2E-4C16-B409-F95272E7468D}" + ProjectSection(ProjectDependencies) = postProject + {1F659D38-B5FC-4A04-B2CA-8942FDAB18E5} = {1F659D38-B5FC-4A04-B2CA-8942FDAB18E5} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TeraFinder.Launcher", "TeraFinder.Launcher\TeraFinder.Launcher.csproj", "{E3234482-506B-4A94-9446-13247EE0A7A3}" ProjectSection(ProjectDependencies) = postProject {4E369721-CF2E-4C16-B409-F95272E7468D} = {4E369721-CF2E-4C16-B409-F95272E7468D} EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TeraFinder.RemoteExecutor", "TeraFinder.RemoteExecutor\TeraFinder.RemoteExecutor.csproj", "{1F659D38-B5FC-4A04-B2CA-8942FDAB18E5}" + ProjectSection(ProjectDependencies) = postProject + {34B925D5-E9EE-45CD-95C2-133D632D5DFD} = {34B925D5-E9EE-45CD-95C2-133D632D5DFD} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TeraFinder.Tests", "TeraFinder.Tests\TeraFinder.Tests.csproj", "{0CB3C5C8-9A89-4C72-8AE3-3D047734C347}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -30,6 +40,14 @@ Global {E3234482-506B-4A94-9446-13247EE0A7A3}.Debug|Any CPU.Build.0 = Debug|Any CPU {E3234482-506B-4A94-9446-13247EE0A7A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {E3234482-506B-4A94-9446-13247EE0A7A3}.Release|Any CPU.Build.0 = Release|Any CPU + {1F659D38-B5FC-4A04-B2CA-8942FDAB18E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F659D38-B5FC-4A04-B2CA-8942FDAB18E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F659D38-B5FC-4A04-B2CA-8942FDAB18E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F659D38-B5FC-4A04-B2CA-8942FDAB18E5}.Release|Any CPU.Build.0 = Release|Any CPU + {0CB3C5C8-9A89-4C72-8AE3-3D047734C347}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CB3C5C8-9A89-4C72-8AE3-3D047734C347}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CB3C5C8-9A89-4C72-8AE3-3D047734C347}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CB3C5C8-9A89-4C72-8AE3-3D047734C347}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE