Misc updates

Detect channel, only detect Channel PIDIV for RS origin (only really
care about method1/2/4 being used when it shouldn't)
Channel does this weird thing called not setting the met level.

Refactor set suggested met location to a method that can suppress
popups.
This commit is contained in:
Kurt 2017-06-29 19:32:29 -07:00
parent 9f9f0e4ab3
commit 1c4a1af633
9 changed files with 125 additions and 65 deletions

View file

@ -618,7 +618,7 @@ namespace PKHeX.Core
{
switch (gift)
{
case WC3 wc3 when wc3.IsEgg && pkm.Met_Level == 0:
case WC3 wc3 when wc3.Met_Level == pkm.Met_Level:
break;
case WC7 wc7 when wc7.MetLevel == pkm.Met_Level:
break;

View file

@ -38,7 +38,7 @@ namespace PKHeX.Core
// Special cases
if (GetLCRNGRoamerMatch(top, bot, IVs, out pidiv))
return pidiv;
if (GetChannelMatch(top, bot, IVs, out pidiv))
if (GetChannelMatch(top, bot, IVs, out pidiv, pk))
return pidiv;
if (GetMG4Match(pid, IVs, out pidiv))
return pidiv;
@ -200,15 +200,35 @@ namespace PKHeX.Core
pidiv = null;
return false;
}
private static bool GetChannelMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
private static bool GetChannelMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv, PKM pk)
{
var ver = pk.Version;
if (ver != (int) GameVersion.R && ver != (int) GameVersion.S)
{
pidiv = null;
return false;
}
var channel = GetSeedsFromPID(RNG.XDRNG, bot, top ^ 0x8000);
foreach (var seed in channel)
{
var E = RNG.XDRNG.Advance(seed, 5);
var C = RNG.XDRNG.Advance(seed, 3); // held item
// no checks, held item can be swapped
var D = RNG.XDRNG.Next(C); // Version
if ((D >> 31) + 1 != ver) // (0-Sapphire, 1-Ruby)
continue;
var E = RNG.XDRNG.Next(D); // OT Gender
if (E >> 31 != pk.OT_Gender)
continue;
if (!GetIVs(RNG.XDRNG, E).SequenceEqual(IVs))
continue;
if (seed >> 16 != pk.SID)
continue;
pidiv = new PIDIV {OriginSeed = RNG.XDRNG.Prev(seed), RNG = RNG.XDRNG, Type = PIDType.Channel};
return true;
}

View file

@ -8,6 +8,8 @@
/// <summary> The RNG seed which immediately generates the PIDIV (starting with PID or IVs, whichever comes first). </summary>
public uint OriginSeed;
/// <summary> Indicates that there is no <see cref="OriginSeed"/> to refer to. </summary>
/// <remarks> Some PIDIVs may be generated without a single seed, but may follow a traceable pattern. </remarks>
public bool NoSeed;
/// <summary> Type of PIDIV correlation </summary>

View file

@ -21,6 +21,8 @@
{
if (encounter.EggEncounter)
return pkm.CurrentLevel == Legal.GetEggHatchLevel(pkm);
if (encounter is MysteryGift g)
return pkm.CurrentLevel == g.Level;
return pkm.CurrentLevel == pkm.Met_Level;
}
return encounter.IsWithinRange(pkm.CurrentLevel);

View file

@ -299,11 +299,14 @@ namespace PKHeX.Core
// Berry Glitch Fix
// PCJP - (December 29, 2003 to March 31, 2004)
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 21121, OT_Name = "ルビー", Language = 1 },
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 21121, OT_Name = "サファイア", Language = 1 },
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 21121, OT_Name = "ルビー", Language = 1, OT_Gender = 1 },
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 21121, OT_Name = "サファイア", Language = 1, OT_Gender = 0 },
// EBGames/GameStop (March 1, 2004 to April 22, 2007), also via multi-game discs
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 30317, OT_Name = "RUBY", Language = 2 },
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 30317, OT_Name = "SAPHIRE", Language = 2 },
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 30317, OT_Name = "RUBY", Language = 2, OT_Gender = 1 },
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 30317, OT_Name = "SAPHIRE", Language = 2, OT_Gender = 0 },
// Channel Jirachi
new WC3 { Species = 385, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.Channel, TID = 40122, SID = -1, OT_Name = "CHANNEL", Met_Level = 0 },
};
internal static readonly MysteryGift[] Encounter_Event3_Common =

View file

@ -17,7 +17,7 @@ namespace PKHeX.Core
public int SID { get; set; }
public int Met_Location { get; internal set; } = 255;
public int Version { get; set; }
public int Language { get; set; }
public int Language { get; set; } = -1;
public override int Species { get; set; }
public override bool IsEgg { get; set; }
public override int[] Moves { get; set; }
@ -41,6 +41,19 @@ namespace PKHeX.Core
public override int ItemID { get; set; }
public override bool IsPokémon { get; set; }
// Synthetic
private int _metLevel = -1;
public int Met_Level
{
get
{
if (IsEgg)
return 0;
return _metLevel < 0 ? Level : _metLevel;
}
set => _metLevel = value;
}
public override PKM ConvertToPKM(SaveFile SAV)
{
throw new NotImplementedException();

View file

@ -372,7 +372,7 @@ namespace PKHeX.Core
InvalidLines.Add("Unknown EV input.");
for (int i = 0; i < evlist.Length / 2; i++)
{
bool valid = ushort.TryParse(evlist[i * 2 + 0], out ushort EV);
bool valid = ushort.TryParse(evlist[i * 2 + 0], out ushort EV);
int index = Array.IndexOf(StatNames, evlist[i * 2 + 1]);
if (valid && index > -1)
EVs[index] = EV;

View file

@ -646,51 +646,8 @@ namespace PKHeX.WinForms.Controls
UpdateLegality(skipMoveRepop: true);
if (Legality.Valid)
return;
var encounter = Legality.GetSuggestedMetInfo();
if (encounter == null || (pkm.Format >= 3 && encounter.Location < 0))
{
WinFormsUtil.Alert("Unable to provide a suggestion.");
if (!SetSuggestedMetLocation())
return;
}
int level = encounter.Level;
int location = encounter.Location;
int minlvl = Legal.GetLowestLevel(pkm, encounter.Species);
if (minlvl == 0)
minlvl = level;
if (pkm.CurrentLevel >= minlvl && pkm.Met_Level == level && pkm.Met_Location == location)
return;
if (minlvl < level)
minlvl = level;
var suggestion = new List<string> { "Suggested:" };
if (pkm.Format >= 3)
{
var met_list = GameInfo.GetLocationList((GameVersion)pkm.Version, pkm.Format, egg: false);
var locstr = met_list.FirstOrDefault(loc => loc.Value == location).Text;
suggestion.Add($"Met Location: {locstr}");
suggestion.Add($"Met Level: {level}");
}
if (pkm.CurrentLevel < minlvl)
suggestion.Add($"Current Level: {minlvl}");
if (suggestion.Count == 1) // no suggestion
return;
string suggest = string.Join(Environment.NewLine, suggestion);
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, suggest) != DialogResult.Yes)
return;
if (pkm.Format >= 3)
{
TB_MetLevel.Text = level.ToString();
CB_MetLocation.SelectedValue = location;
}
if (pkm.CurrentLevel < minlvl)
TB_Level.Text = minlvl.ToString();
pkm = PreparePKM();
UpdateLegality();
@ -733,12 +690,13 @@ namespace PKHeX.WinForms.Controls
UpdateLegality();
}
private bool SetSuggestedMoves(bool random = false)
private bool SetSuggestedMoves(bool random = false, bool silent = false)
{
int[] m = Legality.GetSuggestedMoves(tm: random, tutor: random, reminder: random);
if (m == null)
{
WinFormsUtil.Alert("Suggestions are not enabled for this PKM format.");
if (!silent)
WinFormsUtil.Alert("Suggestions are not enabled for this PKM format.");
return false;
}
@ -751,10 +709,13 @@ namespace PKHeX.WinForms.Controls
if (pkm.Moves.SequenceEqual(m))
return false;
string r = string.Join(Environment.NewLine,
m.Select(v => v >= GameInfo.Strings.movelist.Length ? "ERROR" : GameInfo.Strings.movelist[v]));
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Apply suggested current moves?", r))
return false;
if (!silent)
{
var movestrings = m.Select(v => v >= GameInfo.Strings.movelist.Length ? "ERROR" : GameInfo.Strings.movelist[v]);
string r = string.Join(Environment.NewLine, movestrings);
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Apply suggested current moves?", r))
return false;
}
CB_Move1.SelectedValue = m[0];
CB_Move2.SelectedValue = m[1];
@ -764,6 +725,9 @@ namespace PKHeX.WinForms.Controls
}
private bool SetSuggestedRelearnMoves(bool silent = false)
{
if (pkm.Format < 6)
return false;
int[] m = Legality.GetSuggestedRelearn();
if (m.All(z => z == 0))
if (!pkm.WasEgg && !pkm.WasEvent && !pkm.WasEventEgg && !pkm.WasLink)
@ -776,10 +740,13 @@ namespace PKHeX.WinForms.Controls
if (pkm.RelearnMoves.SequenceEqual(m))
return false;
string r = string.Join(Environment.NewLine,
m.Select(v => v >= GameInfo.Strings.movelist.Length ? "ERROR" : GameInfo.Strings.movelist[v]));
if (!silent && DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Apply suggested relearn moves?", r))
return false;
if (!silent)
{
var movestrings = m.Select(v => v >= GameInfo.Strings.movelist.Length ? "ERROR" : GameInfo.Strings.movelist[v]);
string r = string.Join(Environment.NewLine, movestrings);
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Apply suggested relearn moves?", r))
return false;
}
CB_RelearnMove1.SelectedValue = m[0];
CB_RelearnMove2.SelectedValue = m[1];
@ -787,6 +754,59 @@ namespace PKHeX.WinForms.Controls
CB_RelearnMove4.SelectedValue = m[3];
return true;
}
private bool SetSuggestedMetLocation(bool silent = false)
{
var encounter = Legality.GetSuggestedMetInfo();
if (encounter == null || pkm.Format >= 3 && encounter.Location < 0)
{
if (!silent)
WinFormsUtil.Alert("Unable to provide a suggestion.");
return false;
}
int level = encounter.Level;
int location = encounter.Location;
int minlvl = Legal.GetLowestLevel(pkm, encounter.Species);
if (minlvl == 0)
minlvl = level;
if (pkm.CurrentLevel >= minlvl && pkm.Met_Level == level && pkm.Met_Location == location)
return false;
if (minlvl < level)
minlvl = level;
if (!silent)
{
var suggestion = new List<string> { "Suggested:" };
if (pkm.Format >= 3)
{
var met_list = GameInfo.GetLocationList((GameVersion)pkm.Version, pkm.Format, egg: false);
var locstr = met_list.FirstOrDefault(loc => loc.Value == location).Text;
suggestion.Add($"Met Location: {locstr}");
suggestion.Add($"Met Level: {level}");
}
if (pkm.CurrentLevel < minlvl)
suggestion.Add($"Current Level: {minlvl}");
if (suggestion.Count == 1) // no suggestion
return false;
string suggest = string.Join(Environment.NewLine, suggestion);
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, suggest) != DialogResult.Yes)
return false;
}
if (pkm.Format >= 3)
{
TB_MetLevel.Text = level.ToString();
CB_MetLocation.SelectedValue = location;
}
if (pkm.CurrentLevel < minlvl)
TB_Level.Text = minlvl.ToString();
return true;
}
private void UpdateIVs(object sender, EventArgs e)
{

View file

@ -35,7 +35,7 @@ namespace PKHeX.Tests.PKM
Assert.AreEqual(PIDType.CXD, MethodFinder.Analyze(pk3)?.Type, "Unable to match PID to CXD spread");
// Channel Jirachi
var pkC = new PK3 {PID = 0x9E27D2F6, IVs = new[] {04, 15, 21, 14, 18, 29}};
var pkC = new PK3 {PID = 0x264750D9, IVs = new[] {06, 31, 14, 27, 05, 27}, SID = 45819, OT_Gender = 1, Version = (int)GameVersion.R};
Assert.AreEqual(PIDType.Channel, MethodFinder.Analyze(pkC)?.Type, "Unable to match PID to Channel spread");
}