using System;
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
{
///
///
/// encounter area
///
public abstract class EncounterArea4 : EncounterArea
{
///
/// Reads the GBA Pak Special slots, cloning data from the area's base encounter slots.
///
///
/// These special slots only contain the info of species id; the level is copied from the corresponding index.
///
/// Encounter binary data
/// Offset to read from
/// DP/Pt slotSize = 4 bytes/entry, HG/SS slotSize = 2 bytes/entry
/// Slots from regular encounter table that end up replaced by in-game conditions
/// Slot indexes to replace with read species IDs
/// Slot type of the special encounter
protected static List GetSlots4GrassSlotReplace(byte[] data, int ofs, int slotSize, EncounterSlot[] ReplacedSlots, int[] slotnums, SlotType t = SlotType.Grass)
{
var slots = new List();
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;
var slot = (EncounterSlot4)baseSlot.Clone();
slot.Species = species;
slot.Type = t;
slot.SlotNumber = i;
slots.Add(slot);
}
return slots;
}
protected static IEnumerable MarkStaticMagnetExtras(IEnumerable>> product)
{
var trackPermute = new List();
foreach (var p in product)
MarkStaticMagnetPermute(p.SelectMany(z => z), trackPermute);
return trackPermute;
}
protected static void MarkStaticMagnetPermute(IEnumerable grp, List trackPermute)
{
EncounterUtil.MarkEncountersStaticMagnetPullPermutation(grp, PersonalTable.HGSS, trackPermute);
}
public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain)
{
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();
return GetSlotsMatching(chain, pkm.Met_Level);
}
private IEnumerable GetSlotsMatching(IReadOnlyList chain, int lvl)
{
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(lvl))
break;
yield return slot;
break;
}
}
}
private IEnumerable GetSlotsFuzzy(IReadOnlyList 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;
}
}
}
}
}