mirror of
https://github.com/kwsch/PKHeX
synced 2025-02-16 21:38:40 +00:00
Add GUI For XY Roamer (#4056)
* Add GUI For XY Roamer * Account For Roamer Not Set In XY
This commit is contained in:
parent
3df5478d11
commit
1f6d2de891
5 changed files with 234 additions and 20 deletions
|
@ -19,16 +19,16 @@ public sealed class Encount6 : SaveBlock<SAV6>
|
|||
|
||||
public PokeRadar6 Radar
|
||||
{
|
||||
get => new(Data.Slice(Offset + 0x04, PokeRadar6.SIZE));
|
||||
set => value.Data.CopyTo(Data, Offset + 0x04);
|
||||
get => new(Data.AsMemory(Offset + 0x04, PokeRadar6.SIZE));
|
||||
set => value.Data.CopyTo(Data.AsMemory(Offset + 0x04));
|
||||
}
|
||||
|
||||
// 0x1C
|
||||
|
||||
public Roamer6 Roamer
|
||||
{
|
||||
get => new(Data.Slice(Offset + 0x1C, Roamer6.SIZE));
|
||||
set => value.Data.CopyTo(Data, Offset + 0x1C);
|
||||
get => new(Data.AsMemory(Offset + 0x1C, Roamer6.SIZE));
|
||||
set => value.Data.CopyTo(Data.AsMemory(Offset + 0x1C, Roamer6.SIZE));
|
||||
}
|
||||
|
||||
// 0x44
|
||||
|
@ -44,20 +44,21 @@ public sealed class PokeRadar6
|
|||
private const int MaxCharge = 50;
|
||||
private const int RecordCount = 5;
|
||||
|
||||
public readonly byte[] Data;
|
||||
public readonly Memory<byte> Data;
|
||||
private Span<byte> Span => Data.Span;
|
||||
|
||||
public PokeRadar6(byte[] data) => Data = data;
|
||||
public PokeRadar6(Memory<byte> data) => Data = data;
|
||||
public override string ToString() => ((Species)PokeRadarSpecies).ToString();
|
||||
|
||||
public ushort PokeRadarSpecies { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), value); }
|
||||
private ushort PokeRadarPacked { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), value); }
|
||||
public ushort PokeRadarSpecies { get => ReadUInt16LittleEndian(Span[0..2]); set => WriteUInt16LittleEndian(Span[0..2], value); }
|
||||
private ushort PokeRadarPacked { get => ReadUInt16LittleEndian(Span[2..4]); set => WriteUInt16LittleEndian(Span[2..4], value); }
|
||||
|
||||
public int PokeRadarCharge { get => PokeRadarPacked & 0x3FFF; set => PokeRadarPacked = (ushort)((PokeRadarPacked & ~0x3FFF) | Math.Min(MaxCharge, value)); }
|
||||
public bool PokeRadarFlag1 { get => PokeRadarPacked >> 14 != 0; set => PokeRadarPacked = (ushort)((PokeRadarPacked & ~(1 << 14)) | (value ? (1 << 14) : 0)); }
|
||||
public bool PokeRadarFlag2 { get => PokeRadarPacked >> 15 != 0; set => PokeRadarPacked = (ushort)((PokeRadarPacked & ~(1 << 15)) | (value ? (1 << 15) : 0)); }
|
||||
|
||||
public PokeRadarRecord GetRecord(int index) => PokeRadarRecord.ReadRecord(Data.AsSpan(GetRecordOffset(index)));
|
||||
public void SetRecord(PokeRadarRecord record, int index) => record.WriteRecord(Data.AsSpan(GetRecordOffset(index)));
|
||||
public PokeRadarRecord GetRecord(int index) => PokeRadarRecord.ReadRecord(Span[GetRecordOffset(index)..]);
|
||||
public void SetRecord(PokeRadarRecord record, int index) => record.WriteRecord(Span[GetRecordOffset(index)..]);
|
||||
|
||||
private static int GetRecordOffset(int index)
|
||||
{
|
||||
|
@ -108,21 +109,22 @@ public sealed class Roamer6
|
|||
{
|
||||
public const int SIZE = 0x28;
|
||||
|
||||
public readonly byte[] Data;
|
||||
public readonly Memory<byte> Data;
|
||||
private Span<byte> Span => Data.Span;
|
||||
|
||||
public Roamer6(byte[] data) => Data = data;
|
||||
public Roamer6(Memory<byte> data) => Data = data;
|
||||
public override string ToString() => ((Species)Species).ToString();
|
||||
|
||||
private ushort SpecForm { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), value); }
|
||||
private ushort SpecForm { get => ReadUInt16LittleEndian(Span[0..2]); set => WriteUInt16LittleEndian(Span[0..2], value); }
|
||||
public ushort Species { get => (ushort)(SpecForm & 0x3FF); set => SpecForm = (ushort)((SpecForm & ~0x3FF) | (value & 0x3FF)); }
|
||||
public bool Flag1 { get => SpecForm >> 14 != 0; set => SpecForm = (ushort)((SpecForm & 0xBFFF) | (value ? (1 << 14) : 0)); }
|
||||
public bool Flag2 { get => SpecForm >> 15 != 0; set => SpecForm = (ushort)((SpecForm & 0x7FFF) | (value ? (1 << 15) : 0)); }
|
||||
|
||||
public int CurrentLevel { get => Data[0x04]; set => Data[0x04] = (byte)value; }
|
||||
private int Status { get => Data[0x07]; set => Data[0x07] = (byte)value; }
|
||||
public int CurrentLevel { get => Span[4]; set => Span[4] = (byte)value; }
|
||||
private int Status { get => Span[7]; set => Span[7] = (byte)value; }
|
||||
public Roamer6State RoamStatus { get => (Roamer6State)((Status >> 4) & 0xF); set => Status = (Status & 0x0F) | (((int)value << 4) & 0xF0); }
|
||||
|
||||
public uint TimesEncountered { get => ReadUInt32LittleEndian(Data.AsSpan(0x24)); set => WriteUInt32LittleEndian(Data.AsSpan(0x24), value); }
|
||||
public uint TimesEncountered { get => ReadUInt32LittleEndian(Span[36..40]); set => WriteUInt32LittleEndian(Span[36..40], value); }
|
||||
}
|
||||
|
||||
public enum Roamer6State
|
||||
|
|
|
@ -510,7 +510,6 @@ public partial class SAVEditor : UserControl, ISlotViewer<PictureBox>, ISaveFile
|
|||
private void B_OpenSecretBase_Click(object sender, EventArgs e) => OpenDialog(new SAV_SecretBase(SAV));
|
||||
private void B_CellsStickers_Click(object sender, EventArgs e) => OpenDialog(new SAV_ZygardeCell(SAV));
|
||||
private void B_LinkInfo_Click(object sender, EventArgs e) => OpenDialog(new SAV_Link6(SAV));
|
||||
private void B_Roamer_Click(object sender, EventArgs e) => OpenDialog(new SAV_Roamer3(SAV));
|
||||
private void B_OpenApricorn_Click(object sender, EventArgs e) => OpenDialog(new SAV_Apricorn((SAV4HGSS)SAV));
|
||||
private void B_CGearSkin_Click(object sender, EventArgs e) => OpenDialog(new SAV_CGearSkin(SAV));
|
||||
private void B_OpenTrainerInfo_Click(object sender, EventArgs e) => OpenDialog(GetTrainerEditor(SAV));
|
||||
|
@ -519,6 +518,14 @@ public partial class SAVEditor : UserControl, ISlotViewer<PictureBox>, ISaveFile
|
|||
private void B_OpenGeonetEditor_Click(object sender, EventArgs e) => OpenDialog(new SAV_Geonet4((SAV4)SAV));
|
||||
private void B_OpenUnityTowerEditor_Click(object sender, EventArgs e) => OpenDialog(new SAV_UnityTower((SAV5)SAV));
|
||||
|
||||
private void B_Roamer_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (SAV is SAV3 s3)
|
||||
OpenDialog(new SAV_Roamer3(s3));
|
||||
else if (SAV is SAV6XY xy)
|
||||
OpenDialog(new SAV_Roamer6(xy));
|
||||
}
|
||||
|
||||
private void B_OpenEventFlags_Click(object sender, EventArgs e)
|
||||
{
|
||||
using var form = SAV switch
|
||||
|
@ -1129,7 +1136,7 @@ public partial class SAVEditor : UserControl, ISlotViewer<PictureBox>, ISaveFile
|
|||
B_OtherSlots.Visible = sav is SAV1StadiumJ or SAV1Stadium or SAV2Stadium;
|
||||
B_OpenTrainerInfo.Visible = B_OpenItemPouch.Visible = (sav.HasParty && SAV is not SAV4BR) || SAV is SAV7b; // Box RS & Battle Revolution
|
||||
B_OpenMiscEditor.Visible = sav is SAV3 or SAV4 or SAV5 or SAV8BS;
|
||||
B_Roamer.Visible = sav is SAV3;
|
||||
B_Roamer.Visible = sav is SAV3 or SAV6XY;
|
||||
|
||||
B_OpenHoneyTreeEditor.Visible = sav is SAV4Sinnoh;
|
||||
B_OpenUGSEditor.Visible = sav is SAV4Sinnoh or SAV8BS;
|
||||
|
|
|
@ -8,11 +8,11 @@ public partial class SAV_Roamer3 : Form
|
|||
{
|
||||
private readonly Roamer3 Reader;
|
||||
|
||||
public SAV_Roamer3(SaveFile sav)
|
||||
public SAV_Roamer3(SAV3 sav)
|
||||
{
|
||||
InitializeComponent();
|
||||
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
|
||||
Reader = new Roamer3((SAV3)sav);
|
||||
Reader = new Roamer3(sav);
|
||||
|
||||
CB_Species.InitializeBinding();
|
||||
CB_Species.DataSource = new BindingSource(GameInfo.FilteredSources.Species, null);
|
||||
|
|
151
PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Roamer6.Designer.cs
generated
Normal file
151
PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Roamer6.Designer.cs
generated
Normal file
|
@ -0,0 +1,151 @@
|
|||
namespace PKHeX.WinForms
|
||||
{
|
||||
partial class SAV_Roamer6
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
L_Species = new System.Windows.Forms.Label();
|
||||
CB_Species = new System.Windows.Forms.ComboBox();
|
||||
L_TimesEncountered = new System.Windows.Forms.Label();
|
||||
NUD_TimesEncountered = new System.Windows.Forms.NumericUpDown();
|
||||
L_RoamState = new System.Windows.Forms.Label();
|
||||
CB_RoamState = new System.Windows.Forms.ComboBox();
|
||||
B_Cancel = new System.Windows.Forms.Button();
|
||||
B_Save = new System.Windows.Forms.Button();
|
||||
((System.ComponentModel.ISupportInitialize)NUD_TimesEncountered).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// L_Species
|
||||
//
|
||||
L_Species.AutoSize = true;
|
||||
L_Species.Location = new System.Drawing.Point(15, 10);
|
||||
L_Species.Name = "L_Species";
|
||||
L_Species.Size = new System.Drawing.Size(48, 15);
|
||||
L_Species.TabIndex = 0;
|
||||
L_Species.Text = "Roamer";
|
||||
//
|
||||
// CB_Species
|
||||
//
|
||||
CB_Species.FormattingEnabled = true;
|
||||
CB_Species.Location = new System.Drawing.Point(15, 30);
|
||||
CB_Species.Name = "CB_Species";
|
||||
CB_Species.Size = new System.Drawing.Size(121, 23);
|
||||
CB_Species.TabIndex = 1;
|
||||
CB_Species.SelectedIndexChanged += CB_Species_SelectedIndexChanged;
|
||||
//
|
||||
// L_TimesEncountered
|
||||
//
|
||||
L_TimesEncountered.AutoSize = true;
|
||||
L_TimesEncountered.Location = new System.Drawing.Point(150, 10);
|
||||
L_TimesEncountered.Name = "L_TimesEncountered";
|
||||
L_TimesEncountered.Size = new System.Drawing.Size(108, 15);
|
||||
L_TimesEncountered.TabIndex = 2;
|
||||
L_TimesEncountered.Text = "Times Encountered";
|
||||
//
|
||||
// NUD_TimesEncountered
|
||||
//
|
||||
NUD_TimesEncountered.Location = new System.Drawing.Point(150, 30);
|
||||
NUD_TimesEncountered.Maximum = new decimal(new int[] { 11, 0, 0, 0 });
|
||||
NUD_TimesEncountered.Name = "NUD_TimesEncountered";
|
||||
NUD_TimesEncountered.Size = new System.Drawing.Size(120, 23);
|
||||
NUD_TimesEncountered.TabIndex = 3;
|
||||
NUD_TimesEncountered.ValueChanged += NUD_TimesEncountered_ValueChanged;
|
||||
//
|
||||
// L_RoamState
|
||||
//
|
||||
L_RoamState.AutoSize = true;
|
||||
L_RoamState.Location = new System.Drawing.Point(280, 10);
|
||||
L_RoamState.Name = "L_RoamState";
|
||||
L_RoamState.Size = new System.Drawing.Size(67, 15);
|
||||
L_RoamState.TabIndex = 4;
|
||||
L_RoamState.Text = "Roam State";
|
||||
//
|
||||
// CB_RoamState
|
||||
//
|
||||
CB_RoamState.FormattingEnabled = true;
|
||||
CB_RoamState.Location = new System.Drawing.Point(280, 30);
|
||||
CB_RoamState.Name = "CB_RoamState";
|
||||
CB_RoamState.Size = new System.Drawing.Size(121, 23);
|
||||
CB_RoamState.TabIndex = 5;
|
||||
CB_RoamState.SelectedIndexChanged += CB_RoamState_SelectedIndexChanged;
|
||||
//
|
||||
// B_Cancel
|
||||
//
|
||||
B_Cancel.Location = new System.Drawing.Point(245, 66);
|
||||
B_Cancel.Name = "B_Cancel";
|
||||
B_Cancel.Size = new System.Drawing.Size(75, 23);
|
||||
B_Cancel.TabIndex = 6;
|
||||
B_Cancel.Text = "Cancel";
|
||||
B_Cancel.UseVisualStyleBackColor = true;
|
||||
B_Cancel.Click += B_Cancel_Click;
|
||||
//
|
||||
// B_Save
|
||||
//
|
||||
B_Save.Location = new System.Drawing.Point(326, 66);
|
||||
B_Save.Name = "B_Save";
|
||||
B_Save.Size = new System.Drawing.Size(75, 23);
|
||||
B_Save.TabIndex = 7;
|
||||
B_Save.Text = "Save";
|
||||
B_Save.UseVisualStyleBackColor = true;
|
||||
B_Save.Click += B_Save_Click;
|
||||
//
|
||||
// SAV_Roamer6
|
||||
//
|
||||
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
ClientSize = new System.Drawing.Size(414, 101);
|
||||
Controls.Add(B_Save);
|
||||
Controls.Add(B_Cancel);
|
||||
Controls.Add(CB_RoamState);
|
||||
Controls.Add(L_RoamState);
|
||||
Controls.Add(NUD_TimesEncountered);
|
||||
Controls.Add(L_TimesEncountered);
|
||||
Controls.Add(CB_Species);
|
||||
Controls.Add(L_Species);
|
||||
Icon = Properties.Resources.Icon;
|
||||
Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
Name = "SAV_Roamer6";
|
||||
Text = "Roamer Editor";
|
||||
((System.ComponentModel.ISupportInitialize)NUD_TimesEncountered).EndInit();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label L_Species;
|
||||
private System.Windows.Forms.ComboBox CB_Species;
|
||||
private System.Windows.Forms.Label L_TimesEncountered;
|
||||
private System.Windows.Forms.NumericUpDown NUD_TimesEncountered;
|
||||
private System.Windows.Forms.Label L_RoamState;
|
||||
private System.Windows.Forms.ComboBox CB_RoamState;
|
||||
private System.Windows.Forms.Button B_Cancel;
|
||||
private System.Windows.Forms.Button B_Save;
|
||||
}
|
||||
}
|
54
PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Roamer6.cs
Normal file
54
PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Roamer6.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using PKHeX.Core;
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace PKHeX.WinForms;
|
||||
|
||||
public partial class SAV_Roamer6 : Form
|
||||
{
|
||||
private const int SpeciesOffset = 144;
|
||||
private const int StarterChoiceIndex = 48;
|
||||
private readonly SAV6XY Origin;
|
||||
private readonly SAV6XY SAV;
|
||||
private readonly Roamer6 roamer;
|
||||
|
||||
public SAV_Roamer6(SAV6XY sav)
|
||||
{
|
||||
InitializeComponent();
|
||||
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
|
||||
SAV = (SAV6XY)(Origin = sav).Clone();
|
||||
roamer = SAV.Encount.Roamer;
|
||||
|
||||
var species = GameInfo.Strings.specieslist;
|
||||
var entries = new[] { species[(int)Species.Articuno], species[(int)Species.Zapdos], species[(int)Species.Moltres] };
|
||||
var states = new[] { "Inactive", "Roaming", "Stationary", "Defeated", "Captured" };
|
||||
CB_Species.Items.AddRange(entries);
|
||||
CB_RoamState.Items.AddRange(states);
|
||||
|
||||
CB_Species.SelectedIndex = GetInitialIndex(sav);
|
||||
NUD_TimesEncountered.Value = roamer.TimesEncountered;
|
||||
CB_RoamState.SelectedIndex = (int)roamer.RoamStatus;
|
||||
}
|
||||
|
||||
private int GetInitialIndex(SAV6XY sav)
|
||||
{
|
||||
if (roamer.Species != 0)
|
||||
return roamer.Species - SpeciesOffset;
|
||||
// Roamer Species is not set if the player hasn't beaten the league so derive the species from the starter choice
|
||||
return sav.GetWork(StarterChoiceIndex);
|
||||
}
|
||||
|
||||
private void CB_Species_SelectedIndexChanged(object sender, EventArgs e) => roamer.Species = (ushort)(SpeciesOffset + CB_Species.SelectedIndex);
|
||||
|
||||
private void NUD_TimesEncountered_ValueChanged(object sender, EventArgs e) => roamer.TimesEncountered = (uint)NUD_TimesEncountered.Value;
|
||||
|
||||
private void CB_RoamState_SelectedIndexChanged(object sender, EventArgs e) => roamer.RoamStatus = (Roamer6State)CB_RoamState.SelectedIndex;
|
||||
|
||||
private void B_Cancel_Click(object sender, EventArgs e) => Close();
|
||||
|
||||
private void B_Save_Click(object sender, EventArgs e)
|
||||
{
|
||||
Origin.CopyChangesFrom(SAV);
|
||||
Close();
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue