2021-08-05 22:18:43 +00:00
|
|
|
using static PKHeX.Core.SlotType;
|
2022-10-01 02:26:59 +00:00
|
|
|
using static PKHeX.Core.SlotNumber;
|
2017-11-26 06:28:38 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
namespace PKHeX.Core;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// RNG Encounter Slot Ranges to convert the [0,100) value into a slot index.
|
|
|
|
/// </summary>
|
|
|
|
public static class SlotRange
|
2017-05-15 06:21:34 +00:00
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
private const int Invalid = -1; // all slots are [0,X], unsigned. This will always result in a non-match.
|
|
|
|
|
2021-03-14 18:28:46 +00:00
|
|
|
/// <summary>
|
2022-06-18 18:04:24 +00:00
|
|
|
/// Gets the <see cref="INumberedSlot.SlotNumber"/> from the raw 16bit <see cref="rand"/> seed half.
|
2021-03-14 18:28:46 +00:00
|
|
|
/// </summary>
|
2022-06-18 18:04:24 +00:00
|
|
|
public static int GetSlot(SlotType type, uint rand, FrameType t) => t switch
|
2017-05-15 06:21:34 +00:00
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
FrameType.MethodH => HSlot(type, rand),
|
|
|
|
FrameType.MethodJ => JSlot(type, rand),
|
|
|
|
FrameType.MethodK => KSlot(type, rand),
|
|
|
|
_ => Invalid,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the <see cref="INumberedSlot.SlotNumber"/> from the raw 16bit <see cref="rand"/> seed half.
|
|
|
|
/// </summary>
|
|
|
|
private static int HSlot(SlotType type, uint rand)
|
|
|
|
{
|
|
|
|
var ESV = rand % 100;
|
|
|
|
if ((type & Swarm) != 0)
|
|
|
|
return ESV < 50 ? 0 : Invalid;
|
2017-05-15 06:21:34 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
return type switch
|
2017-05-15 06:21:34 +00:00
|
|
|
{
|
2022-10-01 02:26:59 +00:00
|
|
|
Old_Rod => GetHOldRod(ESV),
|
|
|
|
Good_Rod => GetHGoodRod(ESV),
|
|
|
|
Super_Rod => GetHSuperRod(ESV),
|
|
|
|
Rock_Smash => GetHSurf(ESV),
|
|
|
|
Surf => GetHSurf(ESV),
|
|
|
|
_ => GetHRegular(ESV),
|
2022-06-18 18:04:24 +00:00
|
|
|
};
|
|
|
|
}
|
2018-09-15 05:37:47 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Gets the <see cref="INumberedSlot.SlotNumber"/> from the raw 16bit <see cref="rand"/> seed half.
|
|
|
|
/// </summary>
|
|
|
|
private static int KSlot(SlotType type, uint rand)
|
|
|
|
{
|
|
|
|
var ESV = rand % 100;
|
|
|
|
return type switch
|
2017-05-15 06:21:34 +00:00
|
|
|
{
|
2022-10-01 02:26:59 +00:00
|
|
|
Rock_Smash or Surf => GetHSurf(ESV),
|
|
|
|
Old_Rod or Good_Rod or Super_Rod => GetKSuperRod(ESV),
|
|
|
|
BugContest => GetKBCC(ESV),
|
|
|
|
Headbutt or (Headbutt | Special) => GetKHeadbutt(ESV),
|
|
|
|
_ => GetHRegular(ESV),
|
2022-06-18 18:04:24 +00:00
|
|
|
};
|
|
|
|
}
|
2018-09-15 05:37:47 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Gets the <see cref="INumberedSlot.SlotNumber"/> from the raw 16bit <see cref="rand"/> seed half.
|
|
|
|
/// </summary>
|
|
|
|
private static int JSlot(SlotType type, uint rand)
|
|
|
|
{
|
|
|
|
uint ESV = rand / 656;
|
|
|
|
return type switch
|
2017-05-15 06:21:34 +00:00
|
|
|
{
|
2022-10-01 02:26:59 +00:00
|
|
|
Old_Rod or Rock_Smash or Surf => GetHSurf(ESV),
|
|
|
|
Good_Rod or Super_Rod => GetJSuperRod(ESV),
|
2022-06-18 18:04:24 +00:00
|
|
|
HoneyTree => 0,
|
2022-10-01 02:26:59 +00:00
|
|
|
_ => GetHRegular(ESV),
|
2022-06-18 18:04:24 +00:00
|
|
|
};
|
|
|
|
}
|
2017-05-15 06:21:34 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
public static int GetLevel(EncounterSlot slot, LeadRequired lead, uint lvlrand)
|
|
|
|
{
|
2022-10-01 02:26:59 +00:00
|
|
|
if ((lead & LeadRequired.PressureHustleSpiritFail) == LeadRequired.PressureHustleSpirit)
|
2022-06-18 18:04:24 +00:00
|
|
|
return slot.LevelMax;
|
|
|
|
if (slot.IsFixedLevel)
|
|
|
|
return slot.LevelMin;
|
|
|
|
int delta = slot.LevelMax - slot.LevelMin + 1;
|
|
|
|
var adjust = (int)(lvlrand % delta);
|
|
|
|
|
|
|
|
return slot.LevelMin + adjust;
|
|
|
|
}
|
2018-09-15 05:37:47 +00:00
|
|
|
|
2020-05-26 23:59:47 +00:00
|
|
|
#pragma warning disable IDE0060, RCS1163 // Unused parameter.
|
2022-06-18 18:04:24 +00:00
|
|
|
public static bool GetIsEncounterable<T>(T slot, FrameType frameType, int rand, LeadRequired lead) where T : ISlotRNGType
|
2020-05-26 23:59:47 +00:00
|
|
|
#pragma warning restore IDE0060, RCS1163 // Unused parameter.
|
2022-06-18 18:04:24 +00:00
|
|
|
{
|
2022-09-23 20:36:44 +00:00
|
|
|
var type = slot.Type;
|
|
|
|
if (type.IsSweetScentType())
|
|
|
|
return true;
|
|
|
|
if (type is HoneyTree)
|
2022-06-18 18:04:24 +00:00
|
|
|
return true;
|
|
|
|
return true; // todo
|
|
|
|
//return GetCanEncounter(slot, frameType, rand, lead);
|
|
|
|
}
|
2018-09-15 05:37:47 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
// ReSharper disable once UnusedMember.Global
|
|
|
|
public static bool GetCanEncounter<T>(T slot, FrameType frameType, int rand, LeadRequired lead) where T : ISlotRNGType
|
|
|
|
{
|
|
|
|
int proc = frameType == FrameType.MethodJ ? rand / 656 : rand % 100;
|
|
|
|
var stype = slot.Type;
|
|
|
|
if (stype == Rock_Smash)
|
|
|
|
return proc < 60;
|
|
|
|
if (frameType == FrameType.MethodH)
|
|
|
|
return true; // fishing encounters are disjointed by the hooked message.
|
|
|
|
return GetCanEncounterFish(lead, stype, proc);
|
|
|
|
}
|
2017-11-30 07:20:49 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
private static bool GetCanEncounterFish(LeadRequired lead, SlotType stype, int proc) => stype switch
|
|
|
|
{
|
|
|
|
// Lead:None => can be suction cups
|
|
|
|
Old_Rod => proc switch
|
2021-03-14 23:16:55 +00:00
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
< 25 => true,
|
|
|
|
< 50 => lead == LeadRequired.None,
|
2021-08-20 20:49:20 +00:00
|
|
|
_ => false,
|
2022-06-18 18:04:24 +00:00
|
|
|
},
|
|
|
|
Good_Rod => proc switch
|
|
|
|
{
|
|
|
|
< 50 => true,
|
|
|
|
< 75 => lead == LeadRequired.None,
|
|
|
|
_ => false,
|
|
|
|
},
|
|
|
|
Super_Rod => proc < 75 || lead == LeadRequired.None,
|
2017-12-02 00:33:03 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
_ => false,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Checks both Static and Magnet Pull ability type selection encounters to see if the encounter can be selected.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="slot">Slot Data</param>
|
|
|
|
/// <param name="esv">Rand16 value for the call</param>
|
|
|
|
/// <returns>Slot number from the slot data if the slot is selected on this frame, else an invalid slot value.</returns>
|
|
|
|
internal static int GetSlotStaticMagnet<T>(T slot, uint esv) where T : EncounterSlot, IMagnetStatic, INumberedSlot
|
|
|
|
{
|
|
|
|
if (slot.IsStaticSlot())
|
|
|
|
{
|
|
|
|
var index = esv % slot.StaticCount;
|
|
|
|
if (index == slot.StaticIndex)
|
|
|
|
return slot.SlotNumber;
|
|
|
|
}
|
|
|
|
if (slot.IsMagnetSlot())
|
2017-12-02 00:33:03 +00:00
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
var index = esv % slot.MagnetPullCount;
|
|
|
|
if (index == slot.MagnetPullIndex)
|
|
|
|
return slot.SlotNumber;
|
2017-12-02 00:33:03 +00:00
|
|
|
}
|
2022-06-18 18:04:24 +00:00
|
|
|
return Invalid;
|
2017-05-15 06:21:34 +00:00
|
|
|
}
|
|
|
|
}
|