PKHeX/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8.cs
Kurt ccf87242c1 Eliminate boxing on encounter search (criteria)
struct implementing interface is boxed when passed to method that accepts interface (not generic method).
Removes IDexLevel (no other inheritors but EvoCriteria) and uses the primitive the data is stored (array, not IReadOnlyList) for slightly better perf.
2022-05-07 18:29:36 -07:00

120 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using static PKHeX.Core.OverworldCorrelation8Requirement;
namespace PKHeX.Core
{
/// <summary>
/// Generation 8 Static Encounter
/// </summary>
/// <inheritdoc cref="EncounterStatic"/>
public record EncounterStatic8(GameVersion Version) : EncounterStatic(Version), IDynamaxLevel, IGigantamax, IRelearn, IOverworldCorrelation8
{
public sealed override int Generation => 8;
public bool ScriptedNoMarks { get; init; }
public bool CanGigantamax { get; set; }
public byte DynamaxLevel { get; set; }
public IReadOnlyList<int> Relearn { get; init; } = Array.Empty<int>();
public AreaWeather8 Weather {get; init; } = AreaWeather8.Normal;
protected override bool IsMatchLevel(PKM pkm, EvoCriteria evo)
{
var met = pkm.Met_Level;
var lvl = Level;
if (met == lvl)
return true;
if (lvl < EncounterArea8.BoostLevel && EncounterArea8.IsBoostedArea60(Location))
return met == EncounterArea8.BoostLevel;
return false;
}
public override bool IsMatchExact(PKM pkm, EvoCriteria evo)
{
if (pkm is IDynamaxLevel d && d.DynamaxLevel < DynamaxLevel)
return false;
if (pkm.Met_Level < EncounterArea8.BoostLevel && Weather is AreaWeather8.Heavy_Fog && EncounterArea8.IsBoostedArea60Fog(Location))
return false;
return base.IsMatchExact(pkm, evo);
}
protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk)
{
base.ApplyDetails(sav, criteria, pk);
if (Weather is AreaWeather8.Heavy_Fog && EncounterArea8.IsBoostedArea60Fog(Location))
pk.CurrentLevel = pk.Met_Level = EncounterArea8.BoostLevel;
var req = GetRequirement(pk);
if (req != MustHave)
{
pk.SetRandomEC();
return;
}
var shiny = Shiny == Shiny.Random ? Shiny.FixedValue : Shiny;
Overworld8RNG.ApplyDetails(pk, criteria, shiny, FlawlessIVCount);
}
public bool IsOverworldCorrelation
{
get
{
if (Gift)
return false; // gifts can have any 128bit seed from overworld
if (ScriptedNoMarks)
return false; // scripted encounters don't act as saved spawned overworld encounters
return true;
}
}
public OverworldCorrelation8Requirement GetRequirement(PKM pk) => IsOverworldCorrelation
? MustHave
: MustNotHave;
public bool IsOverworldCorrelationCorrect(PKM pk)
{
return Overworld8RNG.ValidateOverworldEncounter(pk, Shiny == Shiny.Random ? Shiny.FixedValue : Shiny, FlawlessIVCount);
}
public override EncounterMatchRating GetMatchRating(PKM pkm)
{
var rating = base.GetMatchRating(pkm);
if (rating != EncounterMatchRating.Match)
return rating;
var req = GetRequirement(pkm);
bool correlation = IsOverworldCorrelationCorrect(pkm);
if ((req == MustHave) != correlation)
return EncounterMatchRating.DeferredErrors;
// Only encounter slots can have these marks; defer for collisions.
if (pkm.Species == (int) Core.Species.Shedinja)
{
// Loses Mark on evolution to Shedinja, but not affixed ribbon value.
return pkm switch
{
IRibbonSetMark8 {RibbonMarkCurry: true} => EncounterMatchRating.DeferredErrors,
PK8 {AffixedRibbon: (int) RibbonIndex.MarkCurry} => EncounterMatchRating.Deferred,
_ => EncounterMatchRating.Match,
};
}
if (pkm is IRibbonSetMark8 m && (m.RibbonMarkCurry || m.RibbonMarkFishing || m.HasWeatherMark()))
return EncounterMatchRating.DeferredErrors;
return EncounterMatchRating.Match;
}
}
public interface IOverworldCorrelation8
{
OverworldCorrelation8Requirement GetRequirement(PKM pk);
bool IsOverworldCorrelationCorrect(PKM pk);
}
public enum OverworldCorrelation8Requirement
{
CanBeEither,
MustHave,
MustNotHave,
}
}