Merge pull request #1030 from wwwwwwzx/master

Fix and simplify gen4 encounter file reading
This commit is contained in:
Kurt 2017-04-06 23:20:40 -07:00 committed by GitHub
commit ad28ab58c3
3 changed files with 55 additions and 162 deletions

View File

@ -507,10 +507,7 @@ private static EncounterArea[] getTables2(GameVersion Version)
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 @@ private static IEnumerable<EncounterSlot> getSlots3_F(byte[] data, ref int ofs,
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 @@ private static EncounterSlot[] getSlots4_DPPt_G(byte[] data, ref int ofs, int nu
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 @@ private static EncounterSlot[] getSlots4_HGSS_G(byte[] data, ref int ofs, int nu
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 @@ private static IEnumerable<EncounterSlot> getSlots4_G_Replace(byte[] data, ref i
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,38 +381,9 @@ private static IEnumerable<EncounterSlot> getSlots4_G_Replace(byte[] data, ref i
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)
{
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 j = 0; j < 2; j++)
{
int species = BitConverter.ToInt32(data, ofs + j * 4);
if (species <= 0)
continue;
var slot = GrassSlots[slotnums[j]].Clone();
slot.Species = species;
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
// Original encounter should not be removed
// 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 +401,10 @@ private static IEnumerable<EncounterSlot> getSlots4DPPt_WFR(byte[] data, ref int
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 +424,6 @@ private static IEnumerable<EncounterSlot> getSlots4HGSS_WFR(byte[] data, ref int
Type = t
});
}
ofs += numslots * 4;
return slots;
}
@ -498,61 +457,51 @@ private static EncounterArea getArea3(byte[] data)
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);
Slots.AddRange(GrassSlots);
//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_Replace(data, 0x6E, 4, GrassSlots, Legal.Slot4_Time)); // Morning
Slots.AddRange(getSlots4_G_Replace(data, 0x76, 4, GrassSlots, Legal.Slot4_Time)); // Night
//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 +510,50 @@ private static EncounterArea getArea4DPPt(byte[] data)
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 @@ public static partial class Legal
#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 @@ public static partial class Legal
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 },