mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-26 05:50:22 +00:00
Update 23.07.09
This commit is contained in:
parent
b340e2327a
commit
26cabd022b
29 changed files with 242 additions and 135 deletions
|
@ -1,6 +1,6 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>23.06.03</Version>
|
||||
<Version>23.07.09</Version>
|
||||
<LangVersion>11</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<NeutralLanguage>en</NeutralLanguage>
|
||||
|
|
|
@ -298,7 +298,8 @@ public sealed class ShowdownSet : IBattleTemplate
|
|||
var val = Util.ToInt32(value);
|
||||
if ((uint)val > 10)
|
||||
return false;
|
||||
return (DynamaxLevel = (byte)val) is (>= 0 and <= 10);
|
||||
DynamaxLevel = (byte)val;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ParseTeraType(ReadOnlySpan<char> value)
|
||||
|
|
|
@ -42,7 +42,7 @@ internal static class Encounters3FRLG
|
|||
new(129, 05, FRLG) { Gift = true, Location = 099 }, // Magikarp @ Route 4
|
||||
new(131, 25, FRLG) { Gift = true, Location = 134 }, // Lapras @ Silph Co.
|
||||
new(133, 25, FRLG) { Gift = true, Location = 094 }, // Eevee @ Celadon City
|
||||
new(175, 05, FRLG) { Gift = true, EggLocation = 253 }, // Togepi Egg
|
||||
new(175, 05, FRLG) { Gift = true, EggLocation = 253, Moves = new(045,204,118) }, // Togepi Egg
|
||||
|
||||
// Celadon City Game Corner
|
||||
new(063, 09, FR) { Gift = true, Location = 94 }, // Abra
|
||||
|
|
|
@ -171,7 +171,7 @@ public static class Encounters5B2W2
|
|||
private static readonly EncounterStatic5[] Encounter_B2W2 = ArrayUtil.ConcatAll(Encounter_B2W2_Regular, Encounter_B2W2_N, Encounter_DreamRadar);
|
||||
#endregion
|
||||
#region Trade Tables
|
||||
internal static readonly EncounterTrade5[] TradeGift_B2W2_Regular =
|
||||
private static readonly EncounterTrade5[] TradeGift_B2W2_Regular =
|
||||
{
|
||||
new(B2 ) { Species = 548, Level = 20, Ability = OnlySecond, TID16 = 65217, SID16 = 00000, OTGender = 1, Gender = 1, IVs = new(20,20,20,20,31,20), Nature = Nature.Timid }, // Petilil
|
||||
new( W2) { Species = 546, Level = 20, Ability = OnlyFirst, TID16 = 05720, SID16 = 00001, OTGender = 0, Gender = 0, IVs = new(20,20,20,20,31,20), Nature = Nature.Modest }, // Cottonee
|
||||
|
|
|
@ -21,7 +21,6 @@ public sealed record EncounterEgg(ushort Species, byte Form, byte Level, int Gen
|
|||
public AbilityPermission Ability => AbilityPermission.Any12H;
|
||||
|
||||
public bool CanHaveVoltTackle => Species is (int)Core.Species.Pichu && (Generation > 3 || Version is GameVersion.E);
|
||||
public bool CanInheritMoves => Breeding.GetCanInheritMoves(Species);
|
||||
|
||||
public PKM ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
|
@ -44,33 +44,40 @@ public sealed record EncounterSlot2 : EncounterSlot, INumberedSlot
|
|||
pk2.Met_TimeOfDay = ((EncounterArea2)Area).Time.RandomValidTime();
|
||||
}
|
||||
|
||||
private static readonly Dictionary<int, int> Trees = new()
|
||||
private static ReadOnlySpan<byte> TreeIndexes => new byte[]
|
||||
{
|
||||
{ 02, 0x3FF_3FF }, // Route 29
|
||||
{ 04, 0x0FF_3FF }, // Route 30
|
||||
{ 05, 0x3FE_3FF }, // Route 31
|
||||
{ 08, 0x3EE_3FF }, // Route 32
|
||||
{ 11, 0x240_3FF }, // Route 33
|
||||
{ 12, 0x37F_3FF }, // Azalea Town
|
||||
{ 14, 0x3FF_3FF }, // Ilex Forest
|
||||
{ 15, 0x001_3FE }, // Route 34
|
||||
{ 18, 0x261_3FF }, // Route 35
|
||||
{ 20, 0x3FF_3FF }, // Route 36
|
||||
{ 21, 0x2B9_3FF }, // Route 37
|
||||
{ 25, 0x3FF_3FF }, // Route 38
|
||||
{ 26, 0x184_3FF }, // Route 39
|
||||
{ 34, 0x3FF_3FF }, // Route 42
|
||||
{ 37, 0x3FF_3FF }, // Route 43
|
||||
{ 38, 0x3FF_3FF }, // Lake of Rage
|
||||
{ 39, 0x2FF_3FF }, // Route 44
|
||||
{ 91, 0x200_1FF }, // Route 26
|
||||
{ 92, 0x2BB_3FF }, // Route 27
|
||||
02, 04, 05, 08, 11, 12, 14, 15, 18, 20, 21, 25, 26, 34, 37, 38, 39, 91, 92,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<int> Trees => new[]
|
||||
{
|
||||
0x3FF_3FF, // Route 29
|
||||
0x0FF_3FF, // Route 30
|
||||
0x3FE_3FF, // Route 31
|
||||
0x3EE_3FF, // Route 32
|
||||
0x240_3FF, // Route 33
|
||||
0x37F_3FF, // Azalea Town
|
||||
0x3FF_3FF, // Ilex Forest
|
||||
0x001_3FE, // Route 34
|
||||
0x261_3FF, // Route 35
|
||||
0x3FF_3FF, // Route 36
|
||||
0x2B9_3FF, // Route 37
|
||||
0x3FF_3FF, // Route 38
|
||||
0x184_3FF, // Route 39
|
||||
0x3FF_3FF, // Route 42
|
||||
0x3FF_3FF, // Route 43
|
||||
0x3FF_3FF, // Lake of Rage
|
||||
0x2FF_3FF, // Route 44
|
||||
0x200_1FF, // Route 26
|
||||
0x2BB_3FF, // Route 27
|
||||
};
|
||||
|
||||
public bool IsTreeAvailable(ushort trainerID)
|
||||
{
|
||||
if (!Trees.TryGetValue(Location, out var permissions))
|
||||
var treeIndex = TreeIndexes.BinarySearch((byte)Location);
|
||||
if (treeIndex < 0)
|
||||
return false;
|
||||
var permissions = Trees[treeIndex];
|
||||
|
||||
var pivot = trainerID % 10;
|
||||
var type = Area.Type;
|
||||
|
|
|
@ -50,7 +50,7 @@ public sealed record EncounterSlot7GO : EncounterSlotGO
|
|||
protected override void SetEncounterMoves(PKM pk, GameVersion version, int level)
|
||||
{
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
var source = GameData.GetLearnSource(GameVersion.GG);
|
||||
ILearnSource source = LearnSource7GG.Instance;
|
||||
source.SetEncounterMoves(Species, Form, level, moves);
|
||||
pk.SetMoves(moves);
|
||||
pk.SetMaximumPPCurrent(moves);
|
||||
|
|
|
@ -103,7 +103,7 @@ public sealed record EncounterSlot8GO : EncounterSlotGO, IFixedOTFriendship, IEn
|
|||
s.HeightScalar = PokeSizeUtil.GetRandomScalar();
|
||||
s.WeightScalar = PokeSizeUtil.GetRandomScalar();
|
||||
if (pk is IScaledSize3 s3)
|
||||
s3.Scale = s.HeightScalar = PokeSizeUtil.GetRandomScalar();
|
||||
s3.Scale = s.HeightScalar;
|
||||
}
|
||||
|
||||
if (pk is PA8 pa8)
|
||||
|
|
|
@ -18,7 +18,7 @@ public struct EvolutionNode
|
|||
/// </summary>
|
||||
/// <param name="link">Link to register</param>
|
||||
/// <exception cref="InvalidOperationException"> is thrown if the node is full.</exception>
|
||||
public void Add(EvolutionLink link)
|
||||
public void Add(in EvolutionLink link)
|
||||
{
|
||||
if (First.IsEmpty)
|
||||
First = link;
|
||||
|
|
|
@ -84,7 +84,7 @@ public static class EvolutionReversal
|
|||
return false;
|
||||
}
|
||||
|
||||
private static EvoCriteria Create(EvolutionLink link, byte currentMaxLevel) => new()
|
||||
private static EvoCriteria Create(in EvolutionLink link, byte currentMaxLevel) => new()
|
||||
{
|
||||
Species = link.Species,
|
||||
Form = link.Form,
|
||||
|
|
|
@ -18,13 +18,13 @@ public sealed class EvolutionReverseLookup : IEvolutionLookup
|
|||
MaxSpecies = maxSpecies;
|
||||
}
|
||||
|
||||
private void Register(EvolutionLink link, int index)
|
||||
private void Register(in EvolutionLink link, int index)
|
||||
{
|
||||
ref var node = ref Nodes[index];
|
||||
node.Add(link);
|
||||
}
|
||||
|
||||
public void Register(EvolutionLink link, ushort species, byte form)
|
||||
public void Register(in EvolutionLink link, ushort species, byte form)
|
||||
{
|
||||
if (form == 0)
|
||||
{
|
||||
|
|
|
@ -459,10 +459,14 @@ public sealed class BallVerifier : Verifier
|
|||
if (species is >= (int)Species.Sprigatito and <= (int)Species.Quaquaval) // G9 Starters
|
||||
return VerifyBallEquals(data, (int)Poke);
|
||||
|
||||
// PLA Voltorb: Only via PLA (transfer only, not wild)
|
||||
// PLA Voltorb: Only via PLA (transfer only, not wild) and GO
|
||||
if (enc is { Species: (ushort)Species.Voltorb, Form: 1 })
|
||||
return VerifyBallEquals(data, BallUseLegality.WildPokeballs8g);
|
||||
|
||||
// S/V Tauros forms > 1: Only local Wild Balls for Blaze/Aqua breeds -- can't inherit balls from Kantonian/Combat.
|
||||
if (enc is { Species: (ushort)Species.Tauros, Form: > 1 })
|
||||
return VerifyBallEquals(data, BallUseLegality.WildPokeballs9);
|
||||
|
||||
var pk = data.Entity;
|
||||
if (IsPaldeaCatchAndBreed(species) && IsBallPermitted(BallUseLegality.WildPokeballs9, pk.Ball))
|
||||
return GetValid(LBallSpeciesPass);
|
||||
|
|
|
@ -81,8 +81,6 @@ public sealed class HistoryVerifier : Verifier
|
|||
data.AddLine(GetInvalid(LTransferCurrentHandlerInvalid));
|
||||
if ((Info.Generation != pk.Format || neverOT) && pk.CurrentHandler != 1)
|
||||
data.AddLine(GetInvalid(LTransferHTFlagRequired));
|
||||
if (pk is IHomeTrack { HasTracker: true } && pk.IsUntraded) // HOME sets HT name on moving in and out.
|
||||
data.AddLine(GetInvalid(LTransferHTMismatchName));
|
||||
}
|
||||
|
||||
private static bool IsUntradeableEncounter(IEncounterTemplate enc) => enc switch
|
||||
|
|
|
@ -25,8 +25,8 @@ public static class RibbonStrings
|
|||
var index = line.IndexOf('\t');
|
||||
if (index < 0)
|
||||
continue;
|
||||
var name = line[..index];
|
||||
var text = line[(index + 1)..];
|
||||
var name = line[..index];
|
||||
RibbonNames[name] = text;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class EntityCharacteristic
|
||||
{
|
||||
public static int GetCharacteristic(uint ec, uint iv32)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
|
||||
int maxStatIndex = index;
|
||||
var maxStatValue = 0u;
|
||||
do
|
||||
{
|
||||
var value = iv32 >> (index * 5) & 0x1F;
|
||||
if (value > maxStatValue)
|
||||
{
|
||||
maxStatIndex = index;
|
||||
maxStatValue = value;
|
||||
}
|
||||
if (index != 5)
|
||||
index++;
|
||||
else
|
||||
index = 0;
|
||||
} while (maxStatIndex != index);
|
||||
|
||||
return (maxStatIndex * 5) + ((int)maxStatValue % 5);
|
||||
}
|
||||
|
||||
public static int GetCharacteristic(uint ec, Span<int> ivs)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
|
||||
int maxStatIndex = index;
|
||||
var maxStatValue = 0;
|
||||
do
|
||||
{
|
||||
var value = ivs[index];
|
||||
if (value > maxStatValue)
|
||||
{
|
||||
maxStatIndex = index;
|
||||
maxStatValue = value;
|
||||
}
|
||||
if (index != 5)
|
||||
index++;
|
||||
else
|
||||
index = 0;
|
||||
} while (maxStatIndex != index);
|
||||
|
||||
return (maxStatIndex * 5) + (maxStatValue % 5);
|
||||
}
|
||||
|
||||
public static int GetCharacteristicInvertFields(uint ec, uint iv32)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
|
||||
int maxStatIndex = index;
|
||||
var maxStatValue = 0u;
|
||||
do
|
||||
{
|
||||
// IVs are stored in reverse order, get the bits from the end of the IV value
|
||||
var value = iv32 >> (27 - (index * 5)) & 0x1F;
|
||||
if (value > maxStatValue)
|
||||
{
|
||||
maxStatIndex = index;
|
||||
maxStatValue = value;
|
||||
}
|
||||
if (index != 5)
|
||||
index++;
|
||||
else
|
||||
index = 0;
|
||||
} while (maxStatIndex != index);
|
||||
|
||||
return (maxStatIndex * 5) + ((int)maxStatValue % 5);
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ namespace PKHeX.Core;
|
|||
/// <summary>
|
||||
/// Side game data for <see cref="PA8"/> data transferred into HOME.
|
||||
/// </summary>
|
||||
public sealed class GameDataPA8 : HomeOptional1, IGameDataSide<PA8>, IScaledSizeAbsolute, IScaledSize3, IGameDataSplitAbility
|
||||
public sealed class GameDataPA8 : HomeOptional1, IGameDataSide<PA8>, IScaledSizeAbsolute, IScaledSize3, IGameDataSplitAbility, IPokerusStatus
|
||||
{
|
||||
private const HomeGameDataFormat ExpectFormat = HomeGameDataFormat.PA8;
|
||||
private const int SIZE = HomeCrypto.SIZE_2GAME_PA8;
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the ability and ability number for a <see cref="PKM"/> that has side-game specific data.
|
||||
/// </summary>
|
||||
public interface IGameDataSplitAbility
|
||||
{
|
||||
/// <summary>
|
||||
/// Ability ID for the <see cref="PKM"/>.
|
||||
/// </summary>
|
||||
ushort Ability { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability number for the <see cref="PKM"/>.
|
||||
/// </summary>
|
||||
byte AbilityNumber { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,11 +1,29 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for a HOME storage system.
|
||||
/// </summary>
|
||||
public interface IHomeStorage
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the given tracker exists in the storage system.
|
||||
/// </summary>
|
||||
/// <param name="tracker">Tracker to check</param>
|
||||
/// <returns>True if the tracker exists, false otherwise.</returns>
|
||||
bool Exists(ulong tracker);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HOME entity for the given <see cref="PKM"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Input PKM type</typeparam>
|
||||
/// <param name="pk">PKM to get the entity for</param>
|
||||
/// <returns>HOME entity for the given <see cref="PKM"/>.</returns>
|
||||
PKH GetEntity<T>(T pk) where T : PKM;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for a HOME storage system.
|
||||
/// </summary>
|
||||
public sealed class HomeStorageFacade : IHomeStorage
|
||||
{
|
||||
public bool Exists(ulong tracker) => false;
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the Pokerus status of a <see cref="PKM"/>.
|
||||
/// </summary>
|
||||
public interface IPokerusStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Pokerus Strain and Duration
|
||||
/// </summary>
|
||||
byte PKRS { get; set; }
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ public static class ObedienceExtensions
|
|||
{
|
||||
if (entity.Species is (int)Species.Koraidon or (int)Species.Miraidon && entity is PK9 { FormArgument: not 0 })
|
||||
return 0; // Box Legend ride-able is default 0. Everything else is met level!
|
||||
if (entity.Version is not (int)GameVersion.SL or (int)GameVersion.VL)
|
||||
if (entity.Version is not ((int)GameVersion.SL or (int)GameVersion.VL))
|
||||
return (byte)entity.CurrentLevel; // foreign, play it safe.
|
||||
// Can just assume min-level
|
||||
return (byte)originalMet;
|
114
PKHeX.Core/PKM/Util/EntityCharacteristic.cs
Normal file
114
PKHeX.Core/PKM/Util/EntityCharacteristic.cs
Normal file
|
@ -0,0 +1,114 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for calculating the characteristic behavior of Pokémon.
|
||||
/// </summary>
|
||||
public static class EntityCharacteristic
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the characteristic index from the input parameters.
|
||||
/// </summary>
|
||||
/// <param name="maxStatIndex">Index of the highest IV.</param>
|
||||
/// <param name="maxStatValue">Value of the highest IV.</param>
|
||||
/// <returns>Characteristic index.</returns>
|
||||
public static int GetCharacteristic(int maxStatIndex, int maxStatValue) => (maxStatIndex * 5) + (maxStatValue % 5);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the characteristic index of the given IVs in Little Endian format.
|
||||
/// </summary>
|
||||
/// <param name="ec">Encryption Constant.</param>
|
||||
/// <param name="iv32">Lumped IVs in Little Endian format.</param>
|
||||
/// <returns>Characteristic index.</returns>
|
||||
public static int GetCharacteristic(uint ec, uint iv32)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
|
||||
// Get individual IVs from the lumped value.
|
||||
// The IVs are stored in the following order: HP, Atk, Def, Spe, SpA, SpD
|
||||
// Check all IVs, get the highest IV and its index. If there are multiple highest IVs, the first index checked is chosen.
|
||||
int maxStatIndex = index;
|
||||
var maxStatValue = 0u;
|
||||
do
|
||||
{
|
||||
var value = iv32 >> (index * 5) & 0x1F;
|
||||
if (value > maxStatValue)
|
||||
{
|
||||
maxStatIndex = index;
|
||||
maxStatValue = value;
|
||||
}
|
||||
if (index != 5)
|
||||
index++;
|
||||
else
|
||||
index = 0;
|
||||
} while (maxStatIndex != index);
|
||||
|
||||
return GetCharacteristic(maxStatIndex, (int)maxStatValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the characteristic index of the given unpacked IVs.
|
||||
/// </summary>
|
||||
/// <param name="ec">Encryption Constant.</param>
|
||||
/// <param name="ivs">Unpacked IVs.</param>
|
||||
/// <returns>Characteristic index.</returns>
|
||||
public static int GetCharacteristic(uint ec, Span<int> ivs)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
|
||||
// Get individual IVs from the lumped value.
|
||||
// The IVs are stored in the following order: HP, Atk, Def, Spe, SpA, SpD
|
||||
// Check all IVs, get the highest IV and its index. If there are multiple highest IVs, the first index checked is chosen.
|
||||
int maxStatIndex = index;
|
||||
var maxStatValue = 0;
|
||||
do
|
||||
{
|
||||
var value = ivs[index];
|
||||
if (value > maxStatValue)
|
||||
{
|
||||
maxStatIndex = index;
|
||||
maxStatValue = value;
|
||||
}
|
||||
if (index != 5)
|
||||
index++;
|
||||
else
|
||||
index = 0;
|
||||
} while (maxStatIndex != index);
|
||||
|
||||
return GetCharacteristic(maxStatIndex, maxStatValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the characteristic index of the given IVs in Big Endian format.
|
||||
/// </summary>
|
||||
/// <param name="ec">Encryption Constant.</param>
|
||||
/// <param name="iv32">Lumped IVs in Big Endian format.</param>
|
||||
/// <returns>Characteristic index.</returns>
|
||||
public static int GetCharacteristicInvertFields(uint ec, uint iv32)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
|
||||
// Get individual IVs from the lumped value.
|
||||
// The IVs are stored in the following order: SpD, SpA, Spe, Def, Atk, HP
|
||||
// Check all IVs, get the highest IV and its index. If there are multiple highest IVs, the first index checked is chosen.
|
||||
int maxStatIndex = index;
|
||||
var maxStatValue = 0u;
|
||||
do
|
||||
{
|
||||
// IVs are stored in reverse order, get the bits from the end of the IV value
|
||||
var value = iv32 >> (27 - (index * 5)) & 0x1F;
|
||||
if (value > maxStatValue)
|
||||
{
|
||||
maxStatIndex = index;
|
||||
maxStatValue = value;
|
||||
}
|
||||
if (index != 5)
|
||||
index++;
|
||||
else
|
||||
index = 0;
|
||||
} while (maxStatIndex != index);
|
||||
|
||||
return GetCharacteristic(maxStatIndex, (int)maxStatValue);
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -15,7 +15,7 @@ internal sealed class SAV2Offsets
|
|||
LoadOffsetsKorean();
|
||||
else
|
||||
LoadOffsetsInternational(sav.Version);
|
||||
Daycare = PokedexSeen + 0x1F + 28 + 1; // right after first unown seen
|
||||
Daycare = PokedexSeen + 0x1F + 28 + 1; // right after first Unown seen
|
||||
EventWork = EventFlag - 0x100;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ internal sealed class SAV2Offsets
|
|||
public int Gender { get; private set; } = -1;
|
||||
public int AccumulatedChecksumEnd { get; private set; } = -1;
|
||||
public int OverallChecksumPosition { get; private set; } = -1;
|
||||
public int OverallChecksumPosition2 { get; private set; }
|
||||
public int EventFlag { get; private set; } = -1;
|
||||
public int EventWork { get; }
|
||||
public int Daycare { get; }
|
||||
|
@ -112,7 +113,7 @@ internal sealed class SAV2Offsets
|
|||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException(nameof(version));
|
||||
throw new ArgumentOutOfRangeException(nameof(version), version, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,12 +177,10 @@ internal sealed class SAV2Offsets
|
|||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException(nameof(version));
|
||||
throw new ArgumentOutOfRangeException(nameof(version), version, null);
|
||||
}
|
||||
}
|
||||
|
||||
public int OverallChecksumPosition2 { get; set; }
|
||||
|
||||
private void LoadOffsetsKorean()
|
||||
{
|
||||
RTCFlags = 0x1060;
|
||||
|
|
|
@ -262,7 +262,7 @@ public abstract class InventoryPouch
|
|||
{
|
||||
// Cap at absolute maximum
|
||||
<= 2 when count > byte.MaxValue => byte.MaxValue,
|
||||
>= 3 when count > ushort.MaxValue => ushort.MaxValue,
|
||||
_ when count > ushort.MaxValue => ushort.MaxValue,
|
||||
_ => count,
|
||||
};
|
||||
return true;
|
||||
|
|
|
@ -119,15 +119,24 @@ public static partial class Util
|
|||
return result;
|
||||
}
|
||||
|
||||
public static byte[] GetBytesFromHexString(ReadOnlySpan<char> seed)
|
||||
/// <summary>
|
||||
/// Parses a variable length hex string (non-spaced, bytes in reverse order).
|
||||
/// </summary>
|
||||
public static byte[] GetBytesFromHexString(ReadOnlySpan<char> input)
|
||||
{
|
||||
byte[] result = new byte[input.Length / 2];
|
||||
GetBytesFromHexString(input, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="GetBytesFromHexString(ReadOnlySpan{char})"/>
|
||||
public static void GetBytesFromHexString(ReadOnlySpan<char> input, Span<byte> result)
|
||||
{
|
||||
byte[] result = new byte[seed.Length / 2];
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var slice = seed.Slice(i * 2, 2);
|
||||
result[^(i+1)] = (byte)GetHexValue(slice);
|
||||
var slice = input.Slice(i * 2, 2);
|
||||
result[^(i + 1)] = (byte)GetHexValue(slice);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private const string HexChars = "0123456789ABCDEF";
|
||||
|
|
|
@ -108,7 +108,7 @@ public partial class SizeCP : UserControl
|
|||
var label = L_SizeH;
|
||||
var value = ss.HeightScalar;
|
||||
label.Text = SizeClass[(int)PokeSizeUtil.GetSizeRating(value)];
|
||||
SetLabelColorHeightWeight(label, value);
|
||||
SetLabelColorHeightWeight(label);
|
||||
}
|
||||
|
||||
if (!CHK_Auto.Checked || Loading || sv == null)
|
||||
|
@ -128,7 +128,7 @@ public partial class SizeCP : UserControl
|
|||
var label = L_SizeW;
|
||||
var value = ss.WeightScalar;
|
||||
label.Text = SizeClass[(int)PokeSizeUtil.GetSizeRating(value)];
|
||||
SetLabelColorHeightWeight(label, value);
|
||||
SetLabelColorHeightWeight(label);
|
||||
}
|
||||
|
||||
if (!CHK_Auto.Checked || Loading || sv == null)
|
||||
|
@ -158,12 +158,10 @@ public partial class SizeCP : UserControl
|
|||
}
|
||||
}
|
||||
|
||||
private void SetLabelColorHeightWeight(Control label, byte value)
|
||||
private void SetLabelColorHeightWeight(Control label)
|
||||
{
|
||||
if (scale is not null)
|
||||
label.ForeColor = Color.Gray; // not indicative of actual size
|
||||
else if (value is 255 && scale is PA8)
|
||||
label.ForeColor = Color.Red; // Alpha or (unlikely, user error?)
|
||||
else
|
||||
label.ResetForeColor();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,27 @@
|
|||
PKHeX - By Kaphotics
|
||||
http://projectpokemon.org/pkhex/
|
||||
|
||||
23/06/03 - New Update:
|
||||
23/07/09 - New Update:
|
||||
- Legality: Updated evolution checking algorithms to better identify game visitation. Thanks @Lusamine & @sora10pls !
|
||||
- - Added: HOME 3.0.0 move sharing logic for learning moves via HOME instead of in-game.
|
||||
- - Added: HOME 3.0.0 ball inheritance logic for breeding encounters for/from Scarlet/Violet.
|
||||
- - Added: GO Master Ball legality checks now allows Master Ball when encounter date & type permits.
|
||||
- - Added: GO encounters outside the availability window now display a detailed illegal message.
|
||||
- Added: Gen4/5 Geonet/Unity Tower editor. Thanks @abcboy101 !
|
||||
- Changed: Gen9 Tera Type icons now use higher quality sprites from HOME. Thanks @sora10pls !
|
||||
- Changed: Gen8a Move Shop editor GUI has been redesigned for a more visual experience.
|
||||
- Changed: Gen7b+ Height/Weight now show as gray whenever Scale takes precedence in sizing determinations.
|
||||
- Fixed: Batch Editor filters now work correctly for Box/Slot when using operators other than ! or =
|
||||
- Fixed: Gen7b Randomize IV/AV buttons now center correctly within the form.
|
||||
- Fixed: Gen7 Report grid now shows Resort (Poké Pelago) slots correctly.
|
||||
- Fixed: Gen6/7 Memory Editor now shows Country/Region visitation correctly.
|
||||
- Fixed: Gen6 Hall of Fame editor now keeps leading zeroes on the TID/SID entry fields.
|
||||
- Fixed: Gen5 unused second Roamer block editor editing now reads from the correct offsets. Thanks SaltedNeos !
|
||||
- Fixed: Gen4 Ranch checksums are now applied correctly again. Thanks @Zazsona !
|
||||
- Fixed: Gen3 adding Ferry Tickets no longer causes the program to error when your Key Items bag is full.
|
||||
- Fixed: Gen2 International Crystal saves now set the backup checksum to the correct offset. Thanks @Zazsona !
|
||||
|
||||
23/06/03 - New Update: (178908) [6981641]
|
||||
- Added: HOME 3.0.0 initial support. Legality analysis is still under research. Thanks @Lusamine & @sora10pls !
|
||||
- - Lacks full support for cross-game transfers involving evolutions and moves. Please be patient, there's a lot of things to handle!
|
||||
- Added: Tech Record editor GUI has been redesigned for a more visual experience. Can now sort alphabetically, owned, or move type.
|
||||
|
@ -10,7 +30,7 @@ http://projectpokemon.org/pkhex/
|
|||
- Changed: Gen7 Totem Form sprites now display with an Orange-colored glow, similar to Gen3 C/XD shadow purple.
|
||||
- Changed: DPI scaling adjusted for better appearance on high resolution monitors.
|
||||
|
||||
23/05/11 - New Update:
|
||||
23/05/11 - New Update: (80094) [6802733]
|
||||
- Legality:
|
||||
- - Changed: Creating a new PKM from template will set current moves same as the games.
|
||||
- - Changed: Pokérus strains 0 & 8 now permitted due to official implementation errors in Gen2 & Gen3.
|
||||
|
@ -29,7 +49,7 @@ http://projectpokemon.org/pkhex/
|
|||
- Fixed: Gen3 XD un-purified shadow Pokémon no longer flag w/o Ribbon if they have a Shadow Gauge of 0 (ready to purify).
|
||||
- Changed: Sub-form scaling mode changed to "Inherit" -- added a Display setting to revert back to Form scaling (from Dpi).
|
||||
|
||||
23/04/06 - New Update:
|
||||
23/04/06 - New Update: (166321) [6722639]
|
||||
- Legality:
|
||||
- - Changed: Vivillon 3DS Region handling reworked to handle all regions. Thanks @abcboy101!
|
||||
- - Fixed: BDSP footprint ribbon now checks correctly.
|
||||
|
|
Loading…
Reference in a new issue