mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 14:44:24 +00:00
Include date legality parameters for LGPE
Extract common abstract class for GO transferred encounters Clamp minlevel instead of met level Add optional parameter for GO IV randomization Update go legality binaries with latest
This commit is contained in:
parent
770f7584c9
commit
26e0f31c95
13 changed files with 250 additions and 217 deletions
|
@ -28,7 +28,7 @@ namespace PKHeX.Core
|
|||
return areas;
|
||||
}
|
||||
|
||||
private const int entrySize = 2;
|
||||
private const int entrySize = (2 * sizeof(int)) + 2;
|
||||
|
||||
private static EncounterArea7g GetArea(byte[] data)
|
||||
{
|
||||
|
@ -36,39 +36,45 @@ namespace PKHeX.Core
|
|||
int species = sf & 0x7FF;
|
||||
int form = sf >> 11;
|
||||
|
||||
// Files are padded to be multiples of 4 bytes. The last entry might actually be padding.
|
||||
// Since we aren't saving a count up-front, just check if the last entry is valid.
|
||||
int count = (data.Length - 2) / entrySize;
|
||||
if (data[data.Length - 1] == 0) // type of "None" is not valid
|
||||
count--;
|
||||
|
||||
var result = new EncounterSlot7GO[count];
|
||||
var area = new EncounterArea7g(species, form) {Slots = result};
|
||||
|
||||
var result = new EncounterSlot7GO[(data.Length - 2) / entrySize];
|
||||
var area = new EncounterArea7g(species, form) { Slots = result };
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var offset = (i * entrySize) + 2;
|
||||
var shiny = (Shiny)data[offset];
|
||||
var type = (PogoType)data[offset + 1];
|
||||
result[i] = new EncounterSlot7GO(area, species, form, shiny, type);
|
||||
result[i] = ReadSlot(data, offset, area, species, form);
|
||||
}
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
private static EncounterSlot7GO ReadSlot(byte[] data, int offset, EncounterArea7g area, int species, int form)
|
||||
{
|
||||
int start = BitConverter.ToInt32(data, offset);
|
||||
int end = BitConverter.ToInt32(data, offset + 4);
|
||||
var shiny = (Shiny)data[offset + 8];
|
||||
var type = (PogoType)data[offset + 9];
|
||||
return new EncounterSlot7GO(area, species, form, type, shiny, start, end);
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
bool exists = chain.Any(z => z.Species == Species && z.Form == Form);
|
||||
if (!exists)
|
||||
var sf = chain.FirstOrDefault(z => z.Species == Species && z.Form == Form);
|
||||
if (sf == null)
|
||||
yield break;
|
||||
|
||||
var stamp = EncounterSlotGO.GetTimeStamp(pkm.Met_Year + 2000, pkm.Met_Month, pkm.Met_Day);
|
||||
var met = Math.Max(sf.MinLevel, pkm.Met_Level);
|
||||
foreach (var s in Slots)
|
||||
{
|
||||
var slot = (EncounterSlot7GO)s;
|
||||
if (!slot.IsLevelWithinRange(pkm.Met_Level))
|
||||
if (!slot.IsLevelWithinRange(met))
|
||||
continue;
|
||||
//if (!slot.IsBallValid(ball)) -- can have any of the in-game balls due to re-capture
|
||||
// continue;
|
||||
if (!slot.Shiny.IsValid(pkm))
|
||||
continue;
|
||||
if (!slot.IsWithinStartEnd(stamp))
|
||||
continue;
|
||||
yield return slot;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,16 +83,17 @@ namespace PKHeX.Core
|
|||
if (pkm.TSV == 0) // HOME doesn't assign TSV=0 to accounts.
|
||||
yield break;
|
||||
|
||||
bool exists = chain.Any(z => z.Species == Species && z.Form == Form);
|
||||
if (!exists)
|
||||
var sf = chain.FirstOrDefault(z => z.Species == Species && z.Form == Form);
|
||||
if (sf == null)
|
||||
yield break;
|
||||
|
||||
var ball = (Ball)pkm.Ball;
|
||||
var stamp = EncounterSlot8GO.GetTimeStamp(pkm.Met_Year + 2000, pkm.Met_Month, pkm.Met_Day);
|
||||
var stamp = EncounterSlotGO.GetTimeStamp(pkm.Met_Year + 2000, pkm.Met_Month, pkm.Met_Day);
|
||||
var met = Math.Max(sf.MinLevel, pkm.Met_Level);
|
||||
foreach (var s in Slots)
|
||||
{
|
||||
var slot = (EncounterSlot8GO)s;
|
||||
if (!slot.IsLevelWithinRange(pkm.Met_Level))
|
||||
if (!slot.IsLevelWithinRange(met))
|
||||
continue;
|
||||
if (!slot.IsBallValid(ball))
|
||||
continue;
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public sealed class EncounterSlot7GO : EncounterSlot, IPogoSlot
|
||||
{
|
||||
public override int Generation => 7;
|
||||
public PogoType Type { get; }
|
||||
public Shiny Shiny { get; }
|
||||
|
||||
public override string LongName => $"{Name} ({Type})";
|
||||
|
||||
public EncounterSlot7GO(EncounterArea7g area, int species, int form, Shiny shiny, PogoType type) : base(area)
|
||||
{
|
||||
Species = species;
|
||||
Form = form;
|
||||
LevelMin = type.GetMinLevel();
|
||||
LevelMax = EncountersGO.MAX_LEVEL;
|
||||
|
||||
Shiny = shiny;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public sealed class EncounterSlot8GO : EncounterSlot, IPogoSlotTime
|
||||
{
|
||||
public override int Generation => 8;
|
||||
public GameVersion OriginGroup { get; }
|
||||
|
||||
public PogoType Type { get; }
|
||||
public Shiny Shiny { get; }
|
||||
public int Start { get; }
|
||||
public int End { get; }
|
||||
|
||||
public override string LongName
|
||||
{
|
||||
get
|
||||
{
|
||||
var init = $"{Name} ({Type})";
|
||||
if (Start == 0 && End == 0)
|
||||
return init;
|
||||
return $"{init}: {GetDateString(Start)}-{GetDateString(End)}";
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetDateString(int time) => time == 0 ? "X" : GetDate(time).ToString("yyyy.MM.dd");
|
||||
|
||||
private static DateTime GetDate(int time)
|
||||
{
|
||||
var d = time & 0xFF;
|
||||
var m = (time >> 8) & 0xFF;
|
||||
var y = time >> 16;
|
||||
return new DateTime(y, m, d);
|
||||
}
|
||||
|
||||
public bool IsWithinStartEnd(int y, int m, int d)
|
||||
{
|
||||
var stamp = GetTimeStamp(y, m, d);
|
||||
return IsWithinStartEnd(stamp);
|
||||
}
|
||||
|
||||
public bool IsWithinStartEnd(int stamp)
|
||||
{
|
||||
if (End == 0)
|
||||
return Start <= stamp;
|
||||
if (Start == 0)
|
||||
return stamp <= End;
|
||||
return Start <= stamp && stamp <= End;
|
||||
}
|
||||
|
||||
public static int GetTimeStamp(int y, int m, int d) => (y << 16) | (m << 8) | d;
|
||||
|
||||
public EncounterSlot8GO(EncounterArea8g area, int species, int form, GameVersion gameVersion, PogoType type, Shiny shiny, int start, int end) : base(area)
|
||||
{
|
||||
Species = species;
|
||||
Form = form;
|
||||
LevelMin = type.GetMinLevel();
|
||||
LevelMax = 40;
|
||||
Start = start;
|
||||
End = end;
|
||||
|
||||
Shiny = shiny;
|
||||
Type = type;
|
||||
|
||||
OriginGroup = gameVersion;
|
||||
}
|
||||
|
||||
public int GetMinIV() => Type.GetMinIV();
|
||||
public bool IsBallValid(Ball ball) => Type.IsBallValid(ball);
|
||||
|
||||
protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk)
|
||||
{
|
||||
base.ApplyDetails(sav, criteria, pk);
|
||||
if (Start != 0 || End != 0)
|
||||
pk.MetDate = GetRandomValidDate();
|
||||
pk.Ball = (int)Type.GetValidBall();
|
||||
}
|
||||
|
||||
public DateTime GetRandomValidDate()
|
||||
{
|
||||
if (Start == 0)
|
||||
return End == 0 ? DateTime.Now : GetDate(End);
|
||||
|
||||
var end = Math.Max(Start, End);
|
||||
var delta = end - Start;
|
||||
var bias = Util.Rand.Next(0, delta + 1);
|
||||
return GetDate(Start).AddDays(bias);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPogoSlot
|
||||
{
|
||||
Shiny Shiny { get; }
|
||||
PogoType Type { get; }
|
||||
}
|
||||
|
||||
public interface IPogoSlotTime : IPogoSlot
|
||||
{
|
||||
int Start { get; }
|
||||
int End { get; }
|
||||
}
|
||||
|
||||
public enum PogoType : byte
|
||||
{
|
||||
None, // Don't use this.
|
||||
|
||||
Wild,
|
||||
Egg,
|
||||
|
||||
/// <summary> Raid Boss, requires Lv. 15 and IV=1 </summary>
|
||||
Raid15 = 10,
|
||||
/// <summary> Raid Boss, requires Lv. 20 and IV=10 </summary>
|
||||
Raid20,
|
||||
|
||||
/// <summary> Field Research, requires Lv. 15 and IV=1 </summary>
|
||||
Field15 = 20,
|
||||
/// <summary> Field Research, requires Lv. 15 and IV=10 (Mythicals) </summary>
|
||||
FieldM,
|
||||
/// <summary> Field Research, requires Lv. 15 and IV=10 (Mythicals, Poké Ball only) </summary>
|
||||
FieldP,
|
||||
/// <summary> Field Research, requires Lv. 20 and IV=10 (GBL Mythicals) </summary>
|
||||
Field20,
|
||||
|
||||
/// <summary> Purified, requires Lv. 8 and IV=1 (Premier Ball) </summary>
|
||||
Shadow = 30,
|
||||
/// <summary> Purified, requires Lv. 8 and IV=1 (No Premier Ball) </summary>
|
||||
ShadowPGU,
|
||||
}
|
||||
|
||||
public static class PogoTypeExtensions
|
||||
{
|
||||
public static int GetMinLevel(this PogoType t) => t switch
|
||||
{
|
||||
PogoType.Raid15 => 15,
|
||||
PogoType.Raid20 => 20,
|
||||
PogoType.Field15 => 15,
|
||||
PogoType.FieldM => 15,
|
||||
PogoType.Field20 => 20,
|
||||
PogoType.Shadow => 8,
|
||||
PogoType.ShadowPGU => 8,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
public static int GetMinIV(this PogoType t) => t switch
|
||||
{
|
||||
PogoType.Wild => 0,
|
||||
PogoType.Raid20 => 10,
|
||||
PogoType.FieldM => 10,
|
||||
PogoType.FieldP => 10,
|
||||
PogoType.Field20 => 10,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
public static bool IsBallValid(this PogoType t, Ball b)
|
||||
{
|
||||
var req = t.GetValidBall();
|
||||
if (req == Ball.None)
|
||||
return (uint) (b - 2) <= 2; // Poke, Great, Ultra
|
||||
return b == req;
|
||||
}
|
||||
|
||||
public static Ball GetValidBall(this PogoType t) => t switch
|
||||
{
|
||||
PogoType.Egg => Ball.Poke,
|
||||
PogoType.FieldP => Ball.Poke,
|
||||
PogoType.Raid15 => Ball.Premier,
|
||||
PogoType.Raid20 => Ball.Premier,
|
||||
_ => Ball.None, // Poke, Great, Ultra
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public sealed class EncounterSlot7GO : EncounterSlotGO
|
||||
{
|
||||
public override int Generation => 7;
|
||||
|
||||
public EncounterSlot7GO(EncounterArea7g area, int species, int form, PogoType type, Shiny shiny, int start, int end)
|
||||
: base(area, start, end, type, shiny)
|
||||
{
|
||||
Species = species;
|
||||
Form = form;
|
||||
}
|
||||
|
||||
protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk)
|
||||
{
|
||||
base.ApplyDetails(sav, criteria, pk);
|
||||
var pb = (PB7) pk;
|
||||
pb.AwakeningSetAllTo(2);
|
||||
pb.HeightScalar = PokeSizeUtil.GetRandomScalar();
|
||||
pb.WeightScalar = PokeSizeUtil.GetRandomScalar();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public sealed class EncounterSlot8GO : EncounterSlotGO
|
||||
{
|
||||
public override int Generation => 8;
|
||||
public GameVersion OriginGroup { get; }
|
||||
|
||||
public EncounterSlot8GO(EncounterArea8g area, int species, int form, GameVersion gameVersion, PogoType type, Shiny shiny, int start, int end)
|
||||
: base(area, start, end, type, shiny)
|
||||
{
|
||||
Species = species;
|
||||
Form = form;
|
||||
|
||||
OriginGroup = gameVersion;
|
||||
}
|
||||
|
||||
public int GetMinIV() => Type.GetMinIV();
|
||||
public bool IsBallValid(Ball ball) => Type.IsBallValid(ball);
|
||||
|
||||
protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk)
|
||||
{
|
||||
var pk8 = (PK8)pk;
|
||||
pk8.HT_Name = "PKHeX";
|
||||
pk8.HT_Language = 2;
|
||||
pk8.CurrentHandler = 1;
|
||||
|
||||
base.ApplyDetails(sav, criteria, pk);
|
||||
pk.Ball = (int)Type.GetValidBall();
|
||||
|
||||
pk8.HeightScalar = PokeSizeUtil.GetRandomScalar();
|
||||
pk8.WeightScalar = PokeSizeUtil.GetRandomScalar();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public abstract class EncounterSlotGO : EncounterSlot, IPogoSlotTime
|
||||
{
|
||||
public PogoType Type { get; }
|
||||
public Shiny Shiny { get; }
|
||||
public int Start { get; }
|
||||
public int End { get; }
|
||||
|
||||
protected EncounterSlotGO(EncounterArea area, int start, int end, PogoType type, Shiny shiny) : base(area)
|
||||
{
|
||||
LevelMin = type.GetMinLevel();
|
||||
LevelMax = EncountersGO.MAX_LEVEL;
|
||||
|
||||
Start = start;
|
||||
End = end;
|
||||
|
||||
Shiny = shiny;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public sealed override string LongName
|
||||
{
|
||||
get
|
||||
{
|
||||
var init = $"{Name} ({Type})";
|
||||
if (Start == 0 && End == 0)
|
||||
return init;
|
||||
return $"{init}: {GetDateString(Start)}-{GetDateString(End)}";
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetDateString(int time) => time == 0 ? "X" : GetDate(time).ToString("yyyy.MM.dd");
|
||||
|
||||
private static DateTime GetDate(int time)
|
||||
{
|
||||
var d = time & 0xFF;
|
||||
var m = (time >> 8) & 0xFF;
|
||||
var y = time >> 16;
|
||||
return new DateTime(y, m, d);
|
||||
}
|
||||
|
||||
public bool IsWithinStartEnd(int stamp)
|
||||
{
|
||||
if (End == 0)
|
||||
return Start <= stamp;
|
||||
if (Start == 0)
|
||||
return stamp <= End;
|
||||
return Start <= stamp && stamp <= End;
|
||||
}
|
||||
|
||||
public static int GetTimeStamp(int y, int m, int d) => (y << 16) | (m << 8) | d;
|
||||
|
||||
public DateTime GetRandomValidDate()
|
||||
{
|
||||
if (Start == 0)
|
||||
return End == 0 ? DateTime.Now : GetDate(End);
|
||||
|
||||
var end = Math.Max(Start, End);
|
||||
var delta = end - Start;
|
||||
var bias = Util.Rand.Next(0, delta + 1);
|
||||
return GetDate(Start).AddDays(bias);
|
||||
}
|
||||
|
||||
protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk)
|
||||
{
|
||||
base.ApplyDetails(sav, criteria, pk);
|
||||
if (Start != 0 || End != 0)
|
||||
pk.MetDate = GetRandomValidDate();
|
||||
pk.SetRandomIVsGO(Type.GetMinIV());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public interface IPogoSlot
|
||||
{
|
||||
Shiny Shiny { get; }
|
||||
PogoType Type { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public interface IPogoSlotTime : IPogoSlot
|
||||
{
|
||||
int Start { get; }
|
||||
int End { get; }
|
||||
}
|
||||
}
|
71
PKHeX.Core/Legality/Encounters/EncounterSlot/GO/PogoType.cs
Normal file
71
PKHeX.Core/Legality/Encounters/EncounterSlot/GO/PogoType.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public enum PogoType : byte
|
||||
{
|
||||
None, // Don't use this.
|
||||
|
||||
Wild,
|
||||
Egg,
|
||||
|
||||
/// <summary> Raid Boss, requires Lv. 15 and IV=1 </summary>
|
||||
Raid15 = 10,
|
||||
/// <summary> Raid Boss, requires Lv. 20 and IV=10 </summary>
|
||||
Raid20,
|
||||
|
||||
/// <summary> Field Research, requires Lv. 15 and IV=1 </summary>
|
||||
Field15 = 20,
|
||||
/// <summary> Field Research, requires Lv. 15 and IV=10 (Mythicals) </summary>
|
||||
FieldM,
|
||||
/// <summary> Field Research, requires Lv. 15 and IV=10 (Mythicals, Poké Ball only) </summary>
|
||||
FieldP,
|
||||
/// <summary> Field Research, requires Lv. 20 and IV=10 (GBL Mythicals) </summary>
|
||||
Field20,
|
||||
|
||||
/// <summary> Purified, requires Lv. 8 and IV=1 (Premier Ball) </summary>
|
||||
Shadow = 30,
|
||||
/// <summary> Purified, requires Lv. 8 and IV=1 (No Premier Ball) </summary>
|
||||
ShadowPGU,
|
||||
}
|
||||
|
||||
public static class PogoTypeExtensions
|
||||
{
|
||||
public static int GetMinLevel(this PogoType t) => t switch
|
||||
{
|
||||
PogoType.Raid15 => 15,
|
||||
PogoType.Raid20 => 20,
|
||||
PogoType.Field15 => 15,
|
||||
PogoType.FieldM => 15,
|
||||
PogoType.Field20 => 20,
|
||||
PogoType.Shadow => 8,
|
||||
PogoType.ShadowPGU => 8,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
public static int GetMinIV(this PogoType t) => t switch
|
||||
{
|
||||
PogoType.Wild => 0,
|
||||
PogoType.Raid20 => 10,
|
||||
PogoType.FieldM => 10,
|
||||
PogoType.FieldP => 10,
|
||||
PogoType.Field20 => 10,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
public static bool IsBallValid(this PogoType t, Ball b)
|
||||
{
|
||||
var req = t.GetValidBall();
|
||||
if (req == Ball.None)
|
||||
return (uint)(b - 2) <= 2; // Poke, Great, Ultra
|
||||
return b == req;
|
||||
}
|
||||
|
||||
public static Ball GetValidBall(this PogoType t) => t switch
|
||||
{
|
||||
PogoType.Egg => Ball.Poke,
|
||||
PogoType.FieldP => Ball.Poke,
|
||||
PogoType.Raid15 => Ball.Premier,
|
||||
PogoType.Raid20 => Ball.Premier,
|
||||
_ => Ball.None, // Poke, Great, Ultra
|
||||
};
|
||||
}
|
||||
}
|
|
@ -990,13 +990,13 @@ namespace PKHeX.Core
|
|||
return IVs = ivs;
|
||||
}
|
||||
|
||||
private int[] SetRandomIVsGO()
|
||||
public int[] SetRandomIVsGO(int minIV = 0)
|
||||
{
|
||||
int[] ivs = new int[6];
|
||||
var rnd = Util.Rand;
|
||||
ivs[0] = (rnd.Next(16) << 1) | 1; // hp
|
||||
ivs[1] = ivs[4] = (rnd.Next(16) << 1) | 1; // attack
|
||||
ivs[2] = ivs[5] = (rnd.Next(16) << 1) | 1; // defense
|
||||
ivs[0] = (rnd.Next(minIV, 16) << 1) | 1; // hp
|
||||
ivs[1] = ivs[4] = (rnd.Next(minIV, 16) << 1) | 1; // attack
|
||||
ivs[2] = ivs[5] = (rnd.Next(minIV, 16) << 1) | 1; // defense
|
||||
ivs[3] = rnd.Next(MaxIV + 1); // speed
|
||||
return IVs = ivs;
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue