Misc updates

Add global link mission stats (thanks Holla!)
remove some ToArray() linq in favor of direct copies
Relocate encounter suggestion logic to separate class
Closes #1396, addresses other edge cases like entree-non HA & happiny
egg.
This commit is contained in:
Kurt
2017-08-15 21:16:47 -07:00
parent 9864d84704
commit 7fb9ce4131
7 changed files with 180 additions and 112 deletions

View File

@@ -20,8 +20,8 @@ public partial class LegalityAnalysis
private string EncounterName => $"{(EncounterOriginalGB ?? EncounterMatch).GetEncounterTypeName()} ({SpeciesStrings[EncounterMatch.Species]})";
private CheckResult Encounter, History;
public bool Parsed { get; }
public bool Valid { get; }
public readonly bool Parsed;
public readonly bool Valid;
public LegalInfo Info { get; private set; }
public bool ParsedValid => Parsed && Valid;
public bool ParsedInvalid => Parsed && !Valid;
@@ -360,6 +360,7 @@ private string GetVerboseLegalityReport()
return GetLegalityReport() + string.Join(Environment.NewLine, lines);
}
// Suggestions
public int[] GetSuggestedRelearn()
{
if (Info.RelearnBase == null || pkm.GenNumber < 6 || !pkm.IsOriginValid)
@@ -369,12 +370,13 @@ public int[] GetSuggestedRelearn()
return Info.RelearnBase;
List<int> window = new List<int>(Info.RelearnBase);
var vMoves = Info.Moves;
window.AddRange(pkm.Moves.Where((v, i) => !vMoves[i].Valid || vMoves[i].Flag));
window.AddRange(pkm.Moves.Where((v, i) => !Info.Moves[i].Valid || Info.Moves[i].Flag));
window = window.Distinct().ToList();
if (window.Count < 4)
window.AddRange(new int[4 - window.Count]);
return window.Skip(window.Count - 4).ToArray();
int[] moves = new int[4];
int start = Math.Max(0, window.Count - 4);
int count = Math.Min(4, window.Count);
window.CopyTo(start, moves, 0, count);
return moves;
}
public int[] GetSuggestedMoves(bool tm, bool tutor, bool reminder)
{
@@ -384,102 +386,6 @@ public int[] GetSuggestedMoves(bool tm, bool tutor, bool reminder)
return new int[4];
return Legal.GetValidMoves(pkm, Info.EvoChainsAllGens, Tutor: tutor, Machine: tm, MoveReminder: reminder).Skip(1).ToArray(); // skip move 0
}
public EncounterStatic GetSuggestedMetInfo()
{
if (pkm == null)
return null;
int loc = GetSuggestedTransferLocation(pkm);
if (pkm.WasEgg)
{
int lvl = 1; // gen5+
if (!pkm.IsNative)
lvl = pkm.CurrentLevel; // be generous with transfer conditions
else if (pkm.Format < 5) // and native
lvl = 0;
return new EncounterStatic
{
Species = Legal.GetBaseSpecies(pkm),
Location = loc != -1 ? loc : GetSuggestedEggMetLocation(pkm),
Level = lvl,
};
}
var area = EncounterGenerator.GetCaptureLocation(pkm);
if (area != null)
{
var slots = area.Slots.OrderBy(s => s.LevelMin);
return new EncounterStatic
{
Species = slots.First().Species,
Location = loc != -1 ? loc : area.Location,
Level = slots.First().LevelMin,
};
}
var encounter = EncounterGenerator.GetStaticLocation(pkm);
if (loc != -1 && encounter != null)
encounter.Location = loc;
return encounter;
}
private static int GetSuggestedEggMetLocation(PKM pkm)
{
// Return one of legal hatch locations for game
switch ((GameVersion)pkm.Version)
{
case GameVersion.R:
case GameVersion.S:
case GameVersion.E:
case GameVersion.FR:
case GameVersion.LG:
switch (pkm.Format)
{
case 3:
return pkm.FRLG ? 146 /* Four Island */ : 32; // Route 117
case 4:
return 0x37; // Pal Park
default:
return 30001; // Transporter
}
case GameVersion.D:
case GameVersion.P:
case GameVersion.Pt:
return pkm.Format > 4 ? 30001 /* Transporter */ : 4; // Solaceon Town
case GameVersion.HG:
case GameVersion.SS:
return pkm.Format > 4 ? 30001 /* Transporter */ : 182; // Route 34
case GameVersion.B:
case GameVersion.W:
return 16; // Route 3
case GameVersion.X:
case GameVersion.Y:
return 38; // Route 7
case GameVersion.AS:
case GameVersion.OR:
return 318; // Battle Resort
case GameVersion.SN:
case GameVersion.MN:
return 50; // Route 4
}
return -1;
}
private static int GetSuggestedTransferLocation(PKM pkm)
{
// Return one of legal hatch locations for game
if (pkm.HasOriginalMetLocation)
return -1;
if (pkm.VC1)
return 30013;
if (pkm.Format == 4) // Pal Park
return 0x37;
if (pkm.Format == 5) // Transporter
return 30001;
return -1;
}
public EncounterStatic GetSuggestedMetInfo() => EncounterSuggestion.GetSuggestedMetInfo(pkm);
}
}

View File

@@ -85,13 +85,22 @@ private void VerifyECPID()
case EncounterStatic s:
if (s.Shiny != null && (bool)s.Shiny ^ pkm.IsShiny)
AddLine(Severity.Invalid, V209, CheckIdentifier.Shiny);
if (pkm.GenNumber == 5 && !s.Gift && !s.Roaming && s.Ability != 4)
VerifyG5PID_IDCorrelation();
// gen5 correlation
if (pkm.GenNumber != 5)
break;
if (s.Location == 75) // Entree Forest
break;
if (s.Gift || s.Roaming || s.Ability != 4)
break;
if (s.NSparkle)
break;
VerifyG5PID_IDCorrelation();
break;
case EncounterSlot w:
if (pkm.IsShiny && w.Type == SlotType.HiddenGrotto)
AddLine(Severity.Invalid, V221, CheckIdentifier.Shiny);
if (pkm.GenNumber == 5 && pkm.AbilityNumber != 4)
if (pkm.GenNumber == 5 && w.Type != SlotType.HiddenGrotto)
VerifyG5PID_IDCorrelation();
break;
case PCD d: // fixed PID

View File

@@ -354,7 +354,10 @@ private static IEnumerable<EncounterStatic> GetMatchingStaticEncounters(PKM pkm,
if (e.Nature != Nature.Random && pkm.Nature != (int)e.Nature)
continue;
if (pkm.WasEgg ^ e.EggEncounter && pkm.Egg_Location == 0 && pkm.Format > 3)
continue;
{
if (!pkm.IsEgg)
continue;
}
if (pkm.Gen3 && e.EggLocation != 0) // Gen3 Egg
{
if (pkm.Format == 3 && pkm.IsEgg && e.EggLocation != pkm.Met_Location)

View File

@@ -0,0 +1,133 @@
using System.Linq;
namespace PKHeX.Core
{
internal static class EncounterSuggestion
{
public static EncounterStatic GetSuggestedMetInfo(PKM pkm)
{
if (pkm == null)
return null;
int loc = GetSuggestedTransferLocation(pkm);
if (pkm.WasEgg)
return GetSuggestedEncounterEgg(pkm, loc);
var w = EncounterGenerator.GetCaptureLocation(pkm);
if (w != null)
return GetSuggestedEncounterWild(w, loc);
var s = EncounterGenerator.GetStaticLocation(pkm);
if (s != null)
return GetSuggestedEncounterStatic(s, loc);
return null;
}
private static EncounterStatic GetSuggestedEncounterEgg(PKM pkm, int loc)
{
int lvl = 1; // gen5+
if (!pkm.IsNative)
lvl = pkm.CurrentLevel; // be generous with transfer conditions
else if (pkm.Format < 5) // and native
lvl = 0;
return new EncounterStatic
{
Species = Legal.GetBaseSpecies(pkm),
Location = loc != -1 ? loc : GetSuggestedEggMetLocation(pkm),
Level = lvl,
};
}
private static EncounterStatic GetSuggestedEncounterWild(EncounterArea area, int loc)
{
var slots = area.Slots.OrderBy(s => s.LevelMin);
var first = slots.First();
var encounter = new EncounterStatic
{
Species = first.Species,
Location = first.Location,
Level = first.LevelMin,
};
if (loc != -1) // forced location
encounter.Location = loc;
return encounter;
}
private static EncounterStatic GetSuggestedEncounterStatic(EncounterStatic s, int loc)
{
if (loc == -1)
loc = s.Location;
// don't leak out the original EncounterStatic object
var encounter = s.Clone(loc);
return encounter;
}
/// <summary>
/// Gets a valid Egg hatch location for the origin game.
/// </summary>
private static int GetSuggestedEggMetLocation(PKM pkm)
{
// Return one of legal hatch locations for game
switch ((GameVersion)pkm.Version)
{
case GameVersion.R:
case GameVersion.S:
case GameVersion.E:
case GameVersion.FR:
case GameVersion.LG:
switch (pkm.Format)
{
case 3:
return pkm.FRLG ? 146 /* Four Island */ : 32; // Route 117
case 4:
return 0x37; // Pal Park
default:
return 30001; // Transporter
}
case GameVersion.D:
case GameVersion.P:
case GameVersion.Pt:
return pkm.Format > 4 ? 30001 /* Transporter */ : 4; // Solaceon Town
case GameVersion.HG:
case GameVersion.SS:
return pkm.Format > 4 ? 30001 /* Transporter */ : 182; // Route 34
case GameVersion.B:
case GameVersion.W:
return 16; // Route 3
case GameVersion.X:
case GameVersion.Y:
return 38; // Route 7
case GameVersion.AS:
case GameVersion.OR:
return 318; // Battle Resort
case GameVersion.SN:
case GameVersion.MN:
return 50; // Route 4
}
return -1;
}
/// <summary>
/// Gets the correct Met location for the origin game.
/// </summary>
/// <remarks>
/// Returns -1 if the met location is not overriden with a transfer location
/// </remarks>
private static int GetSuggestedTransferLocation(PKM pkm)
{
// Return one of legal hatch locations for game
if (pkm.HasOriginalMetLocation)
return -1;
if (pkm.VC1)
return 30013;
if (pkm.Format == 4) // Pal Park
return 0x37;
if (pkm.Format == 5) // Transporter
return 30001;
return -1;
}
}
}

View File

@@ -16,9 +16,11 @@ public WC6(byte[] data = null)
Data = (byte[])(data?.Clone() ?? new byte[Size]);
if (Data.Length == SizeFull)
{
if (Data[0x205] == 0)
Data = new byte[Data.Length]; // Invalidate
Data = Data.Skip(SizeFull - Size).ToArray();
byte[] wc6 = new byte[Size];
if (Data[0x205] != 0) // Valid data
Array.Copy(Data, SizeFull - Size, wc6, 0, wc6.Length);
Data = wc6;
DateTime now = DateTime.Now;
Year = (uint)now.Year;
Month = (uint)now.Month;

View File

@@ -15,7 +15,9 @@ public WC7(byte[] data = null)
Data = (byte[])(data?.Clone() ?? new byte[Size]);
if (Data.Length == SizeFull)
{
Data = Data.Skip(SizeFull - Size).ToArray();
byte[] wc6 = new byte[Size];
Array.Copy(Data, SizeFull - Size, wc6, 0, wc6.Length);
Data = wc6;
DateTime now = DateTime.Now;
Year = (uint)now.Year;
Month = (uint)now.Month;

View File

@@ -656,6 +656,19 @@ private void B_GenTID_Click(object sender, EventArgs e)
{172, "Berry Tree Battles won"},
{173, "Bubbling Spot Encounters/Items"},
{174, "Times laid down in Own Bed"},
{175, "Trade Pokémon at the GTS!"},
{176, "176 - Global Mission"},
{177, "Hatch a lot of Eggs!"},
{178, "Harvest Poké Beans!"},
{179, "179 - Global Mission"},
{180, "Find Pokémon using Island Scan!"},
{181, "181 - Global Mission"},
{182, "Defend your Champion title!"},
{183, "Fish Pokémon at rare spots!"},
{185, "Try your luck!"},
{186, "186 - Global Mission"},
{187, "Catch a lot of Pokémon!"},
};
}
}