mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 12:33:06 +00:00
Update gen4 Shedinja handling
PK4->PK5 fixes gendered Shedinja -> genderless. Clean up PK4 ball value setters and expose those 2 properties separately. Add edge case permission for HG/SS Sport Ball Shedinja being legal if evolved on DP (DP doesn't change 0x86, lol) Copy PokéathlonStat and ball values individually for BK4<->PK4 conversion Co-Authored-By: Lusamine <30205550+Lusamine@users.noreply.github.com>
This commit is contained in:
parent
f50684b794
commit
24e1898410
4 changed files with 56 additions and 78 deletions
|
@ -47,6 +47,8 @@ namespace PKHeX.Core
|
|||
// Only Gen3 origin Shedinja can copy the wild ball.
|
||||
// Evolution chains will indicate if it could have existed as Shedinja in Gen3.
|
||||
// The special move verifier has a similar check!
|
||||
if (pkm.HGSS && pkm.Ball == (int)Sport) // Can evolve in DP to retain the HG/SS ball -- not able to be captured in any other ball
|
||||
return VerifyBallEquals(data, (int)Sport);
|
||||
if (Info.Generation != 3 || Info.EvoChainsAllGens[3].Count != 2)
|
||||
return VerifyBallEquals(data, (int)Poke); // Pokeball Only
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -305,34 +304,12 @@ namespace PKHeX.Core
|
|||
private byte PKRS { get => Data[0x82]; set => Data[0x82] = value; }
|
||||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); }
|
||||
|
||||
public override int Ball
|
||||
{
|
||||
get => Math.Max(Data[0x86], Data[0x83]);
|
||||
// Pokemon obtained in HGSS have the HGSS ball set (@0x86)
|
||||
// However, this info is not set when receiving a wondercard!
|
||||
// The PGT contains a preformatted PK4 file, which is slightly modified.
|
||||
// No HGSS balls were used, and no HGSS ball info is set.
|
||||
|
||||
// Sneaky way = return the higher of the two values.
|
||||
|
||||
set
|
||||
{
|
||||
// Ball to display in DPPt
|
||||
Data[0x83] = (byte)(value <= 0x10 ? value : 4); // Cap at Cherish Ball
|
||||
|
||||
// HGSS Exclusive Balls -- If the user wants to screw things up, let them. Any legality checking could catch hax.
|
||||
if (value > 0x10 || (HGSS && !FatefulEncounter))
|
||||
Data[0x86] = (byte)(value <= 0x18 ? value : 4); // Cap at Comp Ball
|
||||
else
|
||||
Data[0x86] = 0; // Unused
|
||||
}
|
||||
}
|
||||
|
||||
public override byte BallDPPt { get => Data[0x83]; set => Data[0x83] = value; }
|
||||
public override int Met_Level { get => Data[0x84] >> 1; set => Data[0x84] = (byte)((Data[0x84] & 0x1) | value << 1); }
|
||||
public override int OT_Gender { get => Data[0x84] & 1; set => Data[0x84] = (byte)((Data[0x84] & ~0x1) | (value & 1)); }
|
||||
public override GroundTileType GroundTile { get => (GroundTileType)Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
// Unused 0x87
|
||||
public override byte BallHGSS { get => Data[0x86]; set => Data[0x86] = value; }
|
||||
public override byte PokéathlonStat { get => Data[0x87]; set => Data[0x87] = value; }
|
||||
#endregion
|
||||
|
||||
// Not stored
|
||||
|
@ -355,18 +332,6 @@ namespace PKHeX.Core
|
|||
return chk;
|
||||
}
|
||||
|
||||
// Synthetic Trading Logic
|
||||
public bool Trade(string SAV_Trainer, int SAV_TID, int SAV_SID, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2009)
|
||||
{
|
||||
// Eggs do not have any modifications done if they are traded
|
||||
if (IsEgg && !(SAV_Trainer == OT_Name && SAV_TID == TID && SAV_SID == SID && SAV_GENDER == OT_Gender))
|
||||
{
|
||||
SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade4);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override byte[] Encrypt()
|
||||
{
|
||||
RefreshChecksum();
|
||||
|
|
|
@ -283,35 +283,12 @@ namespace PKHeX.Core
|
|||
private byte PKRS { get => Data[0x82]; set => Data[0x82] = value; }
|
||||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); }
|
||||
|
||||
public override int Ball
|
||||
{
|
||||
get =>
|
||||
// Pokemon obtained in HGSS have the HGSS ball set (@0x86)
|
||||
// However, this info is not set when receiving a wondercard!
|
||||
// The PGT contains a preformatted PK4 file, which is slightly modified.
|
||||
// No HGSS balls were used, and no HGSS ball info is set.
|
||||
|
||||
// Sneaky way = return the higher of the two values.
|
||||
Math.Max(Data[0x86], Data[0x83]);
|
||||
set
|
||||
{
|
||||
// Ball to display in DPPt
|
||||
Data[0x83] = (byte)(value <= 0x10 ? value : 4); // Cap at Cherish Ball
|
||||
|
||||
// HGSS Exclusive Balls -- If the user wants to screw things up, let them. Any legality checking could catch hax.
|
||||
if (value > 0x10 || (HGSS && !FatefulEncounter))
|
||||
Data[0x86] = (byte)(value <= 0x18 ? value : 4); // Cap at Comp Ball
|
||||
else
|
||||
Data[0x86] = 0; // Unused
|
||||
}
|
||||
}
|
||||
|
||||
public override byte BallDPPt { get => Data[0x83]; set => Data[0x83] = value; }
|
||||
public override int Met_Level { get => Data[0x84] & ~0x80; set => Data[0x84] = (byte)((Data[0x84] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0x84] >> 7; set => Data[0x84] = (byte)((Data[0x84] & ~0x80) | value << 7); }
|
||||
public override GroundTileType GroundTile { get => (GroundTileType)Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
public byte PokéathlonStat { get => Data[0x87]; set => Data[0x87] = value; }
|
||||
// Unused 0x87
|
||||
public override byte BallHGSS { get => Data[0x86]; set => Data[0x86] = value; }
|
||||
public override byte PokéathlonStat { get => Data[0x87]; set => Data[0x87] = value; }
|
||||
#endregion
|
||||
|
||||
#region Battle Stats
|
||||
|
@ -337,18 +314,6 @@ namespace PKHeX.Core
|
|||
return PokeCrypto.EncryptArray45(Data);
|
||||
}
|
||||
|
||||
// Synthetic Trading Logic
|
||||
public bool Trade(string SAV_Trainer, int SAV_TID, int SAV_SID, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2009)
|
||||
{
|
||||
// Eggs do not have any modifications done if they are traded
|
||||
if (IsEgg && !(SAV_Trainer == OT_Name && SAV_TID == TID && SAV_SID == SID && SAV_GENDER == OT_Gender))
|
||||
{
|
||||
SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade4);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public BK4 ConvertToBK4()
|
||||
{
|
||||
BK4 bk4 = ConvertTo<BK4>();
|
||||
|
@ -424,6 +389,10 @@ namespace PKHeX.Core
|
|||
if (Array.IndexOf(banned, Move4) != -1) Move4 = 0;
|
||||
pk5.FixMoves();
|
||||
|
||||
// D/P(not Pt)/HG/SS created Shedinja forget to set Gender to Genderless.
|
||||
if (pk5.Species is (int)Core.Species.Shedinja)
|
||||
pk5.Gender = 2; // Genderless
|
||||
|
||||
pk5.RefreshChecksum();
|
||||
return pk5;
|
||||
}
|
||||
|
|
|
@ -165,6 +165,46 @@ namespace PKHeX.Core
|
|||
public abstract byte CNT_Sheen { get; set; }
|
||||
|
||||
public abstract GroundTileType GroundTile { get; set; }
|
||||
public abstract byte BallDPPt { get; set; }
|
||||
public abstract byte BallHGSS { get; set; }
|
||||
public abstract byte PokéathlonStat { get; set; }
|
||||
|
||||
public sealed override int Ball
|
||||
{
|
||||
// HG/SS added new ball IDs mid-generation, and the previous Gen4 games couldn't handle invalid ball values.
|
||||
// Pokémon obtained in HG/SS have the HG/SS ball value set (@0x86) to the capture ball.
|
||||
// However, this info is not set in event gift data!
|
||||
// Event gift data contains a pre-formatted PK4 template, which is slightly mutated.
|
||||
// No HG/SS ball values were used in these event gifts, and no HG/SS ball values are set (0).
|
||||
|
||||
// To get the display ball (assume HG/SS +), return the higher of the two values.
|
||||
get => Math.Max(BallHGSS, BallDPPt);
|
||||
set
|
||||
{
|
||||
static byte Clamp(int value, Ball max) => (uint)value <= (uint)max ? (byte)value : (byte)Core.Ball.Poke;
|
||||
|
||||
// Ball to display in DPPt
|
||||
BallDPPt = Clamp(value, Core.Ball.Cherish);
|
||||
|
||||
// Only set the HG/SS value if it originated in HG/SS and was not an event.
|
||||
if (!HGSS || FatefulEncounter)
|
||||
BallHGSS = 0;
|
||||
else
|
||||
BallHGSS = Clamp(value, Core.Ball.Sport);
|
||||
}
|
||||
}
|
||||
|
||||
// Synthetic Trading Logic
|
||||
public bool Trade(string SAV_Trainer, int SAV_TID, int SAV_SID, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2009)
|
||||
{
|
||||
// Eggs do not have any modifications done if they are traded
|
||||
if (IsEgg && !(SAV_Trainer == OT_Name && SAV_TID == TID && SAV_SID == SID && SAV_GENDER == OT_Gender))
|
||||
{
|
||||
SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade4);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected T ConvertTo<T>() where T : G4PKM, new()
|
||||
{
|
||||
|
@ -222,8 +262,10 @@ namespace PKHeX.Core
|
|||
Version = Version,
|
||||
PKRS_Days = PKRS_Days,
|
||||
PKRS_Strain = PKRS_Strain,
|
||||
Ball = Ball,
|
||||
BallDPPt = BallDPPt,
|
||||
BallHGSS = BallHGSS,
|
||||
GroundTile = GroundTile,
|
||||
PokéathlonStat = PokéathlonStat,
|
||||
FatefulEncounter = FatefulEncounter,
|
||||
|
||||
Met_Level = Met_Level,
|
||||
|
|
Loading…
Reference in a new issue