2019-09-13 06:20:52 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
|
|
namespace PKHeX.Core
|
|
|
|
|
{
|
2019-09-13 16:08:12 +00:00
|
|
|
|
/// <inheritdoc />
|
2019-09-13 06:20:52 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="GameVersion.Gen4"/> encounter area
|
|
|
|
|
/// </summary>
|
|
|
|
|
public abstract class EncounterArea4 : EncounterArea
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Reads the GBA Pak Special slots, cloning <see cref="EncounterSlot"/> data from the area's base encounter slots.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// These special slots only contain the info of species id; the level is copied from the corresponding <see cref="slotnums"/> index.
|
|
|
|
|
/// </remarks>
|
|
|
|
|
/// <param name="data">Encounter binary data</param>
|
|
|
|
|
/// <param name="ofs">Offset to read from</param>
|
|
|
|
|
/// <param name="slotSize">DP/Pt slotSize = 4 bytes/entry, HG/SS slotSize = 2 bytes/entry</param>
|
|
|
|
|
/// <param name="ReplacedSlots">Slots from regular encounter table that end up replaced by in-game conditions</param>
|
|
|
|
|
/// <param name="slotnums">Slot indexes to replace with read species IDs</param>
|
|
|
|
|
/// <param name="t">Slot type of the special encounter</param>
|
2020-08-21 23:35:49 +00:00
|
|
|
|
protected static List<EncounterSlot4> GetSlots4GrassSlotReplace(byte[] data, int ofs, int slotSize, EncounterSlot[] ReplacedSlots, int[] slotnums, SlotType t = SlotType.Grass)
|
2019-09-13 06:20:52 +00:00
|
|
|
|
{
|
2020-08-21 23:35:49 +00:00
|
|
|
|
var slots = new List<EncounterSlot4>();
|
2019-09-13 06:20:52 +00:00
|
|
|
|
|
|
|
|
|
int numslots = slotnums.Length;
|
|
|
|
|
for (int i = 0; i < numslots; i++)
|
|
|
|
|
{
|
|
|
|
|
var baseSlot = ReplacedSlots[slotnums[i]];
|
|
|
|
|
if (baseSlot.LevelMin <= 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
int species = BitConverter.ToUInt16(data, ofs + (i / (4 / slotSize) * slotSize));
|
|
|
|
|
if (species <= 0 || baseSlot.Species == species) // Empty or duplicate
|
|
|
|
|
continue;
|
|
|
|
|
|
2020-08-21 23:35:49 +00:00
|
|
|
|
var slot = (EncounterSlot4)baseSlot.Clone();
|
2019-09-13 06:20:52 +00:00
|
|
|
|
slot.Species = species;
|
|
|
|
|
slot.Type = t;
|
|
|
|
|
slot.SlotNumber = i;
|
|
|
|
|
slots.Add(slot);
|
|
|
|
|
}
|
|
|
|
|
return slots;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-21 23:35:49 +00:00
|
|
|
|
protected static IEnumerable<EncounterSlot4> MarkStaticMagnetExtras(IEnumerable<IEnumerable<List<EncounterSlot4>>> product)
|
2019-09-13 06:20:52 +00:00
|
|
|
|
{
|
2020-08-21 23:35:49 +00:00
|
|
|
|
var trackPermute = new List<EncounterSlot4>();
|
2019-09-13 06:20:52 +00:00
|
|
|
|
foreach (var p in product)
|
|
|
|
|
MarkStaticMagnetPermute(p.SelectMany(z => z), trackPermute);
|
|
|
|
|
return trackPermute;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-21 23:35:49 +00:00
|
|
|
|
protected static void MarkStaticMagnetPermute(IEnumerable<EncounterSlot4> grp, List<EncounterSlot4> trackPermute)
|
2019-09-13 06:20:52 +00:00
|
|
|
|
{
|
|
|
|
|
EncounterUtil.MarkEncountersStaticMagnetPullPermutation(grp, PersonalTable.HGSS, trackPermute);
|
|
|
|
|
}
|
2019-09-19 23:19:07 +00:00
|
|
|
|
|
2020-08-21 23:35:49 +00:00
|
|
|
|
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
2019-09-19 23:19:07 +00:00
|
|
|
|
{
|
2020-08-21 23:35:49 +00:00
|
|
|
|
if (pkm.Format != 4) // Met Location and Met Level are changed on PK4->PK5
|
|
|
|
|
return GetSlotsFuzzy(chain);
|
|
|
|
|
if (pkm.Met_Location != Location)
|
|
|
|
|
return Array.Empty<EncounterSlot>();
|
|
|
|
|
return GetSlotsMatching(chain, pkm.Met_Level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IEnumerable<EncounterSlot> GetSlotsMatching(IReadOnlyList<EvoCriteria> chain, int lvl)
|
|
|
|
|
{
|
|
|
|
|
foreach (var slot in Slots)
|
|
|
|
|
{
|
|
|
|
|
foreach (var evo in chain)
|
|
|
|
|
{
|
|
|
|
|
if (slot.Species != evo.Species)
|
|
|
|
|
continue;
|
2019-09-19 23:19:07 +00:00
|
|
|
|
|
2020-08-21 23:35:49 +00:00
|
|
|
|
if (slot.Form != evo.Form && !Legal.WildChangeFormAfter.Contains(slot.Species))
|
|
|
|
|
break;
|
|
|
|
|
if (!slot.IsLevelWithinRange(lvl))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
yield return slot;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IEnumerable<EncounterSlot> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> chain)
|
|
|
|
|
{
|
|
|
|
|
foreach (var slot in Slots)
|
|
|
|
|
{
|
|
|
|
|
foreach (var evo in chain)
|
|
|
|
|
{
|
|
|
|
|
if (slot.Species != evo.Species)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (slot.Form != evo.Form && !Legal.WildChangeFormAfter.Contains(slot.Species))
|
|
|
|
|
break;
|
|
|
|
|
if (!slot.IsLevelWithinRange(evo.MinLevel, evo.Level))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
yield return slot;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-19 23:19:07 +00:00
|
|
|
|
}
|
2019-09-13 06:20:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|