Split wild encounters for crossover & weather

Certain Mark values (ribbon) are only obtainable if the encounter was
obtained in some weather (I really hope there's no crossover cases for
this), and non-symbol encounters can't wander to another zone.

I wonder if you can wander from one zone with one exclusive weather, to
another zone, and get an 'unobtainable' mark (with the new zone's
weather) on the crossover mon's weather. yikes lmao
This commit is contained in:
Kurt 2019-11-27 22:46:14 -08:00
parent a0ee7a3e51
commit 5a1bffb2ba
10 changed files with 122 additions and 8 deletions

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@ -7,7 +8,7 @@ namespace PKHeX.Core
/// <summary>
/// <see cref="GameVersion.SWSH"/> encounter area
/// </summary>
public sealed class EncounterArea8 : EncounterArea32
public sealed class EncounterArea8 : EncounterAreaSH
{
/// <inheritdoc />
public override bool IsMatchLocation(int location)
@ -15,6 +16,9 @@ namespace PKHeX.Core
if (Location == location)
return true;
if (!PermitCrossover)
return false;
// get all other areas that can bleed encounters to the met location
if (!ConnectingArea8.TryGetValue(location, out var others))
return false;
@ -117,4 +121,85 @@ namespace PKHeX.Core
// Lake of Outrage is just itself.
};
}
public abstract class EncounterAreaSH : EncounterArea
{
/// <summary>
/// Slots from this area can cross over to another area, resulting in a different met location.
/// </summary>
public bool PermitCrossover { get; internal set; }
/// <summary>
/// Gets an array of areas from an array of raw area data
/// </summary>
/// <param name="entries">Simplified raw format of an Area</param>
/// <returns>Array of areas</returns>
public static T[] GetArray<T>(byte[][] entries) where T : EncounterAreaSH, new()
{
T[] data = new T[entries.Length];
for (int i = 0; i < data.Length; i++)
{
var loc = data[i] = new T();
loc.LoadSlots(entries[i]);
}
return data;
}
private void LoadSlots(byte[] areaData)
{
Location = areaData[0];
Slots = new EncounterSlot[areaData[1]];
int ctr = 0;
int ofs = 2;
do
{
var flags = (AreaWeather8)BitConverter.ToUInt16(areaData, ofs);
var min = areaData[ofs + 2];
var max = areaData[ofs + 3];
var count = areaData[ofs + 4];
// ofs+5 reserved
ofs += 6;
for (int i = 0; i < count; i++, ctr++, ofs += 2)
{
var specForm = BitConverter.ToUInt16(areaData, ofs);
Slots[ctr] = new EncounterSlot8(specForm, min, max, flags);
}
} while (ctr != Slots.Length);
foreach (var slot in Slots)
slot.Area = this;
}
}
[Flags]
public enum AreaWeather8
{
None,
Normal = 1,
Overcast = 1 << 1,
Raining = 1 << 2,
Thunderstorm = 1 << 3,
Intense_Sun = 1 << 4,
Snowing = 1 << 5,
Snowstorm = 1 << 6,
Sandstorm = 1 << 7,
Heavy_Fog = 1 << 8,
Shaking_Trees = 1 << 9,
Fishing = 1 << 10,
}
public sealed class EncounterSlot8 : EncounterSlot
{
public readonly AreaWeather8 Weather;
public EncounterSlot8(int specForm, int min, int max, AreaWeather8 weather)
{
Species = specForm & 0x7FF;
Form = specForm >> 11;
LevelMin = min;
LevelMax = max;
Weather = weather;
}
}
}

View file

@ -31,6 +31,18 @@ namespace PKHeX.Core
return EncounterArea32.GetArray<T>(Data.UnpackMini(mini, ident));
}
/// <summary>
/// Direct fetch for <see cref="EncounterArea"/> data; can also be used to fetch supplementary encounter streams.
/// </summary>
/// <param name="ident">Unpacking identification ASCII characters (first two bytes of binary)</param>
/// <param name="resource">Resource name (will be prefixed with "encounter_"</param>
/// <returns>Array of encounter areas</returns>
internal static T[] GetEncounterTables8<T>(string ident, string resource) where T : EncounterAreaSH, new()
{
byte[] mini = Util.GetBinaryResource($"encounter_{resource}.pkl");
return EncounterAreaSH.GetArray<T>(Data.UnpackMini(mini, ident));
}
/// <summary>
/// Combines <see cref="EncounterArea"/> slot arrays with the same <see cref="EncounterArea.Location"/>.
/// </summary>

View file

@ -6,16 +6,29 @@ using static PKHeX.Core.Encounters8Nest;
namespace PKHeX.Core
{
/// <summary>
/// Generation 8 Encounters
/// </summary>
internal static class Encounters8
{
internal static readonly EncounterArea8[] SlotsSW = GetEncounterTables<EncounterArea8>("sw", "sw");
internal static readonly EncounterArea8[] SlotsSH = GetEncounterTables<EncounterArea8>("sh", "sh");
internal static readonly EncounterArea8[] SlotsSW_Symbol = GetEncounterTables8<EncounterArea8>("sw", "sw_symbol");
internal static readonly EncounterArea8[] SlotsSH_Symbol = GetEncounterTables8<EncounterArea8>("sh", "sh_symbol");
internal static readonly EncounterArea8[] SlotsSW_Hidden = GetEncounterTables8<EncounterArea8>("sw", "sw_hidden");
internal static readonly EncounterArea8[] SlotsSH_Hidden = GetEncounterTables8<EncounterArea8>("sh", "sh_hidden");
internal static readonly EncounterArea8[] SlotsSW, SlotsSH;
internal static readonly EncounterStatic[] StaticSW, StaticSH;
static Encounters8()
{
SlotsSW = ArrayUtil.ConcatAll(SlotsSW_Symbol, SlotsSW_Hidden);
SlotsSH = ArrayUtil.ConcatAll(SlotsSH_Symbol, SlotsSH_Hidden);
SlotsSW.SetVersion(SW);
SlotsSH.SetVersion(SH);
foreach (var area in SlotsSW_Symbol)
area.PermitCrossover = true;
foreach (var area in SlotsSH_Symbol)
area.PermitCrossover = true;
Encounter_SWSH.SetVersion(SWSH);
TradeGift_SWSH.SetVersion(SWSH);
Nest_Common.SetVersion(SWSH);

View file

@ -51,13 +51,15 @@
<None Remove="Resources\byte\encounter_rb_f.pkl" />
<None Remove="Resources\byte\encounter_red.pkl" />
<None Remove="Resources\byte\encounter_s.pkl" />
<None Remove="Resources\byte\encounter_sh.pkl" />
<None Remove="Resources\byte\encounter_sh_hidden.pkl" />
<None Remove="Resources\byte\encounter_sh_symbol.pkl" />
<None Remove="Resources\byte\encounter_silver.pkl" />
<None Remove="Resources\byte\encounter_silver_h.pkl" />
<None Remove="Resources\byte\encounter_sn.pkl" />
<None Remove="Resources\byte\encounter_sn_sos.pkl" />
<None Remove="Resources\byte\encounter_ss.pkl" />
<None Remove="Resources\byte\encounter_sw.pkl" />
<None Remove="Resources\byte\encounter_sw_hidden.pkl" />
<None Remove="Resources\byte\encounter_sw_symbol.pkl" />
<None Remove="Resources\byte\encounter_us.pkl" />
<None Remove="Resources\byte\encounter_us_sos.pkl" />
<None Remove="Resources\byte\encounter_um.pkl" />
@ -838,13 +840,15 @@
<EmbeddedResource Include="Resources\byte\encounter_rb_f.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_red.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_s.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_sh.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_sh_hidden.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_sh_symbol.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_silver.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_silver_h.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_sn.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_sn_sos.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_ss.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_sw.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_sw_hidden.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_sw_symbol.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_us.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_us_sos.pkl" />
<EmbeddedResource Include="Resources\byte\encounter_um.pkl" />

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.