├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report--non-legality-.md │ ├── feature-request.md │ └── legality-errors.md └── PULL_REQUEST_TEMPLATE │ ├── pull_request_template_fix.md │ └── pull_request_template_improvement.md ├── .gitignore ├── AutoLegalityMod ├── AutoModPlugins.csproj ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── GUI │ ├── ALMError.Designer.cs │ ├── ALMError.cs │ ├── ALMError.resx │ ├── ALMSettings.Designer.cs │ ├── ALMSettings.cs │ ├── ALMSettings.resx │ ├── LiveHexUI.Designer.cs │ ├── LiveHexUI.cs │ ├── LiveHexUI.resx │ ├── ShowdownSetLoader.cs │ ├── SimpleHexEditor.Designer.cs │ ├── SimpleHexEditor.cs │ ├── SimpleHexEditor.resx │ ├── WinFormsTranslator.cs │ └── WinFormsUtil.cs ├── PluginSettings.cs ├── Plugins │ ├── AutoModPlugin.cs │ ├── ExportBoxToShowdown.cs │ ├── GPSSPlugin.cs │ ├── LegalizeBoxes.cs │ ├── LiveHex.cs │ ├── LivingDex.cs │ ├── MGDBDownloader.cs │ ├── PKSMBankPlugin.cs │ ├── PasteImporter.cs │ ├── SettingsEditor.cs │ ├── SmogonGenner.cs │ └── URLGenning.cs ├── Properties │ ├── Resources.Designer.cs │ └── Resources.resx ├── Resources │ ├── img │ │ ├── autolegalitymod.png │ │ ├── blmicon.ico │ │ ├── exportboxtoshowdown.png │ │ ├── exportqrcode.png │ │ ├── exporttrainerdata.png │ │ ├── flagbrew.png │ │ ├── icon.ico │ │ ├── legalizeboxes.png │ │ ├── livingdex.png │ │ ├── menuautolegality.png │ │ ├── mgdbdownload.png │ │ ├── pglqrcode.png │ │ ├── settings.png │ │ ├── smogongenner.png │ │ ├── uploadgpss.png │ │ ├── urlimport.png │ │ └── wifi.png │ └── text │ │ ├── almlang_de.txt │ │ ├── almlang_en.txt │ │ ├── almlang_es.txt │ │ ├── almlang_fr.txt │ │ ├── almlang_it.txt │ │ ├── almlang_ja.txt │ │ ├── almlang_ko.txt │ │ └── almlang_zh.txt ├── app.config └── packages.config ├── AutoModTests ├── AutoModTests.csproj ├── FeatureMonitor.cs ├── FeatureTests.cs ├── Legality │ ├── Illegal │ │ └── 706_-_Goodra_-_971B6773DCC2.pk7 │ └── Legal │ │ └── 080 - Slowbro - A0935F4796B1.pk7 ├── LegalityTests.cs ├── LivingDexTests.cs ├── LogicTests.cs ├── ShowdownSetGenningTests.cs ├── ShowdownSets │ ├── Anubis Tests │ │ ├── Anubis - pa8.txt │ │ ├── Anubis - pb7.txt │ │ ├── Anubis - pb8.txt │ │ ├── Anubis - pk2.txt │ │ ├── Anubis - pk3.txt │ │ ├── Anubis - pk4.txt │ │ ├── Anubis - pk5.txt │ │ ├── Anubis - pk6.txt │ │ ├── Anubis - pk7.txt │ │ ├── Anubis - pk8.txt │ │ ├── Anubis - pk9.txt │ │ ├── Anubis VC - pk7.txt │ │ ├── Anubis notransfer - pb7.txt │ │ ├── Anubis notransfer - pk7.txt │ │ ├── Anubis transferred - pk7.txt │ │ └── Anubis transferred - pk8.txt │ ├── RoCs-PC Tests │ │ ├── RoC - pa8.txt │ │ ├── RoC - pb7.txt │ │ ├── RoC - pb8.txt │ │ ├── RoC - pk1.txt │ │ ├── RoC - pk2.txt │ │ ├── RoC - pk3.txt │ │ ├── RoC - pk4.txt │ │ ├── RoC - pk5.txt │ │ ├── RoC - pk6.txt │ │ ├── RoC - pk7.txt │ │ ├── RoC - pk8.txt │ │ ├── RoC - pk9.txt │ │ ├── RoC VC - pk7.txt │ │ ├── RoC notransfer - pk1.txt │ │ ├── RoC notransfer - pk3.txt │ │ ├── RoC notransfer - pk4.txt │ │ ├── RoC notransfer - pk5.txt │ │ ├── RoC notransfer - pk6.txt │ │ └── RoC notransfer - pk7.txt │ └── Underleveled Tests │ │ ├── Underlevel - pk1.txt │ │ ├── Underlevel - pk2.txt │ │ ├── Underlevel - pk3.txt │ │ ├── Underlevel - pk4.txt │ │ ├── Underlevel - pk5.txt │ │ ├── Underlevel - pk6.txt │ │ ├── Underlevel - pk7.txt │ │ ├── Underlevel VC - pk7.txt │ │ └── Underlevel notransfer - pk4.txt ├── TeamTests.cs ├── TestUtil.cs └── WebSetFetch.cs ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Directory.Build.props ├── LICENSE ├── PKHeX-Plugins.sln ├── PKHeX.Core.AutoMod ├── AutoMod │ ├── ALMTraceback.cs │ ├── APILegality.cs │ ├── AutoModErrorCode.cs │ ├── Legalization │ │ ├── AbilityRequest.cs │ │ ├── LegalEdits.cs │ │ ├── LegalizationResult.cs │ │ ├── Legalizer.cs │ │ ├── ShowdownEdits.cs │ │ └── SimpleEdits.cs │ ├── Regeneration │ │ ├── RegenSet.cs │ │ ├── RegenSetting.cs │ │ ├── RegenTemplate.cs │ │ ├── RegenTemplateExtensions.cs │ │ └── RegenUtil.cs │ ├── Seeds │ │ ├── BACD_R │ │ │ └── WC3Seeds.cs │ │ └── XOROSHIRO │ │ │ └── Overworld8Search.cs │ ├── Trainers │ │ ├── PokeTrainerDetails.cs │ │ └── TrainerSettings.cs │ └── Util │ │ ├── LivingDexUtils.cs │ │ └── Version.cs ├── Enhancements │ ├── Aesthetics.cs │ ├── BattleTemplateLegality.cs │ ├── EasterEggs.cs │ ├── GlyphLegality.cs │ └── ModLogic.cs └── PKHeX.Core.AutoMod.csproj ├── PKHeX.Core.Enhancements ├── Enhancements │ ├── EventsGallery.cs │ ├── NetUtil.cs │ ├── PKMPreview.cs │ └── PKSMUtil.cs ├── PKHeX.Core.Enhancements.csproj └── Teams │ ├── RentalTeam.cs │ ├── ShowdownTeamSet.cs │ ├── ShowdownUtil.cs │ ├── SmogonSetList.cs │ └── TeamPasteInfo.cs ├── PKHeX.Core.Injection ├── BlockData.cs ├── BotController │ ├── Controllers │ │ ├── NTRClient.cs │ │ ├── SysBotMini.cs │ │ └── UsbBotMini.cs │ ├── Decoder.cs │ ├── ICommunicator.cs │ ├── LiveHexController.cs │ ├── NTRAPIFramework.cs │ ├── PokeSysBotMini.cs │ └── SwitchCommand.cs ├── Enums │ ├── LiveHeXValidation.cs │ ├── LiveHeXVersion.cs │ ├── SwitchButton.cs │ └── SwitchStick.cs ├── InjectionBase │ └── InjectionBase.cs ├── LiveHeXBlockClasses │ ├── ICustomBlock.cs │ └── SwayGrass.cs ├── LiveHeXOffsets │ ├── LiveHeXBlocks.cs │ ├── Offsets8.cs │ └── RamOffsets.cs ├── PKHeX.Core.Injection.csproj ├── PointerCache │ └── PointerCache.cs ├── Protocols │ ├── LPBDSP.cs │ ├── LPBasic.cs │ ├── LPLGPE.cs │ └── LPPointer.cs └── Util │ ├── ArrayUtil.cs │ └── InjectionUtil.cs ├── README.md ├── azure-pipelines.yml ├── setup_bleedingedge.ps1 └── setup_stable.ps1 /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | csharp_style_var_for_built_in_types=true:silent 3 | csharp_style_var_when_type_is_apparent=true:silent 4 | csharp_style_var_elsewhere=true:silent 5 | 6 | dotnet_diagnostic.IDE0055.severity = none 7 | 8 | ## 9 | ## StyleCop.Analyzers 10 | ## 11 | 12 | dotnet_diagnostic.SA1000.severity = none 13 | dotnet_diagnostic.SA1009.severity = none 14 | dotnet_diagnostic.SA1111.severity = none 15 | dotnet_diagnostic.SA1118.severity = none 16 | dotnet_diagnostic.SA1137.severity = none 17 | dotnet_diagnostic.SA1500.severity = none 18 | dotnet_diagnostic.SA1501.severity = none 19 | dotnet_diagnostic.SA1502.severity = none 20 | dotnet_diagnostic.SA1504.severity = none 21 | dotnet_diagnostic.SA1516.severity = none 22 | dotnet_diagnostic.SA1001.severity = none 23 | dotnet_diagnostic.SA1002.severity = none 24 | dotnet_diagnostic.SA1003.severity = none 25 | dotnet_diagnostic.SA1007.severity = none 26 | dotnet_diagnostic.SA1008.severity = none 27 | dotnet_diagnostic.SA1010.severity = none 28 | dotnet_diagnostic.SA1011.severity = none 29 | dotnet_diagnostic.SA1012.severity = none 30 | dotnet_diagnostic.SA1013.severity = none 31 | dotnet_diagnostic.SA1014.severity = none 32 | dotnet_diagnostic.SA1015.severity = none 33 | dotnet_diagnostic.SA1016.severity = none 34 | dotnet_diagnostic.SA1017.severity = none 35 | dotnet_diagnostic.SA1018.severity = none 36 | dotnet_diagnostic.SA1019.severity = none 37 | dotnet_diagnostic.SA1020.severity = none 38 | dotnet_diagnostic.SA1021.severity = none 39 | dotnet_diagnostic.SA1022.severity = none 40 | dotnet_diagnostic.SA1023.severity = none 41 | dotnet_diagnostic.SA1024.severity = none 42 | dotnet_diagnostic.SA1025.severity = none 43 | dotnet_diagnostic.SA1026.severity = none 44 | dotnet_diagnostic.SA1027.severity = none 45 | dotnet_diagnostic.SA1028.severity = none 46 | dotnet_diagnostic.SA1102.severity = none 47 | dotnet_diagnostic.SA1103.severity = none 48 | dotnet_diagnostic.SA1104.severity = none 49 | dotnet_diagnostic.SA1105.severity = none 50 | dotnet_diagnostic.SA1107.severity = none 51 | dotnet_diagnostic.SA1110.severity = none 52 | dotnet_diagnostic.SA1112.severity = none 53 | dotnet_diagnostic.SA1113.severity = none 54 | dotnet_diagnostic.SA1114.severity = none 55 | dotnet_diagnostic.SA1115.severity = none 56 | dotnet_diagnostic.SA1116.severity = none 57 | dotnet_diagnostic.SA1117.severity = none 58 | dotnet_diagnostic.SA1127.severity = none 59 | dotnet_diagnostic.SA1128.severity = none 60 | dotnet_diagnostic.SA1136.severity = none 61 | dotnet_diagnostic.SA1505.severity = none 62 | dotnet_diagnostic.SA1506.severity = none 63 | dotnet_diagnostic.SA1507.severity = none 64 | dotnet_diagnostic.SA1508.severity = none 65 | dotnet_diagnostic.SA1509.severity = none 66 | dotnet_diagnostic.SA1510.severity = none 67 | dotnet_diagnostic.SA1511.severity = none 68 | dotnet_diagnostic.SA1517.severity = none 69 | dotnet_diagnostic.SA1518.severity = none -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report--non-legality-.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report (non-Legality) 3 | about: Create a report to help us fix a crash / incorrect behavior 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/legality-errors.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Legality issues with Auto-Legality Mod 3 | about: Legal set is not being generated or Pokemon not being legalized 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the problem** 11 | A clear and concise description of what the bug is. This is not to ask why impossible sets cannot be legalized. That should be obvious. 12 | If you encounter a legal pokemon that timed out or didn't legalize properly, upload the `error_log.txt` file present in the same directory as PKHeX 13 | 14 | **To Reproduce** 15 | Please provide the exact set that failed to legalize or a PKM file that failed legalization or adequate information so that we may quickly replicate the parsing behavior on our end. Also specify if any trainerdata was being used. 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots of Plugin Settings help explain your problem. 22 | 23 | **Additional context** 24 | Add any other context about the problem here. -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/pull_request_template_fix.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Fix 3 | about: Provide a fix for this project 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Please describe your fix.** 11 | A clear and concise description of what the pull request contains. -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/pull_request_template_improvement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Improvement 3 | about: Provide an improvement for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Please describe your improvement.** 11 | A clear and concise description of what the pull request contains. -------------------------------------------------------------------------------- /AutoLegalityMod/AutoModPlugins.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0-windows 5 | true 6 | true 7 | 8 | 9 | 10 | portable 11 | true 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | True 32 | True 33 | Resources.resx 34 | 35 | 36 | True 37 | True 38 | Settings.settings 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /AutoLegalityMod/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /AutoLegalityMod/GUI/ALMError.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | 6 | namespace AutoModPlugins.GUI 7 | { 8 | public partial class ALMError : Form 9 | { 10 | public ALMError(string error_txt, string[] buttons) 11 | { 12 | if (buttons.Length > 4) 13 | throw new Exception($"Expected 4 buttons at maximum but found {buttons.Length}."); 14 | if (buttons.Length == 0) 15 | throw new Exception("Need at least 1 button."); 16 | 17 | InitializeComponent(); 18 | label1.Text = error_txt; 19 | var btn_ctrls = new[] { BTN1, BTN2, BTN3, BTN4 }; 20 | buttons = buttons.Reverse().ToArray(); 21 | var btn_loc = label1.Location.Y + label1.Size.Height + 10; 22 | var height_diff = btn_loc - BTN1.Location.Y; 23 | for (int i = 0; i < buttons.Length; i++) 24 | { 25 | btn_ctrls[i].Visible = true; 26 | btn_ctrls[i].Enabled = true; 27 | btn_ctrls[i].Text = buttons[i]; 28 | } 29 | Size = new Size(Size.Width, Size.Height + height_diff); 30 | } 31 | 32 | private void BTN4_Click(object sender, EventArgs e) 33 | { 34 | DialogResult = DialogResult.Yes; 35 | Close(); 36 | } 37 | 38 | private void BTN3_Click(object sender, EventArgs e) 39 | { 40 | DialogResult = DialogResult.No; 41 | Close(); 42 | } 43 | 44 | private void BTN2_Click(object sender, EventArgs e) 45 | { 46 | DialogResult = DialogResult.Retry; 47 | Close(); 48 | } 49 | 50 | private void BTN1_Click(object sender, EventArgs e) 51 | { 52 | DialogResult = DialogResult.OK; 53 | Close(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /AutoLegalityMod/GUI/ALMSettings.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace AutoModPlugins.GUI 2 | { 3 | partial class ALMSettings 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.PG_Settings = new System.Windows.Forms.PropertyGrid(); 32 | this.SuspendLayout(); 33 | // 34 | // PG_Settings 35 | // 36 | this.PG_Settings.Dock = System.Windows.Forms.DockStyle.Fill; 37 | this.PG_Settings.Location = new System.Drawing.Point(0, 0); 38 | this.PG_Settings.Name = "PG_Settings"; 39 | this.PG_Settings.Size = new System.Drawing.Size(334, 328); 40 | this.PG_Settings.TabIndex = 1; 41 | // 42 | // ALMSettings 43 | // 44 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; 45 | this.AutoSize = true; 46 | this.ClientSize = new System.Drawing.Size(334, 328); 47 | this.Controls.Add(this.PG_Settings); 48 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; 49 | this.Icon = global::AutoModPlugins.Properties.Resources.icon; 50 | this.KeyPreview = true; 51 | this.MaximizeBox = false; 52 | this.MinimizeBox = false; 53 | this.MinimumSize = new System.Drawing.Size(350, 367); 54 | this.Name = "ALMSettings"; 55 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 56 | this.Text = "Auto Legality Plugin Settings"; 57 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ALMSettings_FormClosing); 58 | this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.SettingsEditor_KeyDown); 59 | this.ResumeLayout(false); 60 | 61 | } 62 | 63 | #endregion 64 | 65 | private System.Windows.Forms.PropertyGrid PG_Settings; 66 | } 67 | } -------------------------------------------------------------------------------- /AutoLegalityMod/GUI/ALMSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Windows.Forms; 6 | 7 | namespace AutoModPlugins.GUI 8 | { 9 | public partial class ALMSettings : Form 10 | { 11 | private PluginSettings pluginSettings; 12 | 13 | public ALMSettings(PluginSettings obj) 14 | { 15 | pluginSettings = obj; 16 | InitializeComponent(); 17 | EditSettingsProperties(obj); 18 | PG_Settings.SelectedObject = obj; 19 | this.TranslateInterface(WinFormsTranslator.CurrentLanguage); 20 | var parent = FindForm(); 21 | if (parent != null) 22 | this.CenterToForm(parent); 23 | } 24 | 25 | private void SettingsEditor_KeyDown(object sender, KeyEventArgs e) 26 | { 27 | if (e.KeyCode == Keys.W && ModifierKeys == Keys.Control) 28 | Close(); 29 | } 30 | 31 | private void ALMSettings_FormClosing(object sender, FormClosingEventArgs e) 32 | { 33 | // ALM Settings 34 | ShowdownSetLoader.SetAPILegalitySettings(pluginSettings); 35 | 36 | pluginSettings.Save(); 37 | } 38 | 39 | private static void EditSettingsProperties(object _settings) 40 | { 41 | var lang = WinFormsTranslator.CurrentLanguage; 42 | var translation = WinFormsTranslator.GetContext(lang); 43 | var type_descriptor = TypeDescriptor 44 | .GetProvider(_settings) 45 | .GetTypeDescriptor(_settings); 46 | if (type_descriptor == null) 47 | return; 48 | var ctd = new PropertyOverridingTypeDescriptor(type_descriptor); 49 | foreach (var pd in TypeDescriptor.GetProperties(_settings).OfType()) 50 | { 51 | var desc = "Property Description needs to be defined. Please raise this issue on GitHub or at the discord: https://discord.gg/tDMvSRv"; 52 | if (pd.Description != null) 53 | desc = translation.GetTranslatedText($"{pd.Name}_description", pd.Description); 54 | 55 | var category = "Uncategorized Settings"; 56 | if (pd.Category != null) 57 | category = translation.GetTranslatedText($"{pd.Name}_category", pd.Category); 58 | if (desc == null || category == null) 59 | throw new Exception("Category / Description translations are null"); 60 | PropertyDescriptor pd2 = TypeDescriptor.CreateProperty( 61 | _settings.GetType(), 62 | pd, 63 | new DescriptionAttribute(desc), 64 | new CategoryAttribute(category) 65 | ); 66 | ctd.OverrideProperty(pd2); 67 | } 68 | TypeDescriptor.AddProvider(new TypeDescriptorOverridingProvider(ctd), _settings); 69 | } 70 | } 71 | 72 | public class PropertyOverridingTypeDescriptor(ICustomTypeDescriptor parent) : CustomTypeDescriptor(parent) 73 | { 74 | private readonly Dictionary overridePds = []; 75 | 76 | public void OverrideProperty(PropertyDescriptor pd) 77 | { 78 | overridePds[pd.Name] = pd; 79 | } 80 | 81 | public override object GetPropertyOwner(PropertyDescriptor? pd) 82 | { 83 | var o = base.GetPropertyOwner(pd); 84 | return o ?? this; 85 | } 86 | 87 | public PropertyDescriptorCollection GetPropertiesImpl(PropertyDescriptorCollection pdc) 88 | { 89 | var pdl = new List(pdc.Count + 1); 90 | 91 | foreach (PropertyDescriptor pd in pdc) 92 | pdl.Add(overridePds.GetValueOrDefault(pd.Name, pd)); 93 | 94 | return new PropertyDescriptorCollection([.. pdl]); 95 | } 96 | 97 | public override PropertyDescriptorCollection GetProperties() 98 | { 99 | return GetPropertiesImpl(base.GetProperties()); 100 | } 101 | 102 | public override PropertyDescriptorCollection GetProperties(Attribute[]? attributes) 103 | { 104 | return GetPropertiesImpl(base.GetProperties(attributes)); 105 | } 106 | } 107 | 108 | public class TypeDescriptorOverridingProvider(ICustomTypeDescriptor ctd) : TypeDescriptionProvider 109 | { 110 | public override ICustomTypeDescriptor GetTypeDescriptor(Type? objectType, object? instance) => ctd; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /AutoLegalityMod/GUI/WinFormsUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Media; 6 | using System.Windows.Forms; 7 | using AutoModPlugins.GUI; 8 | using static PKHeX.Core.AutoMod.ALMVersion; 9 | 10 | namespace AutoModPlugins 11 | { 12 | public static class WinFormsUtil 13 | { 14 | public static DialogResult Alert(params string[] lines) 15 | { 16 | SystemSounds.Asterisk.Play(); 17 | string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); 18 | return MessageBox.Show( 19 | msg, 20 | nameof(Alert), 21 | MessageBoxButtons.OK, 22 | MessageBoxIcon.Information 23 | ); 24 | } 25 | 26 | public static DialogResult Prompt(MessageBoxButtons btn, params string[] lines) 27 | { 28 | SystemSounds.Question.Play(); 29 | string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); 30 | return MessageBox.Show(msg, nameof(Prompt), btn, MessageBoxIcon.Asterisk); 31 | } 32 | 33 | /// 34 | /// Displays a dialog showing the details of an error. 35 | /// 36 | /// User-friendly message about the error. 37 | /// The associated with the dialog. 38 | public static DialogResult Error(params string[] lines) 39 | { 40 | SystemSounds.Hand.Play(); 41 | string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); 42 | return MessageBox.Show(msg, nameof(Error), MessageBoxButtons.OK, MessageBoxIcon.Error); 43 | } 44 | 45 | public static ALMError ALMErrorMismatch(AssemblyVersions versions) 46 | { 47 | // ReSharper disable once SuspiciousTypeConversion.Global 48 | var msg = 49 | "Version mismatch between ALM and PKHeX.\n\n" 50 | + $"Current ALM version: {versions.AlmVersionCurrent}\n" 51 | + $"Current PKHeX version: {versions.CoreVersionCurrent}\n\n" 52 | + "Click the \"Wiki\" button to learn how to fix this error."; 53 | 54 | return new ALMError(msg, ["Wiki", "Cancel"]); 55 | } 56 | 57 | public static ALMError ALMErrorBasic(string msg, bool updateButton = false) 58 | { 59 | SystemSounds.Hand.Play(); 60 | return new ALMError(msg, [updateButton ? "Update" : "Wiki", "Cancel"]); 61 | } 62 | 63 | /// 64 | /// Opens a dialog to open a PKM/SAV file. 65 | /// 66 | /// Misc extensions of files supported. 67 | /// Output result path 68 | /// Result of whether a file is to be loaded from the output path. 69 | public static bool OpenSAVPKMDialog(IEnumerable Extensions, out string? path) 70 | { 71 | string supported = string.Join( 72 | ";", 73 | Extensions.Select(s => $"*.{s}").Concat(["*.pkm"]) 74 | ); 75 | using var ofd = new OpenFileDialog(); 76 | ofd.Filter = "All Files|*.*" 77 | + $"|Supported Files (*.*)|main;*.bin;{supported};*.bak" 78 | + "|Save Files (*.sav)|main" 79 | + "|Decrypted PKM File (*.pkm)|" 80 | + supported 81 | + "|Binary File|*.bin" 82 | + "|Backup File|*.bak"; 83 | if (ofd.ShowDialog() != DialogResult.OK) 84 | { 85 | path = null; 86 | return false; 87 | } 88 | 89 | path = ofd.FileName; 90 | return true; 91 | } 92 | 93 | internal static void CenterToForm(this Control child, Control parent) 94 | { 95 | int x = parent.Location.X + ((parent.Width - child.Width) / 2); 96 | int y = parent.Location.Y + ((parent.Height - child.Height) / 2); 97 | child.Location = new Point(Math.Max(x, 0), Math.Max(y, 0)); 98 | } 99 | 100 | public static T? FirstFormOfType() 101 | where T : Form => FormsOfType().FirstOrDefault(); 102 | 103 | public static IEnumerable FormsOfType() 104 | where T : Form => Application.OpenForms.OfType(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/ExportBoxToShowdown.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using AutoModPlugins.Properties; 4 | using PKHeX.Core; 5 | using PKHeX.Core.AutoMod; 6 | 7 | namespace AutoModPlugins 8 | { 9 | public class ExportBoxToShowdown : AutoModPlugin 10 | { 11 | public override string Name => "Export Box to ALM Showdown Template"; 12 | public override int Priority => 1; 13 | 14 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 15 | { 16 | var ctrl = new ToolStripMenuItem(Name) { Image = Resources.exportboxtoshowdown }; 17 | ctrl.Click += (_, _) => Export(SaveFileEditor); 18 | ctrl.Name = "Menu_ExportBoxtoShowdown"; 19 | modmenu.DropDownItems.Add(ctrl); 20 | } 21 | 22 | private static void Export(ISaveFileProvider provider) 23 | { 24 | try 25 | { 26 | var str = provider.GetRegenSetsFromBoxCurrent(); 27 | if (string.IsNullOrWhiteSpace(str)) 28 | return; 29 | Clipboard.SetText(str); 30 | WinFormsUtil.Alert("Exported the active box in RegenTemplate format to clipboard."); 31 | } 32 | catch (Exception e) 33 | { 34 | WinFormsUtil.Error("Unable to export text to clipboard.", e.Message); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/LegalizeBoxes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Windows.Forms; 4 | using AutoModPlugins.Properties; 5 | using PKHeX.Core; 6 | using PKHeX.Core.AutoMod; 7 | 8 | namespace AutoModPlugins 9 | { 10 | public class LegalizeBoxes : AutoModPlugin 11 | { 12 | public override string Name => "Legalize Active Pokemon"; 13 | public override int Priority => 1; 14 | 15 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 16 | { 17 | var ctrl = new ToolStripMenuItem(Name) { Image = Resources.legalizeboxes }; 18 | ctrl.Click += Legalize; 19 | ctrl.Name = "Menu_LeaglizeBoxes"; 20 | modmenu.DropDownItems.Add(ctrl); 21 | } 22 | 23 | private void Legalize(object? sender, EventArgs e) 24 | { 25 | try 26 | { 27 | var box = (Control.ModifierKeys & Keys.Control) == Keys.Control; 28 | if (!box) 29 | { 30 | LegalizeActive(); 31 | return; 32 | } 33 | 34 | var all = (Control.ModifierKeys & Keys.Shift) == Keys.Shift; 35 | if (!all) 36 | LegalizeCurrent(); 37 | else 38 | LegalizeAllBoxes(); 39 | } 40 | catch (MissingMethodException) 41 | { 42 | var errorstr = 43 | "The PKHeX-Plugins version does not match the PKHeX version.\nRefer to the Wiki for how to fix this error.\n\n" 44 | + $"The current ALM Version is {ALMVersion.Versions.AlmVersionCurrent}\n" 45 | + $"The current PKHeX Version is {ALMVersion.Versions.CoreVersionCurrent}"; 46 | 47 | var error = WinFormsUtil.ALMErrorBasic(errorstr); 48 | error.ShowDialog(); 49 | 50 | var res = error.DialogResult; 51 | if (res == DialogResult.Retry) 52 | { 53 | var pi = new ProcessStartInfo 54 | { 55 | FileName = "https://github.com/architdate/PKHeX-Plugins/wiki/Installing-PKHeX-Plugins", 56 | UseShellExecute = true, 57 | }; 58 | Process.Start(pi); 59 | } 60 | } 61 | } 62 | 63 | private void LegalizeCurrent() 64 | { 65 | var sav = SaveFileEditor.SAV; 66 | var count = sav.LegalizeBox(sav.CurrentBox); 67 | if (count <= 0) // failed to modify anything 68 | return; 69 | SaveFileEditor.ReloadSlots(); 70 | WinFormsUtil.Alert($"Legalized {count} Pokémon in Current Box!"); 71 | } 72 | 73 | private void LegalizeAllBoxes() 74 | { 75 | var sav = SaveFileEditor.SAV; 76 | var count = sav.LegalizeBoxes(); 77 | if (count <= 0) // failed to modify anything 78 | return; 79 | SaveFileEditor.ReloadSlots(); 80 | WinFormsUtil.Alert($"Legalized {count} Pokémon across all boxes!"); 81 | } 82 | 83 | private void LegalizeActive() 84 | { 85 | var pk = PKMEditor.PreparePKM(); 86 | var la = new LegalityAnalysis(pk); 87 | if (la.Valid) 88 | return; // already valid, don't modify it 89 | 90 | var sav = SaveFileEditor.SAV; 91 | var result = sav.Legalize(pk); 92 | 93 | // let's double-check 94 | 95 | la = new LegalityAnalysis(result); 96 | if (!la.Valid) 97 | { 98 | const string errorstr = "Unable to make the Active Pokemon legal!\n\n" 99 | + "No legal Pokémon matches the provided traits.\n\n" 100 | + "Visit the Wiki to learn how to import Showdown Sets."; 101 | 102 | var error = WinFormsUtil.ALMErrorBasic(errorstr); 103 | error.ShowDialog(); 104 | 105 | var res = error.DialogResult; 106 | if (res != DialogResult.Retry) 107 | return; 108 | 109 | var pi = new ProcessStartInfo 110 | { 111 | FileName = "https://github.com/architdate/PKHeX-Plugins/wiki/Getting-Started-with-Auto-Legality-Mod", 112 | UseShellExecute = true, 113 | }; 114 | Process.Start(pi); 115 | return; 116 | } 117 | 118 | PKMEditor.PopulateFields(result); 119 | WinFormsUtil.Alert("Legalized Active Pokemon!"); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/LiveHex.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | using AutoModPlugins.Properties; 3 | using PKHeX.Core; 4 | using PKHeX.Core.Injection; 5 | 6 | namespace AutoModPlugins 7 | { 8 | public class LiveHeX : AutoModPlugin 9 | { 10 | public override string Name => "Open LiveHeX"; 11 | public override int Priority => 1; 12 | 13 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 14 | { 15 | var c1 = new ToolStripMenuItem(Name) { Image = Resources.wifi }; 16 | c1.Click += (_, _) => 17 | { 18 | var sav = SaveFileEditor.SAV; 19 | if (!RamOffsets.IsLiveHeXSupported(sav)) 20 | { 21 | WinFormsUtil.Error( 22 | "Must have a 3DS or Switch main line game save file currently loaded." 23 | ); 24 | return; 25 | } 26 | 27 | var editor = WinFormsUtil.FirstFormOfType(); 28 | if (editor == null) 29 | { 30 | editor = new LiveHeXUI(SaveFileEditor, PKMEditor, _settings); 31 | editor.Show(); 32 | } 33 | else 34 | { 35 | editor.Focus(); 36 | // WinFormsUtil.Alert("LiveHeX already open!"); 37 | } 38 | }; 39 | c1.Name = "Menu_LiveHeX"; 40 | modmenu.DropDownItems.Add(c1); 41 | } 42 | 43 | public override void NotifySaveLoaded() 44 | { 45 | if (SaveFileEditor.SAV is SAV8SWSH) 46 | return; 47 | 48 | // close any windows & connections to force disconnect 49 | var forms = WinFormsUtil.FormsOfType(); 50 | foreach (var form in forms) 51 | form.Close(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/LivingDex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Windows.Forms; 4 | using AutoModPlugins.Properties; 5 | using PKHeX.Core; 6 | using PKHeX.Core.AutoMod; 7 | 8 | namespace AutoModPlugins 9 | { 10 | public class LivingDex : AutoModPlugin 11 | { 12 | public override string Name => "Generate Living Dex"; 13 | public override int Priority => 1; 14 | 15 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 16 | { 17 | var ctrl = new ToolStripMenuItem(Name) { Image = Resources.livingdex }; 18 | ctrl.Click += GenLivingDex; 19 | ctrl.Name = "Menu_LivingDex"; 20 | modmenu.DropDownItems.Add(ctrl); 21 | } 22 | 23 | private void GenLivingDex(object? sender, EventArgs e) 24 | { 25 | var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Generate a Living Dex?"); 26 | if (prompt != DialogResult.Yes) 27 | return; 28 | 29 | var sav = SaveFileEditor.SAV; 30 | Span pkms = sav.GenerateLivingDex().ToArray(); 31 | Span bd = sav.BoxData.ToArray(); 32 | if (pkms.Length > bd.Length) 33 | pkms = pkms[..bd.Length]; 34 | pkms.CopyTo(bd); 35 | sav.BoxData = bd.ToArray(); 36 | SaveFileEditor.ReloadSlots(); 37 | 38 | System.Diagnostics.Debug.WriteLine($"Generated Living Dex with {pkms.Length} entries."); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/MGDBDownloader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Windows.Forms; 4 | using AutoModPlugins.Properties; 5 | using PKHeX.Core; 6 | using PKHeX.Core.Enhancements; 7 | 8 | namespace AutoModPlugins 9 | { 10 | public class MGDBDownloader : AutoModPlugin 11 | { 12 | public override string Name => "Download MGDB"; 13 | public override int Priority => 1; 14 | public static string MGDatabasePath => 15 | Path.Combine(Directory.GetCurrentDirectory(), "mgdb"); 16 | 17 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 18 | { 19 | var ctrl = new ToolStripMenuItem(Name) { Image = Resources.mgdbdownload }; 20 | ctrl.Click += DownloadMGDB; 21 | ctrl.Name = "Menu_MGDBDownloader"; 22 | modmenu.DropDownItems.Add(ctrl); 23 | } 24 | 25 | private static void DownloadMGDB(object? o, EventArgs e) 26 | { 27 | if (Directory.Exists(MGDatabasePath)) 28 | { 29 | var result = WinFormsUtil.Prompt( 30 | MessageBoxButtons.YesNo, 31 | "MGDB already exists!", 32 | "Update MGDB?" 33 | ); 34 | if (result != DialogResult.Yes) 35 | return; 36 | DeleteDirectory(MGDatabasePath); // Adding events will be handled by the next conditional 37 | } 38 | if (Directory.Exists(MGDatabasePath)) 39 | return; 40 | 41 | var prompt = WinFormsUtil.Prompt( 42 | MessageBoxButtons.YesNoCancel, 43 | "Download entire database?", 44 | "Download the entire database, which includes past generation events?", 45 | "Selecting No will download only the public release of the database." 46 | ); 47 | 48 | if (prompt == DialogResult.Cancel) 49 | return; 50 | var entire = prompt == DialogResult.Yes; 51 | EventsGallery.DownloadMGDBFromGitHub(MGDatabasePath, entire); 52 | WinFormsUtil.Alert("Download Finished"); 53 | EncounterEvent.RefreshMGDB(MGDatabasePath); 54 | } 55 | 56 | public static void DeleteDirectory(string target_dir) 57 | { 58 | var files = Directory.GetFiles(target_dir); 59 | var dirs = Directory.GetDirectories(target_dir); 60 | 61 | foreach (string file in files) 62 | { 63 | File.SetAttributes(file, FileAttributes.Normal); 64 | File.Delete(file); 65 | } 66 | 67 | foreach (string dir in dirs) 68 | { 69 | DeleteDirectory(dir); 70 | } 71 | 72 | Directory.Delete(target_dir, false); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/PKSMBankPlugin.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows.Forms; 3 | using AutoModPlugins.Properties; 4 | using PKHeX.Core.Enhancements; 5 | 6 | namespace AutoModPlugins 7 | { 8 | public class PKSMBankPlugin : AutoModPlugin 9 | { 10 | public override string Name => "PKSM Bank Tools"; 11 | public override int Priority => 2; 12 | 13 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 14 | { 15 | var ctrl = new ToolStripMenuItem(Name) { Name = "Menu_PKSMBank" }; 16 | 17 | var c1 = new ToolStripMenuItem("Merge PKM into PKSM Bank") 18 | { 19 | Image = Resources.uploadgpss 20 | }; 21 | c1.Click += (_, _) => Import(); 22 | c1.Name = "Menu_CreatePKSMBank"; 23 | var c2 = new ToolStripMenuItem("Split PKSM Bank into PKM") 24 | { 25 | Image = Resources.mgdbdownload 26 | }; 27 | c2.Click += (_, _) => Export(); 28 | c2.Name = "Menu_ExportPKSMBank"; 29 | 30 | ctrl.DropDownItems.Add(c1); 31 | ctrl.DropDownItems.Add(c2); 32 | modmenu.DropDownItems.Add(ctrl); 33 | 34 | ctrl.Image = Resources.flagbrew; 35 | } 36 | 37 | private static void Export() 38 | { 39 | if (!WinFormsUtil.OpenSAVPKMDialog(new[] { ".bnk" }, out var path)) 40 | return; 41 | 42 | var bank = File.ReadAllBytes(path!); 43 | using var fbd = new FolderBrowserDialog(); 44 | if (fbd.ShowDialog() != DialogResult.OK) 45 | return; 46 | var count = PKSMUtil.ExportBank(bank, fbd.SelectedPath, out var previews); 47 | PKMPreview.ExportCSV(previews, fbd.SelectedPath); 48 | WinFormsUtil.Alert("Bank Exported!", $"Dumped {count} Pokémon!"); 49 | } 50 | 51 | private static void Import() 52 | { 53 | using var fbd = new FolderBrowserDialog(); 54 | if (fbd.ShowDialog() != DialogResult.OK) 55 | return; 56 | var count = PKSMUtil.CreateBank(fbd.SelectedPath); 57 | WinFormsUtil.Alert("Bank Created!", $"Added {count} Pokémon to the bank!"); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/PasteImporter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Windows.Forms; 4 | using AutoModPlugins.Properties; 5 | using PKHeX.Core.Enhancements; 6 | 7 | namespace AutoModPlugins 8 | { 9 | /// 10 | /// Main Plugin with clipboard import calls 11 | /// 12 | public class PasteImporter : AutoModPlugin 13 | { 14 | // TODO: Check for Auto-Legality Mod Updates 15 | public override string Name => "Import with Auto-Legality Mod"; 16 | public override int Priority => 0; 17 | 18 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 19 | { 20 | var ctrl = new ToolStripMenuItem(Name) 21 | { 22 | Image = Resources.autolegalitymod, 23 | ShortcutKeys = Keys.Control | Keys.I, 24 | }; 25 | ctrl.Click += ImportPaste; 26 | ctrl.Name = "Menu_PasteImporter"; 27 | modmenu.DropDownItems.Add(ctrl); 28 | var parent = modmenu.OwnerItem; 29 | var form = ( 30 | parent?.GetCurrentParent()?.Parent ?? throw new Exception("Parent not found") 31 | ).FindForm(); 32 | if (form is not null) 33 | form.Icon = Resources.icon; 34 | 35 | ShowdownSetLoader.PKMEditor = PKMEditor; 36 | ShowdownSetLoader.SaveFileEditor = SaveFileEditor; 37 | } 38 | 39 | private static void ImportPaste(object? sender, EventArgs e) 40 | { 41 | // Check for showdown data in clipboard 42 | var text = GetTextShowdownData(); 43 | if (string.IsNullOrWhiteSpace(text)) 44 | return; 45 | ShowdownSetLoader.Import(text); 46 | } 47 | 48 | /// 49 | /// Check whether the showdown text is supposed to be loaded via a text file. If so, set the clipboard to its contents. 50 | /// 51 | /// output boolean that tells if the data provided is valid or not 52 | private static string? GetTextShowdownData() 53 | { 54 | bool skipClipboardCheck = (Control.ModifierKeys & Keys.Shift) == Keys.Shift; 55 | if (!skipClipboardCheck && Clipboard.ContainsText()) 56 | { 57 | var txt = Clipboard.GetText(); 58 | if (ShowdownUtil.IsTextShowdownData(txt)) 59 | return txt; 60 | } 61 | 62 | if (!WinFormsUtil.OpenSAVPKMDialog(["txt"], out var path)) 63 | { 64 | WinFormsUtil.Alert("No data provided."); 65 | return null; 66 | } 67 | 68 | if (path == null) 69 | { 70 | WinFormsUtil.Alert("Path invalid."); 71 | return null; 72 | } 73 | 74 | var text = File.ReadAllText(path).TrimEnd(); 75 | if (ShowdownUtil.IsTextShowdownData(text)) 76 | return text; 77 | 78 | WinFormsUtil.Alert( 79 | "Text file with invalid data provided. Please provide a text file with proper Showdown data" 80 | ); 81 | return null; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/SettingsEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using AutoModPlugins.GUI; 4 | using AutoModPlugins.Properties; 5 | 6 | namespace AutoModPlugins 7 | { 8 | public class SettingsEditor : AutoModPlugin 9 | { 10 | public override string Name => "Plugin Settings"; 11 | public override int Priority => 3; 12 | 13 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 14 | { 15 | var ctrl = new ToolStripMenuItem(Name) { Image = Resources.settings }; 16 | ctrl.Click += SettingsForm; 17 | ctrl.Name = "Menu_ALMSettingsEditor"; 18 | modmenu.DropDownItems.Add(ctrl); 19 | } 20 | 21 | private static void SettingsForm(object? sender, EventArgs e) 22 | { 23 | using var form = new ALMSettings(_settings); 24 | form.ShowDialog(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/SmogonGenner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using AutoModPlugins.Properties; 4 | using PKHeX.Core; 5 | using PKHeX.Core.Enhancements; 6 | 7 | namespace AutoModPlugins 8 | { 9 | public class SmogonGenner : AutoModPlugin 10 | { 11 | public override string Name => "Generate Smogon Sets"; 12 | public override int Priority => 1; 13 | public static bool PromptForImport { get; set; } 14 | 15 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 16 | { 17 | var ctrl = new ToolStripMenuItem(Name) 18 | { 19 | Name = "Menu_SmogonGenner", 20 | Image = Resources.smogongenner 21 | }; 22 | modmenu.DropDownItems.Add(ctrl); 23 | ctrl.Click += SmogonGenning; 24 | } 25 | 26 | private void SmogonGenning(object? sender, EventArgs e) 27 | { 28 | var rough = PKMEditor.PreparePKM(); 29 | GenSmogonSets(rough); 30 | } 31 | 32 | private static void GenSmogonSets(PKM rough) 33 | { 34 | SmogonSetList info; 35 | try 36 | { 37 | info = new SmogonSetList(rough); 38 | } 39 | catch (Exception ex) 40 | { 41 | WinFormsUtil.Error( 42 | $"An error occured while trying to obtain the contents of the URL. This is most likely an issue with your Internet Connection. The exact error is as follows: {ex}" 43 | ); 44 | return; 45 | } 46 | 47 | if (!info.Valid || info.Sets.Count == 0) 48 | { 49 | WinFormsUtil.Error( 50 | "No movesets available. Perhaps you could help out? Check the Contributions & Corrections forum.\n\nForum: https://www.smogon.com/forums/forums/contributions-corrections.388/" 51 | ); 52 | return; 53 | } 54 | 55 | if (PromptForImport) 56 | { 57 | for (int i = 0; i < info.Sets.Count; ) 58 | { 59 | if ( 60 | DialogResult.Yes 61 | != WinFormsUtil.Prompt( 62 | MessageBoxButtons.YesNo, 63 | "Import this set?", 64 | $"[{info.SetFormat[i]}] {info.SetName[i]}", 65 | info.Sets[i].Text 66 | ) 67 | ) 68 | { 69 | info.Sets.RemoveAt(i); 70 | info.SetFormat.RemoveAt(i); 71 | info.SetName.RemoveAt(i); 72 | info.SetConfig.RemoveAt(i); 73 | info.SetText.RemoveAt(i); 74 | continue; 75 | } 76 | i++; 77 | } 78 | } 79 | 80 | ShowdownSetLoader.Import(info.Sets, PromptForImport); 81 | WinFormsUtil.Alert(info.Summary); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /AutoLegalityMod/Plugins/URLGenning.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using AutoModPlugins.Properties; 4 | using PKHeX.Core.Enhancements; 5 | 6 | namespace AutoModPlugins 7 | { 8 | public class URLGenning : AutoModPlugin 9 | { 10 | public override string Name => "Generate from URL"; 11 | public override int Priority => 1; 12 | 13 | protected override void AddPluginControl(ToolStripDropDownItem modmenu) 14 | { 15 | var ctrl = new ToolStripMenuItem(Name) { Image = Resources.urlimport }; 16 | ctrl.Click += URLGen; 17 | ctrl.Name = "Menu_URLGenning"; 18 | modmenu.DropDownItems.Add(ctrl); 19 | } 20 | 21 | private static void URLGen(object? sender, EventArgs e) 22 | { 23 | var url = Clipboard.GetText().Trim(); 24 | TeamPasteInfo info; 25 | try 26 | { 27 | info = new TeamPasteInfo(url); 28 | } 29 | catch (Exception ex) 30 | { 31 | WinFormsUtil.Error( 32 | "An error occurred while trying to obtain the contents of the URL.", 33 | $"The exact error is as follows: {ex}" 34 | ); 35 | return; 36 | } 37 | if (!info.Valid) 38 | { 39 | WinFormsUtil.Error("The data inside the URL are not valid Showdown Sets"); 40 | return; 41 | } 42 | if (info.Source == TeamPasteInfo.PasteSource.None) 43 | { 44 | WinFormsUtil.Error("The URL provided is not from a supported website."); 45 | return; 46 | } 47 | 48 | ShowdownSetLoader.Import(info.Sets); 49 | 50 | var response = $"All sets generated from the following URL: {info.URL}"; 51 | WinFormsUtil.Alert(response, info.Summary); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/autolegalitymod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/autolegalitymod.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/blmicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/blmicon.ico -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/exportboxtoshowdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/exportboxtoshowdown.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/exportqrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/exportqrcode.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/exporttrainerdata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/exporttrainerdata.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/flagbrew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/flagbrew.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/icon.ico -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/legalizeboxes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/legalizeboxes.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/livingdex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/livingdex.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/menuautolegality.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/menuautolegality.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/mgdbdownload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/mgdbdownload.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/pglqrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/pglqrcode.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/settings.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/smogongenner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/smogongenner.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/uploadgpss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/uploadgpss.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/urlimport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/urlimport.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/img/wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoLegalityMod/Resources/img/wifi.png -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/text/almlang_en.txt: -------------------------------------------------------------------------------- 1 | ALMSettings=Auto Legality Plugin Settings 2 | 3 | LiveHeXUI=LiveHeXUI 4 | LiveHeXUI.B_ReadCurrent=Read Current Box 5 | LiveHeXUI.B_WriteCurrent=Write Current Box 6 | LiveHeXUI.checkBox1=Read On Change Box 7 | LiveHeXUI.L_USBState=USB-Botbase Mode 8 | LiveHeXUI.L_IP=IP: 9 | LiveHeXUI.L_Port=Port: 10 | LiveHeXUI.B_Connect=Connect 11 | LiveHeXUI.B_Disconnect=Disconnect 12 | LiveHeXUI.groupBox1=Boxes 13 | LiveHeXUI.checkBox2=Inject In Slot 14 | LiveHeXUI.groupBox2=PKM Editor 15 | LiveHeXUI.L_ReadOffset=Offset: 16 | LiveHeXUI.B_ReadOffset=Read from Offset 17 | LiveHeXUI.L_Slot=Slot: 18 | LiveHeXUI.L_Box=Box: 19 | LiveHeXUI.B_ReadSlot=Read from Slot 20 | LiveHeXUI.B_WriteSlot=Write to Slot 21 | LiveHeXUI.groupBox3=Ram Editor 22 | LiveHeXUI.B_ReadRAM=Edit RAM 23 | LiveHeXUI.L_ReadRamOffset=Offset: 24 | LiveHeXUI.L_ReadRamSize=Size: 25 | LiveHeXUI.groupBox4=Pointer Lookup 26 | LiveHeXUI.groupBox5=Block Editor 27 | LiveHeXUI.groupBox6=RAM Config 28 | LiveHeXUI.L_Pointer=Pointer: 29 | LiveHeXUI.B_CopyAddress=Copy Address 30 | LiveHeXUI.B_ReadPointer=Read Pointer 31 | LiveHeXUI.B_EditBlock=Edit Block 32 | LiveHeXUI.B_EditPointer=Edit RAM 33 | LiveHeXUI.L_OffsRelative=RAM offsets relative to: 34 | LiveHeXUI.L_Block=Block: 35 | 36 | SimpleHexEditor=RAMEdit 37 | SimpleHexEditor.B_Update=Update 38 | 39 | Main.Menu_AutoLegality=Auto-Legality Mod 40 | Main.Menu_ExportBoxtoShowdown=Export Box to ALM Showdown Template 41 | Main.Menu_PasteImporter=Import with Auto-Legality Mod 42 | Main.Menu_PKSMBank=PKSM Bank Tools 43 | Main.Menu_CreatePKSMBank=Merge PKM into PKSM Bank 44 | Main.Menu_ExportPKSMBank=Split PKSM Bank into PKM 45 | Main.Menu_LeaglizeBoxes=Legalize Active Pokemon 46 | Main.Menu_LiveHeX=Open LiveHeX 47 | Main.Menu_LivingDex=Generate Living Dex 48 | Main.Menu_MGDBDownloader=Download MGDB 49 | Main.Menu_SmogonGenner=Generate Smogon Sets 50 | Main.Menu_URLGenning=Generate from URL 51 | Main.Menu_GPSSPlugin=GPSS Tools 52 | Main.Menu_UploadtoGPSS=Upload to GPSS 53 | Main.Menu_ImportfromGPSSURL=Import from GPSS URL 54 | Main.Menu_ALMSettingsEditor=Plugin Settings 55 | 56 | AllowTrainerOverride_description=Allows overriding trainer data with "OT", "TID", "SID", and "OTGender" as part of a Showdown set. 57 | UseTrainerData_description=Enables use of custom trainer data based on the "trainers" folder. 58 | DefaultOT_description=Default OT Name to use while generating Pokémon. 59 | DefaultTID16_description=Default TID to use while generating Pokémon. (TID16) 60 | DefaultSID16_description=Default SID to use while generating Pokémon. (SID16) 61 | LatestIP_description=Stores the last IP used by LiveHeX. 62 | LatestPort_description=Stores the last port used by LiveHeX. 63 | USBBotBasePreferred_description=Allows LiveHeX to use USB-Botbase instead of sys-botbase. 64 | UseCachedPointers_description=Stores pointer addresses to cache for faster lookups. 65 | ForceSpecifiedBall_description=Allows overriding Poké Ball with "Ball" in a Showdown set. 66 | PrioritizeEncounters_description=Defines the order in which Pokémon encounters are prioritized. 67 | PrioritizeGame_description=If enabled, tries to generate a Pokémon based on PrioritizeGameVersion first. 68 | PriorityGameVersion_description=Setting this to "Any" prioritizes the current save game, and setting a specific game prioritizes that instead. 69 | SetAllLegalRibbons_description=Adds all ribbons that are legal according to PKHeX legality. 70 | SetBattleVersion_description=Sets all past-generation Pokémon as Battle Ready for games that support it. 71 | SetMatchingBalls_description=Attempts to choose a matching Poké Ball based on Pokémon color. 72 | Timeout_description=Global timeout per Pokémon being generated (in seconds) 73 | UseXOROSHIRO_description=Generates legal nonshiny Generation 8 raid Pokémon based on the game's RNG. 74 | EnableEasterEggs_description=Produces an Easter Egg Pokémon if the provided set is illegal. 75 | IncludeForms_description=Generate all forms of the Pokémon. Note that some generations may not have enough box space for all forms. 76 | NativeOnly_description=Only generate Pokémon natively available in the game version pair. 77 | SetAlpha_description=Try to generate the alpha version of the Pokémon if possible. 78 | SetShiny_description=Try to generate the shiny version of the Pokémon if possible. 79 | GPSSBaseURL_description=Base URL for Flagbrew's Global PKSM Sharing Service (GPSS) features. 80 | PromptForSmogonImport_description=Used for "Generate Smogon Sets". If set to true, ALM will ask for approval for each set before attempting to generate it. 81 | UseMarkings_description=Sets markings on the Pokémon based on IVs. 82 | UseCompetitiveMarkings_description=Sets IVs of 31 to blue and 30 to red if enabled. Otherwise, sets IVs of 31 to blue and 0 to red. 83 | EnableDevMode_description=If enabled, ignores version mismatch warnings until the next PKHeX.Core release. Also bypasses Switch connection checks. 84 | 85 | AllowTrainerOverride_category=Trainer Data 86 | UseTrainerData_category=Trainer Data 87 | DefaultOT_category=Trainer Data 88 | DefaultTID16_category=Trainer Data 89 | DefaultSID16_category=Trainer Data 90 | LatestIP_category=Connection 91 | LatestPort_category=Connection 92 | USBBotBasePreferred_category=Connection 93 | UseCachedPointers_category=Connection 94 | ForceSpecifiedBall_category=Customization 95 | PrioritizeGame_category=Customization 96 | PriorityGameVersion_category=Customization 97 | SetAllLegalRibbons_category=Customization 98 | SetBattleVersion_category=Customization 99 | SetMatchingBalls_category=Customization 100 | Timeout_category=Legality 101 | PrioritizeEncounters_category=Legality 102 | UseXOROSHIRO_category=Legality 103 | EnableEasterEggs_category=Legality 104 | IncludeForms_category=Living Dex 105 | SetShiny_category=Living Dex 106 | NativeOnly_category=Living Dex 107 | SetAlpha_category=Living Dex 108 | GPSSBaseURL_category=Miscellaneous 109 | PromptForSmogonImport_category=Miscellaneous 110 | UseMarkings_category=Miscellaneous 111 | UseCompetitiveMarkings_category=Miscellaneous 112 | EnableDevMode_category=Development -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/text/almlang_ja.txt: -------------------------------------------------------------------------------- 1 | ALMSettings=自動合法化プラグインの設定 2 | 3 | LiveHeXUI=LiveHeXUI 4 | LiveHeXUI.B_ReadCurrent=現在のボックスを読み込む 5 | LiveHeXUI.B_WriteCurrent=現在のボックスを書き込む 6 | LiveHeXUI.checkBox1=ボックスの変更時に読み込む 7 | LiveHeXUI.L_USBState=USBボットベースモード 8 | LiveHeXUI.L_IP=IP: 9 | LiveHeXUI.L_Port=ポート: 10 | LiveHeXUI.B_Connect=接続 11 | LiveHeXUI.B_Disconnect=切断 12 | LiveHeXUI.groupBox1=ボックス 13 | LiveHeXUI.checkBox2=スロットに挿入 14 | LiveHeXUI.groupBox2=PKMの編集 15 | LiveHeXUI.L_ReadOffset=オフセット: 16 | LiveHeXUI.B_ReadOffset=オフセットから読み込む 17 | LiveHeXUI.L_Slot=スロット: 18 | LiveHeXUI.L_Box=ボックス: 19 | LiveHeXUI.B_ReadSlot=スロットから読み込む 20 | LiveHeXUI.B_WriteSlot=スロットに書き込む 21 | LiveHeXUI.groupBox3=RAMの編集 22 | LiveHeXUI.B_ReadRAM=RAMを編集 23 | LiveHeXUI.L_ReadRamOffset=オフセット: 24 | LiveHeXUI.L_ReadRamSize=サイズ: 25 | LiveHeXUI.groupBox4=ポインターを探す 26 | LiveHeXUI.groupBox5=ブロックの編集 27 | LiveHeXUI.groupBox6=RAMの設定 28 | LiveHeXUI.L_Pointer=ポインター: 29 | LiveHeXUI.B_CopyAddress=アドレスをコピー 30 | LiveHeXUI.B_ReadPointer=ポインターから読み込む 31 | LiveHeXUI.B_EditBlock=ブロックを編集 32 | LiveHeXUI.B_EditPointer=RAMを編集 33 | LiveHeXUI.L_OffsRelative=相対的なRAMオフセット: 34 | LiveHeXUI.L_Block=ブロック: 35 | 36 | SimpleHexEditor=RAMを編集 37 | SimpleHexEditor.B_Update=アップデート 38 | 39 | Main.Menu_AutoLegality=自動合法化MOD 40 | Main.Menu_ExportBoxtoShowdown=ボックスをALM Showdownテンプレートにエクスポート 41 | Main.Menu_PasteImporter=自動合法化MODにインポート 42 | Main.Menu_PKSMBank=PKSM Bankツール 43 | Main.Menu_CreatePKSMBank=PKMをPKSM Bankに統合 44 | Main.Menu_ExportPKSMBank=PKSM BankをPKMに分割 45 | Main.Menu_LeaglizeBoxes=アクティブなポケモンを合法化 46 | Main.Menu_LiveHeX=LiveHeXを開く 47 | Main.Menu_LivingDex=Living Dexを生成 48 | Main.Menu_MGDBDownloader=MGDBをダウンロード 49 | Main.Menu_SmogonGenner=Smogonセットを生成 50 | Main.Menu_URLGenning=URLから生成 51 | Main.Menu_GPSSPlugin=GPSSツール 52 | Main.Menu_UploadtoGPSS=GPSSにアップロード 53 | Main.Menu_ImportfromGPSSURL=GPSS URLからインポート 54 | Main.Menu_ALMSettingsEditor=プラグインの設定 55 | 56 | AllowTrainerOverride_description=トレーナーデータの「OT」、「TID」、「SID」、「OTGender」をShowdownセットの一部として上書きできます。 57 | UseTrainerData_description=「trainers」フォルダーに基づくカスタムトレーナーデータの使用を有効化します。 58 | DefaultOT_description=ポケモンの生成時に使用するデフォルトのOT名。 59 | DefaultTID16_description=ポケモンの生成時に使用するデフォルトのTID。(TID16) 60 | DefaultSID16_description=ポケモンの生成時に使用するデフォルトのSID。(SID16) 61 | LatestIP_description=LiveHeXによって使用された最後のIPを格納します。 62 | LatestPort_description=LiveHeXによって使用された最後のポートを格納します。 63 | USBBotBasePreferred_description=LiveHeXがsys-botbaseの代わりにUSB-Botbaseを使用できるようにします。 64 | UseCachedPointers_description=より高速な検索のためにキャッシュにポインターアドレスを格納します。 65 | ForceSpecifiedBall_description=Showdownセットに「ボール」でモンスターボールを上書きできます。 66 | PrioritizeEncounters_description=ポケモンとの出会いを優先させる順番を設定します。 67 | PrioritizeGame_description=有効化をすると、PrioritizeGameVersionに基づいてポケモンの生成を行ないます。 68 | PriorityGameVersion_description=「Any」に設定すると、現在のセーブデータが優先され、特定のゲームを設定すると、代わりにそれが優先されます。 69 | SetAllLegalRibbons_description=PKHeXの合法性に従い、合法であるすべてのリボンを追加します。 70 | SetBattleVersion_description=対応しているゲームですべての前世代のポケモンをBattle Readyに設定します。 71 | SetMatchingBalls_description=ポケモンの色からマッチをするモンストを選択します。 72 | Timeout_description=各ポケモンの生成のグローバルタイムアウト(秒) 73 | UseXOROSHIRO_description=ゲームのRNGに基づいて、色違いのない合法的な第8世代のレイドバトルのポケモンを生成します。 74 | EnableEasterEggs_description=与えられたセットが違法である場合、イースターエッグポケモンを生成します。 75 | IncludeForms_description=ポケモンのフォルムチェンジをすべて生成します。世代によっては、すべてのフォームを収納するボックスのスペースがない問題が発生する事があります。 76 | NativeOnly_description=ゲーム版のペアでネイティブに使用可能なポケモンのみを生成します。 77 | SetAlpha_description=可能であればそのポケモンのアルファ版を生成するようにします。 78 | SetShiny_description=可能であればそのポケモンの色違いを生成するようにします。 79 | GPSSBaseURL_description=FlagbrewのグローバルPKSM共有サービス(GPSS)機能のベースURLです。 80 | PromptForSmogonImport_description=「Smogonセットの生成」に使用されます。「True」に設定されている場合、ALMはセットを生成する前に各セットの承認を求めます。 81 | UseMarkings_description==IVに基づいてポケモンにマーキングを設定します。 82 | UseCompetitiveMarkings_description=有効化されている場合に、31のIVを青に設定し、30を赤に設定します。それ以外の場合は、31のIVを青に、0を赤に設定します。 83 | EnableDevMode_description=有効化をすると、次のPKHeX.Coreのリリースまでバージョン不一致の警告を無視します。またSwitchの接続チェックもバイパスをします。 84 | 85 | AllowTrainerOverride_category=トレーナーデータ 86 | UseTrainerData_category=トレーナーデータ 87 | DefaultOT_category=トレーナーデータ 88 | DefaultTID16_category=トレーナーデータ 89 | DefaultSID16_category=トレーナーデータ 90 | LatestIP_category=接続 91 | LatestPort_category=接続 92 | USBBotBasePreferred_category=接続 93 | UseCachedPointers_category=接続 94 | ForceSpecifiedBall_category=カスタマイズ 95 | PrioritizeGame_category=カスタマイズ 96 | PriorityGameVersion_category=カスタマイズ 97 | SetAllLegalRibbons_category=カスタマイズ 98 | SetBattleVersion_category=カスタマイズ 99 | SetMatchingBalls_category=カスタマイズ 100 | Timeout_category=合法性 101 | PrioritizeEncounters_category=合法性 102 | UseXOROSHIRO_category=合法性 103 | EnableEasterEggs_category=合法性 104 | IncludeForms_category=Living Dex 105 | SetShiny_category=Living Dex 106 | NativeOnly_category=Living Dex 107 | SetAlpha_category=Living Dex 108 | GPSSBaseURL_category=その他 109 | PromptForSmogonImport_category=その他 110 | UseMarkings_category=その他 111 | UseCompetitiveMarkings_category=その他 112 | EnableDevMode_category=開発 113 | -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/text/almlang_ko.txt: -------------------------------------------------------------------------------- 1 | ALMSettings=Auto Legality Plugin Settings 2 | 3 | LiveHeXUI=LiveHeXUI 4 | LiveHeXUI.B_ReadCurrent=Read Current Box 5 | LiveHeXUI.B_WriteCurrent=Write Current Box 6 | LiveHeXUI.checkBox1=Read On Change Box 7 | LiveHeXUI.L_USBState=USB-Botbase Mode 8 | LiveHeXUI.L_IP=IP: 9 | LiveHeXUI.L_Port=Port: 10 | LiveHeXUI.B_Connect=Connect 11 | LiveHeXUI.B_Disconnect=Disconnect 12 | LiveHeXUI.groupBox1=Boxes 13 | LiveHeXUI.checkBox2=Inject In Slot 14 | LiveHeXUI.groupBox2=PKM Editor 15 | LiveHeXUI.L_ReadOffset=Offset: 16 | LiveHeXUI.B_ReadOffset=Read from Offset 17 | LiveHeXUI.L_Slot=Slot: 18 | LiveHeXUI.L_Box=Box: 19 | LiveHeXUI.B_ReadSlot=Read from Slot 20 | LiveHeXUI.B_WriteSlot=Write to Slot 21 | LiveHeXUI.groupBox3=Ram Editor 22 | LiveHeXUI.B_ReadRAM=Edit RAM 23 | LiveHeXUI.L_ReadRamOffset=Offset: 24 | LiveHeXUI.L_ReadRamSize=Size: 25 | LiveHeXUI.groupBox4=Pointer Lookup 26 | LiveHeXUI.groupBox5=Block Editor 27 | LiveHeXUI.groupBox6=RAM Config 28 | LiveHeXUI.L_Pointer=Pointer: 29 | LiveHeXUI.B_CopyAddress=Copy Address 30 | LiveHeXUI.B_ReadPointer=Read from Pointer 31 | LiveHeXUI.B_EditBlock=Edit Block 32 | LiveHeXUI.B_EditPointer=Edit RAM 33 | LiveHeXUI.L_OffsRelative=RAM offsets relative to: 34 | LiveHeXUI.L_Block=Block: 35 | 36 | SimpleHexEditor=RAMEdit 37 | SimpleHexEditor.B_Update=Update 38 | 39 | Main.Menu_AutoLegality=Auto-Legality Mod 40 | Main.Menu_ExportBoxtoShowdown=Export Box to ALM Showdown Template 41 | Main.Menu_PasteImporter=Import with Auto-Legality Mod 42 | Main.Menu_PKSMBank=PKSM Bank Tools 43 | Main.Menu_CreatePKSMBank=Merge PKM into PKSM Bank 44 | Main.Menu_ExportPKSMBank=Export PKSM Bank to PKM 45 | Main.Menu_LeaglizeBoxes=Legalize Active Pokemon 46 | Main.Menu_LiveHeX=Open LiveHeX 47 | Main.Menu_LivingDex=Generate Living Dex 48 | Main.Menu_MGDBDownloader=Download MGDB 49 | Main.Menu_SmogonGenner=Generate Smogon Sets 50 | Main.Menu_URLGenning=Generate from URL 51 | Main.Menu_GPSSPlugin=GPSS Tools 52 | Main.Menu_UploadtoGPSS=Upload to GPSS 53 | Main.Menu_ImportfromGPSSURL=Import from GPSS URL 54 | Main.Menu_ALMSettingsEditor=Plugin Settings 55 | 56 | AllowTrainerOverride_description=Allows overriding trainer data with "OT", "TID", "SID", and "OTGender" as part of a Showdown set. 57 | UseTrainerData_description=Enables use of custom trainer data based on the "trainers" folder. 58 | DefaultOT_description=Default OT Name to use while generating Pokémon. 59 | DefaultTID16_description=Default TID to use while generating Pokémon. (TID16) 60 | DefaultSID16_description=Default SID to use while generating Pokémon. (SID16) 61 | LatestIP_description=Stores the last IP used by LiveHeX. 62 | LatestPort_description=Stores the last port used by LiveHeX. 63 | USBBotBasePreferred_description=Allows LiveHeX to use USB-Botbase instead of sys-botbase. 64 | UseCachedPointers_description=Stores pointer addresses to cache for faster lookups. 65 | ForceSpecifiedBall_description=Allows overriding Poké Ball with "Ball" in a Showdown set. 66 | PrioritizeEncounters_description=Defines the order in which Pokémon encounters are prioritized. 67 | PrioritizeGame_description=If enabled, tries to generate a Pokémon based on PrioritizeGameVersion first. 68 | PriorityGameVersion_description=Setting this to "Any" prioritizes the current save game, and setting a specific game prioritizes that instead. 69 | SetAllLegalRibbons_description=Adds all ribbons that are legal according to PKHeX legality. 70 | SetBattleVersion_description=Sets all past-generation Pokémon as Battle Ready for games that support it. 71 | SetMatchingBalls_description=Attempts to choose a matching Poké Ball based on Pokémon color. 72 | Timeout_description=Global timeout per Pokémon being generated (in seconds) 73 | UseXOROSHIRO_description=Generates legal nonshiny Generation 8 raid Pokémon based on the game's RNG. 74 | EnableEasterEggs_description=Produces an Easter Egg Pokémon if the provided set is illegal. 75 | IncludeForms_description=Generate all forms of the Pokémon. Note that some generations may not have enough box space for all forms. 76 | NativeOnly_description=Only generate Pokémon natively available in the game version pair. 77 | SetAlpha_description=Try to generate the alpha version of the Pokémon if possible. 78 | SetShiny_description=Try to generate the shiny version of the Pokémon if possible. 79 | GPSSBaseURL_description=Base URL for Flagbrew's Global PKSM Sharing Service (GPSS) features. 80 | PromptForSmogonImport_description=Used for "Generate Smogon Sets". If set to true, ALM will ask for approval for each set before attempting to generate it. 81 | UseMarkings_description=Sets markings on the Pokémon based on IVs. 82 | UseCompetitiveMarkings_description=Sets IVs of 31 to blue and 30 to red if enabled. Otherwise, sets IVs of 31 to blue and 0 to red. 83 | EnableDevMode_description=If enabled, ignores version mismatch warnings until the next PKHeX.Core release. Also bypasses Switch connection checks. 84 | 85 | AllowTrainerOverride_category=Trainer Data 86 | UseTrainerData_category=Trainer Data 87 | DefaultOT_category=Trainer Data 88 | DefaultTID16_category=Trainer Data 89 | DefaultSID16_category=Trainer Data 90 | LatestIP_category=Connection 91 | LatestPort_category=Connection 92 | USBBotBasePreferred_category=Connection 93 | UseCachedPointers_category=Connection 94 | ForceSpecifiedBall_category=Customization 95 | PrioritizeGame_category=Customization 96 | PriorityGameVersion_category=Customization 97 | SetAllLegalRibbons_category=Customization 98 | SetBattleVersion_category=Customization 99 | SetMatchingBalls_category=Customization 100 | Timeout_category=Legality 101 | PrioritizeEncounters_category=Legality 102 | UseXOROSHIRO_category=Legality 103 | EnableEasterEggs_category=Legality 104 | IncludeForms_category=Living Dex 105 | SetShiny_category=Living Dex 106 | NativeOnly_category=Living Dex 107 | SetAlpha_category=Living Dex 108 | GPSSBaseURL_category=Miscellaneous 109 | PromptForSmogonImport_category=Miscellaneous 110 | UseMarkings_category=Miscellaneous 111 | UseCompetitiveMarkings_category=Miscellaneous 112 | EnableDevMode_category=Development -------------------------------------------------------------------------------- /AutoLegalityMod/Resources/text/almlang_zh.txt: -------------------------------------------------------------------------------- 1 | ALMSettings=自动合法插件设置 2 | 3 | LiveHeXUI=LiveHeXUI 4 | LiveHeXUI.B_ReadCurrent=读取当前盒子 5 | LiveHeXUI.B_WriteCurrent=写入当前盒子 6 | LiveHeXUI.CB_ReadBox=切换盒子时读取 7 | LiveHeXUI.L_USBState=USB-Botbase模式 8 | LiveHeXUI.L_IP=IP: 9 | LiveHeXUI.L_Port=端口: 10 | LiveHeXUI.B_Connect=连接 11 | LiveHeXUI.B_Disconnect=断开 12 | LiveHeXUI.groupBox1=盒子 13 | LiveHeXUI.checkBox2=注入当前槽位 14 | LiveHeXUI.groupBox2=宝可梦 15 | LiveHeXUI.L_ReadOffset=偏移: 16 | LiveHeXUI.B_ReadOffset=从偏移读取 17 | LiveHeXUI.L_Slot=槽位: 18 | LiveHeXUI.L_Box=盒子: 19 | LiveHeXUI.B_ReadSlot=读取当前槽位 20 | LiveHeXUI.B_WriteSlot=写入当前槽位 21 | LiveHeXUI.groupBox3=内存编辑器 22 | LiveHeXUI.B_ReadRAM=编辑内存 23 | LiveHeXUI.L_ReadRamOffset=偏移: 24 | LiveHeXUI.L_ReadRamSize=长度: 25 | LiveHeXUI.groupBox4=指针查找 26 | LiveHeXUI.groupBox5=数据块配置 27 | LiveHeXUI.groupBox6=内存配置 28 | LiveHeXUI.L_Pointer=指针: 29 | LiveHeXUI.B_CopyAddress=复制地址 30 | LiveHeXUI.B_ReadPointer=从指针地址读取 31 | LiveHeXUI.B_EditBlock=编辑数据块 32 | LiveHeXUI.B_EditPointer=编辑指针 33 | LiveHeXUI.L_OffsRelative=内存偏移相对于: 34 | LiveHeXUI.L_Block=数据块: 35 | 36 | SimpleHexEditor=内存编辑 37 | SimpleHexEditor.B_Update=更新 38 | 39 | Main.Menu_AutoLegality=自动合法插件 40 | Main.Menu_ExportBoxtoShowdown=导出当前盒子到ALM Showdown模板 41 | Main.Menu_PasteImporter=使用自动合法插件导入 42 | Main.Menu_PKSMBank=PKSM Bank工具 43 | Main.Menu_CreatePKSMBank=将PKM合并到PKSM Bank 44 | Main.Menu_ExportPKSMBank=将PKSM Bank拆分为PKM 45 | Main.Menu_LeaglizeBoxes=合法化当前宝可梦 46 | Main.Menu_LiveHeX=打开LiveHeX 47 | Main.Menu_LivingDex=生成Living Dex 48 | Main.Menu_MGDBDownloader=下载MGDB 49 | Main.Menu_SmogonGenner=生成Smogon Sets 50 | Main.Menu_URLGenning=从URL生成 51 | Main.Menu_GPSSPlugin=GPSS工具 52 | Main.Menu_UploadtoGPSS=上传到 GPSS 53 | Main.Menu_ImportfromGPSSURL=从GPSS URL导入 54 | Main.Menu_ALMSettingsEditor=插件设置 55 | 56 | AllowTrainerOverride_description=允许使用“OT”,“TID”,“SID”和“ OT性别”覆盖训练家数据,作为Showdown集的一部分。 57 | UseTrainerData_description=启用使用基于“trainers”文件夹的自定义训练家数据。 58 | DefaultOT_description=生成宝可梦时使用的默认OT名称。 59 | DefaultTID16_description=生成宝可梦时使用的默认TID(TID16)。 60 | DefaultSID16_description=生成宝可梦时使用的默认SID(SID16)。 61 | LatestIP_description=保存LiveHeX使用的最后一个IP地址。 62 | LatestPort_description=保存LiveHeX使用的最后一个端口。 63 | USBBotBasePreferred_description=允许LiveHeX使用USB-Botbase代替sys-botbase。 64 | UseCachedPointers_description=存储指针地址到缓存以进行更快的查找。 65 | ForceSpecifiedBall_description=允许使用精灵球替代Showdown集中的球种。 66 | PrioritizeEncounters_description=定义宝可梦遭遇的先后顺序。 67 | PrioritizeGame_description=如果开启,首先尝试根据PrioritizeGameVersion生成宝可梦。 68 | PriorityGameVersion_description=设置为"Any"时,优先当前存档游戏版本,否则优先使用设定的游戏版本。 69 | SetAllLegalRibbons_description=添加所有可通过PKHeX合法性校验的奖章。 70 | SetBattleVersion_description=将所有前代宝可梦设置为本作支持的对战状态 71 | SetMatchingBalls_description=尝试根据宝可梦颜色选择匹配的球种。 72 | Timeout_description=生成每个宝可梦的全局超时时间(单位:秒) 73 | UseXOROSHIRO_description=根据游戏RNG生成合法、非异色、8代、来自宝可梦巢穴的宝可梦。 74 | EnableEasterEggs_description=如果提供的宝可梦非法,则生成一个复活节彩蛋宝可梦。 75 | IncludeForms_description=生成所有形态的宝可梦。请注意,某些世代可能没有足够的槽位容纳所有宝可梦数据。 76 | NativeOnly_description=仅生成本地游戏版本可用的宝可梦。 77 | SetAlpha_description=如果条件允许,尝试Living Dex生成阿尔宙斯宝可梦的头目形态。 78 | SetShiny_description=如果条件允许,尝试Living Dex生成闪亮的宝可梦。 79 | GPSSBaseURL_description=Flagbrew的全球PKSM分享服务(GPSS)功能的基础URL地址。 80 | PromptForSmogonImport_description=用于"生成Smogon Sets"。如果设置为true,ALM会尝试在每次生成时询问确认。 81 | UseMarkings_description=根据宝可梦的个体值设置标记。 82 | UseCompetitiveMarkings_description=该项启用时,个体值为全31时显示蓝色、30显示红色。否则全31时显示蓝色、0显示红色. 83 | EnableDevMode_description=如果启用,则忽略版本不匹配警告,直到下一个PKHeX.Core版本. 也绕过 Switch 连接检查。 84 | 85 | AllowTrainerOverride_category=训练家数据 86 | UseTrainerData_category=训练家数据 87 | DefaultOT_category=训练家数据 88 | DefaultTID16_category=训练家数据 89 | DefaultSID16_category=训练家数据 90 | LatestIP_category=连接 91 | LatestPort_category=连接 92 | USBBotBasePreferred_category=连接 93 | UseCachedPointers_category=连接 94 | ForceSpecifiedBall_category=个性化 95 | PrioritizeGame_category=个性化 96 | PriorityGameVersion_category=个性化 97 | SetAllLegalRibbons_category=个性化 98 | SetBattleVersion_category=个性化 99 | SetMatchingBalls_category=个性化 100 | Timeout_category=合法性 101 | PrioritizeEncounters_category=合法性 102 | UseXOROSHIRO_category=合法性 103 | EnableEasterEggs_category=合法性 104 | IncludeForms_category=Living Dex 105 | SetShiny_category=Living Dex 106 | NativeOnly_category=Living Dex 107 | SetAlpha_category=Living Dex 108 | GPSSBaseURL_category=其他 109 | PromptForSmogonImport_category=其他 110 | UseMarkings_category=其他 111 | UseCompetitiveMarkings_category=其他 112 | EnableDevMode_category=显影 -------------------------------------------------------------------------------- /AutoLegalityMod/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 111.111.111.111 13 | 14 | 15 | 16 | 17 | flagbrew.org 18 | 19 | 20 | True 21 | 22 | 23 | True 24 | 25 | 26 | True 27 | 28 | 29 | False 30 | 31 | 32 | True 33 | 34 | 35 | True 36 | 37 | 38 | 192.168.1.65 39 | 40 | 41 | True 42 | 43 | 44 | True 45 | 46 | 47 | False 48 | 49 | 50 | False 51 | 52 | 53 | False 54 | 55 | 56 | True 57 | 58 | 59 | True 60 | 61 | 62 | 15 63 | 64 | 65 | False 66 | 67 | 68 | False 69 | 70 | 71 | False 72 | 73 | 74 | True 75 | 76 | 77 | False 78 | 79 | 80 | 0.0.0.0 81 | 82 | 83 | False 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /AutoLegalityMod/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /AutoModTests/AutoModTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | false 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /AutoModTests/FeatureMonitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using FluentAssertions; 3 | using PKHeX.Core.Enhancements; 4 | using Xunit; 5 | 6 | namespace AutoModTests 7 | { 8 | public static class FeatureMonitor 9 | { 10 | [Fact] 11 | public static void EventsGalleryExists() 12 | { 13 | var url = EventsGallery.GetMGDBDownloadURL(); 14 | string.IsNullOrWhiteSpace(url).Should().BeFalse("Download URL should exist"); 15 | 16 | var isUri = Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute); 17 | isUri.Should().BeTrue("Download URL should be valid"); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /AutoModTests/Legality/Illegal/706_-_Goodra_-_971B6773DCC2.pk7: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoModTests/Legality/Illegal/706_-_Goodra_-_971B6773DCC2.pk7 -------------------------------------------------------------------------------- /AutoModTests/Legality/Legal/080 - Slowbro - A0935F4796B1.pk7: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architdate/PKHeX-Plugins/c8e23a43dc48147a8099ee30ad8481c5af839ebb/AutoModTests/Legality/Legal/080 - Slowbro - A0935F4796B1.pk7 -------------------------------------------------------------------------------- /AutoModTests/LegalityTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using FluentAssertions; 3 | using PKHeX.Core; 4 | using PKHeX.Core.AutoMod; 5 | using Xunit; 6 | 7 | namespace AutoModTests 8 | { 9 | public static class LegalityTests 10 | { 11 | private static readonly string PKMFolder = TestUtil.GetTestFolder("Legality"); 12 | 13 | [Fact] 14 | public static void TestLegal() => VerifyAll(PKMFolder, "Legal", true); 15 | 16 | [Fact] 17 | public static void TestIllegal() => VerifyAll(PKMFolder, "Illegal", false); 18 | 19 | // ReSharper disable once UnusedParameter.Local 20 | private static void VerifyAll(string folder, string name, bool isValid) 21 | { 22 | var path = Path.Combine(folder, name); 23 | Directory 24 | .Exists(path) 25 | .Should() 26 | .BeTrue($"the specified test directory at '{path}' should exist"); 27 | 28 | var dev = APILegality.EnableDevMode; 29 | APILegality.EnableDevMode = true; 30 | 31 | var files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories); 32 | try 33 | { 34 | foreach (var file in files) 35 | { 36 | var fi = new FileInfo(file); 37 | var pk = GetPKM(file, fi); 38 | 39 | // double check initial state 40 | var la = new LegalityAnalysis(pk); 41 | var dir = fi.Directory!; 42 | la.Valid 43 | .Should() 44 | .Be( 45 | isValid, 46 | $"because the file '{dir.Name}\\{fi.Name}' should be {(isValid ? "Valid" : "Invalid")}" 47 | ); 48 | 49 | // try legalizing, should end up as legal 50 | var updated = pk.Legalize(); 51 | var la2 = new LegalityAnalysis(updated); 52 | la2.Valid 53 | .Should() 54 | .Be(true, $"because the file '{dir.Name}\\{fi.Name}' should be legal"); 55 | } 56 | } 57 | finally 58 | { 59 | APILegality.EnableDevMode = dev; 60 | } 61 | } 62 | 63 | private static PKM GetPKM(string file, FileInfo fi) 64 | { 65 | fi.Should().NotBeNull($"the test file '{file}' should be a valid file"); 66 | EntityDetection 67 | .IsSizePlausible(fi.Length) 68 | .Should() 69 | .BeTrue($"the test file '{file}' should have a valid file length"); 70 | 71 | var data = File.ReadAllBytes(file); 72 | var prefer = EntityFileExtension.GetContextFromExtension(file); 73 | var pkm = EntityFormat.GetFromBytes(data, prefer: prefer); 74 | pkm.Should().NotBeNull($"the PKM '{new FileInfo(file).Name}' should have been loaded"); 75 | return pkm!; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /AutoModTests/LogicTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using PKHeX.Core; 3 | using PKHeX.Core.AutoMod; 4 | using Xunit; 5 | using static PKHeX.Core.Species; 6 | 7 | namespace AutoModTests 8 | { 9 | public static class LogicTests 10 | { 11 | [Theory] 12 | [InlineData(Pikachu, 1)] 13 | public static void TestShinyLockInfo(Species species, int form, bool locked = true) 14 | { 15 | var result = SimpleEdits.IsShinyLockedSpeciesForm((int)species, form); 16 | result.Should().Be(locked); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /AutoModTests/ShowdownSetGenningTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using PKHeX.Core; 3 | using PKHeX.Core.AutoMod; 4 | using Xunit; 5 | 6 | namespace AutoModTests 7 | { 8 | public static class ShowdownSetGenningTests 9 | { 10 | static ShowdownSetGenningTests() => TestUtil.InitializePKHeXEnvironment(); 11 | 12 | [Theory] 13 | [InlineData(GameVersion.US, Meowstic)] 14 | [InlineData(GameVersion.US, Darkrai)] 15 | [InlineData(GameVersion.B2, Genesect)] 16 | public static void VerifyManually(GameVersion game, string txt) 17 | { 18 | var dev = APILegality.EnableDevMode; 19 | APILegality.EnableDevMode = true; 20 | 21 | var sav = SaveUtil.GetBlankSAV(game, "ALM"); 22 | TrainerSettings.Register(sav); 23 | 24 | var trainer = TrainerSettings.GetSavedTrainerData(game.GetGeneration(), game); 25 | RecentTrainerCache.SetRecentTrainer(trainer); 26 | 27 | var set = new ShowdownSet(txt); 28 | var almres = sav.GetLegalFromSet(set); 29 | APILegality.EnableDevMode = dev; 30 | 31 | var la = new LegalityAnalysis(almres.Created); 32 | la.Valid.Should().BeTrue(); 33 | } 34 | 35 | private const string Darkrai = 36 | @"Darkrai 37 | IVs: 7 Atk 38 | Ability: Bad Dreams 39 | Shiny: Yes 40 | Timid Nature 41 | - Hypnosis 42 | - Feint Attack 43 | - Nightmare 44 | - Double Team"; 45 | 46 | private const string Genesect = 47 | @"Genesect 48 | Ability: Download 49 | Shiny: Yes 50 | Hasty Nature 51 | - Extreme Speed 52 | - Techno Blast 53 | - Blaze Kick 54 | - Shift Gear"; 55 | 56 | private const string Meowstic = 57 | @"Meowstic-F @ Life Orb 58 | Ability: Competitive 59 | EVs: 4 Def / 252 SpA / 252 Spe 60 | Timid Nature 61 | - Psyshock 62 | - Signal Beam 63 | - Hidden Power Ground 64 | - Calm Mind"; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/Anubis Tests/Anubis - pk6.txt: -------------------------------------------------------------------------------- 1 | Diglett (F) 2 | IVs: 29 SpA 3 | Ability: Arena Trap 4 | Level: 1 5 | Shiny: Yes 6 | Jolly Nature 7 | ~=Version=XY 8 | .Version=25 9 | - Reversal 10 | - Memento 11 | - Pursuit 12 | - Screech 13 | 14 | Magmar (M) 15 | IVs: 0 Atk / 30 SpA 16 | Ability: Flame Body 17 | Level: 30 18 | Modest Nature 19 | Ball: Cherish Ball 20 | Language: Japanese 21 | ~=Location=40059 22 | ~=Version=BW 23 | .Version=21 24 | - Incinerate 25 | - Rock Smash 26 | - Secret Power 27 | - Power-Up Punch 28 | 29 | ひろしま (Magikarp) (M) @ Stardust 30 | IVs: 22 HP / 12 Atk / 19 Def / 3 SpA / 6 SpD / 2 Spe 31 | Ability: Swift Swim 32 | Level: 1 33 | Shiny: Yes 34 | Adamant Nature 35 | Ball: Cherish Ball 36 | ~=Location=40010 37 | ~=Version=XY 38 | .Version=25 39 | - Splash 40 | - Celebrate 41 | - Happy Hour 42 | 43 | Eevee (M) 44 | IVs: 26 HP / 0 Atk / 24 Def / 0 SpA / 14 SpD / 0 Spe 45 | Ability: Anticipation 46 | Level: 15 47 | Shiny: Yes 48 | Bashful Nature 49 | Ball: Cherish Ball 50 | Language: Japanese 51 | ~=Location=40001 52 | ~=Version=ORAS 53 | .Version=27 54 | - Swift 55 | - Quick Attack 56 | - Baby-Doll Eyes 57 | - Helping Hand 58 | 59 | Aerodactyl (F) 60 | EVs: 252 Atk / 4 Def / 252 Spe 61 | Ability: Unnerve 62 | Shiny: Yes 63 | Jolly Nature 64 | ~=Version=ORAS 65 | .Version=27 66 | - Pursuit 67 | - Stone Edge 68 | - Hone Claws 69 | - Aqua Tail 70 | 71 | Zapdos 72 | IVs: 22 Atk / 30 Def 73 | EVs: 180 HP / 4 Def / 20 SpA / 180 SpD / 124 Spe 74 | Ability: Static 75 | Level: 70 76 | Calm Nature 77 | Ball: Cherish Ball 78 | ~=Location=40001 79 | ~=Version=ORAS 80 | .Version=27 81 | - Thunderbolt 82 | - Hidden Power [Ice] 83 | - Tailwind 84 | - Roost 85 | 86 | Tyranitar (M) @ Chople Berry 87 | EVs: 252 HP / 4 Def / 252 SpD 88 | Ability: Sand Stream 89 | Shiny: Yes 90 | Sassy Nature 91 | ~=Version=XY 92 | .Version=25 93 | - Foul Play 94 | - Superpower 95 | - Stealth Rock 96 | - Pursuit 97 | 98 | Celebi 99 | IVs: 0 Atk 100 | Ability: Natural Cure 101 | Bold Nature 102 | Ball: Cherish Ball 103 | ~=Location=40001 104 | ~=Version=ORAS 105 | .Version=27 106 | - Confusion 107 | - Recover 108 | - Heal Bell 109 | - Safeguard 110 | 111 | Absol (M) 112 | IVs: 6 SpA 113 | Ability: Super Luck 114 | Level: 1 115 | Shiny: Yes 116 | Jolly Nature 117 | ~=Version=XY 118 | .Version=25 119 | - Play Rough 120 | - Sucker Punch 121 | - Baton Pass 122 | - Zen Headbutt 123 | 124 | Jirachi 125 | IVs: 30 HP / 30 Def 126 | Ability: Serene Grace 127 | Level: 50 128 | Hasty Nature 129 | Ball: Cherish Ball 130 | Language: Japanese 131 | ~=Location=40015 132 | ~=Version=BW 133 | .Version=21 134 | - Draco Meteor 135 | - Meteor Mash 136 | - Power-Up Punch 137 | - Follow Me 138 | 139 | Infernape (M) 140 | Ability: Blaze 141 | Jolly Nature 142 | Ball: Cherish Ball 143 | Language: Japanese 144 | ~=Location=40015 145 | ~=Version=BW 146 | .Version=21 147 | - Hone Claws 148 | - Dig 149 | - Retaliate 150 | - Power-Up Punch 151 | 152 | MonoMire (Volcarona) (M) 153 | IVs: 0 Atk / 30 SpA / 30 SpD 154 | EVs: 252 SpA / 6 SpD / 252 Spe 155 | Ability: Flame Body 156 | Shiny: Yes 157 | Timid Nature 158 | ~=Version=XY 159 | .Version=24 160 | - Quiver Dance 161 | - Giga Drain 162 | - Bug Buzz 163 | - Fire Blast 164 | 165 | Tornadus (M) @ Leppa Berry 166 | IVs: 30 SpD 167 | Ability: Prankster 168 | Level: 50 169 | Shiny: Yes 170 | Hasty Nature 171 | Ball: Master Ball 172 | ~=Location=348 173 | ~=Version=ORAS 174 | .Version=27 175 | - Extrasensory 176 | - Agility 177 | - Air Slash 178 | - Crunch 179 | 180 | Reshiram 181 | IVs: 29 Atk / 29 SpD 182 | Ability: Turboblaze 183 | Level: 50 184 | Shiny: Yes 185 | Timid Nature 186 | Ball: Master Ball 187 | ~=Location=340 188 | ~=Version=ORAS 189 | .Version=27 190 | - Dragon Breath 191 | - Slash 192 | - Extrasensory 193 | - Fusion Flare 194 | 195 | Landorus (M) @ Leppa Berry 196 | IVs: 15 HP / 27 SpA / 18 Spe 197 | Ability: Sand Force 198 | Level: 50 199 | Shiny: Yes 200 | Impish Nature 201 | Ball: Master Ball 202 | ~=Location=348 203 | ~=Version=ORAS 204 | .Version=27 205 | - Extrasensory 206 | - Swords Dance 207 | - Earth Power 208 | - Rock Slide 209 | 210 | 211 | Landorus-Therian (M) 212 | IVs: 7 SpA / 30 Spe 213 | EVs: 20 HP / 252 Atk / 54 SpD / 184 Spe 214 | Ability: Intimidate 215 | Level: 50 216 | Adamant Nature 217 | Ball: Master Ball 218 | ~=Location=348 219 | ~=Version=ORAS 220 | .Version=26 221 | - Rock Slide 222 | - U-turn 223 | - Earthquake 224 | - Extrasensory 225 | 226 | Inkay (M) @ Aspear Berry 227 | IVs: 16 HP / 8 Atk / 22 Def / 3 SpD / 12 Spe 228 | Ability: Suction Cups 229 | Level: 10 230 | Jolly Nature 231 | Ball: Cherish Ball 232 | ~=Location=40019 233 | ~=Version=XY 234 | .Version=25 235 | - Happy Hour 236 | - Foul Play 237 | - Hypnosis 238 | - Topsy-Turvy 239 | 240 | Pumpkaboo-Super (M) @ Rocky Helmet 241 | IVs: 13 HP / 0 Atk / 5 SpA 242 | Ability: Pickup 243 | Level: 50 244 | Bold Nature 245 | Ball: Cherish Ball 246 | ~=Location=40001 247 | ~=Version=XY 248 | .Version=25 249 | - Incinerate 250 | - Flash 251 | - Rock Smash 252 | - Secret Power 253 | 254 | Xerneas 255 | IVs: 18 Atk / 30 SpA / 30 Spe 256 | Ability: Fairy Aura 257 | Shiny: Yes 258 | Modest Nature 259 | Ball: Cherish Ball 260 | ~=Location=40001 261 | ~=Version=ORAS 262 | .Version=27 263 | - Geomancy 264 | - Moonblast 265 | - Aromatherapy 266 | - Focus Blast 267 | 268 | Yveltal 269 | IVs: 1 Atk 270 | Ability: Dark Aura 271 | Shiny: Yes 272 | Modest Nature 273 | Ball: Cherish Ball 274 | ~=Location=40011 275 | ~=Version=ORAS 276 | .Version=27 277 | - Oblivion Wing 278 | - Sucker Punch 279 | - Dark Pulse 280 | - Foul Play 281 | 282 | Diancie 283 | IVs: 30 Atk / 30 SpA / 30 Spe 284 | Ability: Clear Body 285 | Level: 50 286 | Hasty Nature 287 | Ball: Cherish Ball 288 | ~=Location=40001 289 | ~=Version=ORAS 290 | .Version=27 291 | - Diamond Storm 292 | - Moonblast 293 | - Dazzling Gleam 294 | - Protect 295 | 296 | Hoopa @ Focus Sash 297 | IVs: 27 SpA 298 | Ability: Magician 299 | Level: 50 300 | Jolly Nature 301 | Ball: Cherish Ball 302 | ~=Location=40001 303 | ~=Version=ORAS 304 | .Version=27 305 | - Hyperspace Hole 306 | - Psychic 307 | - Astonish 308 | - Nasty Plot -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/Anubis Tests/Anubis notransfer - pb7.txt: -------------------------------------------------------------------------------- 1 | Xander (Eevee-Starter) (M) 2 | Ability: Adaptability 3 | Level: 42 4 | Bashful Nature 5 | ~=Location=28 6 | ~=Version=LE 7 | .Version=43 8 | - Double-Edge 9 | - Glitzy Glow 10 | - Sparkly Swirl 11 | - Quick Attack -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/Anubis Tests/Anubis notransfer - pk7.txt: -------------------------------------------------------------------------------- 1 | Magatsuhi (Gengar) (M) 2 | IVs: 0 Atk 3 | EVs: 6 Def / 252 SpA / 252 Spe 4 | Ability: Levitate 5 | Shiny: Yes 6 | Timid Nature 7 | ~=Version=SM 8 | .Version=31 9 | - Taunt 10 | - Destiny Bond 11 | - Focus Blast 12 | - Shadow Ball -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/RoCs-PC Tests/RoC notransfer - pk1.txt: -------------------------------------------------------------------------------- 1 | Haunter (F) 2 | IVs: 12 HP / 3 Atk / 7 Def / 2 SpA / 2 SpD / 2 Spe 3 | Level: 20 4 | - Lick 5 | - Confuse Ray 6 | - Night Shade -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/RoCs-PC Tests/RoC notransfer - pk3.txt: -------------------------------------------------------------------------------- 1 | Gengar (F) 2 | IVs: 13 HP / 27 Atk / 23 Def / 15 SpA / 24 SpD / 2 Spe 3 | Ability: Levitate 4 | Level: 21 5 | Brave Nature 6 | Ball: Master Ball 7 | ~=Version=FRLG 8 | .Version=4 9 | - Spite 10 | - Curse 11 | - Night Shade 12 | - Confuse Ray -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/RoCs-PC Tests/RoC notransfer - pk5.txt: -------------------------------------------------------------------------------- 1 | Gengar (F) 2 | IVs: 13 HP / 27 Atk / 23 Def / 15 SpA / 24 SpD / 2 Spe 3 | Ability: Levitate 4 | Level: 21 5 | Brave Nature 6 | Ball: Master Ball 7 | ~=Version=FRLG 8 | .Version=4 9 | - Spite 10 | - Curse 11 | - Night Shade 12 | - Confuse Ray 13 | 14 | Gengar (F) 15 | IVs: 30 HP / 10 Atk / 26 Def / 13 SpA / 2 SpD / 25 Spe 16 | Ability: Levitate 17 | Level: 25 18 | Lax Nature 19 | Ball: Master Ball 20 | ~=Version=DP 21 | .Version=11 22 | - Night Shade 23 | - Shadow Punch 24 | - Sucker Punch 25 | - Curse 26 | 27 | Gengar (F) 28 | IVs: 17 HP / 18 Atk / 29 Def / 15 SpA / 21 SpD / 12 Spe 29 | Ability: Levitate 30 | Level: 25 31 | Adamant Nature 32 | Ball: Master Ball 33 | ~=Location=75 34 | ~=Version=B2W2 35 | .Version=23 36 | - Sucker Punch 37 | - Shadow Punch 38 | - Confuse Ray 39 | - Sludge Wave -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/RoCs-PC Tests/RoC notransfer - pk6.txt: -------------------------------------------------------------------------------- 1 | Pikachu-Rock-Star (F) 2 | IVs: 11 HP / 13 Def / 17 SpD 3 | Ability: Lightning Rod 4 | Level: 20 5 | Lonely Nature 6 | - Quick Attack 7 | - Electro Ball 8 | - Thunder Wave 9 | - Meteor Mash 10 | 11 | Gengar (F) 12 | IVs: 13 HP / 27 Atk / 23 Def / 15 SpA / 24 SpD / 2 Spe 13 | Ability: Levitate 14 | Level: 21 15 | Brave Nature 16 | Ball: Master Ball 17 | ~=Version=FRLG 18 | .Version=4 19 | - Spite 20 | - Curse 21 | - Night Shade 22 | - Confuse Ray 23 | 24 | Gengar (F) 25 | IVs: 30 HP / 10 Atk / 26 Def / 13 SpA / 2 SpD / 25 Spe 26 | Ability: Levitate 27 | Level: 25 28 | Lax Nature 29 | Ball: Master Ball 30 | ~=Version=DP 31 | .Version=11 32 | - Night Shade 33 | - Shadow Punch 34 | - Sucker Punch 35 | - Curse 36 | 37 | Gengar (F) 38 | IVs: 17 HP / 18 Atk / 29 Def / 15 SpA / 21 SpD / 12 Spe 39 | Ability: Levitate 40 | Level: 25 41 | Adamant Nature 42 | Ball: Master Ball 43 | ~=Location=75 44 | ~=Version=B2W2 45 | .Version=23 46 | - Sucker Punch 47 | - Shadow Punch 48 | - Confuse Ray 49 | - Sludge Wave 50 | 51 | Gengar (M) @ Gengarite 52 | IVs: 23 HP / 21 Atk / 29 Def / 10 SpA / 28 SpD / 22 Spe 53 | Ability: Levitate 54 | Level: 38 55 | Mild Nature 56 | Ball: Master Ball 57 | ~=Location=82 58 | ~=Version=XY 59 | .Version=24 60 | - Sucker Punch 61 | - Shadow Punch 62 | - Payback 63 | - Shadow Ball -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/RoCs-PC Tests/RoC notransfer - pk7.txt: -------------------------------------------------------------------------------- 1 | Marowak-Alola-Totem (F) 2 | IVs: 22 HP / 11 Atk / 0 Spe 3 | Ability: Rock Head 4 | Level: 25 5 | Lonely Nature 6 | - Leer 7 | - Hex 8 | - Bonemerang 9 | - Will-O-Wisp 10 | 11 | Ribombee-Totem (F) 12 | IVs: 13 Def / 22 SpA / 26 SpD 13 | Ability: Sweet Veil 14 | Level: 50 15 | Quirky Nature 16 | =MetLevel=50 17 | ~=Location=202 18 | ~=Version=USUM 19 | .Version=32 20 | - Bug Buzz 21 | - Dazzling Gleam 22 | - Aromatherapy 23 | - Quiver Dance 24 | 25 | Araquanid-Totem (M) 26 | IVs: 14 Def / 20 SpD / 26 Spe 27 | Ability: Water Bubble 28 | Level: 25 29 | Adamant Nature 30 | =MetLevel=25 31 | ~=Location=202 32 | ~=Version=USUM 33 | .Version=33 34 | - Spider Web 35 | - Bug Bite 36 | - Bubble Beam 37 | - Bite 38 | 39 | Togedemaru-Totem (F) 40 | IVs: 24 HP / 11 SpA / 29 SpD 41 | Ability: Sturdy 42 | Level: 35 43 | Relaxed Nature 44 | =MetLevel=35 45 | ~=Location=202 46 | ~=Version=USUM 47 | .Version=33 48 | - Nuzzle 49 | - Magnet Rise 50 | - Discharge 51 | - Zing Zap -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/Underleveled Tests/Underlevel - pk1.txt: -------------------------------------------------------------------------------- 1 | Metapod (F) 2 | IVs: 4 HP / 4 Atk / 3 Def / 2 SpA / 2 SpD / 2 Spe 3 | Level: 6 4 | - Harden 5 | 6 | Metapod (M) 7 | IVs: 9 HP / 13 Atk / 10 Def / 1 SpA / 1 SpD / 8 Spe 8 | Level: 4 9 | - Harden 10 | 11 | Kakuna (M) 12 | IVs: 13 HP / 13 Atk / 3 Def / 7 SpA / 7 SpD / 2 Spe 13 | Level: 4 14 | - Harden 15 | 16 | Pidgeotto (F) 17 | IVs: 6 HP / 2 Atk / 11 Def / 2 SpA / 2 SpD / 1 Spe 18 | Level: 9 19 | - Gust 20 | - Sand Attack 21 | 22 | Pidgeotto (F) 23 | IVs: 3 HP / 4 Atk / 14 Def / 7 Spe 24 | Level: 17 25 | - Gust 26 | - Sand Attack 27 | - Quick Attack 28 | 29 | Raticate (M) 30 | IVs: 9 HP / 13 Atk / 4 Def / 3 SpA / 3 SpD / 12 Spe 31 | Level: 17 32 | - Tackle 33 | - Tail Whip 34 | - Quick Attack 35 | - Hyper Fang 36 | 37 | Fearow (M) 38 | IVs: 9 HP / 9 Atk / 2 Def / 9 SpA / 9 SpD / 10 Spe 39 | Level: 19 40 | - Peck 41 | - Growl 42 | - Leer 43 | - Fury Attack 44 | 45 | SPIKE (Parasect) (F) 46 | IVs: 4 HP / 2 Atk / 9 Def / 8 SpA / 8 SpD / 8 Spe 47 | Level: 5 48 | =OriginalTrainerName=* 49 | - Scratch 50 | - Stun Spore 51 | - Leech Life 52 | 53 | Venomoth (F) 54 | IVs: 1 Atk / 7 Def / 7 SpA / 7 SpD / 5 Spe 55 | Level: 30 56 | - Confusion 57 | - Poison Powder 58 | - Leech Life 59 | - Stun Spore 60 | 61 | GURIO (Dugtrio) (M) 62 | IVs: 6 HP / 10 Atk / 13 Def / 6 SpA / 6 SpD / 9 Spe 63 | Level: 5 64 | =OriginalTrainerName=* 65 | - Scratch 66 | - Growl 67 | - Dig 68 | 69 | Golduck (F) 70 | IVs: 0 HP / 4 Atk / 12 Def / 14 SpA / 14 SpD / 12 Spe 71 | Level: 15 72 | - Scratch 73 | - Tail Whip 74 | 75 | Poliwhirl (M) 76 | IVs: 1 HP / 10 Atk / 0 Def / 5 SpA / 5 SpD / 14 Spe 77 | Level: 15 78 | - Bubble 79 | - Hypnosis 80 | - Water Gun 81 | 82 | Poliwhirl (F) 83 | IVs: 13 HP / 1 Atk / 1 Def / 11 SpA / 11 SpD / 12 Spe 84 | Level: 23 85 | - Bubble 86 | - Hypnosis 87 | - Water Gun 88 | 89 | RICKY (Machamp) (F) 90 | IVs: 6 HP / 0 Atk / 3 Def / 8 SpA / 8 SpD / 3 Spe 91 | Level: 5 92 | =OriginalTrainerName=* 93 | - Karate Chop 94 | - Low Kick 95 | - Leer 96 | 97 | Tentacruel (M) 98 | IVs: 10 HP / 11 Atk / 12 Def / 8 SpA / 8 SpD / 3 Spe 99 | Level: 20 100 | - Acid 101 | - Supersonic 102 | - Wrap 103 | - Poison Sting 104 | 105 | Slowbro (M) 106 | IVs: 11 HP / 13 Atk / 2 Def / 3 SpA / 3 SpD / 5 Spe 107 | Level: 15 108 | - Confusion 109 | - Disable 110 | - Headbutt 111 | 112 | Slowbro (F) 113 | IVs: 4 HP / 6 Atk / 2 SpA / 2 SpD / 14 Spe 114 | Level: 31 115 | - Confusion 116 | - Disable 117 | - Headbutt 118 | - Growl 119 | 120 | Dodrio (M) 121 | IVs: 13 HP / 13 Atk / 13 Def / 13 SpA / 13 SpD / 2 Spe 122 | Level: 29 123 | - Peck 124 | - Growl 125 | - Fury Attack 126 | 127 | CEZANNE (Dewgong) (F) 128 | IVs: 13 HP / 7 Atk / 9 Def / 1 SpA / 1 SpD / 4 Spe 129 | Level: 5 130 | =OriginalTrainerName=* 131 | - Headbutt 132 | - Growl 133 | - Aurora Beam 134 | 135 | UNDERLEVEL (Dewgong) (F) 136 | IVs: 4 HP / 6 Atk / 7 Def / 8 SpA / 8 SpD / 8 Spe 137 | Level: 28 138 | - Headbutt 139 | - Growl 140 | - Aurora Beam 141 | 142 | Muk (F) 143 | IVs: 14 HP / 7 Atk / 13 Def / 8 SpA / 8 SpD / 9 Spe 144 | Level: 37 145 | - Disable 146 | - Poison Gas 147 | - Minimize 148 | - Sludge 149 | 150 | STICKY (Muk) (M) 151 | IVs: 1 HP / 8 Atk / 10 Def / 1 SpA / 1 SpD / 2 Spe 152 | Level: 5 153 | =OriginalTrainerName=* 154 | - Pound 155 | - Disable 156 | - Poison Gas 157 | 158 | Gengar (F) 159 | IVs: 5 HP / 2 Atk / 5 Def / 11 SpA / 11 SpD / 2 Spe 160 | Level: 20 161 | - Lick 162 | - Confuse Ray 163 | - Night Shade 164 | 165 | Kingler (F) 166 | IVs: 13 HP / 5 Atk / 3 Def / 3 SpA / 3 SpD / 10 Spe 167 | Level: 25 168 | - Bubble 169 | - Leer 170 | - Vise Grip 171 | - Guillotine 172 | 173 | DORIS (Electrode) 174 | IVs: 3 HP / 12 Atk / 6 Def / 9 SpA / 9 SpD / 9 Spe 175 | Level: 3 176 | =OriginalTrainerName=* 177 | - Tackle 178 | - Screech 179 | - Sonic Boom 180 | 181 | Marowak (M) 182 | IVs: 12 HP / 9 Atk / 3 Def / 2 SpA / 2 SpD / 0 Spe 183 | Level: 24 184 | - Bone Club 185 | - Tail Whip 186 | - Headbutt 187 | 188 | BUFFY (Rhydon) (F) 189 | IVs: 6 HP / 6 Atk / 13 Def / 6 SpA / 6 SpD / 3 Spe 190 | Level: 15 191 | =OriginalTrainerName=* 192 | - Horn Attack 193 | - Stomp 194 | - Tail Whip 195 | - Fury Attack 196 | 197 | Seadra (M) 198 | IVs: 5 HP / 12 Atk / 7 Def / 9 SpA / 9 SpD / 10 Spe 199 | Level: 25 200 | - Bubble 201 | - Smokescreen 202 | - Leer 203 | 204 | Seadra (M) 205 | IVs: 11 HP / 13 Atk / 12 Def / 9 SpA / 9 SpD / 7 Spe 206 | Level: 20 207 | - Bubble 208 | - Smokescreen 209 | 210 | Seaking (M) 211 | IVs: 3 HP / 10 Atk / 0 Def / 13 SpA / 13 SpD / 7 Spe 212 | Level: 23 213 | - Peck 214 | - Tail Whip 215 | - Supersonic 216 | 217 | NINI (Jynx) (F) 218 | IVs: 8 HP / 6 Def / 6 SpA / 6 SpD / 8 Spe 219 | Level: 10 220 | =OriginalTrainerName=* 221 | - Pound 222 | - Lovely Kiss 223 | 224 | NINI (Jynx) (F) 225 | IVs: 10 HP / 9 Atk / 6 Def / 4 SpA / 4 SpD / 1 Spe 226 | Level: 20 227 | =OriginalTrainerName=* 228 | - Pound 229 | - Lovely Kiss 230 | - Lick 231 | 232 | Gyarados (F) 233 | IVs: 7 HP / 2 Atk / 11 Def / 9 SpA / 9 SpD / 7 Spe 234 | Level: 15 235 | - Tackle 236 | 237 | Dragonair (F) 238 | IVs: 8 HP / 3 Atk / 12 Def / 4 SpA / 4 SpD / 4 Spe 239 | Level: 15 240 | - Wrap 241 | - Leer 242 | - Thunder Wave -------------------------------------------------------------------------------- /AutoModTests/ShowdownSets/Underleveled Tests/Underlevel notransfer - pk4.txt: -------------------------------------------------------------------------------- 1 | Gloom (F) 2 | IVs: 17 HP / 21 Atk / 30 Def / 29 SpA / 30 SpD / 24 Spe 3 | Ability: Chlorophyll 4 | Level: 14 5 | Mild Nature 6 | ~=Location=233 7 | ~=Version=HGSS 8 | .Version=8 9 | - Absorb 10 | - Sweet Scent 11 | - Acid 12 | - Poison Powder 13 | 14 | Poliwhirl (F) 15 | IVs: 15 HP / 13 Atk / 15 Def / 11 SpA / 14 SpD / 30 Spe 16 | Ability: Water Absorb 17 | Level: 15 18 | Timid Nature 19 | ~=Location=233 20 | ~=Version=HGSS 21 | .Version=8 22 | - Bubble 23 | - Hypnosis 24 | - Water Gun 25 | - Double Slap 26 | 27 | Poliwrath (F) 28 | IVs: 14 HP / 7 Atk / 11 SpA / 0 SpD / 19 Spe 29 | Ability: Water Absorb 30 | Level: 15 31 | Serious Nature 32 | ~=Location=233 33 | ~=Version=HGSS 34 | .Version=8 35 | - Bubble 36 | - Hypnosis 37 | - Water Gun 38 | - Double Slap 39 | 40 | Weepinbell (M) 41 | IVs: 10 HP / 30 Atk / 13 Def / 11 SpA / 0 SpD / 6 Spe 42 | Ability: Chlorophyll 43 | Level: 13 44 | Lax Nature 45 | ~=Location=233 46 | ~=Version=HGSS 47 | .Version=8 48 | - Vine Whip 49 | - Growth 50 | - Wrap 51 | - Sleep Powder 52 | 53 | Politoed (F) 54 | IVs: 15 HP / 21 Atk / 16 Def / 19 SpA / 22 SpD / 30 Spe 55 | Ability: Damp 56 | Level: 15 57 | Rash Nature 58 | ~=Location=233 59 | ~=Version=HGSS 60 | .Version=8 61 | - Bubble 62 | - Hypnosis 63 | - Water Gun 64 | - Double Slap 65 | 66 | Octillery (F) @ Focus Band 67 | IVs: 8 HP / 7 Atk / 7 Def / 27 SpA / 23 SpD / 7 Spe 68 | Ability: Sniper 69 | Level: 19 70 | Adamant Nature 71 | ~=Location=233 72 | ~=Version=HGSS 73 | .Version=8 74 | - Psybeam 75 | - Aurora Beam 76 | - Bubble Beam 77 | - Signal Beam 78 | 79 | Pelipper (M) 80 | IVs: 17 HP / 0 Atk / 6 Def / 8 SpA / 12 SpD / 19 Spe 81 | Ability: Keen Eye 82 | Level: 15 83 | Brave Nature 84 | ~=Location=233 85 | ~=Version=HGSS 86 | .Version=8 87 | - Water Sport 88 | - Wing Attack 89 | - Supersonic 90 | - Water Gun 91 | 92 | Gengar (M) 93 | IVs: 15 HP / 8 Atk / 30 Def / 2 SpA / 30 SpD / 27 Spe 94 | Ability: Levitate 95 | Level: 17 96 | Brave Nature 97 | Ball: Master Ball 98 | ~=Version=Pt 99 | - Spite 100 | - Mean Look 101 | - Curse 102 | - Night Shade 103 | 104 | Gengar (F) 105 | IVs: 30 HP / 11 Atk / 4 SpA / 27 SpD / 18 Spe 106 | Ability: Levitate 107 | Level: 16 108 | Gentle Nature 109 | Ball: Master Ball 110 | ~=Version=DP 111 | .Version=10 112 | - Spite 113 | - Mean Look 114 | - Curse 115 | - Night Shade 116 | 117 | Gaspar (Gengar) (M) 118 | IVs: 20 HP / 25 Atk / 15 Def / 15 SpA / 15 SpD / 25 Spe 119 | Ability: Levitate 120 | Level: 35 121 | Hasty Nature 122 | ~=Version=DPPt 123 | =OriginalTrainerName=Mindy 124 | - Sucker Punch 125 | - Shadow Punch 126 | - Payback 127 | - Shadow Ball 128 | 129 | Gengar (M) 130 | IVs: 15 HP / 24 Def / 30 SpA / 3 SpD / 23 Spe 131 | Ability: Levitate 132 | Level: 19 133 | Mild Nature 134 | Ball: Master Ball 135 | ~=Version=HGSS 136 | .Version=7 137 | - Mean Look 138 | - Curse 139 | - Night Shade 140 | - Confuse Ray 141 | 142 | Gengar (M) 143 | IVs: 7 HP / 6 Atk / 8 Def / 20 SpA / 21 SpD / 20 Spe 144 | Ability: Levitate 145 | Level: 17 146 | Sassy Nature 147 | Ball: Master Ball 148 | ~=Version=Pt 149 | - Spite 150 | - Mean Look 151 | - Curse 152 | - Night Shade -------------------------------------------------------------------------------- /AutoModTests/TestUtil.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using PKHeX.Core; 3 | using PKHeX.Core.AutoMod; 4 | 5 | namespace AutoModTests 6 | { 7 | public static class TestUtil 8 | { 9 | static TestUtil() => InitializePKHeXEnvironment(); 10 | 11 | private static bool Initialized; 12 | 13 | private static readonly object _lock = new(); 14 | 15 | private static readonly NicknameRestriction NicknameRestriction = new() { NicknamedTrade = Severity.Fishy, NicknamedMysteryGift = Severity.Fishy }; 16 | 17 | public static void InitializePKHeXEnvironment() 18 | { 19 | lock (_lock) 20 | { 21 | if (Initialized) 22 | return; 23 | EncounterEvent.RefreshMGDB(); 24 | RibbonStrings.ResetDictionary(GameInfo.Strings.ribbons); 25 | Legalizer.EnableEasterEggs = false; 26 | APILegality.SetAllLegalRibbons = false; 27 | APILegality.Timeout = 99999; 28 | ParseSettings.Settings.Handler.CheckActiveHandler = false; 29 | ParseSettings.Settings.HOMETransfer.HOMETransferTrackerNotPresent = Severity.Fishy; 30 | ParseSettings.Settings.Nickname.Nickname12 = NicknameRestriction; 31 | ParseSettings.Settings.Nickname.Nickname3 = NicknameRestriction; 32 | ParseSettings.Settings.Nickname.Nickname4 = NicknameRestriction; 33 | ParseSettings.Settings.Nickname.Nickname5 = NicknameRestriction; 34 | ParseSettings.Settings.Nickname.Nickname6 = NicknameRestriction; 35 | ParseSettings.Settings.Nickname.Nickname7 = NicknameRestriction; 36 | ParseSettings.Settings.Nickname.Nickname7b = NicknameRestriction; 37 | ParseSettings.Settings.Nickname.Nickname8 = NicknameRestriction; 38 | ParseSettings.Settings.Nickname.Nickname8a = NicknameRestriction; 39 | ParseSettings.Settings.Nickname.Nickname8b = NicknameRestriction; 40 | ParseSettings.Settings.Nickname.Nickname9 = NicknameRestriction; 41 | Initialized = true; 42 | } 43 | } 44 | 45 | public static string GetTestFolder(string name) 46 | { 47 | var folder = Directory.GetCurrentDirectory(); 48 | while (!folder.EndsWith(nameof(AutoModTests))) 49 | { 50 | var dir = 51 | Directory.GetParent(folder) 52 | ?? throw new DirectoryNotFoundException( 53 | $"Unable to find a directory named {nameof(AutoModTests)}." 54 | ); 55 | folder = dir.FullName; 56 | } 57 | return Path.Combine(folder, name); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /AutoModTests/WebSetFetch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using FluentAssertions; 4 | using PKHeX.Core; 5 | using PKHeX.Core.Enhancements; 6 | using Xunit; 7 | 8 | namespace AutoModTests 9 | { 10 | public static class WebSetFetch 11 | { 12 | [Theory] 13 | [InlineData(typeof(PK7), GameVersion.MN, (ushort)Species.Venusaur)] 14 | [InlineData(typeof(PK1), GameVersion.RD, (ushort)Species.Charizard)] 15 | [InlineData(typeof(PK3), GameVersion.E, (ushort)Species.Blastoise)] 16 | [InlineData(typeof(PK6), GameVersion.X, (ushort)Species.Venomoth)] 17 | public static void HasSmogonSets(Type t, GameVersion game, ushort species, byte form = 0) 18 | { 19 | var blank = EntityBlank.GetBlank(t); 20 | blank.Version = game; 21 | blank.Species = species; 22 | blank.Form = form; 23 | 24 | var smogon = new SmogonSetList(blank); 25 | smogon.Valid.Should().BeTrue("Sets should exist for this setup"); 26 | var count = smogon.Sets.Count; 27 | count.Should().BeGreaterThan(0, "At least one set should exist"); 28 | smogon.SetConfig.Count 29 | .Should() 30 | .Be(count, "Unparsed text should be captured and match result count"); 31 | smogon.SetText.Count 32 | .Should() 33 | .Be(count, "Reformatted text should be captured and match result count"); 34 | } 35 | 36 | [Theory] 37 | [InlineData( 38 | "https://pokepast.es/73c130c81caab03e", 39 | "STING LIKE A BEE", 40 | (ushort)Species.Beedrill, 41 | (ushort)Species.Magearna 42 | )] // Beedrill, Magearna 43 | public static void HasPokePasteSets(string url, string name, params ushort[] speciesPresent) 44 | { 45 | var tpi = new TeamPasteInfo(url); 46 | tpi.Source.Should().Be(TeamPasteInfo.PasteSource.PokePaste); 47 | tpi.VerifyContents(name, speciesPresent); 48 | } 49 | 50 | [Theory] 51 | [InlineData( 52 | "https://pastebin.com/0x7jJvB4", 53 | "Untitled", 54 | (ushort)Species.Miltank, 55 | (ushort)Species.Braviary 56 | )] // Miltank...Braviary 57 | public static void HasPastebinSets(string url, string name, params ushort[] speciesPresent) 58 | { 59 | var tpi = new TeamPasteInfo(url); 60 | tpi.Source.Should().Be(TeamPasteInfo.PasteSource.Pastebin); 61 | tpi.VerifyContents(name, speciesPresent); 62 | } 63 | 64 | private static void VerifyContents( 65 | this TeamPasteInfo tpi, 66 | string name, 67 | ushort[] speciesPresent 68 | ) 69 | { 70 | tpi.Valid.Should().BeTrue("Data should exist for this paste"); 71 | tpi.Title.Should().Be(name, "Data should have a title present"); 72 | 73 | var team = ShowdownUtil.ShowdownSets(tpi.Sets); 74 | var species = team.ConvertAll(s => s.Species); 75 | var hasAll = speciesPresent.All(species.Contains); 76 | hasAll.Should().BeTrue("Specific species are expected"); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | This project adheres to a **modified** No Code of Conduct. We are all adults. We accept anyone's contributions. ~~Nothing else matters.~~ 4 | 5 | For more information on NCoC please visit the [No Code of Conduct](https://github.com/domgetter/NCoC) homepage. 6 | 7 | In addition to the above clause in the Code of Conduct, the following clauses must be adhered to: 8 | - Don't be an asshole. No one likes them. Please be friendly while making contributions. 9 | - Don't act entitled to perks or Collaborator access just because of a contribution. (Refer to [Code of Merit](https://codeofmerit.org/code/) Clause 4) 10 | - Individual characteristics, including but not limited to, body, sex, sexual preference, race, language, religion, nationality, or political preferences are irrelevant in the scope of the project and will not be taken into account concerning your value or that of your contribution to the project. ([Code of Merit](https://codeofmerit.org/code/) Clause 8) 11 | - If something is illegal outside the scope of the project, it is illegal in the scope of the project. This Code of Merit does not take precedence over governing law. ([Code of Merit](https://codeofmerit.org/code/) Clause 11) 12 | - Participation on the project equates to agreement of this modified code of conduct. 13 | - GitHub users: @architdate, @kwsch and @Lusamine are the only ones allowed to grant users who violate this Code of Conduct an exemption based on the situation and/or their own discretion. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to PKHeX-Plugins 2 | 3 | Thank you for taking the time to contribute to PKHeX-Plugins development. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. 4 | 5 | Before contributing, make sure to read the [Code of Conduct](https://github.com/architdate/PKHeX-Plugins/blob/master/CODE_OF_CONDUCT.md) for this project. All the rules specified there also apply to making contributions. 6 | 7 | PKHeX-Plugins is being used in several different projects such as: 8 | - A plugin extension to [PKHeX](https://github.com/architdate/PKHeX) 9 | - As a legality checker and fixer for [PKSM](https://github.com/FlagBrew/PKSM) and FlagBrew's [CoreAPI](https://github.com/FlagBrew/CoreAPI) 10 | - In [SysBot.NET](https://github.com/kwsch/SysBot.NET) for generating and injecting Pokemon 11 | - In [PKHeX Mobile](https://github.com/kwsch/PKHeX.Mobile) for Auto Legality 12 | .. and a few others that I may not know of. Please ensure that an issue or a feature is relevant to this specific repo rather than another repo that may be utilizing these plugins before contributing 13 | 14 | ### Issues 15 | 16 | When submitting an issue, please use an issue template and ensure you are filling things correctly. If you are unsure, you can always ask on our Discord instead (we monitor both locations)! 17 | 18 | Have a question? Please contact us on Discord (link on [README.md](https://github.com/architdate/PKHeX-Plugins/blob/master/README.md)) instead. Please be patient when expecting a response; this is free software and we aren't available at all times. 19 | 20 | ### Pull Requests 21 | 22 | When submitting a pull request, please try to have everything ready for merging and passing all tests unless it is a big change and you would prefer to open a Draft request for it. In case of longer draft request, please include a TODO checklist in the original PR message for an initial review of the logic intended and to track progress. 23 | 24 | Please make sure your code is maintainable; provide comments and xmldoc when appropriate. If you are coding new GUI features, ensure any non-GUI logic is separate from the GUI specific logic; separating concerns is important for maintainability and portability! 25 | 26 | If you are providing something that interacts with game data, try to model things to match the way the game interacts with the data. When done this way, it is easiest for others to replicate your research and expand upon your improvements. 27 | 28 | ### Forks 29 | 30 | Please keep your own forks of this repository opensource as well! We develop these programs to help out the community, please do the same as well and give back to the community. 31 | 32 | ### Monetary Contributions 33 | 34 | This project does not take monetary contributions at the moment because we believe that there are other causes in the world right now that deserve your money more. Please consider donating to a reputable charity instead. Alternatively, if you want to contribute to the tech projects, we recommend any of the ones that use these plugins (stated on top of this file). -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | 24.5.5 5 | 12 6 | enable 7 | en 8 | $([System.DateTime]::UtcNow.ToString("yyMMddHHmmss")) 9 | 10 | 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Archit Date 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PKHeX-Plugins.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33205.214 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoModPlugins", "AutoLegalityMod\AutoModPlugins.csproj", "{8ED04749-56CC-488C-9D85-B1BE83EF8F0C}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoModTests", "AutoModTests\AutoModTests.csproj", "{07D53A68-26E2-4173-84FB-B2413F505D2A}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PKHeX.Core.AutoMod", "PKHeX.Core.AutoMod\PKHeX.Core.AutoMod.csproj", "{EF5EC3E5-9D9D-4B54-BBF3-9B943DED8B8A}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{C280F954-8B81-4014-881C-D3FBF0CC2E44}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PKHeX.Core.Injection", "PKHeX.Core.Injection\PKHeX.Core.Injection.csproj", "{DB4DA5C0-DFB3-490E-90E1-CDD9330267F2}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PKHeX.Core.Enhancements", "PKHeX.Core.Enhancements\PKHeX.Core.Enhancements.csproj", "{165D144A-DBB4-4F3B-BF39-E783B41008C3}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Release|Any CPU = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {8ED04749-56CC-488C-9D85-B1BE83EF8F0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {8ED04749-56CC-488C-9D85-B1BE83EF8F0C}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {8ED04749-56CC-488C-9D85-B1BE83EF8F0C}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {8ED04749-56CC-488C-9D85-B1BE83EF8F0C}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {07D53A68-26E2-4173-84FB-B2413F505D2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {07D53A68-26E2-4173-84FB-B2413F505D2A}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {07D53A68-26E2-4173-84FB-B2413F505D2A}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {07D53A68-26E2-4173-84FB-B2413F505D2A}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {EF5EC3E5-9D9D-4B54-BBF3-9B943DED8B8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {EF5EC3E5-9D9D-4B54-BBF3-9B943DED8B8A}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {EF5EC3E5-9D9D-4B54-BBF3-9B943DED8B8A}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {EF5EC3E5-9D9D-4B54-BBF3-9B943DED8B8A}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {DB4DA5C0-DFB3-490E-90E1-CDD9330267F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {DB4DA5C0-DFB3-490E-90E1-CDD9330267F2}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {DB4DA5C0-DFB3-490E-90E1-CDD9330267F2}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {DB4DA5C0-DFB3-490E-90E1-CDD9330267F2}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {165D144A-DBB4-4F3B-BF39-E783B41008C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {165D144A-DBB4-4F3B-BF39-E783B41008C3}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {165D144A-DBB4-4F3B-BF39-E783B41008C3}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {165D144A-DBB4-4F3B-BF39-E783B41008C3}.Release|Any CPU.Build.0 = Release|Any CPU 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(NestedProjects) = preSolution 49 | {8ED04749-56CC-488C-9D85-B1BE83EF8F0C} = {C280F954-8B81-4014-881C-D3FBF0CC2E44} 50 | EndGlobalSection 51 | GlobalSection(ExtensibilityGlobals) = postSolution 52 | SolutionGuid = {95162B5A-0896-469B-8682-1266DDCD8749} 53 | EndGlobalSection 54 | EndGlobal 55 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/ALMTraceback.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | 5 | namespace PKHeX.Core.AutoMod 6 | { 7 | [DebuggerDisplay($"{{{nameof(Identifier)}}}: {{{nameof(Comment)}}}")] 8 | public readonly record struct ALMTraceback(TracebackType Identifier, string Comment); 9 | 10 | public interface ITracebackHandler 11 | { 12 | /// 13 | /// Handle traceback when it reaches the handler 14 | /// 15 | /// ALMTraceback object 16 | void Handle(ALMTraceback traceback); 17 | 18 | /// 19 | /// Create an ALMTraceback object and handle 20 | /// 21 | /// TracebackType 22 | /// Comment 23 | void Handle(TracebackType ident, string Comment); 24 | 25 | /// 26 | /// Any output produced by the traceback handler. 27 | /// Can be used post generation 28 | /// 29 | /// Output object 30 | IEnumerable? Output(); 31 | 32 | /// 33 | /// Get Handler type being used currently 34 | /// 35 | /// Handler type 36 | HandlerType GetType(); 37 | } 38 | 39 | public enum TracebackType : byte 40 | { 41 | Encounter, 42 | Trainer, 43 | PID_IV, 44 | EC, 45 | Species, 46 | Level, 47 | Shiny, 48 | Gender, 49 | Form, 50 | Nature, 51 | Ability, 52 | Item, 53 | Moves, 54 | EVs, 55 | AVs, 56 | Size, 57 | HyperTrain, 58 | Friendship, 59 | Misc 60 | } 61 | 62 | public enum HandlerType : byte 63 | { 64 | Disabled, 65 | Debug, 66 | Verbose 67 | } 68 | 69 | public static class HandlerTypeExtensions 70 | { 71 | public static ITracebackHandler GetTracebackHandler(this HandlerType ht) => 72 | ht switch 73 | { 74 | HandlerType.Disabled => new DisabledTBHandler(), 75 | HandlerType.Debug => new DebugTBHandler(), 76 | HandlerType.Verbose => new VerboseTBHandler(), 77 | _ => throw new NotImplementedException("Traceback Handler is not implemented"), 78 | }; 79 | } 80 | 81 | public class DisabledTBHandler : ITracebackHandler 82 | { 83 | public void Handle(ALMTraceback traceback) { } 84 | 85 | public void Handle(TracebackType ident, string Comment) { } 86 | 87 | public IEnumerable? Output() => null; 88 | 89 | HandlerType ITracebackHandler.GetType() => HandlerType.Disabled; 90 | } 91 | 92 | public class DebugTBHandler : ITracebackHandler 93 | { 94 | public void Handle(ALMTraceback traceback) 95 | { 96 | Debug.WriteLine(traceback); 97 | } 98 | 99 | public void Handle(TracebackType ident, string Comment) 100 | { 101 | Debug.WriteLine($"{ident}: {Comment}"); 102 | } 103 | 104 | public IEnumerable? Output() => null; 105 | 106 | HandlerType ITracebackHandler.GetType() => HandlerType.Debug; 107 | } 108 | 109 | public class VerboseTBHandler : ITracebackHandler 110 | { 111 | private readonly List tb = []; 112 | 113 | public void Handle(ALMTraceback traceback) 114 | { 115 | tb.Add(traceback); 116 | } 117 | 118 | public void Handle(TracebackType ident, string comment) 119 | { 120 | var almtb = new ALMTraceback(ident, comment); 121 | tb.Add(almtb); 122 | } 123 | 124 | public IEnumerable Output() => tb; 125 | 126 | HandlerType ITracebackHandler.GetType() => HandlerType.Verbose; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/AutoModErrorCode.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.AutoMod 2 | { 3 | /// 4 | /// Result codes for legalization and import operations. 5 | /// 6 | public enum AutoModErrorCode 7 | { 8 | None, 9 | NoSingleImport, 10 | 11 | /// 12 | /// Don't use this! 13 | /// 14 | CODE_SILENT, 15 | 16 | NotEnoughSpace, 17 | InvalidLines, 18 | VersionMismatch, 19 | } 20 | 21 | public static class AutoModErrorCodeExtensions 22 | { 23 | public static string GetMessage(this AutoModErrorCode code) 24 | { 25 | if (code.IsSilent()) 26 | return string.Empty; 27 | 28 | return code switch 29 | { 30 | AutoModErrorCode.NotEnoughSpace => "Not enough space in the box.", 31 | AutoModErrorCode.InvalidLines => "Invalid lines detected.", 32 | _ => string.Empty, 33 | }; 34 | } 35 | 36 | public static bool IsSilent(this AutoModErrorCode code) => 37 | code <= AutoModErrorCode.CODE_SILENT; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Legalization/AbilityRequest.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.AutoMod 2 | { 3 | public enum AbilityRequest 4 | { 5 | /// 6 | /// Any ability is fine. 7 | /// 8 | Any, 9 | 10 | /// 11 | /// Ability that matches ability number 1. 12 | /// 13 | First, 14 | 15 | /// 16 | /// Ability that matches ability number 2. 17 | /// 18 | Second, 19 | 20 | /// 21 | /// Any ability that is not a hidden ability. 22 | /// 23 | NotHidden, 24 | 25 | /// 26 | /// Requested ability may be possibly hidden (Hidden ability matches one of the requested ability). 27 | /// 28 | PossiblyHidden, 29 | 30 | /// 31 | /// Requested ability is hidden. 32 | /// 33 | Hidden, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Legalization/LegalEdits.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PKHeX.Core.AutoMod 4 | { 5 | /// 6 | /// Suggestion edits that rely on a being done. 7 | /// 8 | public static class LegalEdits 9 | { 10 | private static readonly Dictionary LABallMapping = 11 | new() 12 | { 13 | { Ball.Poke, Ball.LAPoke }, 14 | { Ball.Great, Ball.LAGreat }, 15 | { Ball.Ultra, Ball.LAUltra }, 16 | { Ball.Heavy, Ball.LAHeavy }, 17 | }; 18 | 19 | public static bool ReplaceBallPrefixLA { get; set; } 20 | 21 | /// 22 | /// Set a valid Pokeball based on a legality check's suggestions. 23 | /// 24 | /// Pokémon to modify 25 | /// Set matching ball 26 | /// 27 | /// 28 | public static void SetSuggestedBall( 29 | this PKM pk, 30 | bool matching = true, 31 | bool force = false, 32 | Ball ball = Ball.None, 33 | IEncounterable? enc = null 34 | ) 35 | { 36 | var orig = pk.Ball; 37 | if (ball == Ball.None) 38 | force = false; // accept anything if no ball is specified 39 | 40 | if (enc is MysteryGift) 41 | return; 42 | 43 | var legal = new LegalityAnalysis(pk).Valid; 44 | 45 | if (ball != Ball.None) 46 | { 47 | if (pk.LA && ReplaceBallPrefixLA && LABallMapping.TryGetValue(ball, out var modified)) 48 | ball = modified; 49 | pk.Ball = (byte)ball; 50 | if (!force && !pk.ValidBall()) 51 | pk.Ball = orig; 52 | } 53 | else if (matching) 54 | { 55 | if (!pk.IsShiny) 56 | pk.SetMatchingBall(); 57 | else 58 | Aesthetics.ApplyShinyBall(pk); 59 | } 60 | 61 | var la = new LegalityAnalysis(pk); 62 | if (force || la.Valid) 63 | return; 64 | 65 | if (pk.Generation == 5 && pk.MetLocation == 75) 66 | pk.Ball = (int)Ball.Dream; 67 | else 68 | pk.Ball = orig; 69 | 70 | if (legal && !la.Valid) 71 | pk.Ball = orig; 72 | } 73 | 74 | public static bool ValidBall(this PKM pk) 75 | { 76 | var rep = new LegalityAnalysis(pk).Report(true); 77 | return rep.Contains(LegalityCheckStrings.LBallEnc) 78 | || rep.Contains(LegalityCheckStrings.LBallSpeciesPass); 79 | } 80 | 81 | /// 82 | /// Sets all ribbon flags according to a legality report. 83 | /// 84 | /// Pokémon to modify 85 | /// Encounter matched to 86 | /// Set all valid ribbons only 87 | public static void SetSuggestedRibbons( 88 | this PKM pk, 89 | IBattleTemplate set, 90 | IEncounterable enc, 91 | bool allValid, 92 | ITracebackHandler tb 93 | ) 94 | { 95 | if (!allValid) 96 | return; 97 | RibbonApplicator.SetAllValidRibbons(pk); 98 | tb.Handle(TracebackType.Misc, "Set all valid ribbons"); 99 | if ( 100 | pk is PK8 pk8 101 | && pk8.Species != (int)Species.Shedinja 102 | && pk8.GetRandomValidMark(set, enc, out var mark) 103 | ) 104 | { 105 | pk8.SetRibbonIndex(mark); 106 | tb.Handle(TracebackType.Misc, $"Set random valid mark {mark}"); 107 | } 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Legalization/LegalizationResult.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.AutoMod 2 | { 3 | /// 4 | /// Indication for how a is/was legalized. 5 | /// 6 | public enum LegalizationResult 7 | { 8 | /// 9 | /// Successfully regenerated from data. 10 | /// 11 | Regenerated, 12 | 13 | /// 14 | /// Failed to generate. 15 | /// 16 | Failed, 17 | 18 | /// 19 | /// Timed out while generating 20 | /// 21 | Timeout, 22 | 23 | /// 24 | /// Version mismatch with base PKHeX 25 | /// 26 | VersionMismatch, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Regeneration/RegenSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PKHeX.Core.AutoMod 7 | { 8 | public class RegenSet 9 | { 10 | public static readonly RegenSet Default = new([], PKX.Generation); 11 | 12 | public RegenSetting Extra { get; } 13 | public ITrainerInfo? Trainer { get; } 14 | public StringInstructionSet Batch { get; } 15 | public IReadOnlyList EncounterFilters { get; } 16 | public IReadOnlyList VersionFilters { get; } 17 | 18 | public readonly bool HasExtraSettings; 19 | public readonly bool HasTrainerSettings; 20 | public bool HasBatchSettings => Batch.Filters.Count != 0 || Batch.Instructions.Count != 0; 21 | 22 | public RegenSet(PKM pk) 23 | : this([], pk.Format) 24 | { 25 | Extra.Ball = (Ball)pk.Ball; 26 | Extra.ShinyType = GetShinyType(pk); 27 | if (pk is IAlphaReadOnly { IsAlpha: true }) 28 | Extra.Alpha = true; 29 | } 30 | 31 | private static Shiny GetShinyType(PKM pk) 32 | { 33 | if (pk.ShinyXor == 0) 34 | return Shiny.AlwaysSquare; 35 | if (pk.IsShiny) 36 | return Shiny.AlwaysStar; 37 | return Shiny.Never; 38 | } 39 | 40 | public RegenSet(ICollection lines, byte format, Shiny shiny = Shiny.Never) 41 | { 42 | var modified = lines 43 | .Select(z => z.Replace(">=", "≥").Replace("<=", "≤")) 44 | .ToList(); 45 | 46 | Extra = new RegenSetting { ShinyType = shiny }; 47 | HasExtraSettings = Extra.SetRegenSettings(modified); 48 | HasTrainerSettings = RegenUtil.GetTrainerInfo(modified, format, out var tr); 49 | Trainer = tr; 50 | Batch = new StringInstructionSet(modified.ToArray().AsSpan()); 51 | EncounterFilters = RegenUtil.GetEncounterFilters(modified); 52 | VersionFilters = RegenUtil.GetVersionFilters(modified); 53 | } 54 | 55 | public string GetSummary() 56 | { 57 | var sb = new StringBuilder(); 58 | if (HasExtraSettings) 59 | sb.AppendLine(RegenUtil.GetSummary(Extra)); 60 | if (HasTrainerSettings && Trainer != null) 61 | sb.AppendLine(RegenUtil.GetSummary(Trainer)); 62 | if (HasBatchSettings) 63 | sb.AppendLine(RegenUtil.GetSummary(Batch)); 64 | if (EncounterFilters.Count > 0) 65 | sb.AppendLine(RegenUtil.GetSummary(EncounterFilters)); 66 | if (VersionFilters.Count > 0) 67 | sb.AppendLine(RegenUtil.GetSummary(VersionFilters)); 68 | return sb.ToString(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Regeneration/RegenSetting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace PKHeX.Core.AutoMod 5 | { 6 | public class RegenSetting 7 | { 8 | public Ball Ball { get; set; } 9 | public Shiny ShinyType { get; set; } = Shiny.Never; 10 | public LanguageID? Language { get; set; } 11 | public AbilityRequest Ability { get; set; } = AbilityRequest.Any; 12 | public bool Alpha { get; set; } 13 | 14 | public bool IsShiny => ShinyType != Shiny.Never; 15 | 16 | public bool SetRegenSettings(IEnumerable lines) 17 | { 18 | var split = RegenUtil.Split(lines); 19 | bool any = false; 20 | foreach (var s in split) 21 | { 22 | var key = s.Key; 23 | var value = s.Value; 24 | switch (key) 25 | { 26 | case nameof(Ball): 27 | var ball = Aesthetics.GetBallFromString(value); 28 | if (ball == Ball.Strange) 29 | continue; 30 | Ball = ball; 31 | break; 32 | case nameof(Shiny): 33 | ShinyType = Aesthetics.GetShinyType(value); 34 | break; 35 | case nameof(Language): 36 | Language = Aesthetics.GetLanguageId(value); 37 | break; 38 | case nameof(Ability): 39 | Ability = Enum.TryParse(value, out AbilityRequest ar) 40 | ? ar 41 | : AbilityRequest.Any; 42 | break; 43 | case nameof(Alpha): 44 | Alpha = value == "Yes"; 45 | break; 46 | default: 47 | continue; 48 | } 49 | 50 | any = true; 51 | } 52 | 53 | return any; 54 | } 55 | 56 | public string GetSummary() 57 | { 58 | var result = new List(); 59 | if (Ball != Ball.None) 60 | result.Add($"Ball: {Ball} Ball"); 61 | 62 | if (ShinyType == Shiny.AlwaysStar) 63 | result.Add("Shiny: Star"); 64 | else if (ShinyType == Shiny.AlwaysSquare) 65 | result.Add("Shiny: Square"); 66 | else if (ShinyType == Shiny.Always) 67 | result.Add("Shiny: Yes"); 68 | 69 | if (Language != null) 70 | result.Add($"Language: {Language}"); 71 | 72 | if (Ability != AbilityRequest.Any) 73 | result.Add($"Ability: {Ability}"); 74 | 75 | if (Alpha) 76 | result.Add("Alpha: Yes"); 77 | return string.Join(Environment.NewLine, result); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Regeneration/RegenTemplate.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global 2 | 3 | using System; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace PKHeX.Core.AutoMod 8 | { 9 | public sealed class RegenTemplate : IBattleTemplate 10 | { 11 | public ushort Species { get; set; } 12 | public EntityContext Context { get; set; } 13 | public string Nickname { get; set; } 14 | public byte? Gender { get; set; } 15 | public int HeldItem { get; set; } 16 | public int Ability { get; set; } 17 | public byte Level { get; set; } 18 | public bool Shiny { get; set; } 19 | public byte Friendship { get; set; } 20 | public Nature Nature { get; set; } 21 | public string FormName { get; set; } 22 | public byte Form { get; set; } 23 | public int HiddenPowerType { get; set; } 24 | public bool CanGigantamax { get; set; } 25 | public byte DynamaxLevel { get; set; } 26 | public MoveType TeraType { get; set; } 27 | 28 | public int[] EVs { get; } 29 | public int[] IVs { get; } 30 | public ushort[] Moves { get; set; } 31 | 32 | public RegenSet Regen { get; set; } = RegenSet.Default; 33 | public string Text => GetSummary(); 34 | 35 | private readonly string ParentLines; 36 | 37 | private RegenTemplate(IBattleTemplate set, int gen = PKX.Generation, string text = "") 38 | { 39 | Species = set.Species; 40 | Context = set.Context; 41 | Nickname = set.Nickname; 42 | Gender = set.Gender; 43 | HeldItem = set.HeldItem; 44 | Ability = set.Ability; 45 | Level = (set.Level == 50 && APILegality.ForceLevel100for50) ? (byte)100 : set.Level; 46 | Shiny = set.Shiny; 47 | Friendship = set.Friendship; 48 | Nature = set.Nature; 49 | FormName = set.FormName; 50 | Form = set.Form; 51 | EVs = SanitizeEVs(set.EVs, gen); 52 | IVs = set.IVs; 53 | HiddenPowerType = set.HiddenPowerType; 54 | Moves = set.Moves; 55 | CanGigantamax = set.CanGigantamax; 56 | DynamaxLevel = set.DynamaxLevel; 57 | TeraType = set.TeraType; 58 | 59 | ParentLines = text; 60 | SanitizeMoves(set, Moves); 61 | } 62 | 63 | public RegenTemplate(ShowdownSet set, byte gen = PKX.Generation) 64 | : this(set, gen, set.Text) 65 | { 66 | this.SanitizeForm(gen); 67 | this.SanitizeBattleMoves(); 68 | this.SanitizeTeraTypes(); 69 | 70 | var shiny = Shiny ? Core.Shiny.Always : Core.Shiny.Never; 71 | if (set.InvalidLines.Count == 0) 72 | { 73 | Regen.Extra.ShinyType = shiny; 74 | return; 75 | } 76 | 77 | Regen = new RegenSet(set.InvalidLines, gen, shiny); 78 | Shiny = Regen.Extra.IsShiny; 79 | if (Ability == -1) 80 | Ability = RegenUtil.GetRegenAbility(set.Species, gen, Regen.Extra.Ability); 81 | set.InvalidLines.Clear(); 82 | } 83 | 84 | public RegenTemplate(PKM pk, int gen = PKX.Generation) 85 | : this(new ShowdownSet(pk), gen) 86 | { 87 | this.FixGender(pk.PersonalInfo); 88 | if (!pk.IsNicknamed) 89 | Nickname = string.Empty; 90 | Regen = new RegenSet(pk); 91 | Shiny = Regen.Extra.IsShiny; 92 | } 93 | 94 | private static int[] SanitizeEVs(int[] evs, int gen) 95 | { 96 | var copy = (int[])evs.Clone(); 97 | int maxEV = 98 | gen >= 6 99 | ? 252 100 | : gen >= 3 101 | ? 255 102 | : 65535; 103 | for (int i = 0; i < evs.Length; i++) 104 | { 105 | if (copy[i] > maxEV) 106 | copy[i] = maxEV; 107 | } 108 | return copy; 109 | } 110 | 111 | private static void SanitizeMoves(IBattleTemplate set, ushort[] moves) 112 | { 113 | // Specified moveset, no need to sanitize 114 | if (moves[0] != 0) 115 | return; 116 | 117 | // Sanitize keldeo moves to avoid form mismatches 118 | if (set.Species == (ushort)Core.Species.Keldeo) 119 | moves[0] = set.Form == 0 ? (ushort)Move.AquaJet : (ushort)Move.SecretSword; 120 | } 121 | 122 | private string GetSummary() 123 | { 124 | var sb = new StringBuilder(); 125 | var regen = Regen.GetSummary(); 126 | bool hasRegen = !string.IsNullOrWhiteSpace(regen); 127 | 128 | // Add Showdown content except moves 129 | var split = ParentLines.Split( 130 | new[] { Environment.NewLine }, 131 | StringSplitOptions.RemoveEmptyEntries 132 | ); 133 | var group = split 134 | .Where(z => !IsIgnored(z, Regen)) 135 | .GroupBy(z => z.StartsWith("- ")) 136 | .ToArray(); 137 | if (group.Length == 0) 138 | return sb.ToString(); 139 | sb.AppendLine(string.Join(Environment.NewLine, group[0])); // Not Moves 140 | 141 | // Add non-Showdown content 142 | if (hasRegen) 143 | sb.AppendLine(regen.Trim()); 144 | 145 | // Add Moves 146 | if (group.Length > 1) 147 | sb.AppendLine(string.Join(Environment.NewLine, group[1])); // Moves 148 | return sb.ToString(); 149 | } 150 | 151 | private static bool IsIgnored(string s, RegenSet regen) 152 | { 153 | return regen.HasExtraSettings && s.StartsWith("Shiny: "); 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Regeneration/RegenTemplateExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace PKHeX.Core.AutoMod 5 | { 6 | public static class RegenTemplateExtensions 7 | { 8 | public static void SanitizeForm(this RegenTemplate set, byte gen) 9 | { 10 | if (gen is 9) 11 | { 12 | // Scatterbug and Spewpa must be Fancy 13 | if (set.Species is (ushort)Species.Scatterbug or (ushort)Species.Spewpa) 14 | set.Form = 18; 15 | } 16 | 17 | if (!FormInfo.IsBattleOnlyForm(set.Species, set.Form, gen)) 18 | return; 19 | set.Form = FormInfo.GetOutOfBattleForm(set.Species, set.Form, gen); 20 | } 21 | 22 | /// 23 | /// Showdown quirks lets you have battle only moves in battle only forms. Transform back to base move. 24 | /// 25 | /// 26 | public static void SanitizeBattleMoves(this IBattleTemplate set) 27 | { 28 | switch (set.Species) 29 | { 30 | case (ushort)Species.Zacian: 31 | case (ushort)Species.Zamazenta: 32 | { 33 | // Behemoth Blade and Behemoth Bash -> Iron Head 34 | if (!set.Moves.Contains((ushort)781) && !set.Moves.Contains((ushort)782)) 35 | return; 36 | 37 | for (int i = 0; i < set.Moves.Length; i++) 38 | { 39 | if (set.Moves[i] is 781 or 782) 40 | set.Moves[i] = 442; 41 | } 42 | break; 43 | } 44 | } 45 | } 46 | 47 | /// 48 | /// TeraType restrictions being fixed before the set is even generated 49 | /// 50 | /// 51 | public static void SanitizeTeraTypes(this RegenTemplate set) 52 | { 53 | if (set.Species == (int)Species.Ogerpon && !TeraTypeUtil.IsValidOgerpon((byte)set.TeraType, set.Form)) 54 | set.TeraType = ShowdownEdits.GetValidOpergonTeraType(set.Form); 55 | } 56 | 57 | /// 58 | /// General method to preprocess sets excluding invalid forms. (handled in a future method) 59 | /// 60 | /// Showdown set passed to the function 61 | /// Personal data for the desired form 62 | public static void FixGender(this RegenTemplate set, PersonalInfo personal) 63 | { 64 | if (personal.OnlyFemale && set.Gender != 1) 65 | set.Gender = 1; 66 | else if (personal.OnlyMale && set.Gender != 0) 67 | set.Gender = 0; 68 | } 69 | 70 | public static string GetRegenText(this PKM pk) => 71 | pk.Species == 0 ? string.Empty : new RegenTemplate(pk).Text; 72 | 73 | public static IEnumerable GetRegenSets(this IEnumerable data) => 74 | data.Where(p => p.Species != 0).Select(GetRegenText); 75 | 76 | public static string GetRegenSets(this IEnumerable data, string separator) => 77 | string.Join(separator, data.GetRegenSets()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Seeds/BACD_R/WC3Seeds.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PKHeX.Core.AutoMod 4 | { 5 | // There only exists 9 shiny seeds for wishmaker jirachi bacd_r, just have a list and gen based on nature 6 | public static class WC3Seeds 7 | { 8 | private static readonly Dictionary ShinyWishmakerSeeds = 9 | new() 10 | { 11 | { Nature.Bashful, 0x353d }, 12 | { Nature.Careful, 0xf500 }, 13 | { Nature.Docile, 0xecdd }, 14 | { Nature.Hasty, 0x9359 }, 15 | { Nature.Jolly, 0xcf37 }, 16 | { Nature.Lonely, 0x7236 }, 17 | { Nature.Naughty, 0xa030 }, 18 | { Nature.Timid, 0x7360 }, 19 | { Nature.Serious, 0x3d60 }, 20 | }; 21 | 22 | public static uint GetShinyWishmakerSeed(Nature nature) => 23 | ShinyWishmakerSeeds.TryGetValue(nature, out var seed) ? seed : 0; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Trainers/PokeTrainerDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PKHeX.Core.AutoMod 4 | { 5 | /// 6 | /// Wrapper for a to provide details as if it were a 7 | /// 8 | public class PokeTrainerDetails(PKM pk) : ITrainerInfo, IRegionOrigin 9 | { 10 | private readonly PKM pkm = pk; 11 | 12 | public ushort TID16 13 | { 14 | get => pkm.TID16; 15 | set => throw new ArgumentException("Setter for this object should never be called."); 16 | } 17 | public ushort SID16 18 | { 19 | get => pkm.SID16; 20 | set => throw new ArgumentException("Setter for this object should never be called."); 21 | } 22 | public uint ID32 23 | { 24 | get => (uint)(TID16 | (SID16 << 16)); 25 | set => (TID16, SID16) = ((ushort)value, (ushort)(value >> 16)); 26 | } 27 | public TrainerIDFormat TrainerIDDisplayFormat => this.GetTrainerIDFormat(); 28 | 29 | public string OT 30 | { 31 | get => pkm.OriginalTrainerName; 32 | set => pkm.OriginalTrainerName = value; 33 | } 34 | public byte Gender => pkm.OriginalTrainerGender; 35 | public GameVersion Version => pkm.Version; 36 | public int Language 37 | { 38 | get => pkm.Language; 39 | set => pkm.Language = value; 40 | } 41 | 42 | public byte Country 43 | { 44 | get => pkm is IGeoTrack gt ? gt.Country : (byte)49; 45 | set 46 | { 47 | if (pkm is IGeoTrack gt) 48 | gt.Country = value; 49 | } 50 | } 51 | public byte Region 52 | { 53 | get => pkm is IGeoTrack gt ? gt.Region : (byte)7; 54 | set 55 | { 56 | if (pkm is IGeoTrack gt) 57 | gt.Region = value; 58 | } 59 | } 60 | public byte ConsoleRegion 61 | { 62 | get => pkm is IGeoTrack gt ? gt.ConsoleRegion : (byte)1; 63 | set 64 | { 65 | if (pkm is IGeoTrack gt) 66 | gt.ConsoleRegion = value; 67 | } 68 | } 69 | public byte Generation => pkm.Generation; 70 | public EntityContext Context => pkm.Context; 71 | 72 | public static PokeTrainerDetails Clone(PokeTrainerDetails p) => new(p.pkm.Clone()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Util/LivingDexUtils.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.AutoMod 2 | { 3 | public class LivingDexConfig 4 | { 5 | public bool IncludeForms { get; init; } 6 | public bool SetShiny { get; init; } 7 | public bool SetAlpha { get; init; } 8 | public bool NativeOnly { get; init; } 9 | 10 | public override string ToString() 11 | { 12 | return $"IncludeForms: {IncludeForms}\nSetShiny: {SetShiny}\nSetAlpha: {SetAlpha}\nNativeOnly: {NativeOnly}"; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/AutoMod/Util/Version.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Reflection; 4 | 5 | namespace PKHeX.Core.AutoMod 6 | { 7 | public static partial class ALMVersion 8 | { 9 | private static readonly Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); 10 | public static readonly AssemblyVersions Versions = new(); 11 | 12 | public record AssemblyVersions 13 | { 14 | public readonly Version? AlmVersionCurrent = GetCurrentVersion("PKHeX.Core.AutoMod"); 15 | 16 | public readonly Version? CoreVersionCurrent = GetCurrentVersion("PKHeX.Core"); 17 | public readonly Version? CoreVersionLatest = GetLatestCoreVersion(); 18 | } 19 | 20 | /// 21 | /// Checks for plugin mismatch. If "EnableDevMode" is enabled it will allow a user to skip update warnings until the next release. Will otherwise check plugin mismatch for current versions. 22 | /// 23 | /// True if a plugin mismatch is found. False if any of the versions are null or no mismatch found. 24 | public static bool GetIsMismatch() => 25 | GetIsMismatch( 26 | currentCore: Versions.CoreVersionCurrent, 27 | currentALM: Versions.AlmVersionCurrent, 28 | latestCore: Versions.CoreVersionLatest 29 | ); 30 | 31 | public static bool GetIsMismatch( 32 | Version? currentCore, 33 | Version? currentALM, 34 | Version? latestCore 35 | ) 36 | { 37 | if (currentCore is null || currentALM is null || latestCore is null) 38 | return false; 39 | 40 | var latestAllowed = new Version(APILegality.LatestAllowedVersion); 41 | if (APILegality.EnableDevMode && (latestCore > latestAllowed) && (latestCore > currentCore)) 42 | return true; 43 | return !APILegality.EnableDevMode && (currentCore > currentALM); 44 | } 45 | 46 | /// 47 | /// Gets the current version of the specified assembly. 48 | /// 49 | /// A version representing the current version of the specified assembly, or null if the assembly cannot be found or has no version available. 50 | private static Version? GetCurrentVersion(string assemblyName) 51 | { 52 | var assembly = Array.Find(assemblies, x => x.GetName().Name == assemblyName); 53 | return assembly?.GetName().Version; 54 | } 55 | 56 | private static Version? GetLatestCoreVersion() 57 | { 58 | try 59 | { 60 | return UpdateUtil.GetLatestPKHeXVersion(); 61 | } 62 | catch (Exception ex) 63 | { 64 | Debug.WriteLine(ex.Message); 65 | return null; 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/Enhancements/EasterEggs.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.AutoMod 2 | { 3 | public static class EasterEggs 4 | { 5 | private const int MaxSpeciesID1 = 151; 6 | private const int MaxSpeciesID2 = 251; 7 | private const int MaxSpeciesID3 = 386; 8 | private const int MaxSpeciesID4 = 493; 9 | private const int MaxSpeciesID5 = 649; 10 | private const int MaxSpeciesID6 = 721; 11 | private const int MaxSpeciesID7 = 807; 12 | private const int MaxSpeciesID8 = 890; 13 | private const int MaxSpeciesID9 = 1010; 14 | 15 | public static Species GetMemeSpecies(int gen, PKM format) => 16 | gen switch 17 | { 18 | 1 => Species.Diglett, 19 | 2 => Species.Shuckle, 20 | 3 => Species.Ludicolo, 21 | 4 => Species.Bidoof, 22 | 5 => Species.Stunfisk, 23 | 6 => Species.Sliggoo, 24 | 7 => Species.Cosmog, 25 | 8 when format is PA8 => Species.Porygon, 26 | 8 => Species.Meltan, 27 | 9 => Species.Wiglett, 28 | _ => Species.Diglett, 29 | }; 30 | 31 | public static int GetGeneration(int species) => 32 | species switch 33 | { 34 | <= MaxSpeciesID1 => 1, 35 | <= MaxSpeciesID2 => 2, 36 | <= MaxSpeciesID3 => 3, 37 | <= MaxSpeciesID4 => 4, 38 | <= MaxSpeciesID5 => 5, 39 | <= MaxSpeciesID6 => 6, 40 | <= MaxSpeciesID7 => 7, 41 | <= MaxSpeciesID8 => 8, 42 | <= MaxSpeciesID9 => 9, 43 | _ => 1, 44 | }; 45 | 46 | public static string GetMemeNickname(int gen, PKM format) => 47 | gen switch 48 | { 49 | 1 => "HOWDOIHAK", 50 | 2 => "DONT FCKLE", 51 | 3 => "CANTA", 52 | 4 => "U R A DOOF", 53 | 5 => "PANCAKE", 54 | 6 => "SHOOT DAT GOO", 55 | 7 => "GET IN BAG", 56 | 8 when format is PA8 => "BAD DATA BOI", 57 | 8 => "MATT'S NUT", 58 | 9 => "WIGGLE", 59 | _ => "HOW DO I HAK", 60 | }; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/Enhancements/GlyphLegality.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | 5 | namespace PKHeX.Core.AutoMod 6 | { 7 | public static class GlyphLegality 8 | { 9 | private static readonly Dictionary CharDictionary; 10 | 11 | static GlyphLegality() 12 | { 13 | CharDictionary = []; 14 | const string full = 15 | "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンッァィゥェォャュョ゙゚ー0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+-={}[]|\:;"'<>,.?/"; 16 | const string half = 17 | "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンッァィゥェォャュョ゙゚ー0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+-={}[]|\\:;\"'<>,.?/"; 18 | for (int i = 0; i < full.Length; i++) 19 | CharDictionary.Add(half[i], full[i]); 20 | } 21 | 22 | public static bool ContainsFullWidth(string val) => 23 | val.Any(z => CharDictionary.ContainsValue(z)); 24 | 25 | public static bool ContainsHalfWidth(string val) => 26 | val.Any(z => CharDictionary.ContainsKey(z)); 27 | 28 | public static string StringConvert(string val, StringConversionType type) => 29 | type switch 30 | { 31 | StringConversionType.HalfWidth => val.Normalize(NormalizationForm.FormKC), 32 | StringConversionType.FullWidth 33 | => string.Concat( 34 | val.Select(c => CharDictionary.ContainsKey(c) ? CharDictionary[c] : c) 35 | ), 36 | _ => val, 37 | }; 38 | } 39 | 40 | public enum StringConversionType 41 | { 42 | HalfWidth, 43 | FullWidth, 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /PKHeX.Core.AutoMod/PKHeX.Core.AutoMod.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PKHeX.Core.Enhancements/Enhancements/EventsGallery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.IO.Compression; 4 | using System.Net; 5 | 6 | namespace PKHeX.Core.Enhancements 7 | { 8 | /// 9 | /// Interactions with ProjectPokémon's Event Gallery (hosted on GitHub) 10 | /// 11 | public static class EventsGallery 12 | { 13 | private const string RepoURL = 14 | "https://github.com/projectpokemon/EventsGallery/archive/master.zip"; 15 | private const string RepoReleaseURL = 16 | "https://api.github.com/repos/projectpokemon/EventsGallery/releases/latest"; 17 | 18 | public static string GetMGDBDownloadURL() 19 | { 20 | var json_data = NetUtil.DownloadString(RepoReleaseURL); 21 | return json_data.Split(["browser_download_url"], StringSplitOptions.None)[1][ 22 | 3.. 23 | ].Split('"')[0]; 24 | } 25 | 26 | /// 27 | /// Downloads the entire repository from GitHub and extracts the contents to the . 28 | /// 29 | /// Location to extract the repository to 30 | /// True to Download the current repository, false to only download the latest release. 31 | public static void DownloadMGDBFromGitHub(string dest, bool entire) 32 | { 33 | if (entire) 34 | DownloadEntireRepo(dest); 35 | else 36 | DownloadRelease(dest); 37 | } 38 | 39 | private static void DownloadRelease(string dest) 40 | { 41 | var downloadURL = GetMGDBDownloadURL(); 42 | DownloadAndExtractZip(downloadURL, dest); 43 | } 44 | 45 | private static void DownloadEntireRepo(string dest) 46 | { 47 | DownloadAndExtractZip(RepoURL, dest); 48 | 49 | // clean up; delete unneeded files 50 | var path = Path.Combine(dest, "EventsGallery-master"); 51 | string getPath(string s) => Path.Combine(path, s); 52 | Directory.Delete(getPath("Unreleased"), true); 53 | Directory.Delete(getPath("Extras"), true); 54 | File.Delete(getPath(".gitignore")); 55 | File.Delete(getPath("README.md")); 56 | } 57 | 58 | private static void DownloadAndExtractZip(string url, string dest) 59 | { 60 | const string temp = "temp.zip"; 61 | #pragma warning disable SYSLIB0014 // Type or member is obsolete 62 | using (WebClient client = new()) 63 | client.DownloadFile(new Uri(url), temp); 64 | #pragma warning restore SYSLIB0014 // Type or member is obsolete 65 | 66 | ZipFile.ExtractToDirectory(temp, dest); 67 | File.Delete(temp); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /PKHeX.Core.Enhancements/Enhancements/NetUtil.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Net; 3 | using System.Net.Http; 4 | using System.Threading.Tasks; 5 | 6 | namespace PKHeX.Core.Enhancements 7 | { 8 | /// 9 | /// Internet web request Utility 10 | /// 11 | public static class NetUtil 12 | { 13 | /// 14 | /// Gets the html string from the requested . 15 | /// 16 | /// Address to fetch from 17 | /// Page response 18 | public static string GetPageText(string address) 19 | { 20 | var stream = GetStreamFromURL(address); 21 | return GetStringResponse(stream); 22 | } 23 | 24 | private static Stream GetStreamFromURL(string url) 25 | { 26 | using var client = new HttpClient(); 27 | const string agent = 28 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"; 29 | client.DefaultRequestHeaders.Add("User-Agent", agent); 30 | var response = client.GetAsync(url).Result; 31 | return response.Content.ReadAsStreamAsync().Result; 32 | } 33 | 34 | /// 35 | /// Downloads a string response with hard-coded parameters. 36 | /// 37 | /// Address to fetch from 38 | /// Page response 39 | public static string DownloadString(string address) 40 | { 41 | using var client = new HttpClient(); 42 | client.DefaultRequestHeaders.Add("User-Agent", "PKHeX-Auto-Legality-Mod"); 43 | client.DefaultRequestHeaders.Add("Accept", "application/json"); 44 | var response = client.GetAsync(address).Result; 45 | var stream = response.Content.ReadAsStreamAsync().Result; 46 | return GetStringResponse(stream); 47 | } 48 | 49 | private static string GetStringResponse(Stream? dataStream) 50 | { 51 | if (dataStream == null) 52 | return string.Empty; 53 | using var reader = new StreamReader(dataStream); 54 | return reader.ReadToEnd(); 55 | } 56 | 57 | private static byte[]? GetByteResponse(Stream? dataStream) 58 | { 59 | if (dataStream == null) 60 | return null; 61 | MemoryStream ms = new(); 62 | dataStream.CopyTo(ms); 63 | return ms.ToArray(); 64 | } 65 | 66 | /// 67 | /// GPSS upload function. POST request using multipart form-data 68 | /// 69 | /// pkm data in bytes. 70 | /// The generation for the game the Pokémon is being uploaded from. 71 | /// location to fetch from 72 | public static async Task GPSSPost( 73 | byte[] data, 74 | int generation, 75 | string Url = "flagbrew.org" 76 | ) 77 | { 78 | using var client = new HttpClient(); 79 | 80 | var uploadData = new MultipartFormDataContent 81 | { 82 | { new ByteArrayContent(data), "pkmn", "pkmn" } 83 | }; 84 | 85 | uploadData.Headers.Add("source", "PKHeX AutoMod Plugins"); 86 | uploadData.Headers.Add("generation", generation.ToString()); 87 | 88 | var response = await client.PostAsync( 89 | $"https://{Url}/api/v2/gpss/upload/pokemon", 90 | uploadData 91 | ); 92 | return response; 93 | } 94 | 95 | /// 96 | /// GPSS downloader 97 | /// 98 | /// url long 99 | /// location to fetch from 100 | /// byte array corresponding to a pkm 101 | public static byte[]? GPSSDownload(long code, string Url = "flagbrew.org") 102 | { 103 | // code is returned as a long 104 | var json = DownloadString($"https://{Url}/api/v2/gpss/download/pokemon/{code}"); 105 | if (!json.Contains("\"pokemon\":\"")) 106 | return null; 107 | var b64 = json.Split("\"pokemon\":\"")[1].Split("\"")[0]; 108 | return System.Convert.FromBase64String(b64); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /PKHeX.Core.Enhancements/Enhancements/PKMPreview.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PKHeX.Core.Enhancements 7 | { 8 | public sealed class PKMPreview(PKM p, GameStrings strings) : EntitySummary(p, strings) 9 | { 10 | public static void ExportCSV(IEnumerable pklist, string path) 11 | { 12 | var sortedprev = pklist.OrderBy(p => p.Species).ToList(); 13 | // Todo: Complete function. POC 14 | var sb = new StringBuilder(); 15 | const string headers = 16 | "Nickname, Species, Nature, Gender, ESV, Hidden Power, Ability, Move 1, Move 2, Move 3, Move 4, Held Item, HP, ATK, DEF, SPA, SPD, SPE, Met Location, Egg Location, Ball, OT, Version, OT Language, Legal, Country, Region, 3DS Region, PID, EC, HP IVs, ATK IVs, DEF IVs, SPA IVs, SPD IVs, SPE IVs, EXP, Level, Markings, Handling Trainer, Met Level, Shiny, TID, SID, Friendship, Met Year, Met Month, Met Day"; 17 | sb.AppendLine(headers); 18 | foreach (PKMPreview p in sortedprev) 19 | { 20 | var country = "N/A"; 21 | var region = "N/A"; 22 | var DSRegion = "N/A"; 23 | if (p.pk is IGeoTrack gt) 24 | { 25 | country = gt.Country.ToString(); 26 | region = gt.Region.ToString(); 27 | DSRegion = gt.ConsoleRegion.ToString(); 28 | } 29 | 30 | var markings = "N/A"; 31 | switch (p.pk) 32 | { 33 | case IAppliedMarkings7 m7: 34 | markings = m7.MarkingValue.ToString(); 35 | break; 36 | case IAppliedMarkings4 m4: 37 | markings = m4.MarkingValue.ToString(); 38 | break; 39 | case IAppliedMarkings3 m3: 40 | markings = m3.MarkingValue.ToString(); 41 | break; 42 | } 43 | 44 | sb.AppendLine( 45 | string.Join( 46 | ",", 47 | p.Nickname, 48 | p.Species, 49 | p.Nature, 50 | p.Gender, 51 | p.ESV, 52 | p.HP_Type, 53 | p.Ability, 54 | p.Move1, 55 | p.Move2, 56 | p.Move3, 57 | p.Move4, 58 | p.HeldItem, 59 | p.HP, 60 | p.ATK, 61 | p.DEF, 62 | p.SPA, 63 | p.SPD, 64 | p.SPE, 65 | p.MetLoc, 66 | p.EggLoc, 67 | p.Ball, 68 | p.OT, 69 | p.Version, 70 | p.OTLang, 71 | p.Legal, 72 | country, 73 | region, 74 | DSRegion, 75 | p.PID, 76 | p.EC, 77 | p.IV_HP.ToString(), 78 | p.IV_ATK.ToString(), 79 | p.IV_DEF.ToString(), 80 | p.IV_SPA.ToString(), 81 | p.IV_SPD.ToString(), 82 | p.IV_SPE.ToString(), 83 | p.EXP.ToString(), 84 | p.Level.ToString(), 85 | markings, 86 | p.NotOT, 87 | p.MetLevel.ToString(), 88 | p.IsShiny.ToString(), 89 | p.TID16.ToString(), 90 | p.SID16.ToString(), 91 | p.Friendship.ToString(), 92 | p.MetYear.ToString(), 93 | p.MetMonth.ToString(), 94 | p.MetDay.ToString() 95 | ) 96 | ); 97 | } 98 | 99 | File.WriteAllText(Path.Combine(path, "boxdump.csv"), sb.ToString(), Encoding.UTF8); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /PKHeX.Core.Enhancements/PKHeX.Core.Enhancements.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PKHeX.Core.Enhancements/Teams/RentalTeam.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | 6 | namespace PKHeX.Core.Enhancements 7 | { 8 | /// 9 | /// PGL Website QR Rental Team 10 | /// 11 | public class RentalTeam 12 | { 13 | public readonly IReadOnlyList Team; 14 | public IReadOnlyList GlobalLinkID { get; } 15 | public IReadOnlyList UnknownData { get; } 16 | private static readonly SaveFile Dummy = new SAV7USUM(); 17 | 18 | public RentalTeam(byte[] data) 19 | { 20 | Debug.WriteLine(data.Length); 21 | Team = new[] 22 | { 23 | new QRPK7(data[..0x30]), 24 | new QRPK7(data[0x30..0x60]), 25 | new QRPK7(data[0x60..0x90]), 26 | new QRPK7(data[0x90..0xC0]), 27 | new QRPK7(data[0xC0..0xF0]), 28 | new QRPK7(data[0xF0..0x120]), 29 | }; 30 | 31 | Debug.WriteLine(string.Join(Environment.NewLine, ConvertedTeam.Select(z => z.Text))); 32 | 33 | GlobalLinkID = data[0x120..0x128]; 34 | UnknownData = data[0x128..]; 35 | } 36 | 37 | public IEnumerable ConvertedTeam => 38 | Team.Select(z => z.ConvertToPKM(Dummy)).Select(z => new ShowdownSet(z)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /PKHeX.Core.Enhancements/Teams/ShowdownTeamSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace PKHeX.Core.Enhancements 6 | { 7 | /// 8 | /// Full party worth of data, and page metadata. 9 | /// 10 | public class ShowdownTeamSet(string name, List sets, string format) 11 | { 12 | public readonly List Team = sets; 13 | public readonly string Format = format; 14 | public readonly string TeamName = name; 15 | 16 | public string Summary => $"{Format}: {TeamName}"; 17 | 18 | public static bool IsLineShowdownTeam(string line) => 19 | line.TrimStart().StartsWith("===") && line.TrimEnd().EndsWith("==="); 20 | 21 | public static List GetTeams(string paste) 22 | { 23 | string[] lines = paste.Split(new[] { "\n" }, StringSplitOptions.None); 24 | var result = new List(); 25 | for (int i = 0; i < lines.Length; i++) 26 | { 27 | var line = lines[i].Trim(); 28 | if (string.IsNullOrWhiteSpace(line)) 29 | continue; 30 | 31 | if (!IsLineShowdownTeam(line)) 32 | continue; 33 | 34 | var split = line.Split(new[] { "===" }, 0); 35 | if (split.Length != 3) 36 | continue; 37 | 38 | var split2 = split[1].Trim().Split(']'); 39 | if (split2.Length != 2) 40 | continue; 41 | 42 | var format = split2[0][1..]; 43 | var name = split2[1].TrimStart(); 44 | // find end 45 | 46 | int end = i + 1; 47 | while (end < lines.Length) 48 | { 49 | if (IsLineShowdownTeam(lines[end])) 50 | break; 51 | end++; 52 | } 53 | 54 | var teamlines = lines.Skip(i + 1).Take(end - i - 1); 55 | var sets = ShowdownParsing.GetShowdownSets(teamlines).ToList(); 56 | if (sets.Count == 0) 57 | continue; 58 | result.Add(new ShowdownTeamSet(name, sets, format)); 59 | 60 | i = end - 1; 61 | } 62 | return result; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /PKHeX.Core.Enhancements/Teams/ShowdownUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace PKHeX.Core.Enhancements 6 | { 7 | /// 8 | /// Logic for handling data. 9 | /// 10 | public static class ShowdownUtil 11 | { 12 | /// 13 | /// Checks whether a paste is a showdown team backup 14 | /// 15 | /// paste to check 16 | /// Returns bool 17 | public static bool IsTeamBackup(string paste) => paste.StartsWith("==="); 18 | 19 | // TODO: Update form list with possibly invalid Calyrex forms (non battle)?? 20 | private static string[] InvalidFormes => 21 | new[] 22 | { 23 | "Primal", 24 | "Busted", 25 | "Crowned", 26 | "Noice", 27 | "Gulping", 28 | "Gorging", 29 | "Zen", 30 | "Galar-Zen", 31 | "Hangry", 32 | "Complete" 33 | }; 34 | 35 | public static bool IsInvalidForm(string form) => 36 | form.Contains("Mega") || InvalidFormes.Contains(form); 37 | 38 | /// 39 | /// A method to get a list of ShowdownSet(s) from a string paste 40 | /// Needs to be extended to hold several teams 41 | /// 42 | /// 43 | public static List ShowdownSets(string paste) 44 | { 45 | paste = paste.Trim(); // Remove White Spaces 46 | if (IsTeamBackup(paste)) 47 | return ShowdownTeamSet.GetTeams(paste).SelectMany(z => z.Team).ToList(); 48 | var lines = paste.Split(new[] { "\n" }, StringSplitOptions.None); 49 | return ShowdownParsing.GetShowdownSets(lines).ToList(); 50 | } 51 | 52 | /// 53 | /// Checks the input text is a showdown set or not 54 | /// 55 | /// Concatenated showdown strings 56 | /// boolean of the summary 57 | public static bool IsTextShowdownData(string source) 58 | { 59 | source = source.Trim(); 60 | if (IsTeamBackup(source)) 61 | return true; 62 | string[] stringSeparators = ["\n\r"]; 63 | 64 | var result = source.Split(stringSeparators, StringSplitOptions.None); 65 | return new ShowdownSet(result[0]).Species > 0; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /PKHeX.Core.Enhancements/Teams/TeamPasteInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PKHeX.Core.Enhancements 4 | { 5 | /// 6 | /// Paste Details originating from a common pasting website URL. 7 | /// 8 | public class TeamPasteInfo 9 | { 10 | public readonly bool Valid; 11 | public readonly PasteSource Source; 12 | public readonly string URL; 13 | public readonly string Sets = string.Empty; 14 | 15 | public string Summary => 16 | $"{Source} data:\nTitle: {Title}\nAuthor: {Author}\nDescription: {Description}"; 17 | 18 | public string Author { get; private set; } = "Showdown Paste"; 19 | public string Title { get; private set; } = "Pokémon Trainer"; 20 | public string Description { get; private set; } = "A Mysterious Paste"; 21 | 22 | public enum PasteSource 23 | { 24 | None, 25 | Pastebin, 26 | PokePaste, 27 | } 28 | 29 | private void GetFromPokePaste(string url) 30 | { 31 | var htmldoc = NetUtil.GetPageText(url); 32 | var pastedata = htmldoc.Split(new[] { "" }, 34 | StringSplitOptions.None 35 | )[0]; 36 | 37 | var title = pastedata.Split(new[] { "

" }, StringSplitOptions.None); 38 | if (title.Length > 1) 39 | Title = GetVal(title[1]); 40 | 41 | var auth = pastedata.Split(new[] { "

 by" }, StringSplitOptions.None); 42 | if (auth.Length > 1) 43 | Author = GetVal(auth[1]); 44 | 45 | var desc = pastedata.Split(new[] { "

" }, StringSplitOptions.None); 46 | if (desc.Length > 1) 47 | Description = GetVal(desc[1]); 48 | } 49 | 50 | private void GetFromPasteBin(string url) 51 | { 52 | var page = NetUtil.GetPageText(url); 53 | 54 | var title = page.Split(new[] { "

" }, StringSplitOptions.None)[1]; 55 | Title = GetVal(title); 56 | 57 | var auth = page.Split(new[] { "
" }, StringSplitOptions.None)[ 58 | 1 59 | ].Split('>'); 60 | Author = GetVal(auth[0]); 61 | 62 | var datestr = auth[3]; 63 | var date = GetVal(datestr); 64 | Description = $"Pastebin created on: {date}"; 65 | } 66 | 67 | private static PasteSource GetSource(string url) 68 | { 69 | if (url.Contains("pokepast.es/")) 70 | return PasteSource.PokePaste; 71 | if (url.Contains("pastebin.com/")) 72 | return PasteSource.Pastebin; 73 | return PasteSource.None; 74 | } 75 | 76 | private string GetRawURL(string url) 77 | { 78 | return Source switch 79 | { 80 | PasteSource.PokePaste => url.EndsWith("/raw") ? url : url + "/raw", 81 | PasteSource.Pastebin 82 | => url.Contains("/raw/") 83 | ? url 84 | : url.Replace("pastebin.com/", "pastebin.com/raw/"), 85 | _ => url, // This should never happen 86 | }; 87 | } 88 | 89 | private void LoadMetadata() 90 | { 91 | // Passed URL must be non raw 92 | switch (Source) 93 | { 94 | case PasteSource.PokePaste: 95 | { 96 | var url = URL.Replace("/raw", ""); 97 | GetFromPokePaste(url); 98 | return; 99 | } 100 | case PasteSource.Pastebin: 101 | { 102 | var url = URL.Replace("/raw/", "/"); 103 | GetFromPasteBin(url); 104 | return; 105 | } 106 | default: 107 | return; // This should never happen 108 | } 109 | } 110 | 111 | private static string GetVal(string s, char c = '<') => s.Split(c)[0].Trim(); 112 | 113 | public TeamPasteInfo(string url) 114 | { 115 | URL = url; 116 | var isUri = Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute); 117 | if (!isUri) 118 | return; 119 | Source = GetSource(url); 120 | if (Source == PasteSource.None) 121 | return; 122 | 123 | url = GetRawURL(url); 124 | Sets = NetUtil.GetPageText(url).Trim(); 125 | LoadMetadata(); 126 | Valid = true; 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/BlockData.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.Injection 2 | { 3 | public record BlockData 4 | { 5 | public string Name { get; set; } = string.Empty; 6 | public string Display { get; set; } = string.Empty; 7 | public uint SCBKey { get; set; } 8 | public string Pointer { get; set; } = string.Empty; 9 | public ulong Offset { get; set; } 10 | public SCTypeCode Type { get; set; } = SCTypeCode.None; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/BotController/Controllers/NTRClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace PKHeX.Core.Injection 5 | { 6 | public class NTRClient : ICommunicator 7 | { 8 | private string IP = "192.168.1.106"; 9 | private int Port = 8000; 10 | private static readonly NTR clientNTR = new(); 11 | 12 | private const int timeout = 10; 13 | private bool Connected; 14 | 15 | private readonly object _sync = new(); 16 | private byte[]? _lastMemoryRead; 17 | 18 | public void Connect() 19 | { 20 | clientNTR.Connect(IP, Port); 21 | if (clientNTR.IsConnected) 22 | Connected = true; 23 | } 24 | 25 | bool ICommunicator.Connected 26 | { 27 | get => Connected; 28 | set => Connected = value; 29 | } 30 | int ICommunicator.Port 31 | { 32 | get => Port; 33 | set => Port = value; 34 | } 35 | string ICommunicator.IP 36 | { 37 | get => IP; 38 | set => IP = value; 39 | } 40 | 41 | public void Disconnect() 42 | { 43 | lock (_sync) 44 | { 45 | clientNTR.Disconnect(); 46 | Connected = false; 47 | } 48 | } 49 | 50 | private void HandleMemoryRead(object argsObj) 51 | { 52 | DataReadyWaiting args = (DataReadyWaiting)argsObj; 53 | _lastMemoryRead = args.Data; 54 | } 55 | 56 | public byte[] ReadBytes(ulong offset, int length) 57 | { 58 | lock (_sync) 59 | { 60 | if (!Connected) 61 | Connect(); 62 | 63 | WriteLastLog(""); 64 | DataReadyWaiting myArgs = new(new byte[length], HandleMemoryRead, null); 65 | while (clientNTR.PID == -1) 66 | { 67 | Thread.Sleep(10); 68 | } 69 | clientNTR.AddWaitingForData( 70 | clientNTR.Data((uint)offset, (uint)length, clientNTR.PID), 71 | myArgs 72 | ); 73 | 74 | for (int readcount = 0; readcount < timeout * 100; readcount++) 75 | { 76 | Thread.Sleep(10); 77 | if (CompareLastLog("finished")) 78 | break; 79 | } 80 | 81 | byte[] result = _lastMemoryRead ?? []; 82 | _lastMemoryRead = null; 83 | return result; 84 | } 85 | } 86 | 87 | private static void WriteLastLog(string str) => clientNTR.Lastlog = str; 88 | 89 | private static bool CompareLastLog(string str) => clientNTR.Lastlog.Contains(str); 90 | 91 | public void WriteBytes(ReadOnlySpan data, ulong offset) 92 | { 93 | lock (_sync) 94 | { 95 | if (!Connected) 96 | Connect(); 97 | while (clientNTR.PID == -1) 98 | { 99 | Thread.Sleep(10); 100 | } 101 | clientNTR.Write((uint)offset, data, clientNTR.PID); 102 | int waittimeout; 103 | for (waittimeout = 0; waittimeout < timeout * 100; waittimeout++) 104 | { 105 | WriteLastLog(""); 106 | Thread.Sleep(10); 107 | if (CompareLastLog("finished")) 108 | break; 109 | } 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/BotController/Decoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PKHeX.Core.Injection 4 | { 5 | public static class Decoder 6 | { 7 | private static bool IsNum(char c) => (uint)(c - '0') <= 9; 8 | 9 | private static bool IsHexUpper(char c) => (uint)(c - 'A') <= 5; 10 | 11 | public static byte[] ConvertHexByteStringToBytes(byte[] bytes) 12 | { 13 | var dest = new byte[bytes.Length / 2]; 14 | for (int i = 0; i < dest.Length; i++) 15 | { 16 | var _0 = (char)bytes[(i * 2) + 0]; 17 | var _1 = (char)bytes[(i * 2) + 1]; 18 | dest[i] = DecodeTuple(_0, _1); 19 | } 20 | return dest; 21 | } 22 | 23 | public static byte[] StringToByteArray(string hex) 24 | { 25 | int NumberChars = hex.Length; 26 | byte[] bytes = new byte[NumberChars / 2]; 27 | for (int i = 0; i < NumberChars; i += 2) 28 | bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); 29 | return bytes; 30 | } 31 | 32 | private static byte DecodeTuple(char _0, char _1) 33 | { 34 | byte result; 35 | if (IsNum(_0)) 36 | result = (byte)((_0 - '0') << 4); 37 | else if (IsHexUpper(_0)) 38 | result = (byte)((_0 - 'A' + 10) << 4); 39 | else 40 | throw new ArgumentOutOfRangeException(nameof(_0)); 41 | 42 | if (IsNum(_1)) 43 | result |= (byte)(_1 - '0'); 44 | else if (IsHexUpper(_1)) 45 | result |= (byte)(_1 - 'A' + 10); 46 | else 47 | throw new ArgumentOutOfRangeException(nameof(_1)); 48 | return result; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/BotController/ICommunicator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace PKHeX.Core.Injection 5 | { 6 | public enum InjectorCommunicationType 7 | { 8 | SocketNetwork = 0, 9 | USB = 1, 10 | } 11 | 12 | public interface ICommunicator 13 | { 14 | void Connect(); 15 | void Disconnect(); 16 | void WriteBytes(ReadOnlySpan data, ulong offset); 17 | byte[] ReadBytes(ulong offset, int length); 18 | bool Connected { get; set; } 19 | int Port { get; set; } 20 | string IP { get; set; } 21 | } 22 | 23 | public interface ICommunicatorNX : ICommunicator 24 | { 25 | InjectorCommunicationType Protocol { get; set; } 26 | byte[] ReadBytesMain(ulong offset, int length); 27 | byte[] ReadBytesAbsolute(ulong offset, int length); 28 | ulong GetHeapBase(); 29 | string GetBotbaseVersion(); 30 | string GetTitleID(); 31 | string GetGameInfo(string info); 32 | bool IsProgramRunning(ulong pid); 33 | void WriteBytesMain(ReadOnlySpan data, ulong offset); 34 | void WriteBytesAbsolute(ReadOnlySpan data, ulong offset); 35 | byte[] ReadBytesAbsoluteMulti(Dictionary offsets); 36 | } 37 | 38 | public interface IPokeBlocks : ICommunicator; 39 | } 40 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/BotController/LiveHexController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PKHeX.Core.Injection 4 | { 5 | public class LiveHeXController 6 | { 7 | private readonly ISaveFileProvider SAV; 8 | public readonly IPKMView Editor; 9 | public PokeSysBotMini Bot; 10 | 11 | public LiveHeXController( 12 | ISaveFileProvider boxes, 13 | IPKMView editor, 14 | InjectorCommunicationType ict, 15 | bool useCache = false 16 | ) 17 | { 18 | SAV = boxes; 19 | Editor = editor; 20 | var ValidVers = RamOffsets.GetValidVersions(boxes.SAV); 21 | var com = RamOffsets.GetCommunicator(SAV.SAV, ict); 22 | Bot = new PokeSysBotMini(ValidVers[0], com, useCache); 23 | } 24 | 25 | public void ChangeBox(int box) 26 | { 27 | if (!Bot.Connected) 28 | return; 29 | 30 | var sav = SAV.SAV; 31 | if ((uint)box >= sav.BoxCount) 32 | return; 33 | 34 | ReadBox(box); 35 | } 36 | 37 | public void ReadBox(int box) 38 | { 39 | var sav = SAV.SAV; 40 | var len = 41 | sav.BoxSlotCount 42 | * (RamOffsets.GetSlotSize(Bot.Version) + RamOffsets.GetGapSize(Bot.Version)); 43 | var data = Bot.ReadBox(box, len).AsSpan(); 44 | sav.SetBoxBinary(data, box); 45 | SAV.ReloadSlots(); 46 | } 47 | 48 | public void WriteBox(int box) 49 | { 50 | var boxData = SAV.SAV.GetBoxBinary(box); 51 | Bot.SendBox(boxData, box); 52 | } 53 | 54 | public void WriteActiveSlot(int box, int slot) 55 | { 56 | var pkm = Editor.PreparePKM(); 57 | pkm.ResetPartyStats(); 58 | var data = RamOffsets.WriteBoxData(Bot.Version) 59 | ? pkm.EncryptedBoxData 60 | : pkm.EncryptedPartyData; 61 | Bot.SendSlot(data, box, slot); 62 | } 63 | 64 | public void ReadActiveSlot(int box, int slot) 65 | { 66 | var data = Bot.ReadSlot(box, slot); 67 | var pkm = SAV.SAV.GetDecryptedPKM(data); 68 | Editor.PopulateFields(pkm); 69 | } 70 | 71 | public bool ReadOffset(ulong offset, RWMethod method = RWMethod.Heap) 72 | { 73 | var data = ReadData(offset, method); 74 | var pkm = SAV.SAV.GetDecryptedPKM(data); 75 | 76 | // Since data might not actually exist at the user-specified offset, double check that the pkm data is valid. 77 | if (!pkm.ChecksumValid) 78 | return false; 79 | 80 | Editor.PopulateFields(pkm); 81 | return true; 82 | } 83 | 84 | private byte[] ReadData(ulong offset, RWMethod method) 85 | { 86 | if (Bot.com is not ICommunicatorNX nx) 87 | return Bot.ReadOffset(offset); 88 | return method switch 89 | { 90 | RWMethod.Heap => Bot.ReadOffset(offset), 91 | RWMethod.Main => nx.ReadBytesMain(offset, Bot.SlotSize), 92 | RWMethod.Absolute => nx.ReadBytesAbsolute(offset, Bot.SlotSize), 93 | _ => Bot.ReadOffset(offset), 94 | }; 95 | } 96 | 97 | public byte[] ReadRAM(ulong offset, int size) => Bot.com.ReadBytes(offset, size); 98 | 99 | public void WriteRAM(ulong offset, byte[] data) => Bot.com.WriteBytes(data, offset); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/BotController/PokeSysBotMini.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace PKHeX.Core.Injection 5 | { 6 | public class PokeSysBotMini(LiveHeXVersion lv, ICommunicator communicator, bool useCache) 7 | : InjectionBase(lv, useCache) 8 | { 9 | public readonly long BoxStart = RamOffsets.GetB1S1Offset(lv); 10 | public readonly int SlotSize = RamOffsets.GetSlotSize(lv); 11 | public readonly int SlotCount = RamOffsets.GetSlotCount(lv); 12 | public readonly int GapSize = RamOffsets.GetGapSize(lv); 13 | public readonly LiveHeXVersion Version = lv; 14 | public readonly ICommunicator com = communicator; 15 | public readonly InjectionBase Injector = GetInjector(lv, useCache); 16 | public bool Connected => com.Connected; 17 | 18 | public ulong GetSlotOffset(int box, int slot) => 19 | GetBoxOffset(box) + (ulong)((SlotSize + GapSize) * slot); 20 | 21 | public ulong GetBoxOffset(int box) => 22 | (ulong)BoxStart + (ulong)((SlotSize + GapSize) * SlotCount * box); 23 | 24 | public byte[] ReadSlot(int box, int slot) => Injector.ReadSlot(this, box, slot); 25 | 26 | public byte[] ReadBox(int box, int len) 27 | { 28 | var allpkm = new List(); 29 | return Injector.ReadBox(this, box, len, allpkm); 30 | } 31 | 32 | public void SendSlot(byte[] data, int box, int slot) => 33 | Injector.SendSlot(this, data, box, slot); 34 | 35 | public void SendBox(byte[] boxData, int box) 36 | { 37 | ReadOnlySpan bytes = boxData; 38 | byte[][] pkmData = bytes.Split(SlotSize); 39 | for (int i = 0; i < SlotCount; i++) 40 | SendSlot(pkmData[i], box, i); 41 | 42 | Injector.SendBox(this, boxData, box); 43 | } 44 | 45 | public byte[] ReadOffset(ulong offset) => com.ReadBytes(offset, SlotSize); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/Enums/LiveHeXValidation.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.Injection 2 | { 3 | public enum LiveHeXValidation 4 | { 5 | None = 0, 6 | Botbase = 1, 7 | BlankSAV = 2, 8 | GameVersion = 3, 9 | RAMShift = 4, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/Enums/LiveHeXVersion.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.Injection 2 | { 3 | public enum LiveHeXVersion 4 | { 5 | Unknown = -1, 6 | XY_v150 = 0, 7 | ORAS_v140 = 1, 8 | SM_v120 = 2, 9 | US_v120 = 3, 10 | UM_v120 = 4, 11 | 12 | SWSH_v111 = 5, 13 | SWSH_v121 = 6, 14 | SWSH_v132 = 7, 15 | 16 | LGPE_v102 = 8, 17 | 18 | SP_v100 = 9, 19 | SP_v110 = 10, 20 | SP_v111 = 11, 21 | SP_v130 = 12, 22 | 23 | BD_v100 = 13, 24 | BD_v110 = 14, 25 | BD_v111 = 15, 26 | BD_v130 = 16, 27 | 28 | BDSP_v112 = 17, 29 | BDSP_v113 = 18, 30 | BDSP_v120 = 19, 31 | 32 | LA_v100 = 20, 33 | LA_v101 = 21, 34 | LA_v102 = 22, 35 | LA_v111 = 23, 36 | 37 | SV_v101 = 24, 38 | SV_v110 = 25, 39 | SV_v120 = 26, 40 | SV_v130 = 27, 41 | SV_v131 = 28, 42 | SV_v132 = 29, 43 | SV_v201 = 30, 44 | SV_v202 = 31, 45 | SV_v300 = 32, 46 | SV_v301 = 33, 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/Enums/SwitchButton.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.Injection 2 | { 3 | /// 4 | /// Controller Buttons 5 | /// 6 | public enum SwitchButton 7 | { 8 | A, 9 | B, 10 | X, 11 | Y, 12 | RSTICK, 13 | LSTICK, 14 | L, 15 | R, 16 | ZL, 17 | ZR, 18 | PLUS, 19 | MINUS, 20 | DUP, 21 | DDOWN, 22 | DLEFT, 23 | DRIGHT, 24 | HOME, 25 | CAPTURE, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/Enums/SwitchStick.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.Injection 2 | { 3 | /// 4 | /// Controller Stick differentiation 5 | /// 6 | public enum SwitchStick 7 | { 8 | LEFT, 9 | RIGHT, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/LiveHeXBlockClasses/ICustomBlock.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.Injection 2 | { 3 | public interface ICustomBlock 4 | { 5 | // static byte[]? Getter(PokeSysBotMini psb); 6 | void Setter(PokeSysBotMini psb, byte[] data); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/LiveHeXOffsets/LiveHeXBlocks.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.Injection 2 | { 3 | public static class LiveHeXBlocks 4 | { 5 | /// 6 | /// Check if a special form needs to be open to handle the block 7 | /// 8 | /// saveblock 9 | /// LiveHeX version being edited 10 | /// string value of the form to open 11 | /// Boolean indicating if a special form needs to be opened 12 | public static bool IsSpecialBlock(this string block, PokeSysBotMini psb, out string? value) 13 | { 14 | return psb.Injector.SpecialBlocks.TryGetValue(block, out value); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/LiveHeXOffsets/Offsets8.cs: -------------------------------------------------------------------------------- 1 | namespace PKHeX.Core.Injection 2 | { 3 | public class Offsets8 4 | { 5 | public uint BoxInfo; 6 | public uint PartyInfo; 7 | public uint Items; 8 | public uint MyStatus; 9 | public uint Misc; 10 | public uint KZukan; // SCBlocks 11 | public uint KZukanR1; // SCBlocks 12 | public uint KZukanR2; // SCBlocks 13 | public uint KRentalTeam1; // SCBlocks 14 | 15 | // public uint KRentalTeam2; // SCBlocks 16 | public uint KRentalTeam3; // SCBlocks 17 | public uint KRentalTeam4; // SCBlocks 18 | public uint KRentalTeam5; // SCBlocks 19 | public uint KRentalTeam6; // SCBlocks 20 | public uint BoxLayout; 21 | public uint Played; 22 | public uint Fused; 23 | public uint Daycare; 24 | public uint Records; 25 | public uint TrainerCard; 26 | public uint Fashion; 27 | public uint Raid; 28 | public uint RaidArmor; 29 | public uint RaidCrown; 30 | public uint TitleScreen; 31 | public uint TeamIndexes; 32 | public uint FameTime; 33 | 34 | /// 35 | /// Rigel2 offsets in the ram that correspond to the same data that is found in the saveblock 36 | /// 37 | public static readonly Offsets8 Rigel2 = 38 | new() 39 | { 40 | MyStatus = 0x45068F18, 41 | Items = 0x45067A98, 42 | Raid = 0x450C8A70, 43 | RaidArmor = 0x450C94D8, 44 | RaidCrown = 0x450C9F40, 45 | Misc = 0x45072DF0, 46 | TrainerCard = 0x45127098, 47 | Fashion = 0x450748E8, 48 | KZukan = 0x45069120, 49 | KZukanR1 = 0x4506DC20, 50 | KZukanR2 = 0x450703B0, 51 | }; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/PKHeX.Core.Injection.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/PointerCache/PointerCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PKHeX.Core.Injection 4 | { 5 | public abstract class PointerCache(LiveHeXVersion version, bool useCache = false) 6 | { 7 | private readonly Dictionary> Cache = []; 8 | 9 | public ulong GetCachedPointer(ICommunicatorNX com, string ptr, bool relative = true) 10 | { 11 | ulong pointer = 0; 12 | bool hasEntry = Cache.TryGetValue(version, out var cache); 13 | bool hasPointer = cache is not null && cache.TryGetValue(ptr, out pointer); 14 | if (hasPointer && useCache) 15 | return pointer; 16 | 17 | pointer = com.GetPointerAddress(ptr, relative); 18 | if (!useCache) 19 | return pointer; 20 | 21 | if (!hasEntry) 22 | Cache.Add(version, new() { { ptr, pointer } }); 23 | else 24 | Cache[version].Add(ptr, pointer); 25 | 26 | return pointer; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/Protocols/LPLGPE.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace PKHeX.Core.Injection 6 | { 7 | public class LPLGPE(LiveHeXVersion lv, bool useCache) : InjectionBase(lv, useCache) 8 | { 9 | private static readonly LiveHeXVersion[] SupportedVersions = [LiveHeXVersion.LGPE_v102]; 10 | 11 | public static LiveHeXVersion[] GetVersions() => SupportedVersions; 12 | 13 | public override byte[] ReadBox(PokeSysBotMini psb, int box, int len, List allpkm) 14 | { 15 | var bytes = psb.com.ReadBytes(psb.GetBoxOffset(box), len); 16 | if (psb.GapSize == 0) 17 | return bytes; 18 | var currofs = 0; 19 | for (int i = 0; i < psb.SlotCount; i++) 20 | { 21 | var StoredLength = psb.SlotSize - 0x1C; 22 | var stored = bytes.AsSpan(currofs, psb.SlotSize).ToArray(); 23 | var party = bytes.AsSpan(StoredLength + 0x70, 0x1C).ToArray(); 24 | allpkm.Add([.. stored, .. party]); 25 | currofs += psb.SlotSize + psb.GapSize; 26 | } 27 | return [..allpkm.SelectMany(z => z)]; 28 | } 29 | 30 | public override byte[] ReadSlot(PokeSysBotMini psb, int box, int slot) 31 | { 32 | ReadOnlySpan bytes = psb.com.ReadBytes(psb.GetSlotOffset(box, slot), psb.SlotSize + psb.GapSize); 33 | var StoredLength = psb.SlotSize - 0x1C; 34 | var stored = bytes[..StoredLength]; 35 | var party = bytes.Slice(StoredLength + 0x70, 0x1C); 36 | return [..stored, ..party]; 37 | } 38 | 39 | public override void SendSlot(PokeSysBotMini psb, byte[] data, int box, int slot) 40 | { 41 | var slotofs = psb.GetSlotOffset(box, slot); 42 | var StoredLength = psb.SlotSize - 0x1C; 43 | psb.com.WriteBytes(data[..StoredLength], slotofs); 44 | psb.com.WriteBytes(data.AsSpan(StoredLength).ToArray(), slotofs + (ulong)StoredLength + 0x70); 45 | } 46 | 47 | public override void SendBox(PokeSysBotMini psb, byte[] boxData, int box) 48 | { 49 | ReadOnlySpan bytes = boxData; 50 | byte[][] pkmData = bytes.Split(psb.SlotSize); 51 | for (int i = 0; i < psb.SlotCount; i++) 52 | SendSlot(psb, pkmData[i], box, i); 53 | } 54 | 55 | public static readonly Func GetTrainerData = psb => 56 | { 57 | var lv = psb.Version; 58 | var ofs = RamOffsets.GetTrainerBlockOffset(lv); 59 | var size = RamOffsets.GetTrainerBlockSize(lv); 60 | if (size <= 0 || ofs == 0) 61 | return null; 62 | var data = psb.com.ReadBytes(ofs, size); 63 | return data; 64 | }; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/Util/ArrayUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace PKHeX.Core.Injection 6 | { 7 | /// 8 | /// Array reusable logic 9 | /// 10 | public static class ArrayUtil 11 | { 12 | internal static T[] ConcatAll(params T[][] arr) 13 | { 14 | int len = 0; 15 | foreach (var a in arr) 16 | len += a.Length; 17 | 18 | var result = new T[len]; 19 | 20 | int ctr = 0; 21 | foreach (var a in arr) 22 | { 23 | a.CopyTo(result, ctr); 24 | ctr += a.Length; 25 | } 26 | 27 | return result; 28 | } 29 | 30 | public static T[][] Split(this ReadOnlySpan data, int size) 31 | { 32 | var result = new T[data.Length / size][]; 33 | for (int i = 0; i < data.Length; i += size) 34 | result[i / size] = data.Slice(i, size).ToArray(); 35 | return result; 36 | } 37 | 38 | public static IEnumerable EnumerateSplit(T[] bin, int size, int start = 0) 39 | { 40 | for (int i = start; i < bin.Length; i += size) 41 | yield return bin.AsSpan(i, size).ToArray(); 42 | } 43 | 44 | internal static T[] ConcatAll(T[] arr1, T[] arr2) 45 | { 46 | int len = arr1.Length + arr2.Length; 47 | var result = new T[len]; 48 | arr1.CopyTo(result, 0); 49 | arr2.CopyTo(result, arr1.Length); 50 | return result; 51 | } 52 | 53 | internal static T[] ConcatAll(T[] arr1, T[] arr2, T[] arr3) 54 | { 55 | int len = arr1.Length + arr2.Length + arr3.Length; 56 | var result = new T[len]; 57 | arr1.CopyTo(result, 0); 58 | arr2.CopyTo(result, arr1.Length); 59 | arr3.CopyTo(result, arr1.Length + arr2.Length); 60 | return result; 61 | } 62 | 63 | internal static T? ToClass(this byte[] bytes) 64 | where T : class 65 | { 66 | var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 67 | try 68 | { 69 | return Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)) as T; 70 | } 71 | finally 72 | { 73 | handle.Free(); 74 | } 75 | } 76 | 77 | internal static byte[] ToBytesClass(this T obj) 78 | where T : class 79 | { 80 | int size = Marshal.SizeOf(obj); 81 | byte[] arr = new byte[size]; 82 | 83 | IntPtr ptr = Marshal.AllocHGlobal(size); 84 | Marshal.StructureToPtr(obj, ptr, true); 85 | Marshal.Copy(ptr, arr, 0, size); 86 | Marshal.FreeHGlobal(ptr); 87 | return arr; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /PKHeX.Core.Injection/Util/InjectionUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace PKHeX.Core.Injection 5 | { 6 | public static class InjectionUtil 7 | { 8 | public const ulong INVALID_PTR = 0; 9 | 10 | public static ulong GetPointerAddress( 11 | this ICommunicatorNX sb, 12 | string ptr, 13 | bool heapRelative = true 14 | ) 15 | { 16 | if (string.IsNullOrWhiteSpace(ptr) || ptr.IndexOfAny(['-', '/', '*']) != -1) 17 | return INVALID_PTR; 18 | while (ptr.Contains("]]")) 19 | ptr = ptr.Replace("]]", "]+0]"); 20 | uint finadd = 0; 21 | if (!ptr.EndsWith(']')) 22 | { 23 | finadd = Util.GetHexValue(ptr.Split('+').Last()); 24 | ptr = ptr[..ptr.LastIndexOf('+')]; 25 | } 26 | var jumps = ptr.Replace("main", "") 27 | .Replace("[", "") 28 | .Replace("]", "") 29 | .Split('+', StringSplitOptions.RemoveEmptyEntries); 30 | if (jumps.Length == 0) 31 | return INVALID_PTR; 32 | 33 | var initaddress = Util.GetHexValue(jumps[0].Trim()); 34 | ulong address = BitConverter.ToUInt64(sb.ReadBytesMain(initaddress, 0x8), 0); 35 | foreach (var j in jumps) 36 | { 37 | var val = Util.GetHexValue(j.Trim()); 38 | if (val == initaddress) 39 | continue; 40 | address = BitConverter.ToUInt64(sb.ReadBytesAbsolute(address + val, 0x8), 0); 41 | } 42 | address += finadd; 43 | if (heapRelative) 44 | { 45 | ulong heap = sb.GetHeapBase(); 46 | address -= heap; 47 | } 48 | return address; 49 | } 50 | 51 | public static string ExtendPointer(this string pointer, params uint[] jumps) 52 | { 53 | foreach (var jump in jumps) 54 | pointer = $"[{pointer}]+{jump:X}"; 55 | return pointer; 56 | } 57 | 58 | public static ulong SearchSaveKey(this PokeSysBotMini psb, string saveblocks, uint key) 59 | { 60 | if (psb.com is not ICommunicatorNX nx) 61 | return 0; 62 | 63 | var ptr = psb.GetCachedPointer(nx, saveblocks, false); 64 | var dt = nx.ReadBytesAbsolute(ptr + 8, 16); 65 | var start = BitConverter.ToUInt64(dt.AsSpan()[..8]); 66 | var end = BitConverter.ToUInt64(dt.AsSpan()[8..]); 67 | var size = (ulong)GetBlockSizeSV(psb.Version); 68 | 69 | while (start < end) 70 | { 71 | var block_ct = (end - start) / size; 72 | var mid = start + ((block_ct >> 1) * size); 73 | var found = BitConverter.ToUInt32(nx.ReadBytesAbsolute(mid, 4)); 74 | if (found == key) 75 | return mid; 76 | if (found >= key) 77 | end = mid; 78 | else 79 | start = mid + size; 80 | } 81 | return 0; 82 | } 83 | 84 | private static int GetBlockSizeSV(LiveHeXVersion version) => 85 | version switch 86 | { 87 | >= LiveHeXVersion.SV_v130 => 48, // Thanks, santacrab! 88 | _ => 32, 89 | }; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # .NET Desktop 2 | # Build and run tests for .NET Desktop or Windows classic desktop solutions. 3 | # Add steps that publish symbols, save build artifacts, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net 5 | 6 | trigger: 7 | - master 8 | 9 | pool: 10 | vmImage: 'windows-2022' 11 | 12 | variables: 13 | solution: '$(Build.SourcesDirectory)/PKHeX-Plugins.sln' 14 | buildPlatform: 'Any CPU' 15 | buildConfiguration: 'Release' 16 | 17 | steps: 18 | - task: UseDotNet@2 19 | displayName: Use .NET 8.0 20 | inputs: 21 | packageType: 'sdk' 22 | version: '8.0.x' 23 | 24 | - task: NuGetToolInstaller@1 25 | inputs: 26 | versionSpec: '>=6.4.0' 27 | checkLatest: true 28 | 29 | - task: NuGetCommand@2 30 | inputs: 31 | restoreSolution: '$(solution)' 32 | 33 | - powershell: | 34 | git clone -q --depth=5 --branch=master https://github.com/kwsch/PKHeX.git $(Build.SourcesDirectory)/PKHeX 35 | 36 | - task: NuGetCommand@2 37 | inputs: 38 | command: 'restore' 39 | restoreSolution: '$(Build.SourcesDirectory)/PKHeX/PKHeX.sln' 40 | noCache: true 41 | 42 | - task: MSBuild@1 43 | inputs: 44 | solution: '$(Build.SourcesDirectory)/PKHeX/PKHeX.Core/PKHeX.Core.csproj' 45 | platform: '$(buildPlatform)' 46 | configuration: '$(buildConfiguration)' 47 | createLogFile: true 48 | 49 | - powershell: | 50 | $nugetver = (Get-ChildItem "$(UserProfile)/.nuget/packages/pkhex.core" | Sort-Object -Property LastWriteTime -Descending)[0].Name 51 | Copy-Item "$(Build.SourcesDirectory)\pkhex\PKHeX.Core\bin\Any CPU\Release\net8.0\PKHeX.Core.dll" "$(UserProfile)\.nuget\packages\pkhex.core\$nugetver\lib\net8.0" 52 | 53 | - task: VSBuild@1 54 | inputs: 55 | solution: '$(solution)' 56 | platform: '$(buildPlatform)' 57 | configuration: '$(buildConfiguration)' 58 | createLogFile: true 59 | 60 | - task: CmdLine@2 61 | inputs: 62 | script: | 63 | mkdir bin 64 | xcopy $(Agent.BuildDirectory)\s\AutoLegalityMod\bin\Release\net8.0-windows\AutoModPlugins.dll $(Agent.BuildDirectory)\s\bin 65 | 66 | - task: PublishBuildArtifacts@1 67 | inputs: 68 | PathtoPublish: '$(Agent.BuildDirectory)\s\bin' 69 | ArtifactName: 'PKHeX-Plugins' 70 | publishLocation: 'Container' 71 | -------------------------------------------------------------------------------- /setup_bleedingedge.ps1: -------------------------------------------------------------------------------- 1 | # Setting the TLS protocol to 1.2 instead of the default 1.0 2 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 3 | 4 | # Powershell script to download PKHeX and Plugins (latest) 5 | Write-Host "PKHeX and PKHeX-Plugins downloader (latest releases)" 6 | Write-Host "Please report any issues with this setup file via GitHub issues at https://github.com/architdate/PKHeX-Plugins/issues" 7 | Write-Host "" 8 | Write-Host "" 9 | 10 | # check network path locations 11 | $networkPaths = @("OneDrive", "Dropbox", "Mega") 12 | for ($i=0; $i -lt $networkPaths.Length; $i++) { 13 | $path = $networkPaths[$i] 14 | $currDir = Get-Location 15 | if ($currDir.Path.Contains($path)) { 16 | Write-Host "WARNING: $path is detected on your system. Please move the setup file to a different location before running the program." 17 | Read-Host "Press Enter to exit" 18 | exit 19 | } 20 | } 21 | 22 | # set headers 23 | $headers = @{ 24 | "method"="GET" 25 | "authority"="projectpokemon.org" 26 | "scheme"="https" 27 | "path"="/home/files/file/1-pkhex/" 28 | "cache-control"="max-age=0" 29 | "upgrade-insecure-requests"="1" 30 | "user-agent"="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36" 31 | "accept"="text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" 32 | "sec-fetch-site"="same-origin" 33 | "sec-fetch-mode"="navigate" 34 | "sec-fetch-user"="?1" 35 | "sec-fetch-dest"="document" 36 | "referer"="https://projectpokemon.org/home/files/" 37 | "accept-encoding"="gzip, deflate, br" 38 | "accept-language"="en-US,en;q=0.9" 39 | }; 40 | 41 | # close any open instances of PKHeX that may prevent updating the file 42 | if ((get-process "pkhex" -ea SilentlyContinue) -ne $Null) {Stop-Process -processname "pkhex"} 43 | 44 | # get the ddl with csrf token 45 | $BasePKHeX = ((Invoke-WebRequest -Uri "https://projectpokemon.org/home/files/file/2445-pkhex-development-build/" -Headers $headers -UseBasicParsing -SessionVariable "Session").Links | Where-Object {$_.href -like "https://projectpokemon.org/home/files/file/2445-pkhex-development-build/?do=download*"}).href.replace("&", "&") 46 | 47 | # get cookies after making a webrequest to the official download site 48 | $url = $BasePKHeX 49 | $cookie = $Session.Cookies.GetCookies("https://projectpokemon.org/home/files/file/2445-pkhex-development-build/")[0].Name + "=" + $Session.Cookies.GetCookies("https://projectpokemon.org/home/files/file/2445-pkhex-development-build/")[0].Value + "; " + $Session.Cookies.GetCookies("https://projectpokemon.org/home/files/file/2445-pkhex-development-build/")[1].Name + "=" + $Session.Cookies.GetCookies("https://projectpokemon.org/home/files/file/2445-pkhex-development-build/")[1].Value + "; ips4_ipsTimezone=Asia/Singapore; ips4_hasJS=true" 50 | 51 | # set cookies and ddl path to the header 52 | $headers.cookie = $cookie 53 | $headers.path = $url 54 | 55 | # download as PKHeX.zip 56 | Write-Host "Downloading latest PKHeX Build (latest) from https://projectpokemon.org/home/files/file/2445-pkhex-development-build/ ..." 57 | Invoke-WebRequest $url -OutFile "PKHeX.zip" -Headers $headers -WebSession $session -Method Get -ContentType "application/zip" -UseBasicParsing 58 | 59 | # get latest plugins build 60 | $j = Invoke-WebRequest 'https://dev.azure.com/architdate/40cccbb5-1611-4da1-aa70-c9cc0fba36e2/_apis/build/builds?definitions=1&$top=1&resultFilter=succeeded&api-version=6.0' -UseBasicParsing | ConvertFrom-Json 61 | $buildid = $j.value.id 62 | $aurl = "https://dev.azure.com/architdate/40cccbb5-1611-4da1-aa70-c9cc0fba36e2/_apis/build/builds/$buildid/artifacts?artifactName=PKHeX-Plugins&api-version=6.0" 63 | $a = Invoke-WebRequest $aurl -UseBasicParsing | ConvertFrom-Json 64 | $download = $a.resource.downloadUrl 65 | $file = "PKHeX-Plugins.zip" 66 | 67 | Invoke-WebRequest $download -OutFile $file -ContentType "application/zip" -UseBasicParsing 68 | 69 | # cleanup old files if they exist 70 | Write-Host Cleaning up previous releases if they exist ... 71 | Remove-Item plugins/AutoModPlugins.* -ErrorAction Ignore 72 | Remove-Item plugins/PKHeX.Core.AutoMod.* -ErrorAction Ignore 73 | Remove-Item plugins/QRPlugins.* -ErrorAction Ignore 74 | Remove-Item PKHeX.exe -ErrorAction Ignore 75 | Remove-Item PKHeX.Core.* -ErrorAction Ignore 76 | Remove-Item PKHeX.exe.* -ErrorAction Ignore 77 | Remove-Item PKHeX.pdb -ErrorAction Ignore 78 | Remove-Item PKHeX.Drawing.* -ErrorAction Ignore 79 | Remove-Item QRCoder.dll -ErrorAction Ignore 80 | 81 | # Extract pkhex 82 | Write-Host Extracting PKHeX ... 83 | Expand-Archive -Path PKHeX.zip -DestinationPath $pwd -Force 84 | 85 | # Delete zip file 86 | Write-Host Deleting PKHeX.zip ... 87 | Remove-Item PKHeX.zip 88 | 89 | # Unblock plugins and extract 90 | dir PKHeX-Plugins*.zip | Unblock-File 91 | New-Item -ItemType Directory -Force -Path plugins | Out-Null 92 | Write-Host Extracting Plugins ... 93 | Expand-Archive -Path PKHeX-Plugins*.zip -DestinationPath $pwd -Force 94 | Move-Item -Path PKHeX-Plugins\*.dll -Destination plugins -Force 95 | Write-Host Deleting Plugins ... 96 | Remove-Item PKHeX-Plugins -Recurse 97 | Remove-Item PKHeX-Plugins*.zip 98 | 99 | #Finish up script 100 | Read-Host -Prompt "Press Enter to exit" 101 | -------------------------------------------------------------------------------- /setup_stable.ps1: -------------------------------------------------------------------------------- 1 | # Setting the TLS protocol to 1.2 instead of the default 1.0 2 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 3 | 4 | # Powershell script to download PKHeX and Plugins (stable) 5 | Write-Host "PKHeX and PKHeX-Plugins downloader (stable releases)" 6 | Write-Host "Please report any issues with this setup file via GitHub issues at https://github.com/architdate/PKHeX-Plugins/issues" 7 | Write-Host "" 8 | Write-Host "" 9 | 10 | # check network path locations 11 | $networkPaths = @("OneDrive", "Dropbox", "Mega") 12 | for ($i=0; $i -lt $networkPaths.Length; $i++) { 13 | $path = $networkPaths[$i] 14 | $currDir = Get-Location 15 | if ($currDir.Path.Contains($path)) { 16 | Write-Host "WARNING: $path is detected on your system. Please move the setup file to a different location before running the program." 17 | Read-Host "Press Enter to exit" 18 | exit 19 | } 20 | } 21 | 22 | # set headers 23 | $headers = @{ 24 | "method"="GET" 25 | "authority"="projectpokemon.org" 26 | "scheme"="https" 27 | "path"="/home/files/file/1-pkhex/" 28 | "cache-control"="max-age=0" 29 | "upgrade-insecure-requests"="1" 30 | "user-agent"="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36" 31 | "accept"="text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" 32 | "sec-fetch-site"="same-origin" 33 | "sec-fetch-mode"="navigate" 34 | "sec-fetch-user"="?1" 35 | "sec-fetch-dest"="document" 36 | "referer"="https://projectpokemon.org/home/files/" 37 | "accept-encoding"="gzip, deflate, br" 38 | "accept-language"="en-US,en;q=0.9" 39 | }; 40 | 41 | # close any open instances of PKHeX that may prevent updating the file 42 | if ((get-process "pkhex" -ea SilentlyContinue) -ne $Null) {Stop-Process -processname "pkhex"} 43 | 44 | # get latest stable plugins 45 | $pluginsrepo = "architdate/PKHeX-Plugins" 46 | $baserepo = "kwsch/PKHeX" 47 | $file = "PKHeX-Plugins.zip" 48 | $releases = "https://api.github.com/repos/$pluginsrepo/releases" 49 | $basereleases = "https://api.github.com/repos/$baserepo/releases" 50 | 51 | Write-Host "Determining latest plugin release ..." 52 | $tag = (Invoke-WebRequest $releases -UseBasicParsing | ConvertFrom-Json)[0].tag_name 53 | $basetag = (Invoke-WebRequest $basereleases -UseBasicParsing | ConvertFrom-Json)[0].tag_name 54 | if (!$tag.Equals($basetag)) { 55 | Write-Host "Auto-Legality Mod for the latest stable PKHeX has not been released yet." 56 | Write-Host "Please wait for a new PKHeX-Plugins release before using this setup file." 57 | Write-Host "Alternatively, consider reading the wiki to manually setup ALM with an older PKHeX build." 58 | Read-Host "Press Enter to exit" 59 | exit 60 | } 61 | 62 | # get the correct page for the tag 63 | $BasePKHeX = ((Invoke-WebRequest -Uri "https://projectpokemon.org/home/files/file/1-pkhex/" -Headers $headers -UseBasicParsing -SessionVariable "Session").Links | Where-Object {$_.href -like "https://projectpokemon.org/home/files/file/1-pkhex/?do=download*"}).href.replace("&", "&") 64 | 65 | # get cookies after making a webrequest to the official download site 66 | $url = $BasePKHeX 67 | $cookie = $Session.Cookies.GetCookies("https://projectpokemon.org/home/files/file/1-pkhex/")[0].Name + "=" + $Session.Cookies.GetCookies("https://projectpokemon.org/home/files/file/1-pkhex/")[0].Value + "; " + $Session.Cookies.GetCookies("https://projectpokemon.org/home/files/file/1-pkhex/")[1].Name + "=" + $Session.Cookies.GetCookies("https://projectpokemon.org/home/files/file/1-pkhex/")[1].Value + "; ips4_ipsTimezone=Asia/Singapore; ips4_hasJS=true" 68 | 69 | # set cookies and ddl path to the header 70 | $headers.cookie = $cookie 71 | $headers.path = $url 72 | 73 | # download as PKHeX.zip 74 | Write-Host "Downloading latest PKHeX Release (stable) from https://projectpokemon.org/home/files/file/1-pkhex/ ..." 75 | Invoke-WebRequest $url -OutFile "PKHeX.zip" -Headers $headers -WebSession $session -Method Get -ContentType "application/zip" -UseBasicParsing 76 | 77 | # download as PKHeX-Plugins.zip 78 | Write-Host Downloading latest PKHeX-Plugin Release: $tag 79 | $download = "https://github.com/$pluginsrepo/releases/download/$tag/$file" 80 | 81 | Invoke-WebRequest $download -OutFile $file -ContentType "application/zip" -UseBasicParsing 82 | 83 | # cleanup old files if they exist 84 | Write-Host Cleaning up previous releases if they exist ... 85 | Remove-Item plugins/AutoModPlugins.* -ErrorAction Ignore 86 | Remove-Item plugins/PKHeX.Core.AutoMod.* -ErrorAction Ignore 87 | Remove-Item plugins/QRPlugins.* -ErrorAction Ignore 88 | Remove-Item PKHeX.exe -ErrorAction Ignore 89 | Remove-Item PKHeX.Core.* -ErrorAction Ignore 90 | Remove-Item PKHeX.exe.* -ErrorAction Ignore 91 | Remove-Item PKHeX.pdb -ErrorAction Ignore 92 | Remove-Item PKHeX.Drawing.* -ErrorAction Ignore 93 | Remove-Item QRCoder.dll -ErrorAction Ignore 94 | 95 | 96 | # Extract pkhex 97 | Write-Host Extracting PKHeX ... 98 | Expand-Archive -Path PKHeX.zip -DestinationPath $pwd 99 | 100 | # Delete zip file 101 | Write-Host Deleting PKHeX.zip ... 102 | Remove-Item PKHeX.zip 103 | 104 | # Unblock plugins and extract 105 | dir PKHeX-Plugins*.zip | Unblock-File 106 | New-Item -ItemType Directory -Force -Path plugins | Out-Null 107 | Write-Host Extracting Plugins ... 108 | Expand-Archive -Path PKHeX-Plugins*.zip -Force -DestinationPath plugins 109 | Write-Host Deleting Plugins ... 110 | Remove-Item PKHeX-Plugins*.zip 111 | 112 | #Finish up script 113 | Read-Host -Prompt "Press Enter to exit" --------------------------------------------------------------------------------