2018-05-19 19:07:50 +00:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
namespace PKHeX.Core
|
|
|
|
{
|
|
|
|
/// <summary>
|
2019-03-23 17:36:28 +00:00
|
|
|
/// Information pertaining to a <see cref="PKM"/>'s evolution lineage.
|
2018-05-19 19:07:50 +00:00
|
|
|
/// </summary>
|
2018-07-02 02:55:23 +00:00
|
|
|
public sealed class EvolutionLineage
|
2018-05-19 19:07:50 +00:00
|
|
|
{
|
2019-03-24 01:59:45 +00:00
|
|
|
public readonly List<List<EvolutionMethod>> Chain = new List<List<EvolutionMethod>>();
|
2018-05-19 19:07:50 +00:00
|
|
|
|
|
|
|
public void Insert(EvolutionMethod entry)
|
|
|
|
{
|
|
|
|
int matchChain = -1;
|
|
|
|
for (int i = 0; i < Chain.Count; i++)
|
2018-08-03 03:11:42 +00:00
|
|
|
{
|
2019-03-24 01:59:45 +00:00
|
|
|
if (Chain[i].Any(e => e.Species == entry.Species))
|
2018-05-19 19:07:50 +00:00
|
|
|
matchChain = i;
|
2018-08-03 03:11:42 +00:00
|
|
|
}
|
2018-05-19 19:07:50 +00:00
|
|
|
|
|
|
|
if (matchChain != -1)
|
2019-03-24 01:59:45 +00:00
|
|
|
Chain[matchChain].Add(entry);
|
2018-05-19 19:07:50 +00:00
|
|
|
else
|
2019-03-24 01:59:45 +00:00
|
|
|
Chain.Insert(0, new List<EvolutionMethod> {entry});
|
2018-05-19 19:07:50 +00:00
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
2019-11-26 06:51:07 +00:00
|
|
|
public List<EvoCriteria> GetExplicitLineage(PKM pkm, int maxLevel, bool skipChecks, int maxSpeciesOrigin, int minLevel)
|
2018-05-19 19:07:50 +00:00
|
|
|
{
|
|
|
|
int lvl = maxLevel;
|
2018-07-02 02:55:23 +00:00
|
|
|
var first = new EvoCriteria {Species = pkm.Species, Level = lvl, Form = pkm.AltForm};
|
2018-12-27 06:13:04 +00:00
|
|
|
var dl = new List<EvoCriteria>(3) { first };
|
2018-05-19 19:07:50 +00:00
|
|
|
for (int i = Chain.Count - 1; i >= 0; i--) // reverse evolution!
|
|
|
|
{
|
|
|
|
bool oneValid = false;
|
2019-03-24 01:59:45 +00:00
|
|
|
foreach (var evo in Chain[i])
|
2018-05-19 19:07:50 +00:00
|
|
|
{
|
|
|
|
if (!evo.Valid(pkm, lvl, skipChecks))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (evo.RequiresLevelUp && minLevel >= lvl)
|
|
|
|
break; // impossible evolution
|
|
|
|
|
|
|
|
oneValid = true;
|
|
|
|
UpdateMinValues(dl, evo);
|
|
|
|
int species = evo.Species;
|
|
|
|
|
|
|
|
if (evo.RequiresLevelUp)
|
|
|
|
lvl--;
|
2018-06-19 02:10:21 +00:00
|
|
|
dl.Add(evo.GetEvoCriteria(species, lvl));
|
2018-05-19 19:07:50 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!oneValid)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-02-24 21:57:10 +00:00
|
|
|
// Remove future gen pre-evolutions; no Munchlax from a Gen3 Snorlax, no Pichu from a Gen1-only Raichu, etc
|
2018-05-19 19:07:50 +00:00
|
|
|
var last = dl[dl.Count - 1];
|
|
|
|
if (last.Species > maxSpeciesOrigin && dl.Any(d => d.Species <= maxSpeciesOrigin))
|
|
|
|
dl.RemoveAt(dl.Count - 1);
|
|
|
|
|
2019-02-24 21:57:10 +00:00
|
|
|
// Last species is the wild/hatched species, the minimum level is 1 because it has not evolved from previous species
|
2018-05-19 19:07:50 +00:00
|
|
|
last = dl[dl.Count - 1];
|
|
|
|
last.MinLevel = 1;
|
|
|
|
last.RequiresLvlUp = false;
|
|
|
|
return dl;
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
2018-06-19 02:10:21 +00:00
|
|
|
private static void UpdateMinValues(IReadOnlyList<EvoCriteria> dl, EvolutionMethod evo)
|
2018-05-19 19:07:50 +00:00
|
|
|
{
|
|
|
|
var last = dl[dl.Count - 1];
|
2018-07-02 02:55:23 +00:00
|
|
|
if (!evo.RequiresLevelUp)
|
2018-05-19 19:07:50 +00:00
|
|
|
{
|
2018-07-02 02:55:23 +00:00
|
|
|
// Evolutions like elemental stones, trade, etc
|
|
|
|
last.MinLevel = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (evo.Level == 0)
|
|
|
|
{
|
2019-02-24 21:57:10 +00:00
|
|
|
// Friendship based Evolutions, Pichu -> Pikachu, Eevee -> Umbreon, etc
|
2018-07-02 02:55:23 +00:00
|
|
|
last.MinLevel = 2;
|
2018-05-19 19:07:50 +00:00
|
|
|
|
2018-07-02 02:55:23 +00:00
|
|
|
var first = dl[0];
|
|
|
|
if (dl.Count > 1 && !first.RequiresLvlUp)
|
2019-02-24 21:57:10 +00:00
|
|
|
first.MinLevel = 2; // Raichu from Pikachu would have a minimum level of 1; accounting for Pichu (level up required) results in a minimum level of 2
|
2018-05-19 19:07:50 +00:00
|
|
|
}
|
|
|
|
else // level up evolutions
|
|
|
|
{
|
|
|
|
last.MinLevel = evo.Level;
|
|
|
|
|
|
|
|
var first = dl[0];
|
|
|
|
if (dl.Count > 1)
|
|
|
|
{
|
2019-02-24 21:57:10 +00:00
|
|
|
if (first.RequiresLvlUp)
|
|
|
|
{
|
|
|
|
if (first.MinLevel <= evo.Level)
|
|
|
|
first.MinLevel = evo.Level + 1; // Pokemon like Crobat, its minimum level is Golbat minimum level + 1
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (first.MinLevel < evo.Level)
|
|
|
|
first.MinLevel = evo.Level; // Pokemon like Nidoqueen who evolve with an evolution stone, minimum level is prior evolution minimum level
|
|
|
|
}
|
2018-05-19 19:07:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
last.RequiresLvlUp = evo.RequiresLevelUp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|