mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-09-30 15:48:36 -05:00
Misc fixes
This commit is contained in:
@@ -39,7 +39,7 @@ public bool IsBallValid(Ball ball, ushort currentSpecies)
|
||||
|
||||
protected override PKM GetBlank() => OriginFormat switch
|
||||
{
|
||||
PogoImportFormat.PK7 => new PK8(),
|
||||
PogoImportFormat.PK7 => new PK9(),
|
||||
PogoImportFormat.PB7 => new PB7(),
|
||||
PogoImportFormat.PK8 => new PK8(),
|
||||
PogoImportFormat.PA8 => new PA8(),
|
||||
|
||||
@@ -57,6 +57,9 @@ public IEnumerable<IEncounterable> GetEncounters(PKM pk, EvoCriteria[] chain, Le
|
||||
if (area.Species != evo.Species)
|
||||
continue;
|
||||
|
||||
if (area.Form != evo.Form && !FormInfo.IsFormChangeable(area.Species, area.Form, evo.Form, EntityContext.Gen8, pk.Context))
|
||||
continue;
|
||||
|
||||
var slots = area.GetMatchingSlots(pk, evo);
|
||||
foreach (var z in slots)
|
||||
{
|
||||
|
||||
@@ -44,12 +44,12 @@ private static bool IsValidEvolution(PKM pk, EvolutionHistory history, IEncounte
|
||||
return true; // never evolved
|
||||
|
||||
var current = history.Get(pk.Context);
|
||||
if (!EvolutionUtil.Contains(current, curSpecies))
|
||||
if (!EvolutionHistory.HasVisited(current, curSpecies))
|
||||
return false; // Can't exist as current species
|
||||
|
||||
// Double check that our encounter was able to exist as the encounter species.
|
||||
var original = history.Get(enc.Context);
|
||||
if (!EvolutionUtil.Contains(original, encSpecies))
|
||||
if (!EvolutionHistory.HasVisited(original, encSpecies))
|
||||
return false;
|
||||
|
||||
// Bigender->Fixed (non-Genderless) destination species, accounting for PID-Gender relationship
|
||||
|
||||
@@ -254,5 +254,16 @@ public bool TryDevolve(ISpeciesForm head, PKM pk, byte currentMaxLevel, byte lev
|
||||
=> Tree.Reverse.TryDevolve(head, pk, currentMaxLevel, levelMin, skipChecks, out result);
|
||||
|
||||
public bool TryEvolve(ISpeciesForm head, ISpeciesForm next, PKM pk, byte currentMaxLevel, byte levelMin, bool skipChecks, out EvoCriteria result)
|
||||
=> Tree.Forward.TryEvolve(head, next, pk, currentMaxLevel, levelMin, skipChecks, out result);
|
||||
{
|
||||
var b = Tree.Forward.TryEvolve(head, next, pk, currentMaxLevel, levelMin, skipChecks, out result);
|
||||
return b && !IsEvolutionBanned(head);
|
||||
}
|
||||
|
||||
// Unreleased Item
|
||||
private static bool IsEvolutionBanned(in ISpeciesForm head) => head.Species switch
|
||||
{
|
||||
(int)Species.Slowpoke => head.Form != 1,
|
||||
(int)Species.Slowbro => head.Form != 2,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,16 +83,6 @@ public static int IndexOf(Span<EvoCriteria> result, ushort species)
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static bool Contains(ReadOnlySpan<EvoCriteria> result, ushort species)
|
||||
{
|
||||
foreach (ref readonly var z in result)
|
||||
{
|
||||
if (z.Species == species)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Revises the <see cref="result"/> to account for a new maximum <see cref="level"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -238,7 +238,7 @@ public int GetLevelLearnMove(ushort move)
|
||||
return Levels[index];
|
||||
}
|
||||
|
||||
public ReadOnlySpan<ushort> GetBaseEggMoves(int level)
|
||||
public ReadOnlySpan<ushort> GetBaseEggMoves(byte level)
|
||||
{
|
||||
// Count moves <= level
|
||||
var count = 0;
|
||||
|
||||
@@ -21,9 +21,9 @@ namespace PKHeX.Core;
|
||||
public readonly ReadOnlySpan<ushort> Moves;
|
||||
|
||||
/// <summary> Level the egg originated at. </summary>
|
||||
public readonly int Level;
|
||||
public readonly byte Level;
|
||||
|
||||
public BreedInfo(Span<T> actual, Span<byte> possible, Learnset learnset, ReadOnlySpan<ushort> moves, int level)
|
||||
public BreedInfo(Span<T> actual, Span<byte> possible, Learnset learnset, ReadOnlySpan<ushort> moves, byte level)
|
||||
{
|
||||
Actual = actual;
|
||||
Possible = possible;
|
||||
|
||||
@@ -85,6 +85,34 @@ public static bool IsMatchTeraTypePersonalAnyForm(in ushort species, in byte ori
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsMatchTeraTypeImport(PersonalInfo9SV pi, in byte original)
|
||||
{
|
||||
var import = TeraTypeUtil.GetTeraTypeImport(pi.Type1, pi.Type2);
|
||||
return (MoveType)original == import;
|
||||
}
|
||||
|
||||
public static bool IsMatchTeraTypePersonalImport(in ushort species, in byte form, in byte original)
|
||||
{
|
||||
var pi = PersonalTable.SV[species, form];
|
||||
return IsMatchTeraTypeImport(pi, original);
|
||||
}
|
||||
|
||||
public static bool IsMatchTeraTypePersonalAnyFormImport(in ushort species, in byte original)
|
||||
{
|
||||
var pt = PersonalTable.SV;
|
||||
var pi = pt.GetFormEntry(species, 0);
|
||||
if (pi.IsPresentInGame && IsMatchTeraTypeImport(pi, original))
|
||||
return true;
|
||||
var fc = pi.FormCount;
|
||||
for (byte form = 1; form < fc; form++)
|
||||
{
|
||||
pi = pt.GetFormEntry(species, form);
|
||||
if (pi.IsPresentInGame && IsMatchTeraTypeImport(pi, original))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static byte GetTeraTypeFromPersonal(in ushort species, in byte form, in ulong pivot)
|
||||
{
|
||||
var pi = PersonalTable.SV[species, form];
|
||||
|
||||
@@ -107,7 +107,7 @@ private static bool GetCatchRateMatchesPreEvolution(PK1 pk, byte catch_rate)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!EvolutionTree.Evolves1.Reverse.TryDevolve(head, pk, max, 2, false, out var next))
|
||||
if (!EvolutionGroup1.Instance.TryDevolve(head, pk, max, 2, false, out var next))
|
||||
break;
|
||||
head = next;
|
||||
max = next.LevelMax;
|
||||
|
||||
@@ -110,12 +110,10 @@ public static bool IsFormChangeable(ushort species, byte oldForm, byte newForm,
|
||||
}
|
||||
if (species is (int)Deerling or (int)Sawsbuck)
|
||||
{
|
||||
return origin switch
|
||||
{
|
||||
EntityContext.Gen5 => true,
|
||||
EntityContext.Gen9 => true,
|
||||
_ => false, // todo home sv
|
||||
};
|
||||
if (origin == EntityContext.Gen5)
|
||||
return true; // B/W
|
||||
if (current.Generation() >= 8)
|
||||
return true; // Via S/V
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,13 @@ private CheckResult VerifyFormArgument(LegalityAnalysis data, IFormArgument f)
|
||||
=> GetValid(LFormArgumentValid),
|
||||
|
||||
Furfrou when pk.Form != 0 => !IsFormArgumentDayCounterValid(f, 5, true) ? GetInvalid(LFormArgumentInvalid) : GetValid(LFormArgumentValid),
|
||||
Hoopa when pk.Form == 1 => !IsFormArgumentDayCounterValid(f, 3) ? GetInvalid(LFormArgumentInvalid) : GetValid(LFormArgumentValid),
|
||||
Hoopa when pk.Form == 1 => data.Info.EvoChainsAllGens switch
|
||||
{
|
||||
{ HasVisitedGen9: true } when arg == 0 => GetValid(LFormArgumentValid), // Value not applied on form change, and reset when reverted.
|
||||
{ HasVisitedGen6: true } when IsFormArgumentDayCounterValid(f, 3) => GetValid(LFormArgumentValid), // 0-3 via OR/AS
|
||||
{ HasVisitedGen7: true } when IsFormArgumentDayCounterValid(f, 3) && f.FormArgumentRemain != 0 => GetValid(LFormArgumentValid), // 1-3 via Gen7
|
||||
_ => GetInvalid(LFormArgumentInvalid),
|
||||
},
|
||||
Yamask when pk.Form == 1 => arg switch
|
||||
{
|
||||
not 0 when pk.IsEgg => GetInvalid(LFormArgumentNotAllowed),
|
||||
|
||||
@@ -63,11 +63,14 @@ private static void CheckLearnset(LegalityAnalysis data, PA8 pa)
|
||||
if (moveCount == 4)
|
||||
return;
|
||||
|
||||
// Flag move slots that are empty.
|
||||
if (pa.Tracker != 0 || !ParseSettings.IgnoreTransferIfNoTracker)
|
||||
return; // Can delete moves in PA8 moveset via HOME.
|
||||
|
||||
// Get the bare minimum moveset.
|
||||
Span<ushort> expect = stackalloc ushort[4];
|
||||
var minMoveCount = LoadBareMinimumMoveset(data.EncounterMatch, data.Info.EvoChainsAllGens, pa, expect);
|
||||
|
||||
// Flag move slots that are empty.
|
||||
var moves = data.Info.Moves;
|
||||
for (int i = moveCount; i < minMoveCount; i++)
|
||||
{
|
||||
|
||||
@@ -192,20 +192,20 @@ private void VerifySVStats(LegalityAnalysis data, PK9 pk9)
|
||||
|
||||
public static int GetTeraImportMatch(ReadOnlySpan<EvoCriteria> evos, MoveType actual, IEncounterTemplate enc)
|
||||
{
|
||||
// Sanitize out Form here for Arceus/Silvally -- rewrite via evotree later.
|
||||
if (evos.Length == 0 || evos[0].Species is (int)Species.Arceus or (int)Species.Silvally)
|
||||
// Sanitize out Form here for Arceus
|
||||
if (evos.Length == 0 || evos[0].Species is (int)Species.Arceus)
|
||||
return actual == MoveType.Normal ? 0 : -1;
|
||||
for (int i = evos.Length - 1; i >= 0; i--)
|
||||
{
|
||||
var evo = evos[i];
|
||||
if (FormInfo.IsFormChangeable(evo.Species, enc.Form, evo.Form, enc.Context, EntityContext.Gen9))
|
||||
{
|
||||
if (Tera9RNG.IsMatchTeraTypePersonalAnyForm(evo.Species, (byte)actual))
|
||||
if (Tera9RNG.IsMatchTeraTypePersonalAnyFormImport(evo.Species, (byte)actual))
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Tera9RNG.IsMatchTeraTypePersonal(evo.Species, evo.Form, (byte)actual))
|
||||
if (Tera9RNG.IsMatchTeraTypePersonalImport(evo.Species, evo.Form, (byte)actual))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,6 +399,10 @@ private void EnsureScaleSizeExists()
|
||||
{
|
||||
// Fix for PLA static encounter Alphas with 127 scale.
|
||||
Core.HeightScalar = Core.WeightScalar = 255;
|
||||
if (DataPA8 is { Scale: not 255 } pa8)
|
||||
pa8.Scale = 255;
|
||||
if (DataPK9 is { Scale: not 255 } pk9)
|
||||
pk9.Scale = 255;
|
||||
return;
|
||||
}
|
||||
if (GO_HOME || FirstScaleData is IScaledSize3)
|
||||
|
||||
@@ -150,7 +150,13 @@ public static bool IsConvertibleToFormat(PKM pk, int format)
|
||||
// Every format can eventually feed into HOME. Don't bother checking current type.
|
||||
var type = PKH.GetType(destType);
|
||||
if (type is not HomeGameDataFormat.None)
|
||||
return HOME.GetEntity(pk).ConvertToPKM(type);
|
||||
{
|
||||
var pkh = HOME.GetEntity(pk);
|
||||
var converted = pkh.ConvertToPKM(type);
|
||||
if (converted is null)
|
||||
result = IncompatibleSpecies;
|
||||
return converted;
|
||||
}
|
||||
|
||||
result = NoTransferRoute;
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
@@ -7,23 +5,24 @@ namespace PKHeX.Core.Tests.Legality;
|
||||
|
||||
public class LegalityData
|
||||
{
|
||||
[Fact]
|
||||
public void EvolutionsOrdered() // feebas, see issue #2394
|
||||
[Theory]
|
||||
[InlineData(Species.Feebas, 0)] // feebas, see issue #2394
|
||||
[InlineData(Species.Crabrawler, 0)] // SV Crabrawler added a second, UseItem evolution method. Need to be sure it's before the more restrictive level-up method.
|
||||
public void EvolutionsOrdered(Species species, byte form)
|
||||
{
|
||||
int count = 0;
|
||||
var trees = typeof(EvolutionTree)
|
||||
.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.Select(z => z.GetValue(typeof(EvolutionTree)))
|
||||
.OfType<EvolutionTree>();
|
||||
|
||||
foreach (var tree in trees)
|
||||
for (var context = EntityContext.None + 1; context < EntityContext.MaxInvalid; context++)
|
||||
{
|
||||
var feebas = tree.Forward.GetForward((int)Species.Feebas, 0).Span;
|
||||
if (feebas.Length <= 1)
|
||||
if (!context.IsValid())
|
||||
continue;
|
||||
|
||||
var t1 = feebas[0].Method;
|
||||
var t2 = feebas[1].Method;
|
||||
var tree = EvolutionTree.GetEvolutionTree(context);
|
||||
var possible = tree.Forward.GetForward((ushort)species, form).Span;
|
||||
if (possible.Length <= 1)
|
||||
continue;
|
||||
|
||||
var t1 = possible[0].Method;
|
||||
var t2 = possible[1].Method;
|
||||
|
||||
t1.IsLevelUpRequired().Should().BeFalse();
|
||||
t2.IsLevelUpRequired().Should().BeTrue();
|
||||
@@ -31,20 +30,6 @@ public class LegalityData
|
||||
count++;
|
||||
}
|
||||
|
||||
count.Should().NotBe(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EvolutionsOrderedSV()
|
||||
{
|
||||
// SV Crabrawler added a second, UseItem evolution method. Need to be sure it's before the more restrictive level-up method.
|
||||
var tree = EvolutionTree.Evolves9;
|
||||
var crab = tree.Forward.GetForward((int)Species.Crabrawler, 0).Span;
|
||||
|
||||
var t1 = crab[0].Method;
|
||||
var t2 = crab[1].Method;
|
||||
|
||||
t1.IsLevelUpRequired().Should().BeFalse();
|
||||
t2.IsLevelUpRequired().Should().BeTrue();
|
||||
count.Should().BeGreaterThan(0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user