Continued pkmgen updates

* adds g4 forced shiny seed->pid (Chain Shiny Lake of Rage Gyarados)
* adds cxd starter pid generating handling
* adds g5 forced shiny seed->pid (MG5Shiny Shiny gift Dratini)
* excludes gen4 route45 surf impossible encounters
* actually use ingame trade edge case handler

Up to dragonair (147) yay; yellow dragonair is likely the catch rate
edge case.
This commit is contained in:
Kurt 2018-05-07 21:16:54 -07:00
parent 86bf4201e2
commit 3c31d5798f
4 changed files with 94 additions and 19 deletions

View file

@ -98,6 +98,14 @@ namespace PKHeX.Core
}
if (EggEncounter)
{
bool traded = (int)Version == SAV.Game;
pk.Met_Level = EncounterSuggestion.GetSuggestedEncounterEggMetLevel(pk);
pk.Met_Location = Math.Max(0, EncounterSuggestion.GetSuggestedEggMetLocation(pk));
if (pk.GenNumber >= 4)
{
pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk, traded);
pk.EggMetDate = today;
}
pk.Egg_Location = EggLocation;
pk.EggMetDate = today;
}
@ -164,11 +172,19 @@ namespace PKHeX.Core
private PIDType GetPIDType()
{
if (Roaming)
return PIDType.Method_1_Roamer;
if (Version == GameVersion.HGSS && Location == 233) // Pokéwalker
return PIDType.Pokewalker;
return PIDType.None;
switch (Generation)
{
case 3 when Roaming:
return PIDType.Method_1_Roamer;
case 4 when Shiny == Shiny.Always: // Lake of Rage Gyarados
return PIDType.ChainShiny;
case 4 when Location == 233: // Pokéwalker
return PIDType.Pokewalker;
case 5 when Shiny == Shiny.Always:
return PIDType.G5MGShiny;
default: return PIDType.None;
}
}
}
}

View file

@ -120,6 +120,8 @@ namespace PKHeX.Core
if (Fateful)
pk.FatefulEncounter = true;
UpdateEdgeCase(pk);
if (EvolveOnTrade)
++pk.Species;

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
namespace PKHeX.Core
{
@ -255,15 +256,9 @@ namespace PKHeX.Core
var slots = EncounterSlotGenerator.GetPossible(pk);
foreach (var slot in slots)
{
if (slot.Generation == 2)
{
if (slot.Type.HasFlag(SlotType.Safari))
continue;
if (IsImpossibleSlot(pk, slot))
continue;
if (slot.Type.HasFlag(SlotType.Headbutt))
if (Legal.GetGSCHeadbuttAvailability(slot, pk.TID) != TreeEncounterAvailable.ValidTree)
continue;
}
if (needs.Count == 0)
{
yield return slot;
@ -274,5 +269,27 @@ namespace PKHeX.Core
yield return slot;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsImpossibleSlot(PKM pk, EncounterSlot slot)
{
switch (slot.Generation)
{
case 2:
if (slot.Type.HasFlag(SlotType.Safari)) // Safari Zone is unavailable in Gen 2.
return true;
if (slot.Type.HasFlag(SlotType.Headbutt))
if (Legal.GetGSCHeadbuttAvailability(slot, pk.TID) != TreeEncounterAvailable.ValidTree) // Unreachable Headbutt Trees.
return true;
break;
case 4:
if (slot.Location == 193 && slot.Type == SlotType.Surf) // Johto Route 45 surfing encounter. Unreachable Water tiles.
return true;
break;
}
return false;
}
}
}

View file

@ -66,6 +66,21 @@ namespace PKHeX.Core
private static void SetValuesFromSeedXDRNG(PKM pk, uint seed)
{
var rng = RNG.XDRNG;
switch (pk.Species)
{
case 197: // Colo Umbreon
case 133: // XD Eevee
pk.TID = (int)((seed = rng.Next(seed)) >> 16);
pk.SID = (int)((seed = rng.Next(seed)) >> 16);
seed = rng.Advance(seed, 2); // PID calls consumed
break;
case 196:
pk.TID = (int)((seed = rng.Next(seed)) >> 16);
pk.SID = (int)((seed = rng.Next(seed)) >> 16);
seed = rng.Advance(seed, 5); // skip over Umbreon
seed = rng.Advance(seed, 2); // PID calls consumed
break;
}
var A = rng.Next(seed); // IV1
var B = rng.Next(A); // IV2
var C = rng.Next(B); // Ability?
@ -146,13 +161,30 @@ namespace PKHeX.Core
case PIDType.CuteCharm:
break;
case PIDType.ChainShiny:
break;
return SetRandomChainShinyPID;
case PIDType.G4MGAntiShiny:
break;
}
return (pk, seed) => { };
}
public static void SetRandomChainShinyPID(PKM pk, uint seed)
{
// 13 rand bits
// 1 3-bit for upper
// 1 3-bit for lower
uint Next() => (seed = RNG.LCRNG.Next(seed)) >> 16;
uint lower = Next() & 7;
uint upper = Next() & 7;
for (int i = 0; i < 13; i++)
lower |= (Next() & 1) << (3 + i);
upper = (uint)(lower ^ pk.TID ^ pk.SID) & 0xFFF8 | upper & 0x7;
pk.PID = upper << 16 | lower;
pk.IVs = MethodFinder.GetIVsInt32(Next(), Next());
}
public static void SetRandomPokeSpotPID(PKM pk, int nature, int gender, int ability, int slot)
{
while (true)
@ -244,7 +276,7 @@ namespace PKHeX.Core
SetRandomWildPID4(pk, nature, ability, gender, specific);
break;
case 5:
SetRandomWildPID5(pk, nature, ability, gender);
SetRandomWildPID5(pk, nature, ability, gender, specific);
break;
default:
SetRandomWildPID(pk, nature, ability, gender);
@ -304,7 +336,7 @@ namespace PKHeX.Core
return PIDType.Method_1;
}
private static void SetRandomWildPID5(PKM pk, int nature, int ability, int gender)
private static void SetRandomWildPID5(PKM pk, int nature, int ability, int gender, PIDType specific = PIDType.None)
{
var tidbit = (pk.TID ^ pk.SID) & 1;
pk.RefreshAbility(ability);
@ -317,9 +349,17 @@ namespace PKHeX.Core
while (true)
{
uint seed = Util.Rand32();
var bitxor = (seed >> 31) ^ (seed & 1);
if (bitxor != tidbit)
seed ^= 1;
if (specific == PIDType.G5MGShiny)
{
SetValuesFromSeedMG5Shiny(pk, seed);
seed = pk.PID;
}
else
{
var bitxor = (seed >> 31) ^ (seed & 1);
if (bitxor != tidbit)
seed ^= 1;
}
if (seed % 25 != nature)
continue;