Compare commits

..

1 Commits

Author SHA1 Message Date
Kurt
1891925fe7 Update 26.03.06 2026-03-06 23:13:40 -06:00
218 changed files with 6350 additions and 6882 deletions

View File

@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>26.03.20</Version>
<Version>26.03.06</Version>
<LangVersion>14</LangVersion>
<Nullable>enable</Nullable>
<NeutralLanguage>en</NeutralLanguage>

View File

@ -342,12 +342,12 @@ private bool ParseLineNature(ReadOnlySpan<char> input, ReadOnlySpan<string> natu
return false;
var nature = (Nature)index;
if (!nature.IsFixed)
if (!nature.IsFixed())
{
LogError(NatureUnrecognized, input);
return false;
}
if (Nature.IsFixed && Nature != nature)
if (Nature != Nature.Random && Nature != nature)
{
LogError(NatureAlreadySpecified, input);
return false;
@ -627,7 +627,7 @@ private void AddEVs(List<string> result, in BattleTemplateExportSettings setting
BattleTemplateToken.EVsAppendNature => GetStringStatsNatureAmp(EVs, 0, nameEVs, Nature),
_ => GetStringStats(EVs, 0, nameEVs),
};
if (token is BattleTemplateToken.EVsAppendNature && Nature.IsFixed)
if (token is BattleTemplateToken.EVsAppendNature && Nature.IsFixed())
line += $" ({settings.Localization.Strings.natures[(int)Nature]})";
result.Add(cfg.Push(BattleTemplateToken.EVs, line));
}
@ -1081,7 +1081,7 @@ private bool ParseLineEVs(ReadOnlySpan<char> line, BattleTemplateLocalization lo
return false; // invalid line
}
if (Nature.IsFixed) // specified in a separate Nature line
if (Nature != Nature.Random) // specified in a separate Nature line
LogError(NatureEffortAmpAlreadySpecified, natureName);
else
Nature = (Nature)natureIndex;
@ -1100,7 +1100,7 @@ private bool ParseLineEVs(ReadOnlySpan<char> line, BattleTemplateLocalization lo
result.TreatAmpsAsSpeedNotLast();
var ampNature = AdjustNature(result.Plus, result.Minus);
success &= ampNature;
if (ampNature && currentNature.IsFixed && currentNature != Nature)
if (ampNature && currentNature != Nature.Random && currentNature != Nature)
{
LogError(NatureEffortAmpConflictNature);
Nature = currentNature; // revert to original

View File

@ -205,10 +205,10 @@ public ModifyResult TryModify(TObject entity, IEnumerable<StringInstruction> fil
return result;
}
private static Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[] GetPropertyDictionaries(ReadOnlySpan<Type> types, int expectedMax)
private static Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[] GetPropertyDictionaries(IReadOnlyList<Type> types, int expectedMax)
{
var result = new Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[types.Length];
for (int i = 0; i < types.Length; i++)
var result = new Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[types.Count];
for (int i = 0; i < types.Count; i++)
result[i] = GetPropertyDictionary(types[i], ReflectUtil.GetAllPropertyInfoPublic, expectedMax).GetAlternateLookup<ReadOnlySpan<char>>();
return result;
}

View File

@ -30,10 +30,8 @@ public void SetNickname(string nick)
pk.ClearNickname();
return;
}
pk.PrepareNickname();
pk.Nickname = nick;
pk.IsNicknamed = true;
pk.Nickname = nick;
}
/// <summary>
@ -139,7 +137,7 @@ public bool SetUnshiny()
/// <param name="nature">Desired <see cref="PKM.Nature"/> value to set.</param>
public void SetNature(Nature nature)
{
if (!nature.IsFixed)
if (!nature.IsFixed())
nature = 0; // default valid
var format = pk.Format;

View File

@ -1,12 +1,21 @@
using System;
using System;
namespace PKHeX.Core;
/// <summary>
/// Base class for defining a manipulation of box data.
/// </summary>
public abstract record BoxManipBase(BoxManipType Type, Func<SaveFile, bool> Usable) : IBoxManip
public abstract class BoxManipBase : IBoxManip
{
public BoxManipType Type { get; }
public Func<SaveFile, bool> Usable { get; }
protected BoxManipBase(BoxManipType type, Func<SaveFile, bool> usable)
{
Type = type;
Usable = usable;
}
public abstract string GetPrompt(bool all);
public abstract string GetFail(bool all);
public abstract string GetSuccess(bool all);

View File

@ -5,7 +5,7 @@ namespace PKHeX.Core;
/// <summary>
/// Clears contents of boxes by deleting all that satisfy a criteria.
/// </summary>
public sealed record BoxManipClear(BoxManipType Type, Func<PKM, bool> Criteria, Func<SaveFile, bool> Usable) : BoxManipBase(Type, Usable)
public sealed class BoxManipClear(BoxManipType Type, Func<PKM, bool> criteria, Func<SaveFile, bool> Usable) : BoxManipBase(Type, Usable)
{
public BoxManipClear(BoxManipType Type, Func<PKM, bool> Criteria) : this(Type, Criteria, _ => true) { }
@ -18,6 +18,6 @@ public override int Execute(SaveFile sav, BoxManipParam param)
var (start, stop, reverse) = param;
return sav.ClearBoxes(start, stop, Method);
bool Method(PKM p) => reverse ^ Criteria(p);
bool Method(PKM p) => reverse ^ criteria(p);
}
}

View File

@ -5,7 +5,7 @@ namespace PKHeX.Core;
/// <summary>
/// Clears contents of boxes by deleting all that satisfy a criteria based on a <see cref="SaveFile"/>.
/// </summary>
public sealed record BoxManipClearComplex(BoxManipType Type, Func<PKM, SaveFile, bool> Criteria, Func<SaveFile, bool> Usable) : BoxManipBase(Type, Usable)
public sealed class BoxManipClearComplex(BoxManipType Type, Func<PKM, SaveFile, bool> criteria, Func<SaveFile, bool> Usable) : BoxManipBase(Type, Usable)
{
public BoxManipClearComplex(BoxManipType Type, Func<PKM, SaveFile, bool> Criteria) : this(Type, Criteria, _ => true) { }
@ -18,6 +18,6 @@ public override int Execute(SaveFile sav, BoxManipParam param)
var (start, stop, reverse) = param;
return sav.ClearBoxes(start, stop, Method);
bool Method(PKM p) => reverse ^ Criteria(p, sav);
bool Method(PKM p) => reverse ^ criteria(p, sav);
}
}

View File

@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// Clears contents of boxes by deleting all but the first duplicate detected.
/// </summary>
/// <typeparam name="T">Base type of the "is duplicate" hash for the duplicate detection.</typeparam>
public sealed record BoxManipClearDuplicate<T> : BoxManipBase
public sealed class BoxManipClearDuplicate<T> : BoxManipBase
{
private readonly HashSet<T> HashSet = [];
private readonly Func<PKM, bool> Criteria;

View File

@ -5,8 +5,8 @@ namespace PKHeX.Core;
/// <summary>
/// Modifies contents of boxes by using an <see cref="Action"/> to change data.
/// </summary>
public sealed record BoxManipModify(BoxManipType Type, Action<PKM> Action, Func<SaveFile, bool> Usable)
: BoxManipBase(Type, Usable)
public sealed class BoxManipModify(BoxManipType type, Action<PKM> Action, Func<SaveFile, bool> Usable)
: BoxManipBase(type, Usable)
{
public BoxManipModify(BoxManipType type, Action<PKM> Action) : this(type, Action, _ => true) { }

View File

@ -5,7 +5,7 @@ namespace PKHeX.Core;
/// <summary>
/// Modifies contents of boxes by using an <see cref="Action"/> (referencing a Save File) to change data.
/// </summary>
public sealed record BoxManipModifyComplex(BoxManipType Type, Action<PKM, SaveFile> Action, Func<SaveFile, bool> Usable)
public sealed class BoxManipModifyComplex(BoxManipType Type, Action<PKM, SaveFile> Action, Func<SaveFile, bool> Usable)
: BoxManipBase(Type, Usable)
{
public BoxManipModifyComplex(BoxManipType Type, Action<PKM, SaveFile> Action) : this(Type, Action, _ => true) { }

View File

@ -6,7 +6,7 @@ namespace PKHeX.Core;
/// <summary>
/// Sorts contents of boxes by using a Sorter to determine the order.
/// </summary>
public sealed record BoxManipSort(BoxManipType Type, Func<IEnumerable<PKM>, IEnumerable<PKM>> Sorter, Func<SaveFile, bool> Usable) : BoxManipBase(Type, Usable)
public sealed class BoxManipSort(BoxManipType Type, Func<IEnumerable<PKM>, IEnumerable<PKM>> Sorter, Func<SaveFile, bool> Usable) : BoxManipBase(Type, Usable)
{
public BoxManipSort(BoxManipType Type, Func<IEnumerable<PKM>, IEnumerable<PKM>> Sorter) : this(Type, Sorter, _ => true) { }

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
namespace PKHeX.Core;
@ -6,7 +6,7 @@ namespace PKHeX.Core;
/// <summary>
/// Sorts contents of boxes by using a <see cref="Sorter"/> (referencing a Save File) to determine the order.
/// </summary>
public sealed record BoxManipSortComplex : BoxManipBase
public sealed class BoxManipSortComplex : BoxManipBase
{
private readonly Func<IEnumerable<PKM>, SaveFile, int, IEnumerable<PKM>> Sorter;
public BoxManipSortComplex(BoxManipType type, Func<IEnumerable<PKM>, SaveFile, IEnumerable<PKM>> sorter) : this(type, sorter, _ => true) { }

View File

@ -61,11 +61,11 @@ private static List<SlotInfoMisc> GetExtraSlots2(SAV2 sav)
private static List<SlotInfoMisc> GetExtraSlots3(SAV3 sav)
{
if (sav is not SAV3FRLG frlg)
if (sav is not SAV3FRLG)
return None;
return
[
new(frlg.LargeBlock.SingleDaycareRoute5, 0) {Type = StorageSlotType.Daycare},
new(sav.LargeBuffer[0x3C98..], 0) {Type = StorageSlotType.Daycare},
];
}

View File

@ -51,7 +51,7 @@ public enum StorageSlotType : byte
/// Shiny Overworld Cache
/// </summary>
/// <remarks>
/// <see cref="GameVersion.ZA"/>
/// <see cref="GameVersion.ZA"/>
/// </remarks>
Shiny,

View File

@ -55,7 +55,7 @@ public static class NatureUtil
/// Checks if the provided <see cref="value"/> is a valid stored <see cref="Nature"/> value.
/// </summary>
/// <returns>True if value is an actual nature.</returns>
public bool IsFixed => value != Nature.Random;
public bool IsFixed() => value < Nature.Random;
/// <summary>
/// Checks if the provided <see cref="value"/> is a possible mint nature.
@ -63,12 +63,12 @@ public static class NatureUtil
/// <remarks>
/// The only valid mint natures are those which have a stat amp applied, or neutral nature being Serious.
/// </remarks>
public bool IsMint => (value.IsFixed && (byte)value % 6 != 0) || value == Nature.Serious;
public bool IsMint() => (value.IsFixed() && (byte)value % 6 != 0) || value == Nature.Serious;
/// <summary>
/// Checks if the provided <see cref="value"/> is a neutral nature which has no stat amps applied.
/// </summary>
public bool IsNeutral => value.IsFixed && (byte)value % 6 == 0;
public bool IsNeutral() => value.IsFixed() && (byte)value % 6 == 0;
/// <summary>
/// Converts the provided <see cref="value"/> to a neutral nature.

View File

@ -6,6 +6,8 @@ namespace PKHeX.Core;
public sealed class PlayerBag3E : PlayerBag, IPlayerBag3
{
private const int BaseOffset = 0x0498;
public override IReadOnlyList<InventoryPouch3> Pouches { get; } = GetPouches(ItemStorage3E.Instance);
public override ItemStorage3E Info => ItemStorage3E.Instance;
@ -19,7 +21,7 @@ public sealed class PlayerBag3E : PlayerBag, IPlayerBag3
new(0x000, 50, 999, info, PCItems),
];
public PlayerBag3E(SAV3E sav) : this(sav.LargeBlock.Inventory, sav.SmallBlock.SecurityKey) { }
public PlayerBag3E(SAV3E sav) : this(sav.Large[BaseOffset..], sav.SecurityKey) { }
public PlayerBag3E(ReadOnlySpan<byte> data, uint security)
{
UpdateSecurityKey(security);
@ -27,7 +29,7 @@ public PlayerBag3E(ReadOnlySpan<byte> data, uint security)
}
public override void CopyTo(SaveFile sav) => CopyTo((SAV3E)sav);
public void CopyTo(SAV3E sav) => CopyTo(sav.LargeBlock.Inventory);
public void CopyTo(SAV3E sav) => CopyTo(sav.Large[BaseOffset..]);
public void CopyTo(Span<byte> data) => Pouches.SaveAll(data);
public override int GetMaxCount(InventoryType type, int itemIndex)

View File

@ -6,6 +6,7 @@ namespace PKHeX.Core;
public sealed class PlayerBag3FRLG(bool VC) : PlayerBag, IPlayerBag3
{
private const int BaseOffset = 0x0298;
public override IItemStorage Info => GetInfo(VC);
private static IItemStorage GetInfo(bool vc) => vc ? ItemStorage3FRLG_VC.Instance : ItemStorage3FRLG.Instance;
public override IReadOnlyList<InventoryPouch3> Pouches { get; } = GetPouches(GetInfo(VC));
@ -20,7 +21,7 @@ public sealed class PlayerBag3FRLG(bool VC) : PlayerBag, IPlayerBag3
new(0x000, 30, 999, info, PCItems),
];
public PlayerBag3FRLG(SAV3FRLG sav) : this(sav.LargeBlock.Inventory, sav.SmallBlock.SecurityKey, sav.IsVirtualConsole) { }
public PlayerBag3FRLG(SAV3FRLG sav) : this(sav.Large[BaseOffset..], sav.SecurityKey, sav.IsVirtualConsole) { }
public PlayerBag3FRLG(ReadOnlySpan<byte> data, uint security, bool vc) : this(vc)
{
UpdateSecurityKey(security);
@ -28,7 +29,7 @@ public PlayerBag3FRLG(ReadOnlySpan<byte> data, uint security, bool vc) : this(vc
}
public override void CopyTo(SaveFile sav) => CopyTo((SAV3FRLG)sav);
public void CopyTo(SAV3FRLG sav) => CopyTo(sav.LargeBlock.Inventory);
public void CopyTo(SAV3FRLG sav) => CopyTo(sav.Large[BaseOffset..]);
public void CopyTo(Span<byte> data) => Pouches.SaveAll(data);
public override int GetMaxCount(InventoryType type, int itemIndex)

View File

@ -6,6 +6,8 @@ namespace PKHeX.Core;
public sealed class PlayerBag3RS : PlayerBag
{
private const int BaseOffset = 0x0498;
public override IReadOnlyList<InventoryPouch3> Pouches { get; } = GetPouches(ItemStorage3RS.Instance);
public override ItemStorage3RS Info => ItemStorage3RS.Instance;
@ -19,11 +21,11 @@ public sealed class PlayerBag3RS : PlayerBag
new(0x000, 50, 999, info, PCItems),
];
public PlayerBag3RS(SAV3RS sav) : this(sav.LargeBlock.Inventory) { }
public PlayerBag3RS(SAV3RS sav) : this(sav.Large[BaseOffset..]) { }
public PlayerBag3RS(ReadOnlySpan<byte> data) => Pouches.LoadAll(data);
public override void CopyTo(SaveFile sav) => CopyTo((SAV3RS)sav);
public void CopyTo(SAV3RS sav) => CopyTo(sav.LargeBlock.Inventory);
public void CopyTo(SAV3RS sav) => CopyTo(sav.Large[BaseOffset..]);
public void CopyTo(Span<byte> data) => Pouches.SaveAll(data);
public override int GetMaxCount(InventoryType type, int itemIndex)

View File

@ -13,9 +13,9 @@ public sealed class ItemStorage3E : IItemStorage
public static ReadOnlySpan<ushort> Key =>
[
// R/S
259, 260, 261, 262, 263, 264, 265, 266, 268, 269, 270, 271, 272, 273, 274, 275, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
259, 260, 261, 262, 263, 264, 265, 266, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
// FR/LG
370, 371, 372,
349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
// E
375, 376,
];

View File

@ -13,7 +13,7 @@ public sealed class ItemStorage3FRLG : IItemStorage
public static ReadOnlySpan<ushort> Key =>
[
// R/S
260, 261, 262, 263, 264, 265,
259, 260, 261, 262, 263, 264, 265, 266, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
// FR/LG
349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
];
@ -55,7 +55,7 @@ public sealed class ItemStorage3FRLG_VC : IItemStorage // TODO VC RSE: delete me
// Unobtainable
044, // Berry Juice
// TODO RSE VC: Remove these
046, 047, // Shoal Salt, Shoal Shell
048, 049, 050, 051, // Shards
@ -71,7 +71,7 @@ public sealed class ItemStorage3FRLG_VC : IItemStorage // TODO VC RSE: delete me
173, // Lansat Berry (Event)
174, // Starf Berry (Event)
175, // Enigma Berry (Event)
// TODO RSE VC: Remove these
179, // BrightPowder
180, // White Herb

View File

@ -112,7 +112,7 @@ public EncounterCriteria()
/// Determines whether a specific Nature is specified in the criteria or if complex nature mutations are allowed.
/// </summary>
/// <returns>><see langword="true"/> if a Nature is specified or complex nature mutations are allowed; otherwise, <see langword="false"/>.</returns>
public bool IsSpecifiedNature() => Nature.IsFixed || Mutations.IsComplexNature();
public bool IsSpecifiedNature() => Nature != Nature.Random || Mutations.IsComplexNature();
/// <summary>
/// Determines whether a level range is specified in the criteria.
@ -126,12 +126,6 @@ public EncounterCriteria()
/// <returns>><see langword="true"/> if an Ability is specified; otherwise, <see langword="false"/>.</returns>
public bool IsSpecifiedAbility() => Ability != Any12H;
/// <summary>
/// Determines whether the shiny value is explicitly specified rather than set to random.
/// </summary>
/// <returns>><see langword="true"/> if a Shiny is specified; otherwise, <see langword="false"/>.</returns>
public bool IsSpecifiedShiny() => Shiny != Shiny.Random;
/// <summary>
/// Determines whether all IVs are specified in the criteria.
/// </summary>
@ -189,20 +183,6 @@ public int GetCountSpecifiedIVs() => Convert.ToInt32(IV_HP != RandomIV)
_ => throw new ArgumentOutOfRangeException(nameof(ability), ability, null),
};
/// <summary>
/// Determines whether the specified shiny properties satisfy the shiny criteria based on the current <see cref="Shiny"/> setting.
/// </summary>
/// <returns>><see langword="true"/> if the index satisfies the shiny criteria; otherwise, <see langword="false"/>.</returns>
public bool IsSatisfiedShiny(uint xor, uint cmp) => Shiny switch
{
Shiny.Random => true,
Shiny.Never => xor > cmp, // not shiny
Shiny.AlwaysSquare => xor == 0, // square shiny
Shiny.AlwaysStar => xor < cmp && xor != 0, // star shiny
Shiny.Always => xor < cmp, // shiny
_ => false, // shouldn't be set
};
/// <summary>
/// Determines whether the specified Nature satisfies the criteria.
/// </summary>
@ -211,7 +191,7 @@ public int GetCountSpecifiedIVs() => Convert.ToInt32(IV_HP != RandomIV)
public bool IsSatisfiedNature(Nature nature)
{
if (Mutations.HasFlag(AllowOnlyNeutralNature))
return nature.IsNeutral;
return nature.IsNeutral();
if (Nature == Nature.Random)
return true;
return nature == Nature || Mutations.HasFlag(CanMintNature);
@ -320,7 +300,7 @@ public Nature GetNature(Nature encValue)
/// </summary>
public Nature GetNature()
{
if (Nature.IsFixed)
if (Nature != Nature.Random)
return Nature;
var result = (Nature)Util.Rand.Next(25);
if (Mutations.HasFlag(AllowOnlyNeutralNature))

View File

@ -12,8 +12,6 @@ public enum PogoType : byte
// Pokémon captured in the wild.
Wild,
WildLevel20,
WildLevel25,
// Pokémon hatched from Eggs.
Egg,
@ -139,8 +137,6 @@ public static class PogoTypeExtensions
public byte LevelMin => encounterType switch
{
Wild => 1,
WildLevel20 => 20,
WildLevel25 => 25,
Egg => 1,
Egg12km => 8,
Raid => 20,
@ -208,8 +204,6 @@ public static class PogoTypeExtensions
public int MinimumIV => encounterType switch
{
Wild => 0,
WildLevel20 => 0,
WildLevel25 => 0,
RaidMythical => 10,
RaidShadowMythical => 8,
RaidShadowMythicalGOWA => 8,
@ -330,6 +324,6 @@ public bool IsBallValid(Ball ball)
_ => Ball.None, // Poké, Great, Ultra
};
public bool IsSpecialResearch => encounterType is SpecialResearch or >= SpecialMythical and < TimedMythical;
public bool IsSpecialResearch => encounterType is >= SpecialMythical and < TimedMythical;
}
}

View File

@ -155,7 +155,7 @@ private bool IsMatchNatureGenderShiny(PKM pk)
return false;
if (Gender != FixedGenderUtil.GenderRandom && Gender != pk.Gender)
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
return true;
}

View File

@ -153,7 +153,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
return false;
if (IVs.IsSpecified && !Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pk))
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount)
return false;

View File

@ -167,7 +167,7 @@ private bool IsMatchNatureGenderShiny(PKM pk)
return false;
if (Gender != pk.Gender)
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
return true;
}

View File

@ -145,7 +145,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
return false;
if (IVs.IsSpecified && !Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pk))
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount)
return false;

View File

@ -166,7 +166,7 @@ private bool IsMatchNatureGenderShiny(PKM pk)
return false;
if (Gender != pk.Gender)
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
return true;
}

View File

@ -122,6 +122,8 @@ protected virtual void SetPINGA(PK8 pk, in EncounterCriteria criteria, PersonalI
}
FinishCorrelation(pk, seed);
if (criteria.IsSpecifiedNature() && criteria.Nature != pk.Nature && criteria.Nature.IsMint())
pk.StatNature = criteria.Nature;
}
protected GenerateParam8 GetParam() => GetParam(Info);

View File

@ -57,10 +57,6 @@ protected override void SetPINGA(PK8 pk, in EncounterCriteria criteria, Personal
{
Span<int> iv = stackalloc int[6];
// Honor a shiny request only at the end; generate as never-shiny to avoid shiny PID rejection in main RNG method.
var isShinyRequested = criteria.Shiny.IsShiny();
var iterCriteria = criteria with { Shiny = ShinyMethod };
int ctr = 0;
var rand = new Xoroshiro128Plus(Util.Rand.Rand64());
var param = GetParam(pi);
@ -68,22 +64,23 @@ protected override void SetPINGA(PK8 pk, in EncounterCriteria criteria, Personal
const int max = 100_000;
do
{
if (TryApply(pk, seed = rand.Next(), iv, param, iterCriteria))
if (TryApply(pk, seed = rand.Next(), iv, param, criteria))
break;
} while (++ctr < max);
if (ctr == max) // fail
{
iterCriteria = iterCriteria.WithoutIVs();
if (!TryApply(pk, seed = rand.Next(), iv, param, iterCriteria))
if (!TryApply(pk, seed = rand.Next(), iv, param, criteria.WithoutIVs()))
{
iterCriteria = EncounterCriteria.Unrestricted with { Shiny = ShinyMethod };
while (!TryApply(pk, seed = rand.Next(), iv, param, iterCriteria)) { }
var tmp = EncounterCriteria.Unrestricted with { Shiny = ShinyMethod };
while (!TryApply(pk, seed = rand.Next(), iv, param, tmp)) { }
}
}
FinishCorrelation(pk, seed);
if (isShinyRequested)
if (criteria.IsSpecifiedNature() && criteria.Nature != pk.Nature && criteria.Nature.IsMint())
pk.StatNature = criteria.Nature;
if (criteria.Shiny.IsShiny())
pk.PID = ShinyUtil.GetShinyPID(pk.TID16, pk.SID16, pk.PID, ShinyXor);
}

View File

@ -209,7 +209,7 @@ private bool IsMatchNatureGenderShiny(PKM pk)
{
if (!Shiny.IsValid(pk))
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender)
return false;

View File

@ -154,7 +154,7 @@ private void SetPINGA(PK9 pk, in EncounterCriteria criteria, PersonalInfo9SV pi)
if (Gender != FixedGenderUtil.GenderRandom)
pk.Gender = Gender;
if (Nature.IsFixed)
if (Nature != Nature.Random)
pk.Nature = pk.StatNature = Nature;
}
#endregion
@ -178,7 +178,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
return false;
if (TeraType != GemType.Random && pk is ITeraType t && !Tera9RNG.IsMatchTeraType(TeraType, Species, Form, (byte)t.TeraTypeOriginal))
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
return true;

View File

@ -158,7 +158,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
return false;
if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount)
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
if (pk is IAlphaReadOnly a && a.IsAlpha != IsAlpha)
return false;

View File

@ -135,7 +135,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
return false;
if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount)
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
if (pk is IAlphaReadOnly a && a.IsAlpha != IsAlpha)
return false;

View File

@ -155,7 +155,7 @@ private bool IsMatchNatureGenderShiny(PKM pk)
return false;
if (pk.Gender != Gender)
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
return true;
}
@ -192,7 +192,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
return false;
if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount)
return false;
if (Nature.IsFixed && pk.Nature != Nature)
if (Nature != Nature.Random && pk.Nature != Nature)
return false;
if (pk is IAlphaReadOnly a && a.IsAlpha != IsAlpha)
return false;

View File

@ -36,10 +36,10 @@ public static bool GenerateData(PA9 pk, in GenerateParam9a enc, in EncounterCrit
{
var rand = new Xoroshiro128Plus(seed);
pk.EncryptionConstant = (uint)rand.NextInt(uint.MaxValue);
var pid = GetAdaptedPID(ref rand, pk, enc);
if (enc.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(ShinyUtil.GetShinyXor(pid, pk.ID32), 16))
pk.PID = GetAdaptedPID(ref rand, pk, enc);
if (enc.Shiny is Shiny.Random && criteria.Shiny.IsShiny() != pk.IsShiny)
return false;
pk.PID = pid;
Span<int> ivs = [UNSET, UNSET, UNSET, UNSET, UNSET, UNSET];
if (enc.IVs.IsSpecified)
@ -104,7 +104,7 @@ public static bool GenerateData(PA9 pk, in GenerateParam9a enc, in EncounterCrit
return false;
pk.Gender = gender;
var nature = enc.Nature.IsFixed ? enc.Nature
var nature = enc.Nature != Nature.Random ? enc.Nature
: (Nature)rand.NextInt(25);
// Compromise on Nature -- some are fixed, some are random. If the request wants a specific nature, just mint it.
@ -264,7 +264,7 @@ private static bool IsMatchIVsAndFollowing(PKM pk, in GenerateParam9a enc, Xoros
if (pk.Gender != gender)
return false;
var nature = enc.Nature.IsFixed ? enc.Nature
var nature = enc.Nature != Nature.Random ? enc.Nature
: (Nature)rand.NextInt(25);
if (pk.Nature != nature)
return false;

View File

@ -13,5 +13,5 @@ public interface IFixedNature
/// <summary>
/// Indicates if the nature is a single value (not random).
/// </summary>
bool IsFixedNature => Nature.IsFixed;
bool IsFixedNature => Nature != Nature.Random;
}

View File

@ -20,8 +20,7 @@ public static class Legal
internal const int MaxSpeciesID_3 = 386;
internal const int MaxMoveID_3 = 354;
internal const int MaxItemID_3_RS = 346;
internal const int MaxItemID_3_FRLG = 374;
internal const int MaxItemID_3 = 374;
internal const int MaxItemID_3_E = 376;
internal const int MaxItemID_3_COLO = 547;
internal const int MaxItemID_3_XD = 593;

View File

@ -55,8 +55,7 @@ private static bool TryApplyFromSeed(PK8 pk, in EncounterCriteria criteria, Shin
if (shiny == Shiny.AlwaysStar && type != Shiny.AlwaysStar)
return false;
}
if (shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
return false;
pk.PID = pid;
// IVs

View File

@ -114,7 +114,7 @@ public static bool Verify(PKM pk, ulong seed, Span<int> ivs, in GenerateParam8 p
break;
}
var nature = param.Nature.IsFixed ? param.Nature
var nature = param.Nature != Nature.Random ? param.Nature
: param.Species == (int)Species.Toxtricity
? ToxtricityUtil.GetRandomNature(ref rng, pk.Form)
: (Nature)rng.NextInt(25);
@ -160,8 +160,6 @@ public static bool TryApply(PK8 pk, ulong seed, Span<int> ivs, in GenerateParam8
var trID = (uint)rng.NextInt();
var pid = (uint)rng.NextInt();
// Battle
var xor = GetShinyXor(pid, trID);
bool isShiny = xor < 16;
if (isShiny && param.Shiny == Shiny.Never)
@ -169,8 +167,9 @@ public static bool TryApply(PK8 pk, ulong seed, Span<int> ivs, in GenerateParam8
ForceShinyState(false, ref pid, trID, 0);
isShiny = false;
}
if (param.Shiny is Shiny.Random && isShiny != criteria.Shiny.IsShiny())
return false;
// Captured
if (isShiny)
{
if (!GetIsShiny6(pk.ID32, pid))
@ -182,8 +181,6 @@ public static bool TryApply(PK8 pk, ulong seed, Span<int> ivs, in GenerateParam8
pid ^= 0x1000_0000;
}
if (param.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
return false;
pk.PID = pid;
const int UNSET = -1;
@ -239,7 +236,7 @@ public static bool TryApply(PK8 pk, ulong seed, Span<int> ivs, in GenerateParam8
return false;
pk.Gender = gender;
var nature = param.Nature.IsFixed ? param.Nature
var nature = param.Nature != Nature.Random ? param.Nature
: param.Species == (int)Species.Toxtricity
? ToxtricityUtil.GetRandomNature(ref rng, pk.Form)
: (Nature)rng.NextInt(25);

View File

@ -129,8 +129,6 @@ public static bool TryApplyFromSeed(PA8 pk, in EncounterCriteria criteria, in Ov
if (para.Shiny == Shiny.AlwaysStar && type != Shiny.AlwaysStar)
return false;
}
if (para.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
return false;
pk.PID = pid;
Span<int> ivs = [UNSET, UNSET, UNSET, UNSET, UNSET, UNSET];
@ -174,8 +172,6 @@ public static bool TryApplyFromSeed(PA8 pk, in EncounterCriteria criteria, in Ov
pk.Gender = gender;
var nature = (Nature)rand.NextInt(25);
if (criteria.IsSpecifiedNature() && !criteria.IsSatisfiedNature(nature))
return false;
pk.Nature = pk.StatNature = nature;
var (height, weight) = para.IsAlpha
@ -183,10 +179,16 @@ public static bool TryApplyFromSeed(PA8 pk, in EncounterCriteria criteria, in Ov
: ((byte)(rand.NextInt(0x81) + rand.NextInt(0x80)),
(byte)(rand.NextInt(0x81) + rand.NextInt(0x80)));
pk.HeightScalar = height;
pk.WeightScalar = weight;
pk.ResetHeight();
pk.ResetWeight();
if (pk is IScaledSize s)
{
s.HeightScalar = height;
s.WeightScalar = weight;
if (pk is IScaledSizeValue a)
{
a.ResetHeight();
a.ResetWeight();
}
}
return true;
}

View File

@ -65,8 +65,6 @@ public static bool TryApplyFromSeed(PB8 pk, in EncounterCriteria criteria, Shiny
if (shiny == Shiny.AlwaysStar && type != Shiny.AlwaysStar)
return false;
}
if (shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
return false;
pk.PID = pid;
// Check IVs: Create flawless IVs at random indexes, then the random IVs for not flawless.

View File

@ -65,8 +65,6 @@ public static bool TryApplyFromSeed(PB8 pk, in EncounterCriteria criteria, Shiny
if (shiny == Shiny.AlwaysStar && type != Shiny.AlwaysStar)
return false;
}
if (shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
return false;
pk.PID = pid;
// Check IVs: Create flawless IVs at random indexes, then the random IVs for not flawless.

View File

@ -62,10 +62,10 @@ public static bool GenerateData(PK9 pk, in GenerateParam9 enc, in EncounterCrite
{
var rand = new Xoroshiro128Plus(seed);
pk.EncryptionConstant = (uint)rand.NextInt(uint.MaxValue);
var pid = GetAdaptedPID(ref rand, pk, enc);
if (enc.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
pk.PID = GetAdaptedPID(ref rand, pk, enc);
if (enc.Shiny is Shiny.Random && criteria.Shiny.IsShiny() != pk.IsShiny)
return false;
pk.PID = pid;
const int UNSET = -1;
const int MAX = 31;
@ -121,7 +121,7 @@ public static bool GenerateData(PK9 pk, in GenerateParam9 enc, in EncounterCrite
return false;
pk.Gender = gender;
var nature = enc.Nature.IsFixed ? enc.Nature : enc.Species == (int)Species.Toxtricity
var nature = enc.Nature != Nature.Random ? enc.Nature : enc.Species == (int)Species.Toxtricity
? ToxtricityUtil.GetRandomNature(ref rand, pk.Form)
: (Nature)rand.NextInt(25);
@ -205,7 +205,7 @@ public static bool IsMatch(PKM pk, in GenerateParam9 enc, in ulong seed)
if (pk.Gender != gender)
return false;
var nature = enc.Nature.IsFixed ? enc.Nature : enc.Species == (int)Species.Toxtricity
var nature = enc.Nature != Nature.Random ? enc.Nature : enc.Species == (int)Species.Toxtricity
? ToxtricityUtil.GetRandomNature(ref rand, pk.Form)
: (Nature)rand.NextInt(25);
if (pk.Nature != nature)

View File

@ -4,7 +4,7 @@ namespace PKHeX.Core;
/// Parameters used to generate data for an encounter.
/// </summary>
/// <param name="Species">Species to generate.</param>
/// <param name="GenderRatio">Gender ratio byte from Personal Info.</param>
/// <param name="GenderRatio">Gender ratio byte.</param>
/// <param name="FlawlessIVs">Count of IVs that are perfect.</param>
/// <param name="RollCount">Count of shiny rolls allowed for the PID calculation.</param>
/// <param name="Height">Height value to generate. If zero, full random.</param>

View File

@ -51,7 +51,7 @@ public static bool IsHeldItemAllowed(int item, EntityContext context)
// Combined bitflags for released held items across generations.
private static readonly bool[] ReleasedHeldItems_2 = GetPermitList(MaxItemID_2, HeldItems_GSC);
private static readonly bool[] ReleasedHeldItems_3 = GetPermitList(MaxItemID_3_RS, HeldItems_RS, ItemStorage3RS.Unreleased); // Safari Ball
private static readonly bool[] ReleasedHeldItems_3 = GetPermitList(MaxItemID_3, HeldItems_RS, ItemStorage3RS.Unreleased); // Safari Ball
private static readonly bool[] ReleasedHeldItems_4 = GetPermitList(MaxItemID_4_HGSS, HeldItems_HGSS, ItemStorage4.Unreleased);
private static readonly bool[] ReleasedHeldItems_5 = GetPermitList(MaxItemID_5_B2W2, HeldItems_BW, ItemStorage5.Unreleased);
private static readonly bool[] ReleasedHeldItems_6 = GetPermitList(MaxItemID_6_AO, HeldItems_AO, ItemStorage6XY.Unreleased);

View File

@ -46,7 +46,7 @@ private void VerifyTrash(LegalityAnalysis data, G3PKM pk)
VerifyTrashCXD(data, pk);
}
private static void VerifyTrashCXD(LegalityAnalysis data, G3PKM pk)
private void VerifyTrashCXD(LegalityAnalysis data, G3PKM pk)
{
// Buffers should be entirely clean.
var ot = pk.OriginalTrainerTrash;
@ -122,10 +122,7 @@ private static void VerifyTrashINT(LegalityAnalysis data, PK3 pk)
var trash = pk.OriginalTrainerTrash;
// OT name from save file is copied byte-for-byte. All 8 bytes are initialized to FF on new game.
if (!TrashByteRules3.IsTerminatedFFZero(trash, 7))
{
if (!TrashByteRules3.IsTrashPatternDefaultTrainer(trash, pk.Version, (LanguageID)pk.Language))
data.AddLine(GetInvalid(Trainer, TrashBytesMissingTerminatorFinal));
}
data.AddLine(GetInvalid(Trainer, TrashBytesMissingTerminatorFinal));
// Nickname can be all FF's (nicknamed) or whatever random garbage is in the buffer before filling. Unsure if we can reliably check this, but it should be "dirty" usually.
// If it is clean, flag as fishy.
FlagIsNicknameClean(data, pk);
@ -135,9 +132,7 @@ private static void FlagIsNicknameClean(LegalityAnalysis data, PK3 pk)
{
if (!pk.IsNicknamed || pk.IsEgg)
return;
// Japanese only fills the first 5+1 bytes; everything else is trash.
// International games are 10 chars (full buffer) max; implicit terminator if full.
var nick = pk.GetNicknamePrefillRegion();
var nick = pk.NicknameTrash;
if (!TrashByteRules3.IsTerminatedFF(nick))
data.AddLine(GetInvalid(Trainer, TrashBytesMismatchInitial));
}
@ -150,10 +145,6 @@ public static class TrashByteRules3
// When transferred to Colosseum/XD, the encoding method switches to u16[length], thus discarding the original buffer along with its "trash".
// For original encounters from a mainline save file,
// - OT Name: the game copies the entire buffer from the save file OT as the PK3's OT. Thus, that must match exactly.
// - - Japanese OT names are 5 chars, international is 7 chars. Manually entered strings are FF terminated to max length + 1.
// - - Default OT (Japanese) names were padded with FF to len=6, so they always match manually entered names (no trash).
// - - Default OT (International) names from the character select screen can have trash bytes due to being un-padded (single FF end of string, saves ROM space).
// - - verification of Default OTs todo (if OT dirty, check if is default with expected trash pattern)
// - Nickname: the buffer has garbage RAM data leftover in the nickname field, thus it should be "dirty" usually.
// - Nicknamed: when nicknamed, the game fills the buffer with FFs then applies the nickname.
// For event encounters from GameCube:
@ -182,7 +173,7 @@ public static bool IsResetTrash(PK3 pk3)
public static bool IsTerminatedZero(ReadOnlySpan<byte> data)
{
var first = TrashBytes8.GetTerminatorIndex(data);
if (first == -1 || first >= data.Length - 1)
if (first == -1 || first >= data.Length - 2)
return true;
return !data[(first+1)..].ContainsAnyExcept<byte>(0);
}
@ -190,7 +181,7 @@ public static bool IsTerminatedZero(ReadOnlySpan<byte> data)
public static bool IsTerminatedFF(ReadOnlySpan<byte> data)
{
var first = TrashBytes8.GetTerminatorIndex(data);
if (first == -1 || first >= data.Length - 1)
if (first == -1 || first >= data.Length - 2)
return true;
return !data[(first + 1)..].ContainsAnyExcept<byte>(0xFF);
}
@ -201,77 +192,17 @@ public static bool IsTerminatedFFZero(ReadOnlySpan<byte> data, int preFill = 0)
return IsTerminatedZero(data);
var first = TrashBytes8.GetTerminatorIndex(data);
if (first == -1 || first >= data.Length - 1)
if (first == -1 || first == data.Length - 2)
return true;
first++;
if (first < preFill)
{
var inner = data[first..preFill];
if (inner.ContainsAnyExcept(Terminator))
return false;
first = preFill;
first++;
if (first >= data.Length - 1)
if (first >= data.Length - 2)
return true;
}
return !data[first..].ContainsAnyExcept<byte>(0);
return !data[(first + 1)..].ContainsAnyExcept<byte>(0);
}
// TRASH BYTES: New Game Default OTs
// Default OT names in International (not JPN) Gen3 mainline games memcpy 7 chars and FF from the "default OT name" table, regardless of strlen.
// Copied strings therefore contain trash from the next string entry that is encoded into the rom's string table.
// Below is a list of possible (version, language, trash) default OTs, as initialized by the game. An `*` is used to denote the terminator.
/// <summary>
/// Checks if the specified trash byte pattern matches a default trainer name pattern for the given game <see cref="version"/> and <see cref="language"/>.
/// </summary>
/// <remarks>Default trainer names in certain Generation 3 Pokémon games may include trailing bytes ("trash") due to how names are stored in the game's ROM.
/// This method checks if the provided pattern matches any of these known default patterns for the specified version and language.
/// </remarks>
public static bool IsTrashPatternDefaultTrainer(ReadOnlySpan<byte> trash, GameVersion version, LanguageID language) => version switch
{
GameVersion.R or GameVersion.S => IsTrashPatternDefaultTrainerRS(trash, language),
GameVersion.E => IsTrashPatternDefaultTrainerE(trash, language),
GameVersion.FR => IsTrashPatternDefaultTrainerFR(trash, language),
GameVersion.LG => IsTrashPatternDefaultTrainerLG(trash, language),
_ => false,
};
/// <inheritdoc cref="IsTrashPatternDefaultTrainer"/>
/// <remarks>Default OT names present in <see cref="GameVersion.R"/> and <see cref="GameVersion.S"/> based on the language of the game.</remarks>
public static bool IsTrashPatternDefaultTrainerRS(ReadOnlySpan<byte> trash, LanguageID language) => language switch
{
// TODO
LanguageID.English => trash switch
{
[0xCD, 0xBB, 0xCC, 0xBB, 0xFF, 0xCE, 0xDC] => true, // SARA*Th
_ => false,
},
_ => false,
};
/// <inheritdoc cref="IsTrashPatternDefaultTrainer"/>
/// <remarks>Default OT names present in <see cref="GameVersion.E"/> based on the language of the game.</remarks>
public static bool IsTrashPatternDefaultTrainerE(ReadOnlySpan<byte> trash, LanguageID language) => language switch
{
// TODO
_ => false,
};
/// <inheritdoc cref="IsTrashPatternDefaultTrainer"/>
/// <remarks>Default OT names present in <see cref="GameVersion.FR"/> based on the language of the game.</remarks>
public static bool IsTrashPatternDefaultTrainerFR(ReadOnlySpan<byte> trash, LanguageID language) => language switch
{
// TODO
_ => false,
};
/// <inheritdoc cref="IsTrashPatternDefaultTrainer"/>
/// <remarks>Default OT names present in <see cref="GameVersion.LG"/> based on the language of the game.</remarks>
public static bool IsTrashPatternDefaultTrainerLG(ReadOnlySpan<byte> trash, LanguageID language) => language switch
{
// TODO
_ => false,
};
}

View File

@ -17,7 +17,7 @@ internal static void VerifyStatNature(LegalityAnalysis data, PKM pk)
return;
// Must be a valid mint nature.
if (!statNature.IsMint)
if (!statNature.IsMint())
data.AddLine(Get(Invalid, Misc, StatNatureInvalid));
}

View File

@ -24,7 +24,7 @@ public override void Verify(LegalityAnalysis data)
if (pk.PID == 0)
data.AddLine(Get(Severity.Fishy, PIDZero));
if (!pk.Nature.IsFixed) // out of range
if (!pk.Nature.IsFixed()) // out of range
data.AddLine(GetInvalid(PIDNatureMismatch));
if (data.Info.EncounterMatch is IEncounterEgg egg)
VerifyEggPID(data, pk, egg);

View File

@ -626,7 +626,7 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo)
if (MetLevel != 0 && MetLevel != pk.MetLevel) return false;
if ((Ball == 0 ? 4 : Ball) != pk.Ball) return false;
if (OTGender < 2 && OTGender != pk.OriginalTrainerGender) return false;
if (Nature.IsFixed && pk.Nature != Nature) return false;
if (Nature != Nature.Random && pk.Nature != Nature) return false;
if (Gender != 3 && Gender != pk.Gender) return false;
if (pk is IScaledSize s)

View File

@ -398,15 +398,4 @@ public override int GetStringTerminatorIndex(ReadOnlySpan<byte> data)
public override int GetStringLength(ReadOnlySpan<byte> data)
=> TrashBytes8.GetStringLength(data);
public override int GetBytesPerChar() => 1;
public override void PrepareNickname() => GetNicknamePrefillRegion().Fill(StringConverter3.TerminatorByte);
public Span<byte> GetNicknamePrefillRegion()
{
// Japanese only fills the first 5+1 bytes; everything else is trash.
// International games are 10 chars (full buffer) max; implicit terminator if full.
if (Japanese)
return NicknameTrash[..6];
return NicknameTrash;
}
}

View File

@ -11,7 +11,7 @@ namespace PKHeX.Core;
/// Object representing a <see cref="PKM"/>'s data and derived properties.
/// </summary>
[DynamicallyAccessedMembers(PublicProperties | NonPublicProperties | PublicParameterlessConstructor)]
public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILangNick, IGameValueLimit, INature, IFatefulEncounter, IStringConverter, ITrashIntrospection, IContext
public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILangNick, IGameValueLimit, INature, IFatefulEncounter, IStringConverter, ITrashIntrospection
{
public abstract int SIZE_PARTY { get; }
public abstract int SIZE_STORED { get; }
@ -44,11 +44,6 @@ public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILa
public abstract Span<byte> OriginalTrainerTrash { get; }
public virtual Span<byte> HandlingTrainerTrash => [];
/// <summary>
/// Conditions the <see cref="NicknameTrash"/> data to safely terminate the Nickname string from the text entry screen.
/// </summary>
public virtual void PrepareNickname() { }
protected abstract byte[] Encrypt();
public abstract EntityContext Context { get; }
public byte Format => Context.Generation;

View File

@ -168,7 +168,7 @@ private bool SearchSimple(PKM pk)
return false;
if (Ability > -1 && pk.Ability != Ability)
return false;
if (Nature.IsFixed && pk.StatNature != Nature)
if (Nature.IsFixed() && pk.StatNature != Nature)
return false;
if (Item > -1 && pk.HeldItem != Item)
return false;

View File

@ -17,7 +17,7 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS
public sealed override ushort MaxMoveID => Legal.MaxMoveID_3;
public sealed override ushort MaxSpeciesID => Legal.MaxSpeciesID_3;
public sealed override int MaxAbilityID => Legal.MaxAbilityID_3;
public sealed override int MaxItemID => Legal.MaxItemID_3_E;
public sealed override int MaxItemID => Legal.MaxItemID_3;
public sealed override int MaxBallID => Legal.MaxBallID_3;
public sealed override GameVersion MaxGameID => Legal.MaxGameID_3;
public sealed override int MaxIV => 31;

View File

@ -289,7 +289,7 @@ public sealed override byte Ball
BallDPPt = Clamp(value, Core.Ball.Cherish);
// Only set the HG/SS value if it originated in HG/SS and was not an event.
if (WasCreatedInHGSS && this is not BK4)
if (WasCreatedInHGSS)
BallHGSS = Clamp(value, Core.Ball.Sport);
else
BallHGSS = 0;

View File

@ -35,20 +35,3 @@ public interface IStringConverter
/// <returns>Count of bytes written to <see cref="data"/>.</returns>
int SetString(Span<byte> data, ReadOnlySpan<char> text, int length, StringConverterOption option);
}
public delegate string StringGetter(ReadOnlySpan<byte> data);
public delegate int StringLoader(ReadOnlySpan<byte> data, Span<char> text);
public delegate int StringSetter(Span<byte> data, ReadOnlySpan<char> text, int length, StringConverterOption option);
public sealed class CustomStringConverter : IStringConverter, IGeneration, IContext
{
public required StringGetter Get { get; init; }
public required StringLoader Load { get; init; }
public required StringSetter Set { get; init; }
public required byte Generation { get; init; }
public required EntityContext Context { get; init; }
public string GetString(ReadOnlySpan<byte> data) => Get(data);
public int LoadString(ReadOnlySpan<byte> data, Span<char> text) => Load(data, text);
public int SetString(Span<byte> data, ReadOnlySpan<char> text, int length, StringConverterOption option) => Set(data, text, length, option);
}

View File

@ -73,8 +73,8 @@ public static byte GetItemOld2(ushort item)
NaN, 058, 059, 061, 444, NaN, NaN, 216, 445, 446, // 5
NaN, 447, 051, 038, 039, 040, 478, 464, 456, 484, // 6
NaN, 482, 033, 217, 151, NaN, 237, 244, 149, 153, // 7
152, 245, 221, 156, 150, 485, 086, 087, 222, 486, // 8
NaN, 223, 487, 488, 224, 243, 248, 490, 241, 491, // 9
152, 245, 221, 156, 150, 485, 086, 087, 222, 487, // 8
NaN, 223, 486, 488, 224, 243, 248, 490, 241, 491, // 9
NaN, 489, 240, 473, NaN, 259, 228, 246, 242, 157, // 10
088, 089, 229, 247, 504, NaN, NaN, 239, 258, 230, // 11
NaN, 034, 035, 036, 037, 238, 231, 475, 481, NaN, // 12

View File

@ -31,16 +31,16 @@
"BallSpecies": "無法使用此球種捕獲該寶可夢。",
"BallSpeciesPass": "可使用此球種捕獲該種類寶可夢。",
"BallUnavailable": "於此寶可夢出身游戲世代中,該球種不可獲得。",
"BallG4Sinnoh": "鑽石珍珠白金D/P/Pt的精靈球數值0x83超出有效範圍。",
"BallG4Johto": "心金魂銀HG/SS的擴展精靈球數值0x86超出有效範圍。",
"BallG4Sinnoh": "Ball value for D/P/Pt (0x83) is not within range.",
"BallG4Johto": "Extended Ball value for HG/SS (0x86) is not within range.",
"ContestZero": "華麗大賽狀態值應置「0」。",
"ContestZeroSheen": "華麗大賽光澤度應置「0」。",
"ContestSheenGEQ_0": "華麗大賽光澤度應大於或等於「 {0} 」。",
"ContestSheenLEQ_0": "華麗大賽光澤度應小於或等於「 {0} 」。",
"DateCalendarInvalidMet": "相遇日期不是有效的日期。",
"DateCalendarInvalidEgg": "蛋的相遇日期不是有效的日期。",
"DateLocalInvalidDate": "本地日期超出主機日期範圍。",
"DateLocalInvalidTime": "本地時間不符合有效時間戳格式。",
"DateCalendarInvalidMet": "Met Date is not a valid calendar date.",
"DateCalendarInvalidEgg": "Egg Met Date is not a valid calendar date.",
"DateLocalInvalidDate": "Local Date is outside of console's local time window.",
"DateLocalInvalidTime": "Local Time is not a valid timestamp.",
"DateOutsideDistributionWindow": "遇見日期於神秘禮物配信期間之外。",
"EggContest": "不能調整蛋之華麗大賽狀態。",
"EggEXP": "蛋不能獲得經驗值。",
@ -150,18 +150,18 @@
"G3EReader": "非日版黑暗E-reader寶可夢。未解禁之遇見方式。",
"G3OTGender": "來自圓形競技場/暗黑旋風XD之初訓家不能為女性。",
"G4InvalidTileR45Surf": "城都45號道路之水面遇見類型但該水道不可到達。",
"G4PartnerMoodEgg": "蛋不能有心情值。",
"G4PartnerMoodZero": "不在玩家隊伍中時心情值應為0。",
"G4ShinyLeafBitsInvalid": "閃耀葉片/花冠標誌位無效。",
"G4PartnerMoodEgg": "Eggs cannot have an Mood stat value.",
"G4PartnerMoodZero": "Mood stat value should be zero when not in the player's party.",
"G4ShinyLeafBitsInvalid": "Shiny Leaf/Crown bits are not valid.",
"G4ShinyLeafBitsEgg": "蛋不能携帶閃耀的葉片/王冠。",
"G5IVAll30": "N的寶可夢所有個體值應為30。",
"G5PIDShinyGrotto": "於隱藏洞穴捕獲之寶可夢不能為異色。",
"G5SparkleInvalid": "特殊遊戲內寶可夢N的異色標記不應勾選。",
"G5SparkleRequired": "特殊遊戲內寶可夢N的異色標記缺失。",
"G5PokeStarMustBeZero": "寶可夢好萊塢名氣必須為 0不可參與",
"G5PokeStarImpossibleValue": "寶可夢好萊塢名氣數值不可達。",
"G7BSocialShouldBe100Spirit": "不在玩家隊伍中的寶可夢,其精神值應為 100。",
"G7BSocialShouldBe100Mood": "不在玩家隊伍中的寶可夢,其心情值應為 100。",
"G5PokeStarMustBeZero": "Pokéstar Studios fame must be zero, cannot participate.",
"G5PokeStarImpossibleValue": "Pokéstar Studios fame value is unreachable.",
"G7BSocialShouldBe100Spirit": "Spirit should be 100 for Pokémon not in the player's party.",
"G7BSocialShouldBe100Mood": "Mood should be 100 for Pokémon not in the player's party.",
"GanbaruStatTooHigh": "一項或多項奮鬥等級超過上限 (10 減 IV 個體值提升奮鬥等級)。",
"GenderInvalidNone": "無性別寶可夢不能有性別。",
"GeoBadOrder": "地理位置回憶: 間隔/空白存在。",
@ -227,7 +227,7 @@
"MoveEvoFCombination_0": "招式組合與{0}進化型不相容。",
"MoveFExpectSingle_0": "應該是該招式: {0}。",
"MoveKeldeoMismatch": "凱路迪歐之現時招式與當前形態不匹配。",
"MovePPExpectHealed_01": "招式 {0} 的PP恢復量未達預期值 ({1})。",
"MovePPExpectHealed_01": "Move {0} PP is below the amount expected. ({1})",
"MovePPTooHigh_01": "招式 {0} PP 高於允許值。 ({1})",
"MovePPUpsTooHigh_01": "招式 {0} PP 高於允許值。 ({1})",
"MoveShopAlphaMoveShouldBeMastered_0": "頭目技能應標記爲精通。",
@ -248,7 +248,7 @@
"NickMatchLanguageFail": "昵稱與種類名不匹配。",
"NickMatchLanguageFlag": "昵稱被標記,與種類名匹配。",
"NickMatchNoOthers": "昵稱不與另一種類名匹配。",
"NickMatchNoOthersFail": "昵稱與另一寶可夢種類名匹配 (+語言)。",
"NickMatchNoOthersFail": "昵稱與另一寶可夢種類名匹配 (+language)。",
"OTLanguage": "語言ID應為 {0}, 而不是 {1}。",
"OTLong": "初訓家名字過長。",
"OTShort": "初訓家名字過短。",
@ -268,11 +268,11 @@
"PIDNatureMismatch": "性格與 PID 記載值不匹配。",
"PIDTypeMismatch": "遇見類型與 PID 記載值不匹配。",
"PIDZero": "未設置 PID 。",
"PlusMoveAlphaMissing_0": "當作為頭目個體相遇時,預期應已加強招式 {0}。",
"PlusMoveMultipleInvalid": "多個加強招式標誌無效。",
"PlusMoveInvalid_0": "{0} 無法學習,不能被設置為加強招式。",
"PlusMoveSufficientLevelMissing_0": "必須為 {0} 設置加強招式標誌。",
"PlusMoveCountInvalid": "設置了越界的加強招式標誌索引。",
"PlusMoveAlphaMissing_0": "Expected to have mastered the move {0} when encountered as an alpha.",
"PlusMoveMultipleInvalid": "Multiple Plus Move flags are invalid.",
"PlusMoveInvalid_0": "{0} cannot be learned and set as a Plus Move.",
"PlusMoveSufficientLevelMissing_0": "Plus Move flag for {0} must be set.",
"PlusMoveCountInvalid": "Out of range Plus Move flag index is set.",
"PokerusDaysTooHigh_0": "寶可病毒剩餘天數過長; 應 <= {0}。",
"PokerusStrainUnobtainable_0": "寶可病毒種類 {0} 不可獲得。",
"RibbonAllValid": "所有獎章合法。",
@ -285,9 +285,9 @@
"StatDynamaxInvalid": "極巨化等級不在預期範圍內。",
"StatIncorrectHeight": "計算之高度與存儲值不匹配。",
"StatIncorrectWeight": "計算之重量與存儲值不匹配。",
"StatIncorrectHeightValue_0": "身高應為 {0}。",
"StatIncorrectWeightValue_0": "體重應為 {0}。",
"StatIncorrectScaleValue_0": "大小應為 {0}。",
"StatIncorrectHeightValue_0": "Height should be {0}.",
"StatIncorrectWeightValue_0": "Weight should be {0}.",
"StatIncorrectScaleValue_0": "Scale should be {0}.",
"StatInvalidHeightWeight": "此身高或體重於統計學意義上不可獲得。",
"StatIncorrectCP": "計算之 CP 值與存儲值不匹配。",
"StatGigantamaxInvalid": "超極巨標識不匹配。",
@ -296,8 +296,8 @@
"StatBattleVersionInvalid": "對戰版本不在期望範圍內。",
"StatNobleInvalid": "王標識不合法。",
"StatAlphaInvalid": "頭目標識不合法。",
"StoredSourceEgg": "蛋必須放在盒子裡或野餐籃裡。",
"StoredSlotSourceInvalid_0": "無效的存儲來源:{0}",
"StoredSourceEgg": "Egg must be in Box or Party.",
"StoredSlotSourceInvalid_0": "Invalid Stored Source: {0}",
"SuperComplete": "超級訓練完成標識不匹配。",
"SuperDistro": "神秘禮物配信超級訓練任務未發佈。",
"SuperEgg": "不能對蛋進行超級訓練。",
@ -305,27 +305,27 @@
"SuperNoUnlocked": "當前出身游戲不能有超級訓練解鎖之標記。",
"SuperUnavailable": "所達遊戲版本不能進行超級訓練。",
"SuperUnused": "未使用之超級訓練旗標被標識。",
"G6SuperTrainEggBag": "蛋不能使用沙袋。",
"G6SuperTrainEggHits": "蛋不能擊打沙袋。",
"G6SuperTrainBagInvalid_0": "無法識別的沙袋ID{0}",
"G6SuperTrainBagHitsInvalid_012": "沙袋擊打次數不能為 {0};期望範圍為 [{1},{2}]。",
"G6SuperTrainEggBag": "Egg cannot use a Training Bag.",
"G6SuperTrainEggHits": "Eggs cannot hit Training Bags.",
"G6SuperTrainBagInvalid_0": "Unrecognized Training Bag ID: {0}",
"G6SuperTrainBagHitsInvalid_012": "Training bag cannot have {0} hits; expected value within [{1},{2}].",
"TeraTypeIncorrect": "太晶屬性與期望值不匹配。",
"TeraTypeMismatch": "太晶屬性無法與寶可夢本身任一屬性相匹配。",
"TradeNotAvailable": "該遇見方式寶可夢不可被交換至現時持有之訓練家手上。",
"TrainerIDNoSeed": "訓練家ID無法透過任何隨機數種子生成。",
"TrainerIDNoSeed": "Trainer ID is not obtainable from any RNG seed.",
"TransferBad": "該寶可夢不正確地由前代游戲中傳送而來。",
"TransferCurrentHandlerInvalid": "不合法之現時持有人資訊,儲存資料訓練家信息應是其他值。",
"TransferEgg": "不能跨世代傳送蛋。",
"TransferEggLocationTransporter": "不合法之遇見地點, 應該是虛擬傳送。",
"TransferEggMetLevel": "對於寶可傳送不合法之遇見等級。",
"TransferEggVersion": "蛋無法傳送到目前遊戲。",
"TransferEggVersion": "Can't transfer Eggs to this game.",
"TransferFlagIllegal": "游戲中被標記爲非法 (可濫用之Bug)。",
"TransferHTFlagRequired": "現任處理教練不能是原教練。",
"TransferHTMismatchName": "現時持有人與期望名字不匹配。",
"TransferHTMismatchGender": "處理訓練家的性別與期望的訓練家性別不符。",
"TransferHTMismatchGender": "Handling trainer does not match the expected trainer gender.",
"TransferHTMismatchLanguage": "現時持有人與期望語言不匹配。",
"TransferKoreanGen4": "韓版第四世代遊戲無法與國際版第四世代遊戲互通。",
"TransferMet": "無效的相遇地點,應為寶可夢傳送/索羅亞克(異色三獸)或寶可夢傳送/時拉比(時拉比)。",
"TransferKoreanGen4": "Korean Generation 4 games cannot interact with International Generation 4 games.",
"TransferMet": "Invalid Met Location, expected Poké Transfer/Zoroark (Crown Beasts), Poké Transfer/Celebi (Celebi).",
"TransferNotPossible": "無法將現時寶可夢檔格式轉換爲源寶可夢檔格式。",
"TransferMetLocation": "傳送遇見地點不合法。",
"TransferNature": "對於寶可傳送不合法之性格。",
@ -340,39 +340,39 @@
"TrashBytesMissingTerminatorFinal": "缺少最終終止符。",
"TrashBytesShouldBeEmpty": "垃圾位元組應被清除。",
"TrashBytesResetViaTransfer": "垃圾位元組已在傳輸時重設。",
"EncTradeShouldHaveEvolvedToSpecies_0": "通訊交換獲得的寶可夢應該已進化為:{0}。",
"EncGiftLanguageNotDistributed": "禮物相遇從未以該語言發放。",
"EncGiftRegionNotDistributed": "禮物相遇從未在該主機地區發放。",
"EncTradeShouldHaveEvolvedToSpecies_0": "Trade Encounter should have evolved to species: {0}.",
"EncGiftLanguageNotDistributed": "Gift Encounter was never distributed with this language.",
"EncGiftRegionNotDistributed": "Gift Encounter was never distributed to this Console Region.",
"FormInvalidRangeLEQ_0F": "形態數超過最大值。 應該 <=「 {0} 」, 實際是「 {1} 」。",
"MovesShouldMatchRelearnMoves": "招式應與回憶招式完全一致。",
"MemoryStatEnjoyment_0": "享受度應為{0}。",
"MovesShouldMatchRelearnMoves": "Moves should exactly match Relearn Moves.",
"MemoryStatEnjoyment_0": "Enjoyment should be {0}.",
"MemoryStatFullness_0": "飽腹度應該為{0}。",
"MemoryStatFullnessLEQ_0": "飽腹度應該為 <={0}。",
"OTLanguageShouldBe_0": "語言 ID 應為 {0},而非 {1}。",
"OTLanguageShouldBe_0or1": "語言 ID 應為 {0} 或 {1},而非 {2}。",
"OTLanguageShouldBeLeq_0": "語言 ID 應 ≤ {0},而非 {1}。",
"OTLanguageCannotPlayOnVersion_0": "語言 ID {0} 無法在此版本上遊玩。",
"OTLanguageCannotTransferToConsoleRegion_0": "語言 ID {0} 無法轉移到該主機地區。",
"WordFilterInvalidCharacter_0": "詞語過濾:無效字元 '{0}'0x{1})。",
"WordFilterFlaggedPattern_01": "詞語過濾({1}):檢測到被標記的模式 '{0}'。",
"WordFilterTooManyNumbers_0": "詞語過濾:數字過多(>{0})。",
"BulkCloneDetectedDetails": "檢測到克隆(詳細資訊)。",
"BulkCloneDetectedTracker": "檢測到克隆(重複追蹤器)。",
"HintEvolvesToSpecies_0": "可進化為:{0}。",
"HintEvolvesToRareForm_0": "可進化為稀有形態:{0}。",
"BulkSharingEncryptionConstantGenerationDifferent": "檢測到跨世代共享加密常數。",
"BulkSharingEncryptionConstantGenerationSame": "檢測到加密常數被共享。",
"BulkSharingEncryptionConstantRNGType": "檢測到在不同 RNG 相遇之間共享加密常數。",
"BulkSharingPIDGenerationDifferent": "檢測到跨世代共享 PID。",
"BulkSharingPIDGenerationSame": "檢測到 PID 被共享。",
"BulkSharingPIDRNGType": "檢測到在不同 RNG 相遇之間共享 PID。",
"BulkDuplicateMysteryGiftEggReceived": "檢測到同一不可重複的神秘禮物蛋被多次領取。",
"BulkSharingTrainerID": "檢測到在多個訓練家名稱之間共享訓練家ID。",
"BulkSharingTrainerVersion": "檢測到在多個版本間共享訓練家ID。",
"BulkDuplicateFusionSlot": "檢測到同一融合槽位的寶可夢被重複融合。",
"BulkHeldItemInventoryAssignedNoneHeld_0": "{0} 已標記為玩家持有道具,但在檢查的槽位中未找到對應的寶可夢。",
"BulkHeldItemInventoryMultipleSlots_0": "{0} 是唯一道具,無法被多隻寶可夢同時持有。",
"BulkHeldItemInventoryNotAcquired_0": "{0} 尚未在玩家背包中獲得。",
"BulkHeldItemInventoryUnassigned_0": "{0} 未在玩家背包中標記為已分配。",
"BulkFusionSourceInvalid": "存檔中記錄的被消耗「種族-形態」與該融合槽位應有的「種族-形態」不一致。"
"OTLanguageShouldBe_0": "Language ID should be {0}, not {1}.",
"OTLanguageShouldBe_0or1": "Language ID should be {0} or {1}, not {2}.",
"OTLanguageShouldBeLeq_0": "Language ID should be <= {0}, not {1}.",
"OTLanguageCannotPlayOnVersion_0": "Language ID {0} cannot be played on this version.",
"OTLanguageCannotTransferToConsoleRegion_0": "Language ID {0} cannot be transferred to this Console Region.",
"WordFilterInvalidCharacter_0": "Word Filter: Invalid character '{0}' (0x{1}).",
"WordFilterFlaggedPattern_01": "Word Filter ({1}): Flagged pattern '{0}'.",
"WordFilterTooManyNumbers_0": "Word Filter: Too many numbers (>{0}).",
"BulkCloneDetectedDetails": "Clone detected (Details).",
"BulkCloneDetectedTracker": "Clone detected (Duplicate Tracker).",
"HintEvolvesToSpecies_0": "Evolves to species: {0}.",
"HintEvolvesToRareForm_0": "Evolves to rare form: {0}.",
"BulkSharingEncryptionConstantGenerationDifferent": "Detected sharing of Encryption Constant across generations.",
"BulkSharingEncryptionConstantGenerationSame": "Detected sharing of Encryption Constant.",
"BulkSharingEncryptionConstantRNGType": "Detected sharing of Encryption Constant sharing for different RNG encounters.",
"BulkSharingPIDGenerationDifferent": "Detected sharing of PID across generations.",
"BulkSharingPIDGenerationSame": "Detected sharing of PID.",
"BulkSharingPIDRNGType": "Detected sharing of PID for different RNG encounters.",
"BulkDuplicateMysteryGiftEggReceived": "Detected multiple redemptions of the same non-repeatable Mystery Gift Egg.",
"BulkSharingTrainerID": "Detected sharing of Trainer ID across multiple trainer names.",
"BulkSharingTrainerVersion": "Detected sharing of Trainer ID across multiple versions.",
"BulkDuplicateFusionSlot": "Detected multiple fusions of the same fusion stored slot species.",
"BulkHeldItemInventoryAssignedNoneHeld_0": "{0} is marked as held player inventory, but no Pokémon found in slots checked.",
"BulkHeldItemInventoryMultipleSlots_0": "{0} is a unique item and cannot be held by multiple Pokémon.",
"BulkHeldItemInventoryNotAcquired_0": "{0} has not been acquired in player inventory.",
"BulkHeldItemInventoryUnassigned_0": "{0} is not marked as assigned in player inventory.",
"BulkFusionSourceInvalid": "The subsumed Species-Form stored in the save file does not match the expected Species-Form of the fused slot."
}

View File

@ -24,13 +24,13 @@ MsgFileDeleteCount = {0} Dateien gelöscht.
MsgFolderNotFound = Ordner kann nicht gefunden werden:
MsgWindowClose = Das Fenster wird nun geschlossen.
MsgResearchRequired = Benötigt mehr Recherche.
MsgConfirmQuitProgram = PKHeX beenden?
MsgConfirmQuitProgram = Quit PKHeX?
MsgFileDelete = Diese Datei löschen?
MsgFileDeleteFail = Datei kann nicht gelöscht werden.
MsgFileDeleteSuccess = Datei erfolgreich gelöscht.
MsgFileLoad = Datei wurde geöffnet:
MsgFileLoadAllZero = Datei ist nicht initialisiert (alles null). Bitte stelle sicher, dass sie korrekt gespeichert wurde.
MsgFileLoadAllFFFF = Datei ist nicht initialisiert (alles 0xFF). Bitte stelle sicher, dass sie korrekt gespeichert wurde.
MsgFileLoadAllZero = File is uninitialized (all zero). Please ensure it was properly saved.
MsgFileLoadAllFFFF = File is uninitialized (all 0xFF). Please ensure it was properly saved.
MsgFileLoadFail = Datei kann nicht geöffnet werden.
MsgFileLoadFailAuto = Ein Fehler trat beim Öffnen des Spielstands auf.
MsgFileLoadFailAutoAdvise = Es wird empfohlen ungültiger Dateinamen aus dem Ordner zu entfernen.
@ -45,9 +45,9 @@ MsgFileLoadSaveDetectReload = Möchtest du einen Spielstand von dem folgenden Ve
MsgFileLoadSaveSelectVersion = Wähle die Version.
MsgFileLoadSaveSelectGame = Wähle ein Spiel zum bearbeiten.
MsgFileLoadSaveMultiple = Mehrere Spiele erkannt.
MsgFileLoadSelectFileSave = Wähle eine Speicherdatei...
MsgFileLoadSelectFileBlock = Wähle eine Speicherblock-Datei...
MsgFileLoadSelectFileSecretBase = Wähle eine Geheimbasis-Datei...
MsgFileLoadSelectFileSave = Select a save file...
MsgFileLoadSelectFileBlock = Select a save block file...
MsgFileLoadSelectFileSecretBase = Select a Secret Base file...
MsgFileGameCubeBad = Die GC Memory Card ist ungültig oder beschädigt. Laden abgebrochen.
MsgFileGameCubeDuplicate = Es sind mehrere Spielständen auf der GC Memory Card. Laden abgebrochen.
MsgFileGameCubeNoGames = Es sind keine Pokémon Spielstände auf der GC Memory Card. Laden abgebrochen.
@ -57,7 +57,7 @@ MsgFileSizeLarge = Die Datei ist zu groß.
MsgFileSizeSmall = Die Datei ist zu klein.
MsgFileWriteFail = Spielstand kann nicht geladen werden.
MsgFileWriteProtected = Das Detei Verzeichnis ist schreibgeschützt:
MsgFileWriteProtectedAdvice = Wenn sich die Datei auf einem Wechseldatenträger (SD-Karte) befindet, überprüfe bitte den Schreibschutz Schalter.
MsgFileWriteProtectedAdvice = Wenn sich die Datei auf einem Wechseldatenträger (SD-karte) befindet, überprüfe bitte den Schreibschutz Schalter.
MsgFileInUse = Spielstand kann nicht geladen werden. Die Datei wird möglicherweise von einem anderen Programm benutzt.
MsgFileUnsupported = Es wurde versucht eine nicht unterstützte Datei zu laden. Möglicherweise unterstützt PKHeX den Spielstand nicht, oder dieser ist beschädigt.
MsgPKMUnsupported = Es wurde versucht eine nicht unterstützte Datei zu laden. Möglicherweise handelt es sich um eine Pokémon Datei einer anderen Generation oder sie ist beschädigt.
@ -259,10 +259,10 @@ MsgSaveNumberInvalid = Spielstand {0} ist ungültig.
MsgSecretBaseDeleteConfirm = {0}s Geheimbasis (Eintrag {1:00}) löschen?
MsgSecretBaseDeleteSelf = Deine eigene Geheimbasis kann nicht gelöscht werden.
MsgPluginFailLoad = Plugins konnten nicht geladen werden. Bitte versuche das fehlerhafte Plugin anhand der Fehlermeldung zu erkennen. Ein Plugin ist mölicherweise nicht up-to-date oder nicht kompatibel mit dieser Version von PKHeX.
MsgLegalityPopupCaption = Legalitätsprüfung
MsgLegalityPopupCollapsed = Vollständiger Bericht
MsgLegalityPopupExpanded = Vollständigen Bericht ausblenden
MsgLegalityPopupCopyClipboard = In die Zwischenablage kopieren
MsgDialogFileOverwrite = Überschreiben
MsgDialogFileSaveAs = Speichern unter...
MsgDialogFileSaveReplace = Vorhandene Datei überschreiben?
MsgLegalityPopupCaption = Legality Check
MsgLegalityPopupCollapsed = Full Report
MsgLegalityPopupExpanded = Hide Full Report
MsgLegalityPopupCopyClipboard = Copy to Clipboard
MsgDialogFileOverwrite = Overwrite
MsgDialogFileSaveAs = Save As...
MsgDialogFileSaveReplace = Overwrite existing file?

View File

@ -4,7 +4,7 @@ MsgProgramIllegalModeActive = Modo Ilegal activado.
MsgProgramUpdateAvailable = ¡Actualización disponible!
MsgProgramCloseUnsaved = Cualquier cambio no guardado se perderá.
MsgProgramCloseConfirm = ¿Estás seguro de que quieres cerrar PKHeX?
MsgProgramSaveUnsaved = El Pokémon en el editor tiene cambios sin guardar.
MsgProgramSaveUnsaved = The Pokémon in the editor has unsaved changes.
MsgProgramSaveFileConfirm = ¿Estás seguro de que quieres cargar un nuevo archivo de guardado?
MsgProgramError = ERROR
MsgProgramErrorExpectedHex = Se esperaba texto conteniendo solamente los siguiente caracteres (0-9, A-F).
@ -24,7 +24,7 @@ MsgFileDeleteCount = {0} archivos borrados.
MsgFolderNotFound = No se encuentra el directorio:
MsgWindowClose = La ventana actual se cerrará.
MsgResearchRequired = Se requiere más investigación.
MsgConfirmQuitProgram = ¿Cerrar PKHeX?
MsgConfirmQuitProgram = Quit PKHeX?
MsgFileDelete = ¿Deseas eliminar este archivo?
MsgFileDeleteFail = No se pudo eliminar el archivo.
MsgFileDeleteSuccess = Archivo eliminado correctamente.
@ -45,9 +45,9 @@ MsgFileLoadSaveDetectReload = ¿Abrir el archivo de guardado de la siguiente loc
MsgFileLoadSaveSelectVersion = Escoge la versión.
MsgFileLoadSaveSelectGame = Escoge un juego para editar.
MsgFileLoadSaveMultiple = Múltiples juegos detectados
MsgFileLoadSelectFileSave = Selecciona un archivo de guardado...
MsgFileLoadSelectFileBlock = Selecciona un archivo de bloque de guardado...
MsgFileLoadSelectFileSecretBase = Selecciona un archivo de Base Secreta...
MsgFileLoadSelectFileSave = Select a save file...
MsgFileLoadSelectFileBlock = Select a save block file...
MsgFileLoadSelectFileSecretBase = Select a Secret Base file...
MsgFileGameCubeBad = Tarjeta de Memoria de GameCube no válida o corrupta. Abortando.
MsgFileGameCubeDuplicate = Tarjeta de Memoria de GameCube con archivos de guardado duplicados. Abortando.
MsgFileGameCubeNoGames = Tarjeta de Memoria de GameCube sin ningún archivo de guardado de Pokémon. Abortando.
@ -259,10 +259,10 @@ MsgSaveNumberInvalid = El archivo de guardado {0} no es válido.
MsgSecretBaseDeleteConfirm = ¿Eliminar la Base Secreta de {0} (Entrada {1:00}) de tus registros?
MsgSecretBaseDeleteSelf = No se puede eliminar tu Base Secreta.
MsgPluginFailLoad = No se pudieron cargar los complementos. Consulte el mensaje de error para identificar el complemento defectuoso. Un complemento puede estar desactualizado o ser incompatible con esta versión de PKHeX.
MsgLegalityPopupCaption = Verificación de legalidad
MsgLegalityPopupCollapsed = Informe completo
MsgLegalityPopupExpanded = Ocultar informe completo
MsgLegalityPopupCopyClipboard = Copiar al portapapeles
MsgDialogFileOverwrite = Sobrescribir
MsgDialogFileSaveAs = Guardar como...
MsgDialogFileSaveReplace = ¿Sobrescribir el archivo existente?
MsgLegalityPopupCaption = Legality Check
MsgLegalityPopupCollapsed = Full Report
MsgLegalityPopupExpanded = Hide Full Report
MsgLegalityPopupCopyClipboard = Copy to Clipboard
MsgDialogFileOverwrite = Overwrite
MsgDialogFileSaveAs = Save As...
MsgDialogFileSaveReplace = Overwrite existing file?

View File

@ -4,7 +4,7 @@ MsgProgramIllegalModeActive = Modo Ilegal activado.
MsgProgramUpdateAvailable = ¡Actualización disponible!
MsgProgramCloseUnsaved = Cualquier cambio no guardado se perderá.
MsgProgramCloseConfirm = ¿Estás seguro de que quieres cerrar PKHeX?
MsgProgramSaveUnsaved = El Pokémon en el editor tiene cambios no guardados.
MsgProgramSaveUnsaved = The Pokémon in the editor has unsaved changes.
MsgProgramSaveFileConfirm = ¿Estás seguro de que quieres cargar un nuevo archivo de guardado?
MsgProgramError = ERROR
MsgProgramErrorExpectedHex = Se esperaba texto conteniendo solamente los siguiente caracteres (0-9, A-F).
@ -259,10 +259,10 @@ MsgSaveNumberInvalid = El archivo de guardado {0} no es válido.
MsgSecretBaseDeleteConfirm = ¿Eliminar la Base Secreta de {0} (Entrada {1:00}) de tus registros?
MsgSecretBaseDeleteSelf = No se puede eliminar tu Base Secreta.
MsgPluginFailLoad = No se pudieron cargar los complementos. Consulte el mensaje de error para identificar el complemento defectuoso. Un complemento puede estar desactualizado o ser incompatible con esta versión de PKHeX.
MsgLegalityPopupCaption = Comprobación de legalidad
MsgLegalityPopupCollapsed = Informe completo
MsgLegalityPopupExpanded = Ocultar informe completo
MsgLegalityPopupCopyClipboard = Copiar al portapapeles
MsgDialogFileOverwrite = Sobrescribir
MsgDialogFileSaveAs = Guardar como...
MsgDialogFileSaveReplace = ¿Sobrescribir el archivo existente?
MsgLegalityPopupCaption = Legality Check
MsgLegalityPopupCollapsed = Full Report
MsgLegalityPopupExpanded = Hide Full Report
MsgLegalityPopupCopyClipboard = Copy to Clipboard
MsgDialogFileOverwrite = Overwrite
MsgDialogFileSaveAs = Save As...
MsgDialogFileSaveReplace = Overwrite existing file?

View File

@ -45,9 +45,9 @@ MsgFileLoadSaveDetectReload = Aprire un file di salvataggio da questo percorso?
MsgFileLoadSaveSelectVersion = Seleziona la versione.
MsgFileLoadSaveSelectGame = Seleziona un gioco da editare.
MsgFileLoadSaveMultiple = Rilevati multipli salvataggi.
MsgFileLoadSelectFileSave = Seleziona un file di salvataggio...
MsgFileLoadSelectFileBlock = Seleziona un file di blocco di salvataggio...
MsgFileLoadSelectFileSecretBase = Seleziona un file della Base Segreta...
MsgFileLoadSelectFileSave = Select a save file...
MsgFileLoadSelectFileBlock = Select a save block file...
MsgFileLoadSelectFileSecretBase = Select a Secret Base file...
MsgFileGameCubeBad = Memory Card GC invalida o corrotta.
MsgFileGameCubeDuplicate = Memory Card GC con salvataggi di gioco multipli.
MsgFileGameCubeNoGames = Memory Card GC senza alcun salvataggio di gioco Pokémon.
@ -74,8 +74,8 @@ MsgPKMConvertJapanese = Giapponese
MsgClipboardLegalityExport = Copiare il report negli appunti?
MsgClipboardFailRead = Gli appunti non contengono alcun testo.
MsgClipboardFailWrite = Impossibile inserire testo negli appunti.
MsgLegalityHoverValid = Valido!
MsgLegalityHoverInvalid = Non valido: fai clic per maggiori informazioni.
MsgLegalityHoverValid = Valid!
MsgLegalityHoverInvalid = Invalid: Click for more info.
MsgSimulatorFailClipboard = Dati del set non trovati negli appunti.
MsgSimulatorLoad = Importare questo set?
MsgSimulatorInvalid = Rilevate linee invalide:
@ -172,10 +172,10 @@ MsgIndexMoveRange = Indice mossa oltre il limite:
MsgIndexMoveGame = Impossibile ottenere la mossa nel gioco:
MsgIndexAbilityRange = Indice abilità oltre il limite:
MsgIndexAbilityGame = Impossibile ottenere l'abilità nel gioco:
MsgGeonetPointNone = Niente
MsgGeonetPointBlue = Blu
MsgGeonetPointYellow = Giallo
MsgGeonetPointRed = Rosso
MsgGeonetPointNone = None
MsgGeonetPointBlue = Blue
MsgGeonetPointYellow = Yellow
MsgGeonetPointRed = Red
MsgGearAllCharacterStyles = Tutto
MsgQRDecodeFail = I dati decodificati non corrispondono ad un Pokémon o ad un Dono valido.
MsgQRDecodeSize = Dimensione dati QR: {0} byte
@ -259,10 +259,10 @@ MsgSaveNumberInvalid = Il file di salvataggio {0} non è valido.
MsgSecretBaseDeleteConfirm = Eliminare la base segreta di {0} (Entry {1:00}) dal tuo registro?
MsgSecretBaseDeleteSelf = Impossibile eliminare la tua base segreta.
MsgPluginFailLoad = I Plugin hanno fallito il caricamento. Fai riferimento al messaggio di errore per determinare il Plugin che genera il problema. Un plugin potrebbe essere troppo vecchio / incompatibile con questa versione del programma.
MsgLegalityPopupCaption = Controllo di legalità
MsgLegalityPopupCollapsed = Rapporto completo
MsgLegalityPopupExpanded = Nascondi rapporto completo
MsgLegalityPopupCopyClipboard = Copia negli appunti
MsgDialogFileOverwrite = Sovrascrivere
MsgDialogFileSaveAs = Salva con nome...
MsgDialogFileSaveReplace = Sovrascrivere il file esistente?
MsgLegalityPopupCaption = Legality Check
MsgLegalityPopupCollapsed = Full Report
MsgLegalityPopupExpanded = Hide Full Report
MsgLegalityPopupCopyClipboard = Copy to Clipboard
MsgDialogFileOverwrite = Overwrite
MsgDialogFileSaveAs = Save As...
MsgDialogFileSaveReplace = Overwrite existing file?

View File

@ -4,7 +4,7 @@ MsgProgramIllegalModeActive = 불법 모드를 사용합니다.
MsgProgramUpdateAvailable = 새 업데이트가 있습니다!
MsgProgramCloseUnsaved = 저장하지 않은 변경 사항은 손실됩니다.
MsgProgramCloseConfirm = 정말 PKHeX를 종료하시겠습니까?
MsgProgramSaveUnsaved = 편집기 내 포켓몬에 저장되지 않은 변경 사항이 있습니다.
MsgProgramSaveUnsaved = The Pokémon in the editor has unsaved changes.
MsgProgramSaveFileConfirm = 새로운 저장 파일을 불러오시겠다는 확신이 있습니까?
MsgProgramError = 오류
MsgProgramErrorExpectedHex = 숫자(0-9)와 일부 알파벳(A-F)만 사용할 수 있습니다.
@ -172,7 +172,7 @@ MsgIndexMoveRange = 기술 인덱스가 범위를 벗어남:
MsgIndexMoveGame = 게임에서 얻을 수 없는 기술:
MsgIndexAbilityRange = 특성 인덱스가 범위를 벗어남:
MsgIndexAbilityGame = 특성 인덱스가 범위를 벗어남:
MsgGeonetPointNone = 없음
MsgGeonetPointNone = None
MsgGeonetPointBlue = 파란색
MsgGeonetPointYellow = 노란색
MsgGeonetPointRed = 빨간색
@ -259,10 +259,10 @@ MsgSaveNumberInvalid = {0} 세이브 파일이 잘못되었습니다.
MsgSecretBaseDeleteConfirm = Delete {0}'s secret base (Entry {1:00}) from your records?
MsgSecretBaseDeleteSelf = 당신의 비밀기지를 삭제할 수 없습니다.
MsgPluginFailLoad = 플러그인 로드에 실패했습니다. 오류 메시지를 참고하여 문제가 있는 플러그인을 확인하세요. 플러그인이 오래되었거나 이 프로그램 빌드와 호환되지 않을 수 있습니다.
MsgLegalityPopupCaption = 합법성 검사
MsgLegalityPopupCollapsed = 전체 보고서
MsgLegalityPopupExpanded = 전체 보고서 숨기기
MsgLegalityPopupCopyClipboard = 클립보드에 복사
MsgDialogFileOverwrite = 덮어쓰기
MsgDialogFileSaveAs = 다른 이름으로 저장...
MsgDialogFileSaveReplace = 기존 파일을 덮어쓰시겠습니까?
MsgLegalityPopupCaption = Legality Check
MsgLegalityPopupCollapsed = Full Report
MsgLegalityPopupExpanded = Hide Full Report
MsgLegalityPopupCopyClipboard = Copy to Clipboard
MsgDialogFileOverwrite = Overwrite
MsgDialogFileSaveAs = Save As...
MsgDialogFileSaveReplace = Overwrite existing file?

View File

@ -4,7 +4,7 @@ MsgProgramIllegalModeActive = 使用不合法模式啟動。
MsgProgramUpdateAvailable = 新版本經已發佈!
MsgProgramCloseUnsaved = 未保存之更改將會丟失。
MsgProgramCloseConfirm = 你確定要關閉 PKHeX 嗎?
MsgProgramSaveUnsaved = 編輯器中的寶可夢有未保存的更改。
MsgProgramSaveUnsaved = The Pokémon in the editor has unsaved changes.
MsgProgramSaveFileConfirm = 確定要載入新的儲存資料檔案嗎?
MsgProgramError = 錯誤
MsgProgramErrorExpectedHex = 文本僅能包含以下字元(0-9, A-F)。
@ -259,10 +259,10 @@ MsgSaveNumberInvalid = 儲存資料檔案 {0} 無效。
MsgSecretBaseDeleteConfirm = 是否從記錄中移除 {0}'之秘密基地 (Entry {1:00})?
MsgSecretBaseDeleteSelf = 無法移除秘密基地。
MsgPluginFailLoad = 外掛程式載入失敗。請根據錯誤資訊找到出錯之外掛程式。外掛程式可能經已失效或與本程式之版本不相容。
MsgLegalityPopupCaption = 合法性檢查
MsgLegalityPopupCollapsed = 展開完整報告
MsgLegalityPopupExpanded = 收起完整報告
MsgLegalityPopupCopyClipboard = 複製到剪貼簿
MsgDialogFileOverwrite = 覆蓋
MsgDialogFileSaveAs = 另存為...
MsgDialogFileSaveReplace = 是否覆蓋現有檔案?
MsgLegalityPopupCaption = Legality Check
MsgLegalityPopupCollapsed = Full Report
MsgLegalityPopupExpanded = Hide Full Report
MsgLegalityPopupCopyClipboard = Copy to Clipboard
MsgDialogFileOverwrite = Overwrite
MsgDialogFileSaveAs = Save As...
MsgDialogFileSaveReplace = Overwrite existing file?

View File

@ -14,7 +14,7 @@
0190 e 钢铁能检查GS球
0191 e 钢铁能归还GS球 (与上述旗标绑定)
0192 e GS球能放入桐树林祠堂
1809 * 宝可梦中心没有神秘礼物等待领取
1809 * No Mystery Gift item is waiting in the Pokémon Center
0672 * 已解决 阿露福遗迹凤王拼图谜题
0673 * 已解决 阿露福遗迹化石盔拼图谜题
0674 * 已解决 阿露福遗迹菊石兽拼图谜题

View File

@ -17,7 +17,6 @@
0x404B a Link Battles Trainer Card Sticker 0:None,1:Level 1,2:Level 2,3:Level 3
0x408B s Fossils Super Nerd Defeated (Mt. Moon) 0:No,1:Yes
0x406B s Received Nugget (Nugget Bridge) 0:No,1:Yes
0x407E s S.S. Anne Status 00:In Vermilion City,01:Ready to depart,03:Gone
0x4059 s Defeated Ghost of Marowak 0:No,1:Yes
0x4062 s Given Tea to Guards 0:No,1:Yes

View File

@ -17,7 +17,6 @@
0x404B a Sticker de Batallas Link en la Tarjeta Entrenador 0:Ningún,1:Nivel 1,2:Nivel 2,3:Nivel 3
0x408B s Super Nerd Fósil Derrotado (Mt. Moon) 0:No,1:Sí
0x406B s Recibida Pepita (Puente Pepita) 0:No,1:Sí
0x407E s Estatus del S.S. Anne 00:En Ciudad Carmín,01:Listo para embarcar,03:Ido
0x4059 s Fantasma de Marowak derrotado 0:No,1:Sí
0x4062 s Té entregado a los Guardias 0:No,1:Sí

View File

@ -17,7 +17,6 @@
0x404B a Sticker de Batallas Link en la Tarjeta Entrenador 0:Ningún,1:Nivel 1,2:Nivel 2,3:Nivel 3
0x408B s Super Nerd Fósil Derrotado (Mt. Moon) 0:No,1:Sí
0x406B s Recibida Pepita (Puente Pepita) 0:No,1:Sí
0x407E s Estatus del S.S. Anne 00:En Ciudad Carmín,01:Listo para embarcar,03:Ido
0x4059 s Fantasma de Marowak derrotado 0:No,1:Sí
0x4062 s Té entregado a los Guardias 0:No,1:Sí

View File

@ -17,7 +17,6 @@
0x404B a Sticker Carte Dresseur Combats Link 0:Aucun,1:Niveau 1,2:Niveau 2,3:Niveau 3
0x408B s Grand Maniac des Fossiles Vaincu (Mont Sélénite) 0:Non,1:Oui
0x406B s Pépite Reçu (Pont Pépite) 0:Non,1:Oui
0x407E s Statut de l'Océane 00:À Carmin-sur-mer,01:Prêt à partir,03:Parti
0x4059 s Spectre d'Ossatueur Vaincu 0:Non,1:Oui
0x4062 s Thé Donné aux Gardes 0:Non,1:Oui

View File

@ -17,7 +17,6 @@
0x404B a じまんシール(通信対戦) 0:なし,1:1段階目,2:2段階目,3:3段階目
0x408B s りかけいのおとこミツハル(カセキイベント)を倒した 0:いいえ,1:はい
0x406B s きんのたま受け取った(ゴールデンボールブリッジ) 0:いいえ,1:はい
0x407E s サント・アンヌごうの状態 00:クチバシティにいる,01:出港する直前,03:出港
0x4059 s ガラガラのゆうれいを倒した 0:いいえ,1:はい
0x4062 s おちゃを警備員にあげた 0:いいえ,1:はい

View File

@ -17,7 +17,6 @@
0x404B a 连接对战 训练师卡贴纸 0:无,1:等级1,2:等级2,3:等级3
0x408B s 击败化石理科男 (月见山) 0:否,1:是
0x406B s 获得金珠 (金球大桥) 0:否,1:是
0x407E s 圣特安努号状态 00:在枯叶市,01:准备起航,03:开走了
0x4059 s 击败嘎啦嘎啦幽灵 0:否,1:是
0x4062 s 给金黄市警卫喝茶 0:否,1:是

View File

@ -409,8 +409,8 @@
677 s Received Lift Key
678 s Received Tea
679 e Received Aurora Ticket from Mystery Gift (GBA)/Hall of Fame (Switch)
680 e Received Mystic Ticket from Mystery Gift (GBA)/Hall of Fame (Switch)
679 e Received Aurora Ticket from Mystery Gift
680 e Received Mystic Ticket from Mystery Gift
699 m Powder Jar received
700 r Mewtwo caught/defeated

View File

@ -409,8 +409,8 @@
677 s Recibida Llave Ascensor
678 s Recibido Té
679 e Ori-Ticket recibido mediante Regalo Misterioso (GBA)/Salón de la Fama (Switch)
680 e Misti-Ticket recibido mediante Regalo Misterioso (GBA)/Salón de la Fama (Switch)
679 e Ori-Ticket recibido mediante Regalo Misterioso
680 e Misti-Ticket recibido mediante Regalo Misterioso
699 m Powder Jar received
700 r Mewtwo caught/defeated

View File

@ -409,8 +409,8 @@
677 s Recibida Llave Ascensor
678 s Recibido Té
679 e Ori-Ticket recibido mediante Regalo Misterioso (GBA)/Hall de la Fama (Switch)
680 e Misti-Ticket recibido mediante Regalo Misterioso (GBA)/Hall de la Fama (Switch)
679 e Ori-Ticket recibido mediante Regalo Misterioso
680 e Misti-Ticket recibido mediante Regalo Misterioso
699 m Powder Jar received
700 r Mewtwo caught/defeated

View File

@ -409,8 +409,8 @@
677 s Clé Asc. Reçue
678 s Thé Reçu
679 e Ticketaurora Reçu en Cadeau Mystère (GBA)/Panthéon (Switch)
680 e Ticketmystik Reçu en Cadeau Mystère (GBA)/Panthéon (Switch)
679 e Ticketaurora Reçu en Cadeau Mystère
680 e Ticketmystik Reçu en Cadeau Mystère
699 m Pot Poudre Reçu
700 r Mewtwo Capturé/Vaincu

View File

@ -409,8 +409,8 @@
677 s エレベータのカギ入手済
678 s おちゃ入手済
679 e ふしぎなおくりものでオーロラチケット入手済(GBA)/殿堂入り(Switch)
680 e ふしぎなおくりものでしんぴのチケット入手済(GBA)/殿堂入り(Switch)
679 e ふしぎなおくりものでオーロラチケット入手済
680 e ふしぎなおくりものでしんぴのチケット入手済
699 m こないれ受け取り済み
700 r ミュウツー捕獲済/撃破済

File diff suppressed because it is too large Load Diff

View File

@ -409,8 +409,8 @@
677 s 獲得電梯鑰匙
678 s 獲得茶
679 e 從神秘禮物中獲得極光船票(GBA)/登入名人堂(Switch)
680 e 從神秘禮物中獲得神秘船票(GBA)/登入名人堂(Switch)
679 e 從神秘禮物中獲得極光船票
680 e 從神秘禮物中獲得神秘船票
699 m Powder Jar received
700 r Mewtwo caught/defeated

View File

@ -113,7 +113,7 @@
0303 r Spiritomb Captured
0500 s Sealed Chamber Puzzle Braille Text Disappeared
3007 s Sealed Chamber Puzzle Completed
3008 s Regi Caves Unlocked
3008 r Regi Caves Unlocked
0501 s Desert Ruins Puzzle Braille Text Disappeared
3004 s Desert Ruins Puzzle Completed
0502 s Island Cave Puzzle Braille Text Disappeared
@ -273,8 +273,8 @@
2989 f Discovered Secret Meadow
2982 f (OR) Visited Team Magma Hideout
2983 f (AS) Visited Team Aqua Hideout
2905 s Extremely Harsh Sunlight in eastern Hoenn
2906 s Heavy Rain in eastern Hoenn
2905 * Extremely Harsh Sunlight in eastern Hoenn
2906 * Heavy Rain in eastern Hoenn
3063 s Had Village Sub Combo (Today)
3064 s Had Magnemite Croquette (Today)
3065 s Had Mauville Ramen Bowl (Today)

View File

@ -113,7 +113,7 @@
0303 r Spiritomb capturado
0500 s Texto Braille del puzzle de la Cámara Sellada desaparecido
3007 s Puzzle de la Cámara Sellada completado
3008 s Cuevas de los Regi desbloqueadas
3008 r Cuevas de los Regi desbloqueadas
0501 s Texto Braille del puzzle de Ruinas del Desierto desaparecido
3004 s Puzzle de Ruinas del Desierto completado
0502 s Texto Braille del puzzle de Cueva Insular desaparecido
@ -273,8 +273,8 @@
2989 f Prado Secreto descubierto
2982 f (RO) Guarida Magma visitada
2983 f (ZA) Guarida Aqua visitada
2905 s Sol abrasador en Hoenn oriental
2906 s Diluvio en Hoenn oriental
2905 * Sol abrasador en Hoenn oriental
2906 * Diluvio en Hoenn oriental
3063 s Comido Menú Sandwich Villa (Hoy)
3064 s Comido Magnebóndigas (Hoy)
3065 s Comido Malvaguetis (Hoy)

View File

@ -113,7 +113,7 @@
0303 r Spiritomb capturado
0500 s Texto Braille del puzzle de la Cámara Sellada desaparecido
3007 s Puzzle de la Cámara Sellada completado
3008 s Cuevas de los Regi desbloqueadas
3008 r Cuevas de los Regi desbloqueadas
0501 s Texto Braille del puzzle de Ruinas del Desierto desaparecido
3004 s Puzzle de Ruinas del Desierto completado
0502 s Texto Braille del puzzle de Cueva Insular desaparecido
@ -273,8 +273,8 @@
2989 f Prado Secreto descubierto
2982 f (RO) Guarida Magma visitada
2983 f (ZA) Guarida Aqua visitada
2905 s Sol abrasador en Hoenn oriental
2906 s Diluvio en Hoenn oriental
2905 * Sol abrasador en Hoenn oriental
2906 * Diluvio en Hoenn oriental
3063 s Comido Menú Sandwich Villa (Hoy)
3064 s Comido Magnebóndigas (Hoy)
3065 s Comido Malvaguetis (Hoy)

View File

@ -113,7 +113,7 @@
0303 r Spiritomb Capturé
0500 s Puzzle du Texte en Braille du Sanctuaire Disparu
3007 s Puzzle du Sanctuaire Complété
3008 s Cavernes des Regi Débloquées
3008 r Cavernes des Regi Débloquées
0501 s Puzzle du Texte en Braille des Ruines Désert Disparu
3004 s Puzzle des Ruines Désert Complété
0502 s Puzzle du Texte en Braille de la Grotte de l'Îlot Disparu
@ -273,8 +273,8 @@
2989 f A Découvert Champ Fleuri Secret
2982 f (RO) A Visité Planque Magma
2983 f (SA) A Visité Planque Aqua
2905 s Soleil intense en Hoenn de l'est
2906 s Pluie battante en Hoenn de l'est
2905 * Soleil intense en Hoenn de l'est
2906 * Pluie battante en Hoenn de l'est
3063 s A Eu un Sandwich du Hameau (Aujourd'hui)
3064 s A Eu un Magné-Beignet (Aujourd'hui)
3065 s A Eu des Nouilles Lavandia (Aujourd'hui)

View File

@ -113,7 +113,7 @@
0303 r ミカルゲを捕獲した
0500 s おふれのせきしつ(鍵の間)の点字文字が読めなくなる
3007 s おふれのせきしつのパズルクリア
3008 s レジ洞窟の入り口解放
3008 r レジ洞窟の入り口解放
0501 s さばくいせきの点字文字が読めない状態
3004 s さばくいせきのパズルクリア
0502 s こじまのよこあなの点字文字が読めない状態
@ -273,8 +273,8 @@
2989 f ひみつのはなばたけを発見した
2982 f マグマ団アジトを訪れた(OR)
2983 f アクア団アジトを訪れた(AS)
2905 s ひでり状態(ルネシティイベント)
2906 s おおあめ状態(ルネシティイベント)
2905 * ひでり状態(ルネシティイベント)
2906 * おおあめ状態(ルネシティイベント)
3063 s ビレッジセットをチャレンジした(デイリー)
3064 s コイル焼きをチャレンジした(デイリー)
3065 s キンセツチャンポンをチャレンジした(デイリー)

View File

@ -113,7 +113,7 @@
0303 r 화강돌 잡음
0500 s 고시의 석실 퍼즐 점자 텍스트 사라짐
3007 s 고시의 석실 퍼즐 완료
3008 s 거인 전설의 동굴 개방됨
3008 r 거인 전설의 동굴 개방됨
0501 s 사막유적 퍼즐 점자 텍스트 사라짐
3004 s 사막유적 퍼즐 완료
0502 s 작은 섬 옆굴 퍼즐 점자 텍스트 사라짐
@ -273,8 +273,8 @@
2989 f 비밀의 꽃밭 발견됨
2982 f (OR) 방문함 마그마단아지트
2983 f (AS) 방문함 아쿠아단아지트
2905 s 호연 동부에 햇살이 아주 강한
2906 s 호연 동부에 강한 비
2905 * 호연 동부에 햇살이 아주 강한
2906 * 호연 동부에 강한 비
3063 s 빌리지샌드세트 먹음 (오늘)
3064 s 코일야키 먹음 (오늘)
3065 s 보라짬뽕 먹음 (오늘)

View File

@ -113,7 +113,7 @@
0303 r 已捕获 花岩怪
0500 s 布告石室言语之厅解密盲文消失了
3007 s 布告石室关键之厅解密完成
3008 s 已解锁 雷吉洞穴
3008 r 已解锁 雷吉洞穴
0501 s 沙漠遗迹解密盲文消失了
3004 s 沙漠遗迹解密完成
0502 s 小岛洞穴解密盲文消失了
@ -273,8 +273,8 @@
2989 f 发现秘密花圃
2982 f (OR)到达熔岩队基地
2983 f (AS)到达海洋队基地
2905 s 丰缘东部大晴天
2906 s 丰缘东部降雨
2905 * 丰缘东部大晴天
2906 * 丰缘东部降雨
3063 s 紫堇美食广场村庄三明治组合 单打对战(当天)
3064 s 紫堇美食广场小磁怪烧 双打对战(当天)
3065 s 紫堇美食广场紫堇什锦面 三打对战(当天)

View File

@ -113,7 +113,7 @@
0303 r 已捕獲 花岩怪
0500 s 布告石室言語之廳解密盲文消失了
3007 s 布告石室關鍵之廳解密完成
3008 s 已解鎖 雷吉洞穴
3008 r 已解鎖 雷吉洞穴
0501 s 沙漠遺跡解密盲文消失了
3004 s 沙漠遺跡解密完成
0502 s 小島洞穴解密盲文消失了
@ -273,8 +273,8 @@
2989 f 发现秘密花圃
2982 f (OR)到达熔岩队基地
2983 f (AS)到达海洋队基地
2905 s 丰缘东部大晴天
2906 s 丰缘东部降雨
2905 * 丰缘东部大晴天
2906 * 丰缘东部降雨
3063 s 紫堇美食广场村庄三明治组合 单打对战(当天)
3064 s 紫堇美食广场小磁怪烧 双打对战(当天)
3065 s 紫堇美食广场紫堇什锦面 三打对战(当天)

View File

@ -5,7 +5,7 @@ namespace PKHeX.Core;
/// <summary>
/// Minimal Trainer Information necessary for generating a <see cref="PKM"/>.
/// </summary>
public interface ITrainerInfo : ITrainerID32ReadOnly, IVersion, IGeneration, IContext
public interface ITrainerInfo : ITrainerID32ReadOnly, IVersion, IGeneration
{
string OT { get; }
byte Gender { get; }
@ -13,6 +13,7 @@ public interface ITrainerInfo : ITrainerID32ReadOnly, IVersion, IGeneration, ICo
int Language { get; }
new byte Generation { get; }
EntityContext Context { get; }
}
/// <summary>

View File

@ -1,43 +0,0 @@
using System;
using System.ComponentModel;
namespace PKHeX.Core;
[TypeConverter(typeof(ExpandableObjectConverter))]
public interface ISaveBlock3Large
{
Memory<byte> Raw { get; }
Span<byte> Data { get; }
ushort X { get; set; }
ushort Y { get; set; }
byte PartyCount { get; set; }
Span<byte> PartyBuffer { get; }
uint Money { get; set; }
ushort Coin { get; set; }
ushort RegisteredItem { get; set; }
Span<byte> EReaderBerry { get; }
Gen3MysteryData MysteryData { get; set; }
int DaycareOffset { get; }
int DaycareSlotSize { get; }
int BadgeFlagStart { get; }
int EventFlagCount { get; }
int EventWorkCount { get; }
int EggEventFlag { get; }
Memory<byte> RoamerData { get; }
uint GetRecord(int record);
void SetRecord(int record, uint value);
Mail3 GetMail(int mailIndex);
void SetMail(int mailIndex, Mail3 value);
bool GetEventFlag(int flagNumber);
void SetEventFlag(int flagNumber, bool value);
ushort GetWork(int index);
void SetWork(int index, ushort value);
int SeenOffset2 { get; }
int ExternalEventData { get; }
int SeenOffset3 { get; }
Span<byte> GiftRibbons { get; }
}

View File

@ -1,13 +0,0 @@
using System;
namespace PKHeX.Core;
public interface ISaveBlock3LargeExpansion : ISaveBlock3Large
{
WonderNews3 GetWonderNews(bool isJapanese);
void SetWonderNews(bool isJapanese, ReadOnlySpan<byte> data);
WonderCard3 GetWonderCard(bool isJapanese);
void SetWonderCard(bool isJapanese, ReadOnlySpan<byte> data);
WonderCard3Extra GetWonderCardExtra(bool isJapanese);
void SetWonderCardExtra(bool isJapanese, ReadOnlySpan<byte> data);
}

View File

@ -1,36 +0,0 @@
using System;
using System.ComponentModel;
namespace PKHeX.Core;
[TypeConverter(typeof(ExpandableObjectConverter))]
public interface ISaveBlock3Small
{
Memory<byte> Raw { get; }
Span<byte> Data { get; }
Span<byte> OriginalTrainerTrash { get; }
byte Gender { get; set; }
uint ID32 { get; set; }
ushort TID16 { get; set; }
ushort SID16 { get; set; }
int PlayedHours { get; set; }
int PlayedMinutes { get; set; }
int PlayedSeconds { get; set; }
byte PlayedFrames { get; set; }
byte OptionsButtonMode { get; set; }
int TextSpeed { get; set; }
byte OptionWindowFrame { get; set; }
bool OptionSoundStereo { get; set; }
bool OptionBattleStyle { get; set; }
bool OptionBattleScene { get; set; }
bool OptionIsRegionMapZoom { get; set; }
byte PokedexSort { get; set; }
byte PokedexMode { get; set; }
byte PokedexNationalMagicRSE { get; set; }
byte PokedexNationalMagicFRLG { get; set; }
uint DexPIDUnown { get; set; }
uint DexPIDSpinda { get; set; }
Span<byte> EReaderTrainer { get; }
uint SecurityKey { get; }
}

View File

@ -1,17 +0,0 @@
namespace PKHeX.Core;
/// <summary>
/// Small-block properties common to RS & Emerald save files.
/// </summary>
public interface ISaveBlock3SmallHoenn : ISaveBlock3Small
{
/// <summary>
/// localTimeOffset
/// </summary>
RTC3 ClockInitial { get; set; }
/// <summary>
/// lastBerryTreeUpdate
/// </summary>
RTC3 ClockElapsed { get; set; }
}

View File

@ -1,204 +0,0 @@
using System;
using System.Collections.Generic;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed record SaveBlock3LargeE(Memory<byte> Raw) : ISaveBlock3LargeExpansion, ISaveBlock3LargeHoenn, IRecordStatStorage<RecID3Emerald, uint>
{
public Span<byte> Data => Raw.Span;
public ushort X { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, value); }
public ushort Y { get => ReadUInt16LittleEndian(Data[2..]); set => WriteUInt16LittleEndian(Data[2..], value); }
public byte PartyCount { get => Data[0x234]; set => Data[0x234] = value; }
public Span<byte> PartyBuffer => Data.Slice(0x238, 6 * PokeCrypto.SIZE_3PARTY);
public uint Money { get => ReadUInt32LittleEndian(Data[0x0490..]); set => WriteUInt32LittleEndian(Data[0x0490..], value); }
public ushort Coin { get => ReadUInt16LittleEndian(Data[0x0494..]); set => WriteUInt16LittleEndian(Data[0x0494..], value); }
public ushort RegisteredItem { get => ReadUInt16LittleEndian(Data[0x0496..]); set => WriteUInt16LittleEndian(Data[0x0496..], value); }
public Span<byte> Inventory => Data.Slice(0x0498, 0x3B0);
private Span<byte> PokeBlockData => Data.Slice(0x848, PokeBlock3Case.SIZE);
public PokeBlock3Case PokeBlocks { get => new(PokeBlockData); set => value.Write(PokeBlockData); }
public int SeenOffset2 => 0x988;
private const int OFS_BerryBlenderRecord = 0x9BC;
/// <summary>
/// Max RPM for 2, 3 and 4 players. Each value unit represents 0.01 RPM. Value 0 if no record.
/// </summary>
/// <remarks>2 players: index 0, 3 players: index 1, 4 players: index 2</remarks>
public const int BerryBlenderRPMRecordCount = 3;
private Span<byte> GetBlenderRPMSpan(int index)
{
if ((uint)index >= BerryBlenderRPMRecordCount)
throw new ArgumentOutOfRangeException(nameof(index));
return Data[(OFS_BerryBlenderRecord + (index * 2))..];
}
public ushort GetBerryBlenderRPMRecord(int index) => ReadUInt16LittleEndian(GetBlenderRPMSpan(index));
public void SetBerryBlenderRPMRecord(int index, ushort value) => WriteUInt16LittleEndian(GetBlenderRPMSpan(index), value);
private const int EventFlag = 0x1270;
private const int EventWork = 0x139C;
public int EventFlagCount => 8 * 300;
public int EventWorkCount => 0x100;
public int EggEventFlag => 0x86;
public int BadgeFlagStart => 0x867;
public bool GetEventFlag(int flagNumber)
{
if ((uint)flagNumber >= EventFlagCount)
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
return FlagUtil.GetFlag(Data, EventFlag + (flagNumber >> 3), flagNumber & 7);
}
public void SetEventFlag(int flagNumber, bool value)
{
if ((uint)flagNumber >= EventFlagCount)
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
FlagUtil.SetFlag(Data, EventFlag + (flagNumber >> 3), flagNumber & 7, value);
}
public ushort GetWork(int index) => ReadUInt16LittleEndian(Data[(EventWork + (index * 2))..]);
public void SetWork(int index, ushort value) => WriteUInt16LittleEndian(Data[EventWork..][(index * 2)..], value);
private const int RecordOffset = 0x159C;
private static int GetRecordOffset(RecID3Emerald record)
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)record, (uint)RecID3Emerald.NUM_GAME_STATS);
return RecordOffset + (sizeof(uint) * (int)record);
}
public uint GetRecord(int record) => GetRecord((RecID3Emerald)record);
public void SetRecord(int record, uint value) => SetRecord((RecID3Emerald)record, value);
public uint GetRecord(RecID3Emerald record) => ReadUInt32LittleEndian(Data[GetRecordOffset(record)..]);
public void SetRecord(RecID3Emerald record, uint value) => WriteUInt32LittleEndian(Data[GetRecordOffset(record)..], value);
public void AddRecord(RecID3Emerald record, uint value) => SetRecord(record, GetRecord(record) + value);
private Memory<byte> SecretBaseData => Raw.Slice(0x1A9C, SecretBaseManager3.BaseCount * SecretBase3.SIZE);
public SecretBaseManager3 SecretBases => new(SecretBaseData);
public DecorationInventory3 Decorations => new(Data.Slice(0x2734, DecorationInventory3.SIZE));
private Span<byte> SwarmData => Data.Slice(0x2B90, Swarm3.SIZE);
public Swarm3 Swarm { get => new(SwarmData.ToArray()); set => value.Data.CopyTo(SwarmData); }
private void ClearSwarm() => SwarmData.Clear();
public IReadOnlyList<Swarm3> DefaultSwarms => Swarm3Details.Swarms_E;
public int SwarmIndex
{
get
{
var map = Swarm.MapNum;
for (int i = 0; i < DefaultSwarms.Count; i++)
{
if (DefaultSwarms[i].MapNum == map)
return i;
}
return -1;
}
set
{
var arr = DefaultSwarms;
if ((uint)value >= arr.Count)
ClearSwarm();
else
Swarm = arr[value];
}
}
private const int MailOffset = 0x2BE0;
private static int GetMailOffset(int index) => (index * Mail3.SIZE) + MailOffset;
private Span<byte> GetMailSpan(int ofs) => Data.Slice(ofs, Mail3.SIZE);
public Mail3 GetMail(int mailIndex)
{
var ofs = GetMailOffset(mailIndex);
var span = Data.Slice(ofs, Mail3.SIZE);
return new Mail3(span.ToArray(), ofs);
}
public void SetMail(int mailIndex, Mail3 value)
{
var ofs = GetMailOffset(mailIndex);
value.CopyTo(GetMailSpan(ofs));
}
private const int OFS_TrendyWord = 0x2E20;
public bool GetTrendyWordUnlocked(TrendyWord3E word) => FlagUtil.GetFlag(Data, OFS_TrendyWord + ((byte)word >> 3), (byte)word & 7);
public void SetTrendyWordUnlocked(TrendyWord3E word, bool value) => FlagUtil.SetFlag(Data, OFS_TrendyWord + ((byte)word >> 3), (byte)word & 7, value);
private const int Painting = 0x2F90;
private const int PaintingCount = 5;
private Span<byte> GetPaintingSpan(int index)
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual<uint>((uint)index, PaintingCount);
return Data.Slice(Painting + (Paintings3.SIZE * index), Paintings3.SIZE * PaintingCount);
}
public Paintings3 GetPainting(int index, bool japanese) => new(GetPaintingSpan(index).ToArray(), japanese);
public void SetPainting(int index, Paintings3 value) => value.Data.CopyTo(GetPaintingSpan(index));
public int DaycareOffset => 0x3030;
public int DaycareSlotSize => PokeCrypto.SIZE_3STORED + 0x3C; // 0x38 mail + 4 exp
public uint DaycareSeed
{
get => ReadUInt32LittleEndian(Data[0x3148..]);
set => WriteUInt32LittleEndian(Data[0x3148..], value);
}
public Span<byte> GiftRibbons => Data.Slice(0x31B3, 11);
public int ExternalEventData => 0x31B3;
public Memory<byte> RoamerData => Raw.Slice(0x31DC, Roamer3.SIZE);
private const int OFFSET_EBERRY = 0x31F8;
private const int SIZE_EBERRY = 0x34;
public Span<byte> EReaderBerry => Data.Slice(OFFSET_EBERRY, SIZE_EBERRY);
public const int WonderNewsOffset = 0x322C;
// RAM Script
private Span<byte> MysterySpan => Data.Slice(0x3728, MysteryEvent3.SIZE);
public Gen3MysteryData MysteryData
{
get => new MysteryEvent3(MysterySpan.ToArray());
set => value.Data.CopyTo(MysterySpan);
}
private static int WonderCardOffset(bool isJapanese) => WonderNewsOffset + (isJapanese ? WonderNews3.SIZE_JAP : WonderNews3.SIZE);
private static int WonderCardExtraOffset(bool isJapanese) => WonderCardOffset(isJapanese) + (isJapanese ? WonderCard3.SIZE_JAP : WonderCard3.SIZE);
private Span<byte> WonderNewsData(bool isJapanese) => Data.Slice(WonderNewsOffset, isJapanese ? WonderNews3.SIZE_JAP : WonderNews3.SIZE);
private Span<byte> WonderCardData(bool isJapanese) => Data.Slice(WonderCardOffset(isJapanese), isJapanese ? WonderCard3.SIZE_JAP : WonderCard3.SIZE);
private Span<byte> WonderCardExtraData(bool isJapanese) => Data.Slice(WonderCardExtraOffset(isJapanese), WonderCard3Extra.SIZE);
public WonderNews3 GetWonderNews(bool isJapanese) => new(WonderNewsData(isJapanese).ToArray());
public void SetWonderNews(bool isJapanese, ReadOnlySpan<byte> data) => data.CopyTo(WonderNewsData(isJapanese));
public WonderCard3 GetWonderCard(bool isJapanese) => new(WonderCardData(isJapanese).ToArray());
public void SetWonderCard(bool isJapanese, ReadOnlySpan<byte> data) => data.CopyTo(WonderCardData(isJapanese));
public WonderCard3Extra GetWonderCardExtra(bool isJapanese) => new(WonderCardExtraData(isJapanese).ToArray());
public void SetWonderCardExtra(bool isJapanese, ReadOnlySpan<byte> data) => data.CopyTo(WonderCardExtraData(isJapanese));
private const int OFS_TrainerHillRecord = 0x3718;
/** Each value unit represents 1/60th of a second. Value 0 if no record. */
public uint GetTrainerHillRecord(TrainerHillMode3E mode) => ReadUInt32LittleEndian(Data[(OFS_TrainerHillRecord + ((byte)mode * 4))..]);
public void SetTrainerHillRecord(TrainerHillMode3E mode, uint value) => WriteUInt32LittleEndian(Data[(OFS_TrainerHillRecord + ((byte)mode * 4))..], value);
private Span<byte> RecordMixingData => Data.Slice(0x3B14, RecordMixing3Gift.SIZE);
public RecordMixing3Gift RecordMixingGift
{
get => new(RecordMixingData.ToArray());
set => value.Data.CopyTo(RecordMixingData);
}
public int SeenOffset3 => 0x3B24;
private const int Walda = 0x3D70;
public ushort WaldaBackgroundColor { get => ReadUInt16LittleEndian(Data[(Walda + 0)..]); set => WriteUInt16LittleEndian(Data[(Walda + 0)..], value); }
public ushort WaldaForegroundColor { get => ReadUInt16LittleEndian(Data[(Walda + 2)..]); set => WriteUInt16LittleEndian(Data[(Walda + 2)..], value); }
public byte WaldaIconID { get => Data[Walda + 0x14]; set => Data[Walda + 0x14] = value; }
public byte WaldaPatternID { get => Data[Walda + 0x15]; set => Data[Walda + 0x15] = value; }
public bool WaldaUnlocked { get => Data[Walda + 0x16] != 0; set => Data[Walda + 0x16] = (byte)(value ? 1 : 0); }
}

View File

@ -1,121 +0,0 @@
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed record SaveBlock3LargeFRLG(Memory<byte> Raw) : ISaveBlock3LargeExpansion, IRecordStatStorage<RecID3FRLG, uint>
{
public Span<byte> Data => Raw.Span;
public ushort X { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, value); }
public ushort Y { get => ReadUInt16LittleEndian(Data[2..]); set => WriteUInt16LittleEndian(Data[2..], value); }
public byte PartyCount { get => Data[0x034]; set => Data[0x034] = value; }
public Span<byte> PartyBuffer => Data.Slice(0x038, 6 * PokeCrypto.SIZE_3PARTY);
public uint Money { get => ReadUInt32LittleEndian(Data[0x0290..]); set => WriteUInt32LittleEndian(Data[0x0290..], value); }
public ushort Coin { get => ReadUInt16LittleEndian(Data[0x0294..]); set => WriteUInt16LittleEndian(Data[0x0294..], value); }
public ushort RegisteredItem { get => ReadUInt16LittleEndian(Data[0x0296..]); set => WriteUInt16LittleEndian(Data[0x0296..], value); }
public Span<byte> Inventory => Data.Slice(0x0298, 0x360);
public int SeenOffset2 => 0x5F8;
private const int EventFlag = 0xEE0;
private const int EventWork = 0x1000;
public int EventFlagCount => 8 * 288;
public int EventWorkCount => 0x100;
public int EggEventFlag => 0x266;
public int BadgeFlagStart => 0x820;
public bool GetEventFlag(int flagNumber)
{
if ((uint)flagNumber >= EventFlagCount)
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
return FlagUtil.GetFlag(Data, EventFlag + (flagNumber >> 3), flagNumber & 7);
}
public void SetEventFlag(int flagNumber, bool value)
{
if ((uint)flagNumber >= EventFlagCount)
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
FlagUtil.SetFlag(Data, EventFlag + (flagNumber >> 3), flagNumber & 7, value);
}
public ushort GetWork(int index) => ReadUInt16LittleEndian(Data[(EventWork + (index * 2))..]);
public void SetWork(int index, ushort value) => WriteUInt16LittleEndian(Data[EventWork..][(index * 2)..], value);
private const int RecordOffset = 0x1200;
private static int GetRecordOffset(RecID3FRLG record)
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)record, (uint)RecID3FRLG.NUM_GAME_STATS);
return RecordOffset + (sizeof(uint) * (int)record);
}
public uint GetRecord(int record) => GetRecord((RecID3FRLG)record);
public void SetRecord(int record, uint value) => SetRecord((RecID3FRLG)record, value);
public uint GetRecord(RecID3FRLG record) => ReadUInt32LittleEndian(Data[GetRecordOffset(record)..]);
public void SetRecord(RecID3FRLG record, uint value) => WriteUInt32LittleEndian(Data[GetRecordOffset(record)..], value);
public void AddRecord(RecID3FRLG record, uint value) => SetRecord(record, GetRecord(record) + value);
private const int MailOffset = 0x2CD0;
private static int GetMailOffset(int index) => (index * Mail3.SIZE) + MailOffset;
private Span<byte> GetMailSpan(int ofs) => Data.Slice(ofs, Mail3.SIZE);
public Mail3 GetMail(int mailIndex)
{
var ofs = GetMailOffset(mailIndex);
var span = Data.Slice(ofs, Mail3.SIZE);
return new Mail3(span.ToArray(), ofs);
}
public void SetMail(int mailIndex, Mail3 value)
{
var ofs = GetMailOffset(mailIndex);
value.CopyTo(GetMailSpan(ofs));
}
public int DaycareOffset => 0x2F80;
public int DaycareSlotSize => PokeCrypto.SIZE_3STORED + 0x3C; // 0x38 mail + 4 exp
public ushort DaycareSeed
{
get => ReadUInt16LittleEndian(Data[0x3098..]);
set => WriteUInt16LittleEndian(Data[0x3098..], value);
}
public Span<byte> GiftRibbons => Data.Slice(0x309C, 11);
public int ExternalEventData => 0x30A7;
public Memory<byte> RoamerData => Raw.Slice(0x30D0, Roamer3.SIZE);
private const int OFFSET_EBERRY = 0x30EC;
private const int SIZE_EBERRY = 0x34;
public Span<byte> EReaderBerry => Data.Slice(OFFSET_EBERRY, SIZE_EBERRY);
public const int WonderNewsOffset = 0x3120;
private static int WonderCardOffset(bool isJapanese) => WonderNewsOffset + (isJapanese ? WonderNews3.SIZE_JAP : WonderNews3.SIZE);
private static int WonderCardExtraOffset(bool isJapanese) => WonderCardOffset(isJapanese) + (isJapanese ? WonderCard3.SIZE_JAP : WonderCard3.SIZE);
private Span<byte> WonderNewsData(bool isJapanese) => Data.Slice(WonderNewsOffset, isJapanese ? WonderNews3.SIZE_JAP : WonderNews3.SIZE);
private Span<byte> WonderCardData(bool isJapanese) => Data.Slice(WonderCardOffset(isJapanese), isJapanese ? WonderCard3.SIZE_JAP : WonderCard3.SIZE);
private Span<byte> WonderCardExtraData(bool isJapanese) => Data.Slice(WonderCardExtraOffset(isJapanese), WonderCard3Extra.SIZE);
public WonderNews3 GetWonderNews(bool isJapanese) => new(WonderNewsData(isJapanese).ToArray());
public void SetWonderNews(bool isJapanese, ReadOnlySpan<byte> data) => data.CopyTo(WonderNewsData(isJapanese));
public WonderCard3 GetWonderCard(bool isJapanese) => new(WonderCardData(isJapanese).ToArray());
public void SetWonderCard(bool isJapanese, ReadOnlySpan<byte> data) => data.CopyTo(WonderCardData(isJapanese));
public WonderCard3Extra GetWonderCardExtra(bool isJapanese) => new(WonderCardExtraData(isJapanese).ToArray());
public void SetWonderCardExtra(bool isJapanese, ReadOnlySpan<byte> data) => data.CopyTo(WonderCardExtraData(isJapanese));
public Span<byte> RivalNameTrash => Data.Slice(0x3A4C, 8);
private Span<byte> MysterySpan => Data.Slice(0x361C, MysteryEvent3.SIZE);
public Gen3MysteryData MysteryData
{
get => new MysteryEvent3(MysterySpan.ToArray());
set => value.Data.CopyTo(MysterySpan);
}
public int SeenOffset3 => 0x3A18;
public Memory<byte> SingleDaycareRoute5 => Raw.Slice(0x3C98, PokeCrypto.SIZE_3STORED); // 0x38 mail + 4 exp
}

View File

@ -1,172 +0,0 @@
using System;
using System.Collections.Generic;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed record SaveBlock3LargeRS(Memory<byte> Raw) : ISaveBlock3LargeHoenn, IRecordStatStorage<RecID3RuSa, uint>
{
public Span<byte> Data => Raw.Span;
public ushort X { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, value); }
public ushort Y { get => ReadUInt16LittleEndian(Data[2..]); set => WriteUInt16LittleEndian(Data[2..], value); }
public byte PartyCount { get => Data[0x234]; set => Data[0x234] = value; }
public Span<byte> PartyBuffer => Data.Slice(0x238, 6 * PokeCrypto.SIZE_3PARTY);
public uint Money { get => ReadUInt32LittleEndian(Data[0x0490..]); set => WriteUInt32LittleEndian(Data[0x0490..], value); }
public ushort Coin { get => ReadUInt16LittleEndian(Data[0x0494..]); set => WriteUInt16LittleEndian(Data[0x0494..], value); }
public ushort RegisteredItem { get => ReadUInt16LittleEndian(Data[0x0496..]); set => WriteUInt16LittleEndian(Data[0x0496..], value); }
public Span<byte> Inventory => Data.Slice(0x498, 0x360);
private Span<byte> PokeBlockData => Data.Slice(0x7F8, PokeBlock3Case.SIZE);
public PokeBlock3Case PokeBlocks { get => new(PokeBlockData); set => value.Write(PokeBlockData); }
public int SeenOffset2 => 0x938;
private const int OFS_BerryBlenderRecord = 0x96C;
/// <summary>
/// Max RPM for 2, 3 and 4 players. Each value unit represents 0.01 RPM. Value 0 if no record.
/// </summary>
/// <remarks>2 players: index 0, 3 players: index 1, 4 players: index 2</remarks>
public const int BerryBlenderRPMRecordCount = 3;
private Span<byte> GetBlenderRPMSpan(int index)
{
if ((uint)index >= BerryBlenderRPMRecordCount)
throw new ArgumentOutOfRangeException(nameof(index));
return Data[(OFS_BerryBlenderRecord + (index * 2))..];
}
public ushort GetBerryBlenderRPMRecord(int index) => ReadUInt16LittleEndian(GetBlenderRPMSpan(index));
public void SetBerryBlenderRPMRecord(int index, ushort value) => WriteUInt16LittleEndian(GetBlenderRPMSpan(index), value);
private const int EventFlag = 0x1220;
private const int EventWork = 0x1340;
public int EventFlagCount => 8 * 288;
public int EventWorkCount => 0x100;
public int EggEventFlag => 0x86;
public int BadgeFlagStart => 0x807;
public bool GetEventFlag(int flagNumber)
{
if ((uint)flagNumber >= EventFlagCount)
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to get ({flagNumber}) is greater than max ({EventFlagCount}).");
return FlagUtil.GetFlag(Data, EventFlag + (flagNumber >> 3), flagNumber & 7);
}
public void SetEventFlag(int flagNumber, bool value)
{
if ((uint)flagNumber >= EventFlagCount)
throw new ArgumentOutOfRangeException(nameof(flagNumber), $"Event Flag to set ({flagNumber}) is greater than max ({EventFlagCount}).");
FlagUtil.SetFlag(Data, EventFlag + (flagNumber >> 3), flagNumber & 7, value);
}
public ushort GetWork(int index) => ReadUInt16LittleEndian(Data[(EventWork + (index * 2))..]);
public void SetWork(int index, ushort value) => WriteUInt16LittleEndian(Data[EventWork..][(index * 2)..], value);
private const int RecordOffset = 0x1540;
private static int GetRecordOffset(RecID3RuSa record)
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)record, (uint)RecID3RuSa.NUM_GAME_STATS);
return RecordOffset + (sizeof(uint) * (int)record);
}
public uint GetRecord(int record) => GetRecord((RecID3RuSa)record);
public void SetRecord(int record, uint value) => SetRecord((RecID3RuSa)record, value);
public uint GetRecord(RecID3RuSa record) => ReadUInt32LittleEndian(Data[GetRecordOffset(record)..]);
public void SetRecord(RecID3RuSa record, uint value) => WriteUInt32LittleEndian(Data[GetRecordOffset(record)..], value);
public void AddRecord(RecID3RuSa record, uint value) => SetRecord(record, GetRecord(record) + value);
private Memory<byte> SecretBaseData => Raw.Slice(0x1A08, SecretBaseManager3.BaseCount * SecretBase3.SIZE);
public SecretBaseManager3 SecretBases => new(SecretBaseData);
public DecorationInventory3 Decorations => new(Data.Slice(0x26A0, DecorationInventory3.SIZE));
private Span<byte> SwarmData => Data.Slice(0x2AFC, Swarm3.SIZE);
public Swarm3 Swarm { get => new(SwarmData.ToArray()); set => value.Data.CopyTo(SwarmData); }
private void ClearSwarm() => SwarmData.Clear();
public IReadOnlyList<Swarm3> DefaultSwarms => Swarm3Details.Swarms_RS;
public int SwarmIndex
{
get
{
var map = Swarm.MapNum;
for (int i = 0; i < DefaultSwarms.Count; i++)
{
if (DefaultSwarms[i].MapNum == map)
return i;
}
return -1;
}
set
{
var arr = DefaultSwarms;
if ((uint)value >= arr.Count)
ClearSwarm();
else
Swarm = arr[value];
}
}
private const int MailOffset = 0x2B4C;
private static int GetMailOffset(int index) => (index * Mail3.SIZE) + MailOffset;
private Span<byte> GetMailSpan(int ofs) => Data.Slice(ofs, Mail3.SIZE);
public Mail3 GetMail(int mailIndex)
{
var ofs = GetMailOffset(mailIndex);
var span = Data.Slice(ofs, Mail3.SIZE);
return new Mail3(span.ToArray(), ofs);
}
public void SetMail(int mailIndex, Mail3 value)
{
var ofs = GetMailOffset(mailIndex);
value.CopyTo(GetMailSpan(ofs));
}
private const int Painting = 0x2EFC;
private const int PaintingCount = 5;
private Span<byte> GetPaintingSpan(int index)
{
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual<uint>((uint)index, PaintingCount);
return Data.Slice(Painting + (Paintings3.SIZE * index), Paintings3.SIZE * PaintingCount);
}
public Paintings3 GetPainting(int index, bool japanese) => new(GetPaintingSpan(index).ToArray(), japanese);
public void SetPainting(int index, Paintings3 value) => value.Data.CopyTo(GetPaintingSpan(index));
public int DaycareOffset => 0x2F9C;
public int DaycareSlotSize => PokeCrypto.SIZE_3STORED; // mail stored separate from box mons
public ushort DaycareSeed
{
get => ReadUInt16LittleEndian(Data[0x30B4..]);
set => WriteUInt16LittleEndian(Data[0x30B4..], value);
}
public Span<byte> GiftRibbons => Data.Slice(ExternalEventData - 11, 11);
public int ExternalEventData => 0x311B;
public Memory<byte> RoamerData => Raw.Slice(0x3144, Roamer3.SIZE);
private const int OFFSET_EBERRY = 0x3160;
private const int SIZE_EBERRY = 0x530;
public Span<byte> EReaderBerry => Data.Slice(OFFSET_EBERRY, SIZE_EBERRY);
private Span<byte> MysterySpan => Data.Slice(0x3690, MysteryEvent3.SIZE);
public Gen3MysteryData MysteryData
{
get => new MysteryEvent3(MysterySpan.ToArray());
set => value.Data.CopyTo(MysterySpan);
}
private Span<byte> RecordSpan => Data.Slice(0x3A7C, RecordMixing3Gift.SIZE);
public RecordMixing3Gift RecordMixingGift
{
get => new(RecordSpan.ToArray());
set => value.Data.CopyTo(RecordSpan);
}
public int SeenOffset3 => 0x3A8C;
}

View File

@ -1,67 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed record SaveBlock3SmallE(Memory<byte> Raw) : ISaveBlock3SmallExpansion, ISaveBlock3SmallHoenn
{
public Span<byte> Data => Raw.Span;
public Span<byte> OriginalTrainerTrash => Data[..8];
public byte Gender { get => Data[8]; set => Data[8] = value; }
public uint ID32 { get => ReadUInt32LittleEndian(Data[0x0A..]); set => WriteUInt32LittleEndian(Data[0x0A..], value); }
public ushort TID16 { get => ReadUInt16LittleEndian(Data[0xA..]); set => WriteUInt16LittleEndian(Data[0xA..], value); }
public ushort SID16 { get => ReadUInt16LittleEndian(Data[0xC..]); set => WriteUInt16LittleEndian(Data[0xC..], value); }
public int PlayedHours { get => ReadUInt16LittleEndian(Data[0xE..]); set => WriteUInt16LittleEndian(Data[0xE..], (ushort)value); }
public int PlayedMinutes { get => Data[0x10]; set => Data[0x10] = (byte)value; }
public int PlayedSeconds { get => Data[0x11]; set => Data[0x11] = (byte)value; }
public byte PlayedFrames { get => Data[0x12]; set => Data[0x12] = value; }
public byte OptionsButtonMode { get => Data[0x13]; set => Data[0x13] = value; }
private uint OptionsConfig { get => ReadUInt32LittleEndian(Data[0x14..]); set => WriteUInt32LittleEndian(Data[0x14..], value); }
public int TextSpeed { get => (int)(OptionsConfig & 0b11); set => OptionsConfig = (uint)((byte)value & 0b11) | (OptionsConfig & ~0b11u); }
public byte OptionWindowFrame { get => (byte)((OptionsConfig >> 2) & 0b11111); set => OptionsConfig = (uint)((value & 0b11111) << 2) | (OptionsConfig & ~(0b11111u << 2)); }
public bool OptionSoundStereo { get => (OptionsConfig & 0b100000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b100000) : (OptionsConfig & ~0b100000u); }
public bool OptionBattleStyle { get => (OptionsConfig & 0b1000000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b1000000) : (OptionsConfig & ~0b1000000u); }
public bool OptionBattleScene { get => (OptionsConfig & 0b10000000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b10000000) : (OptionsConfig & ~0b10000000u); }
public bool OptionIsRegionMapZoom { get => (OptionsConfig & 0b100000000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b100000000) : (OptionsConfig & ~0b100000000u); }
public byte PokedexSort { get => Data[0x18]; set => Data[0x18] = value; }
public byte PokedexMode { get => Data[0x19]; set => Data[0x19] = value; }
public byte PokedexNationalMagicRSE { get => Data[0x1A]; set => Data[0x1A] = value; }
public byte PokedexNationalMagicFRLG { get => Data[0x1B]; set => Data[0x1B] = value; }
public uint DexPIDUnown { get => ReadUInt32LittleEndian(Data[0x1C..]); set => WriteUInt32LittleEndian(Data[0x1C..], value); }
public uint DexPIDSpinda { get => ReadUInt32LittleEndian(Data[0x20..]); set => WriteUInt32LittleEndian(Data[0x20..], value); }
private Span<byte> ClockInitialSpan => Data.Slice(0x098, RTC3.Size);
private Span<byte> ClockElapsedSpan => Data.Slice(0x0A0, RTC3.Size);
public RTC3 ClockInitial { get => new(ClockInitialSpan.ToArray()); set => value.Data.CopyTo(ClockInitialSpan); }
public RTC3 ClockElapsed { get => new(ClockElapsedSpan.ToArray()); set => value.Data.CopyTo(ClockElapsedSpan); }
public uint LinkFlags { get => ReadUInt32LittleEndian(Data[0x0A8..]); set => WriteUInt32LittleEndian(Data[0x0A8..], value); }
public uint SecurityKey { get => ReadUInt32LittleEndian(Data[0x0AC..]); set => WriteUInt32LittleEndian(Data[0x0AC..], value); }
// 0xB0: Player Apprentice
// 0xDC: Apprentices
// 0x1EC: Berry Crush
public ushort GetBerryPressSpeed([Range(0, 3)] int index) => ReadUInt16LittleEndian(Data[(0x1EC + (index * 2))..]);
public void SetBerryPressSpeed([Range(0, 3)] int index, ushort value) => WriteUInt16LittleEndian(Data[(0x1EC + (index * 2))..], value);
public uint BerryPowder { get => ReadUInt32LittleEndian(Data[0x1F4..]) ^ SecurityKey; set => WriteUInt32LittleEndian(Data[0x1F4..], value ^ SecurityKey); }
public ushort JoyfulJumpInRow { get => ReadUInt16LittleEndian(Data[0x1FC..]); set => WriteUInt16LittleEndian(Data[0x1FC..], Math.Min((ushort)9999, value)); }
public ushort JoyfulJump5InRow { get => ReadUInt16LittleEndian(Data[0x200..]); set => WriteUInt16LittleEndian(Data[0x200..], Math.Min((ushort)9999, value)); }
public ushort JoyfulJumpGamesMaxPlayers { get => ReadUInt16LittleEndian(Data[0x202..]); set => WriteUInt16LittleEndian(Data[0x202..], Math.Min((ushort)9999, value)); }
public uint JoyfulJumpScore { get => ReadUInt16LittleEndian(Data[0x208..]); set => WriteUInt32LittleEndian(Data[0x208..], Math.Min(99990, value)); }
public uint JoyfulBerriesScore { get => ReadUInt16LittleEndian(Data[0x20C..]); set => WriteUInt32LittleEndian(Data[0x20C..], Math.Min(99990, value)); }
public ushort JoyfulBerriesInRow { get => ReadUInt16LittleEndian(Data[0x210..]); set => WriteUInt16LittleEndian(Data[0x210..], Math.Min((ushort)9999, value)); }
public ushort JoyfulBerries5InRow { get => ReadUInt16LittleEndian(Data[0x212..]); set => WriteUInt16LittleEndian(Data[0x212..], Math.Min((ushort)9999, value)); }
// Battle Frontier: 0x64C
public Span<byte> EReaderTrainer => Data.Slice(0xBEC, 0xBC);
public BattleFrontier3 BattleFrontier => new(Data.Slice(0xCDC, BattleFrontier3.SIZE));
public ushort BP { get => ReadUInt16LittleEndian(Data[0xEB8..]); set => WriteUInt16LittleEndian(Data[0xEB8..], Math.Min((ushort)9999, value)); }
public ushort BPEarned { get => ReadUInt16LittleEndian(Data[0xEBA..]); set => WriteUInt16LittleEndian(Data[0xEBA..], value); }
}

View File

@ -1,79 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed record SaveBlock3SmallFRLG(Memory<byte> Raw) : ISaveBlock3SmallExpansion
{
public Span<byte> Data => Raw.Span;
public Span<byte> OriginalTrainerTrash => Data[..8];
public byte Gender { get => Data[8]; set => Data[8] = value; }
public uint ID32 { get => ReadUInt32LittleEndian(Data[0x0A..]); set => WriteUInt32LittleEndian(Data[0x0A..], value); }
public ushort TID16 { get => ReadUInt16LittleEndian(Data[0xA..]); set => WriteUInt16LittleEndian(Data[0xA..], value); }
public ushort SID16 { get => ReadUInt16LittleEndian(Data[0xC..]); set => WriteUInt16LittleEndian(Data[0xC..], value); }
public int PlayedHours { get => ReadUInt16LittleEndian(Data[0xE..]); set => WriteUInt16LittleEndian(Data[0xE..], (ushort)value); }
public int PlayedMinutes { get => Data[0x10]; set => Data[0x10] = (byte)value; }
public int PlayedSeconds { get => Data[0x11]; set => Data[0x11] = (byte)value; }
public byte PlayedFrames { get => Data[0x12]; set => Data[0x12] = value; }
public byte OptionsButtonMode { get => Data[0x13]; set => Data[0x13] = value; }
private uint OptionsConfig { get => ReadUInt32LittleEndian(Data[0x14..]); set => WriteUInt32LittleEndian(Data[0x14..], value); }
public int TextSpeed { get => (int)(OptionsConfig & 0b11); set => OptionsConfig = (uint)((byte)value & 0b11) | (OptionsConfig & ~0b11u); }
public byte OptionWindowFrame { get => (byte)((OptionsConfig >> 2) & 0b11111); set => OptionsConfig = (uint)((value & 0b11111) << 2) | (OptionsConfig & ~(0b11111u << 2)); }
public bool OptionSoundStereo { get => (OptionsConfig & 0b100000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b100000) : (OptionsConfig & ~0b100000u); }
public bool OptionBattleStyle { get => (OptionsConfig & 0b1000000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b1000000) : (OptionsConfig & ~0b1000000u); }
public bool OptionBattleScene { get => (OptionsConfig & 0b10000000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b10000000) : (OptionsConfig & ~0b10000000u); }
public bool OptionIsRegionMapZoom { get => (OptionsConfig & 0b100000000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b100000000) : (OptionsConfig & ~0b100000000u); }
public byte PokedexSort { get => Data[0x18]; set => Data[0x18] = value; }
public byte PokedexMode { get => Data[0x19]; set => Data[0x19] = value; }
public byte PokedexNationalMagicRSE { get => Data[0x1A]; set => Data[0x1A] = value; }
public byte PokedexNationalMagicFRLG { get => Data[0x1B]; set => Data[0x1B] = value; }
public uint DexPIDUnown { get => ReadUInt32LittleEndian(Data[0x1C..]); set => WriteUInt32LittleEndian(Data[0x1C..], value); }
public uint DexPIDSpinda { get => ReadUInt32LittleEndian(Data[0x20..]); set => WriteUInt32LittleEndian(Data[0x20..], value); }
public uint LinkFlags { get => ReadUInt32LittleEndian(Data[0x0A8..]); set => WriteUInt32LittleEndian(Data[0x0A8..], value); }
public bool DummyFlagTrue
{
get => ReadUInt16LittleEndian(Data[0x0AC..]) != 0;
set => WriteUInt16LittleEndian(Data[0x0AC..], value ? (ushort)1 : (ushort)0);
}
public bool DummyFlagFalse
{
get => ReadUInt16LittleEndian(Data[0x0AE..]) == 0;
set => WriteUInt16LittleEndian(Data[0x0AE..], value ? (ushort)0 : (ushort)1);
}
public void FixDummyFlags()
{
DummyFlagTrue = true;
DummyFlagFalse = false;
}
// Battle Tower: 0xB0
public Span<byte> EReaderTrainer => Data.Slice(0x4A0, 0xBC);
// 0xAF0: Berry Crush
public ushort GetBerryPressSpeed([Range(0,3)] int index) => ReadUInt16LittleEndian(Data[(0xAF0 + (index * 2))..]);
public void SetBerryPressSpeed([Range(0, 3)] int index, ushort value) => WriteUInt16LittleEndian(Data[(0xAF0 + (index * 2))..], value);
public uint BerryPowder { get => ReadUInt32LittleEndian(Data[0xAF8..]) ^ SecurityKey; set => WriteUInt32LittleEndian(Data[0xAF8..], value ^ SecurityKey); }
public ushort JoyfulJumpInRow { get => ReadUInt16LittleEndian(Data[0xB00..]); set => WriteUInt16LittleEndian(Data[0xB00..], Math.Min((ushort)9999, value)); }
public ushort JoyfulJump5InRow { get => ReadUInt16LittleEndian(Data[0xB04..]); set => WriteUInt16LittleEndian(Data[0xB04..], Math.Min((ushort)9999, value)); }
public ushort JoyfulJumpGamesMaxPlayers { get => ReadUInt16LittleEndian(Data[0xB06..]); set => WriteUInt16LittleEndian(Data[0xB06..], Math.Min((ushort)9999, value)); }
public uint JoyfulJumpScore { get => ReadUInt16LittleEndian(Data[0xB0C..]); set => WriteUInt32LittleEndian(Data[0xB0C..], Math.Min(99990, value)); }
public uint JoyfulBerriesScore { get => ReadUInt16LittleEndian(Data[0xB10..]); set => WriteUInt32LittleEndian(Data[0xB10..], Math.Min(99990, value)); }
public ushort JoyfulBerriesInRow { get => ReadUInt16LittleEndian(Data[0xB14..]); set => WriteUInt16LittleEndian(Data[0xB14..], Math.Min((ushort)9999, value)); }
public ushort JoyfulBerries5InRow { get => ReadUInt16LittleEndian(Data[0xB16..]); set => WriteUInt16LittleEndian(Data[0xB16..], Math.Min((ushort)9999, value)); }
public uint SecurityKey
{
get => ReadUInt32LittleEndian(Data[0xF20..]);
set => WriteUInt32LittleEndian(Data[0xF20..], value);
}
}

View File

@ -1,45 +0,0 @@
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed record SaveBlock3SmallRS(Memory<byte> Raw) : ISaveBlock3SmallHoenn
{
public Span<byte> Data => Raw.Span;
public Span<byte> OriginalTrainerTrash => Data[..8];
public byte Gender { get => Data[8]; set => Data[8] = value; }
public uint ID32 { get => ReadUInt32LittleEndian(Data[0x0A..]); set => WriteUInt32LittleEndian(Data[0x0A..], value); }
public ushort TID16 { get => ReadUInt16LittleEndian(Data[0xA..]); set => WriteUInt16LittleEndian(Data[0xA..], value); }
public ushort SID16 { get => ReadUInt16LittleEndian(Data[0xC..]); set => WriteUInt16LittleEndian(Data[0xC..], value); }
public int PlayedHours { get => ReadUInt16LittleEndian(Data[0xE..]); set => WriteUInt16LittleEndian(Data[0xE..], (ushort)value); }
public int PlayedMinutes { get => Data[0x10]; set => Data[0x10] = (byte)value; }
public int PlayedSeconds { get => Data[0x11]; set => Data[0x11] = (byte)value; }
public byte PlayedFrames { get => Data[0x12]; set => Data[0x12] = value; }
public byte OptionsButtonMode { get => Data[0x13]; set => Data[0x13] = value; }
private uint OptionsConfig { get => ReadUInt32LittleEndian(Data[0x14..]); set => WriteUInt32LittleEndian(Data[0x14..], value); }
public int TextSpeed { get => (int)(OptionsConfig & 0b11); set => OptionsConfig = (uint)((byte)value & 0b11) | (OptionsConfig & ~0b11u); }
public byte OptionWindowFrame { get => (byte)((OptionsConfig >> 2) & 0b11111); set => OptionsConfig = (uint)((value & 0b11111) << 2) | (OptionsConfig & ~(0b11111u << 2)); }
public bool OptionSoundStereo { get => (OptionsConfig & 0b100000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b100000) : (OptionsConfig & ~0b100000u); }
public bool OptionBattleStyle { get => (OptionsConfig & 0b1000000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b1000000) : (OptionsConfig & ~0b1000000u); }
public bool OptionBattleScene { get => (OptionsConfig & 0b10000000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b10000000) : (OptionsConfig & ~0b10000000u); }
public bool OptionIsRegionMapZoom { get => (OptionsConfig & 0b100000000) != 0; set => OptionsConfig = value ? (OptionsConfig | 0b100000000) : (OptionsConfig & ~0b100000000u); }
public byte PokedexSort { get => Data[0x18]; set => Data[0x18] = value; }
public byte PokedexMode { get => Data[0x19]; set => Data[0x19] = value; }
public byte PokedexNationalMagicRSE { get => Data[0x1A]; set => Data[0x1A] = value; }
public byte PokedexNationalMagicFRLG { get => Data[0x1B]; set => Data[0x1B] = value; }
public uint DexPIDUnown { get => ReadUInt32LittleEndian(Data[0x1C..]); set => WriteUInt32LittleEndian(Data[0x1C..], value); }
public uint DexPIDSpinda { get => ReadUInt32LittleEndian(Data[0x20..]); set => WriteUInt32LittleEndian(Data[0x20..], value); }
private Span<byte> ClockInitialSpan => Data.Slice(0x098, RTC3.Size);
private Span<byte> ClockElapsedSpan => Data.Slice(0x0A0, RTC3.Size);
public RTC3 ClockInitial { get => new(ClockInitialSpan.ToArray()); set => value.Data.CopyTo(ClockInitialSpan); }
public RTC3 ClockElapsed { get => new(ClockElapsedSpan.ToArray()); set => value.Data.CopyTo(ClockElapsedSpan); }
public uint SecurityKey => 0;
// 0xA8: Battle Tower
public Span<byte> EReaderTrainer => Data.Slice(0x498, 0xBC);
}

View File

@ -293,13 +293,13 @@ public override ushort TID16
public override ushort SID16 { get => 0; set { } }
public string RivalName
public string Rival
{
get => GetString(Data.Slice(Offsets.Rival, MaxStringLengthTrainer));
set => SetString(Data.Slice(Offsets.Rival, MaxStringLengthTrainer), value, MaxStringLengthTrainer, StringConverterOption.Clear50);
}
public Span<byte> RivalNameTrash { get => Data.Slice(Offsets.Rival, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data[Offsets.Rival..]); } }
public Span<byte> RivalTrash { get => Data.Slice(Offsets.Rival, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data[Offsets.Rival..]); } }
public byte RivalStarter { get => Data[Offsets.Starter - 2]; set => Data[Offsets.Starter - 2] = value; }
public byte Starter { get => Data[Offsets.Starter]; set => Data[Offsets.Starter] = value; }

View File

@ -325,13 +325,13 @@ public Span<byte> OriginalTrainerTrash
set { if (value.Length == StringLength) value.CopyTo(Data[(Offsets.Trainer1 + 2)..]); }
}
public string RivalName
public string Rival
{
get => GetString(Data.Slice(Offsets.Rival, (Korean ? 2 : 1) * MaxStringLengthTrainer));
set => SetString(Data.Slice(Offsets.Rival, (Korean ? 2 : 1) * MaxStringLengthTrainer), value, 8, StringConverterOption.Clear50);
}
public Span<byte> RivalNameTrash
public Span<byte> RivalTrash
{
get => Data.Slice(Offsets.Rival, StringLength);
set { if (value.Length == StringLength) value.CopyTo(Data[Offsets.Rival..]); }

Some files were not shown because too many files have changed in this diff Show More