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; } } } } }