Fix and simplify gen4 encounter file reading

Change reference offset to absolute offset in order to read data independently and for troubleshooting
Swarms species ID of dppt can be read from encounter raw file (2 x int32 starting from 0x66)
[Swarms species ID of hgss is at 0xBE but lacking encounter type info]
Timereplace slots of dppt only have morning and night slots, the 1st slot is just swarms
Pokeradar slots should replace normal slots 4,5,10,11 (tested)
While replacing slots, skip the encounters with same species ID (always it's because there is no such slots)
This commit is contained in:
wwwwwwzx 2017-04-06 21:18:02 -07:00
parent 7e2c76bbd2
commit 711cb6e7e4
3 changed files with 56 additions and 139 deletions

View file

@ -507,10 +507,7 @@ namespace PKHeX.Core
var D_HoneyTrees_Slots = SlotsD_HoneyTree.Clone(HoneyTreesLocation);
var P_HoneyTrees_Slots = SlotsP_HoneyTree.Clone(HoneyTreesLocation);
var Pt_HoneyTrees_Slots = SlotsPt_HoneyTree.Clone(HoneyTreesLocation);
MarkG4SwarmSlots(ref D_Slots, SlotsDP_Swarm);
MarkG4SwarmSlots(ref P_Slots, SlotsDP_Swarm);
MarkG4SwarmSlots(ref Pt_Slots, SlotsPt_Swarm);
MarkG4SwarmSlots(ref HG_Slots, SlotsHG_Swarm);
MarkG4SwarmSlots(ref SS_Slots, SlotsSS_Swarm);

View file

@ -313,7 +313,7 @@ namespace PKHeX.Core
return slots;
}
private static EncounterSlot[] getSlots4_DPPt_G(byte[] data, ref int ofs, int numslots, SlotType t)
private static EncounterSlot[] getSlots4_DPPt_G(byte[] data, int ofs, int numslots, SlotType t)
{
var slots = new EncounterSlot[numslots];
@ -330,11 +330,9 @@ namespace PKHeX.Core
Type = t
};
}
ofs += numslots * 8;
return slots;
}
private static EncounterSlot[] getSlots4_HGSS_G(byte[] data, ref int ofs, int numslots, SlotType t)
private static EncounterSlot[] getSlots4_HGSS_G(byte[] data, int ofs, int numslots, SlotType t)
{
var slots = new EncounterSlot[numslots * 3];
// First 36 slots are morning, day and night grass slots
@ -351,24 +349,17 @@ namespace PKHeX.Core
SlotNumber = i,
Type = t
};
}
for (int i = 0; i < numslots; i++)
{
slots[numslots + i] = slots[i].Clone();
slots[numslots + i].Species = BitConverter.ToUInt16(data, ofs + numslots * 3 + i * 2);
slots[numslots + i].Type = t;
}
for (int i = 0; i < numslots; i++)
{
slots[numslots * 2 + i] = slots[i].Clone();
slots[numslots * 2 + i].Species = BitConverter.ToUInt16(data, ofs + numslots * 5 + i * 2);
slots[numslots * 2 + i].Type = t;
}
ofs += numslots * 7;
return slots;
}
private static IEnumerable<EncounterSlot> getSlots4_G_Replace(byte[] data, ref int ofs, int slotSize, EncounterSlot[] ReplacedSlots, int[] slotnums, SlotType t = SlotType.Grass)
private static IEnumerable<EncounterSlot> getSlots4_G_Replace(byte[] data, int ofs, int slotSize, EncounterSlot[] ReplacedSlots, int[] slotnums, SlotType t = SlotType.Grass)
{
//Special slots like GBA Dual Slot. Those slot only contain the info of species id, the level is copied from one of the first grass slots
//for dppt slotSize = 4, for hgss slotSize = 2
@ -382,7 +373,7 @@ namespace PKHeX.Core
continue;
int species = BitConverter.ToUInt16(data, ofs + i / (4 / slotSize) * slotSize);
if (species <= 0)
if (species <= 0 || baseSlot.Species == species) // Empty or duplicate
continue;
var slot = baseSlot.Clone();
@ -390,20 +381,18 @@ namespace PKHeX.Core
slot.Type = t;
slots.Add(slot);
}
ofs += numslots * slotSize * slotSize / 4;
return slots;
}
private static IEnumerable<EncounterSlot> getSlots4_G_TimeReplace(byte[] data, ref int ofs, EncounterSlot[] GrassSlots, SlotType t, int[] slotnums)
private static IEnumerable<EncounterSlot> getSlots4_G_TimeReplace(byte[] data, int ofs, EncounterSlot[] GrassSlots, SlotType t, int[] slotnums)
{
var slots = new List<EncounterSlot>();
// Slots for day, morning and night slots in DPPt. Only contain species data, level is copy from grass slot
for (int i = 0; i < 3; i++)
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
int species = BitConverter.ToInt32(data, ofs + j * 4);
int species = BitConverter.ToInt32(data, ofs + i * 8 + j * 4);
if (species <= 0)
continue;
@ -412,7 +401,6 @@ namespace PKHeX.Core
slot.Type = t;
slots.Add(slot);
}
ofs += 8;
}
// Even if the three time replacer slots overwrite the original grass slot it still possible for that encounter to happen
@ -421,7 +409,7 @@ namespace PKHeX.Core
// Grass slots with species = 0 are added too, it is needed for the swarm encounters, it will be deleted after add swarms
return GrassSlots.Concat(slots);
}
private static IEnumerable<EncounterSlot> getSlots4DPPt_WFR(byte[] data, ref int ofs, int numslots, SlotType t)
private static IEnumerable<EncounterSlot> getSlots4DPPt_WFR(byte[] data, int ofs, int numslots, SlotType t)
{
var slots = new List<EncounterSlot>();
for (int i = 0; i < numslots; i++)
@ -439,12 +427,10 @@ namespace PKHeX.Core
Species = Species,
Type = t
});
}
ofs += numslots * 8;
return slots;
}
private static IEnumerable<EncounterSlot> getSlots4HGSS_WFR(byte[] data, ref int ofs, int numslots, SlotType t)
private static IEnumerable<EncounterSlot> getSlots4HGSS_WFR(byte[] data, int ofs, int numslots, SlotType t)
{
var slots = new List<EncounterSlot>();
for (int i = 0; i < numslots; i++)
@ -464,7 +450,6 @@ namespace PKHeX.Core
Type = t
});
}
ofs += numslots * 4;
return slots;
}
@ -498,61 +483,49 @@ namespace PKHeX.Core
private static EncounterArea getArea4DPPt(byte[] data)
{
EncounterArea Area4 = new EncounterArea();
if (data.Length != 426)
if (data.Length != 0x1AA) // 426 Bytes
{ Area4.Location = 0; Area4.Slots = new EncounterSlot[0]; return Area4; }
var Slots = new List<EncounterSlot>();
Area4.Location = BitConverter.ToUInt16(data, 0);
Area4.Location = BitConverter.ToUInt16(data, 0x00);
var GrassRatio = BitConverter.ToInt32(data, 2);
var ofs = 6;
var GrassRatio = BitConverter.ToInt32(data, 0x02);
if (GrassRatio > 0)
{
EncounterSlot[] GrassSlots = getSlots4_DPPt_G(data, ref ofs, 12, SlotType.Grass);
//Morning, Day and Night slots replace slots 2 and 3
Slots.AddRange(getSlots4_G_TimeReplace(data, ref ofs, GrassSlots, SlotType.Grass, Legal.Slot4_Time));
//Pokéradar slots replace slots 6,7,10 and 11
EncounterSlot[] GrassSlots = getSlots4_DPPt_G(data, 0x06, 12, SlotType.Grass);
//Swarming slots replace slots 0 and 1
Slots.AddRange(getSlots4_G_Replace(data, 0x66, 4, GrassSlots, Legal.Slot4_Swarm, SlotType.Swarm));
//Morning and Night slots replace slots 2 and 3
Slots.AddRange(getSlots4_G_TimeReplace(data, 0x6E, GrassSlots, SlotType.Grass, Legal.Slot4_Time));
//Pokéradar slots replace slots 4,5,10 and 11
//Pokéradar is marked with different slot type because it have different PID-IV generationn
Slots.AddRange(getSlots4_G_Replace(data, ref ofs, 4, GrassSlots, Legal.Slot4_Radar, SlotType.Pokeradar));
ofs += 24; //24 bytes padding
Slots.AddRange(getSlots4_G_Replace(data, 0x7E, 4, GrassSlots, Legal.Slot4_Radar, SlotType.Pokeradar));
//24 bytes padding
//Dual Slots replace slots 8 and 9
Slots.AddRange(getSlots4_G_Replace(data, ref ofs, 4, GrassSlots, Legal.Slot4_Dual)); // Ruby
Slots.AddRange(getSlots4_G_Replace(data, ref ofs, 4, GrassSlots, Legal.Slot4_Dual)); // Sapphire
Slots.AddRange(getSlots4_G_Replace(data, ref ofs, 4, GrassSlots, Legal.Slot4_Dual)); // Emerald
Slots.AddRange(getSlots4_G_Replace(data, ref ofs, 4, GrassSlots, Legal.Slot4_Dual)); // FireRed
Slots.AddRange(getSlots4_G_Replace(data, ref ofs, 4, GrassSlots, Legal.Slot4_Dual)); // LeafGreen
Slots.AddRange(getSlots4_G_Replace(data, 0xA6, 4, GrassSlots, Legal.Slot4_Dual)); // Ruby
Slots.AddRange(getSlots4_G_Replace(data, 0xAE, 4, GrassSlots, Legal.Slot4_Dual)); // Sapphire
Slots.AddRange(getSlots4_G_Replace(data, 0xB6, 4, GrassSlots, Legal.Slot4_Dual)); // Emerald
Slots.AddRange(getSlots4_G_Replace(data, 0xBE, 4, GrassSlots, Legal.Slot4_Dual)); // FireRed
Slots.AddRange(getSlots4_G_Replace(data, 0xC6, 4, GrassSlots, Legal.Slot4_Dual)); // LeafGreen
}
else
ofs = 206;
var SurfRatio = BitConverter.ToInt32(data, ofs);
ofs += 4;
var SurfRatio = BitConverter.ToInt32(data, 0xCE);
if (SurfRatio > 0)
Slots.AddRange(getSlots4DPPt_WFR(data, ref ofs, 5, SlotType.Surf));
else
ofs += 40;
Slots.AddRange(getSlots4DPPt_WFR(data, 0xD2, 5, SlotType.Surf));
ofs += 44; //44 bytes padding
var OldRodRatio = BitConverter.ToInt32(data, 294);
ofs += 4;
//44 bytes padding
var OldRodRatio = BitConverter.ToInt32(data, 0x126);
if (OldRodRatio > 0)
Slots.AddRange(getSlots4DPPt_WFR(data, ref ofs, 5, SlotType.Old_Rod));
else
ofs += 40;
Slots.AddRange(getSlots4DPPt_WFR(data, 0x12A, 5, SlotType.Old_Rod));
var GoodRodRatio = BitConverter.ToInt32(data, 338);
ofs += 4;
var GoodRodRatio = BitConverter.ToInt32(data, 0x152);
if (GoodRodRatio > 0)
Slots.AddRange(getSlots4DPPt_WFR(data, ref ofs, 5, SlotType.Good_Rod));
else
ofs += 40;
Slots.AddRange(getSlots4DPPt_WFR(data, 0x156, 5, SlotType.Good_Rod));
var SuperRodRatio = BitConverter.ToInt32(data, 382);
ofs += 4;
var SuperRodRatio = BitConverter.ToInt32(data, 0x17E);
if (SuperRodRatio > 0)
Slots.AddRange(getSlots4DPPt_WFR(data, ref ofs, 5, SlotType.Super_Rod));
else
ofs += 40;
Slots.AddRange(getSlots4DPPt_WFR(data, 0x182, 5, SlotType.Super_Rod));
Area4.Slots = Slots.ToArray();
return Area4;
@ -561,62 +534,50 @@ namespace PKHeX.Core
private static EncounterArea getArea4HGSS(byte[] data)
{
EncounterArea Area4 = new EncounterArea();
if (data.Length != 198)
if (data.Length != 0xC6)
{ Area4.Location = 0; Area4.Slots = new EncounterSlot[0]; return Area4; }
var Slots = new List<EncounterSlot>();
Area4.Location = BitConverter.ToUInt16(data, 0);
Area4.Location = BitConverter.ToUInt16(data, 0x00);
var GrassRatio = data[2];
var SurfRatio = data[3];
var RockSmashRatio = data[4];
var OldRodRatio = data[5];
var GoodRodRatio = data[6];
var SuperRodRatio = data[7];
var GrassRatio = data[0x02];
var SurfRatio = data[0x03];
var RockSmashRatio = data[0x04];
var OldRodRatio = data[0x05];
var GoodRodRatio = data[0x06];
var SuperRodRatio = data[0x07];
// 2 bytes padding
var ofs = 10;
if (GrassRatio > 0)
{
// First 36 slots are morning, day and night grass slots
// The order is 12 level values, 12 morning species, 12 day species and 12 night species
var GrassSlots = getSlots4_HGSS_G(data, ref ofs, 12, SlotType.Grass);
var GrassSlots = getSlots4_HGSS_G(data, 0x0A, 12, SlotType.Grass);
//Grass slots with species = 0 are added too, it is needed for the swarm encounters, it will be deleted after add swarms
Slots.AddRange(GrassSlots);
// Hoenn Sound and Sinnoh Sound replace slots 4 and 5
Slots.AddRange(getSlots4_G_Replace(data, ref ofs, 2, GrassSlots, Legal.Slot4_Sound)); // Hoenn
Slots.AddRange(getSlots4_G_Replace(data, ref ofs, 2, GrassSlots, Legal.Slot4_Sound)); // Sinnoh
Slots.AddRange(getSlots4_G_Replace(data, 0x5E, 2, GrassSlots, Legal.Slot4_Sound)); // Hoenn
Slots.AddRange(getSlots4_G_Replace(data, 0x62, 2, GrassSlots, Legal.Slot4_Sound)); // Sinnoh
}
else
ofs = 102;
if (SurfRatio > 0)
Slots.AddRange(getSlots4HGSS_WFR(data, ref ofs, 5, SlotType.Surf));
else
ofs += 20;
Slots.AddRange(getSlots4HGSS_WFR(data, 0x66, 5, SlotType.Surf));
if (RockSmashRatio > 0)
Slots.AddRange(getSlots4HGSS_WFR(data, ref ofs, 2, SlotType.Rock_Smash));
else
ofs += 8;
Slots.AddRange(getSlots4HGSS_WFR(data, 0x7A, 2, SlotType.Rock_Smash));
if (OldRodRatio > 0)
Slots.AddRange(getSlots4HGSS_WFR(data, ref ofs, 5, SlotType.Old_Rod));
else
ofs += 20;
Slots.AddRange(getSlots4HGSS_WFR(data, 0x82, 5, SlotType.Old_Rod));
if (GoodRodRatio > 0)
Slots.AddRange(getSlots4HGSS_WFR(data, ref ofs, 5, SlotType.Good_Rod));
else
ofs += 20;
Slots.AddRange(getSlots4HGSS_WFR(data, 0x96, 5, SlotType.Good_Rod));
if (SuperRodRatio > 0)
Slots.AddRange(getSlots4HGSS_WFR(data, ref ofs, 5, SlotType.Super_Rod));
else
ofs += 20;
Slots.AddRange(getSlots4HGSS_WFR(data, 0xAA, 5, SlotType.Super_Rod));
if (data[194] == 120) //Location = 182, 127, 130, 132, 167, 188, 210
// Last 6 bytes only have species ID info
if (data[0xC2] == 120) // Location = 182, 127, 130, 132, 167, 188, 210
Slots.AddRange(SlotsHGSS_Staryu);
Area4.Slots = Slots.ToArray();

View file

@ -570,9 +570,10 @@ namespace PKHeX.Core
#endregion
// Encounter Slots that are replaced
internal static readonly int[] Slot4_Swarm = {0, 1};
internal static readonly int[] Slot4_Time = {2, 3};
internal static readonly int[] Slot4_Sound = {2, 3, 4, 5};
internal static readonly int[] Slot4_Radar = {6, 7, 10, 11};
internal static readonly int[] Slot4_Radar = {4, 5, 10, 11};
internal static readonly int[] Slot4_Dual = {8, 9};
#region Alt Slots
internal static readonly int[] SafariZoneLocation_4 =
@ -1075,48 +1076,6 @@ namespace PKHeX.Core
58, // Floaroma Meadow
};
private static readonly EncounterArea[] SlotsDPPT_Swarm =
{
//reference http://bulbapedia.bulbagarden.net/wiki/Pokémon_outbreak
new EncounterArea {Location = 016, Slots = new[]{new EncounterSlot {Species = 084, Type = SlotType.Grass }, },},// Doduo @ Route 201
new EncounterArea {Location = 017, Slots = new[]{new EncounterSlot {Species = 263, Type = SlotType.Grass }, },},// Zigzagoon @ Route 202
new EncounterArea {Location = 018, Slots = new[]{new EncounterSlot {Species = 104, Type = SlotType.Grass }, },},// Cubone @ Route 203
new EncounterArea {Location = 022, Slots = new[]{new EncounterSlot {Species = 231, Type = SlotType.Grass }, },},// Phanpy @ Route 207
new EncounterArea {Location = 023, Slots = new[]{new EncounterSlot {Species = 206, Type = SlotType.Grass }, },},// Dunsparce @ Route 208
new EncounterArea {Location = 024, Slots = new[]{new EncounterSlot {Species = 209, Type = SlotType.Grass }, },},// Snubbull @ Route 209
new EncounterArea {Location = 029, Slots = new[]{new EncounterSlot {Species = 325, Type = SlotType.Grass }, },},// Spoink @ Route 214
new EncounterArea {Location = 030, Slots = new[]{new EncounterSlot {Species = 096, Type = SlotType.Grass }, },},// Drowzee @ Route 215
new EncounterArea {Location = 033, Slots = new[]{new EncounterSlot {Species = 100, Type = SlotType.Grass }, },},// Voltorb @ Route 218
new EncounterArea {Location = 036, Slots = new[]{new EncounterSlot {Species = 083, Type = SlotType.Grass }, },},// Farfetch'd @ Route 221
new EncounterArea {Location = 037, Slots = new[]{new EncounterSlot {Species = 300, Type = SlotType.Grass }, },},// Skitty @ Route 222
new EncounterArea {Location = 039, Slots = new[]{new EncounterSlot {Species = 177, Type = SlotType.Grass }, },},// Natu @ Route 224
new EncounterArea {Location = 040, Slots = new[]{new EncounterSlot {Species = 296, Type = SlotType.Grass }, },},// Makuhita @ Route 225
new EncounterArea {Location = 041, Slots = new[]{new EncounterSlot {Species = 098, Type = SlotType.Grass }, },},// Krabby @ Route 226
new EncounterArea {Location = 042, Slots = new[]{new EncounterSlot {Species = 327, Type = SlotType.Grass }, },},// Spinda @ Route 227
new EncounterArea {Location = 043, Slots = new[]{new EncounterSlot {Species = 374, Type = SlotType.Grass }, },},// Beldum @ Route 228
new EncounterArea {Location = 045, Slots = new[]{new EncounterSlot {Species = 222, Type = SlotType.Grass }, },},// Corsola @ Route 230
new EncounterArea {Location = 047, Slots = new[]{new EncounterSlot {Species = 309, Type = SlotType.Grass }, },},// Electrike @ Valley Windworks
new EncounterArea {Location = 048, Slots = new[]{new EncounterSlot {Species = 287, Type = SlotType.Grass }, },},// Slakoth @ Eterna Forest
};
private static readonly EncounterArea[] SlotsDP_Swarm = SlotsDPPT_Swarm.Concat(new[] {
new EncounterArea {Location = 021, Slots = new[]{new EncounterSlot {Species = 299, Type = SlotType.Grass }, },},// Nosepass @ Route 206
new EncounterArea {Location = 028, Slots = new[]{new EncounterSlot {Species = 359, Type = SlotType.Grass }, },},// Absol @ Route 213
new EncounterArea {Location = 031, Slots = new[]{new EncounterSlot {Species = 225, Type = SlotType.Grass }, },},// Delibird @ Route 216
new EncounterArea {Location = 032, Slots = new[]{new EncounterSlot {Species = 220, Type = SlotType.Grass }, },},// Swinub @ Route 217
new EncounterArea {Location = 044, Slots = new[]{new EncounterSlot {Species = 016, Type = SlotType.Grass }, },},// Pidgey @ Route 229
new EncounterArea {Location = 049, Slots = new[]{new EncounterSlot {Species = 081, Type = SlotType.Grass }, },},// Magnemite @ Fuego Ironworks
new EncounterArea {Location = 076, Slots = new[]{new EncounterSlot {Species = 283, Type = SlotType.Grass }, },},// Surskit @ Lake Verity
new EncounterArea {Location = 077, Slots = new[]{new EncounterSlot {Species = 108, Type = SlotType.Grass }, },},// Lickitung @ Lake Valor
new EncounterArea {Location = 078, Slots = new[]{new EncounterSlot {Species = 238, Type = SlotType.Grass }, },},// Smoochum @ Lake Acuity
}).ToArray();
private static readonly EncounterArea[] SlotsPt_Swarm = SlotsDPPT_Swarm.Concat(new[] {
new EncounterArea {Location = 021, Slots = new[]{new EncounterSlot {Species = 246, Type = SlotType.Grass }, },},// Larvitar @ Route 206
new EncounterArea {Location = 032, Slots = new[]{new EncounterSlot {Species = 225, Type = SlotType.Grass }, },},// Delibird @ Route 217
new EncounterArea {Location = 044, Slots = new[]{new EncounterSlot {Species = 127, Type = SlotType.Grass }, },},// Pinsir @ Route 229
}).ToArray();
private static readonly EncounterArea[] SlotsHGSS_Swarm =
{
new EncounterArea {Location = 128, Slots = new[]{new EncounterSlot {Species = 340, Type = SlotType.Old_Rod },