mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-03-22 01:55:10 -05:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1891925fe7 |
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) { }
|
||||
|
||||
|
|
|
|||
|
|
@ -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) { }
|
||||
|
|
|
|||
|
|
@ -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) { }
|
||||
|
||||
|
|
|
|||
|
|
@ -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) { }
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public enum StorageSlotType : byte
|
|||
/// Shiny Overworld Cache
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="GameVersion.ZA"/>
|
||||
/// <see cref="GameVersion.ZA"/>
|
||||
/// </remarks>
|
||||
Shiny,
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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 * 已解决 阿露福遗迹菊石兽拼图谜题
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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í
|
||||
|
|
|
|||
|
|
@ -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í
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:はい
|
||||
|
|
|
|||
|
|
@ -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:是
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 キンセツチャンポンをチャレンジした(デイリー)
|
||||
|
|
|
|||
|
|
@ -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 보라짬뽕 먹음 (오늘)
|
||||
|
|
|
|||
|
|
@ -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 紫堇美食广场紫堇什锦面 三打对战(当天)
|
||||
|
|
|
|||
|
|
@ -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 紫堇美食广场紫堇什锦面 三打对战(当天)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
|
|
@ -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); }
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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); }
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue
Block a user