mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-04-27 19:17:19 -05:00
Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a85257da7d | ||
|
|
c2bb4188e5 | ||
|
|
906cae24e8 | ||
|
|
2ff7ad40d9 | ||
|
|
cc7708e9d4 | ||
|
|
3d7a371395 | ||
|
|
8a1c364207 | ||
|
|
0a1e955007 | ||
|
|
e3fd457272 | ||
|
|
08178f70fe | ||
|
|
75e2a7a497 | ||
|
|
516cc25d91 | ||
|
|
4007eb7ca8 | ||
|
|
452c8b5b81 | ||
|
|
ee79ba2f61 | ||
|
|
dfcd86d950 | ||
|
|
c58981e365 | ||
|
|
2f9512e33b | ||
|
|
234f402beb | ||
|
|
021b93b87f | ||
|
|
227b9aaf13 | ||
|
|
2ece772735 | ||
|
|
2cb62f7aa4 | ||
|
|
6b8599b6ed | ||
|
|
b449867e72 | ||
|
|
9c03ef1f23 | ||
|
|
4568392f61 | ||
|
|
2b4a01512e | ||
|
|
13110adfd7 | ||
|
|
2321e764cb | ||
|
|
298a53130c | ||
|
|
d7284ce590 | ||
|
|
301bf1bec0 | ||
|
|
fc80208a06 | ||
|
|
9742ed43da | ||
|
|
0ebf575a03 | ||
|
|
097ff3a870 | ||
|
|
6da88d6232 | ||
|
|
e132a2719a | ||
|
|
5e7fc6c817 | ||
|
|
245873aa8a | ||
|
|
f31503ac7c | ||
|
|
8d24b16fe3 | ||
|
|
d21bc2ff6d | ||
|
|
7c4b15bffa | ||
|
|
02eaca9a0c | ||
|
|
dc2a60f830 | ||
|
|
d09a425e6a | ||
|
|
fcdce737a3 | ||
|
|
d9bdbcae68 | ||
|
|
5f44fb75d4 | ||
|
|
d15526a0be | ||
|
|
5567577a26 | ||
|
|
e41797d0cb | ||
|
|
5b511a8078 | ||
|
|
d8481e711b | ||
|
|
aad2839736 | ||
|
|
49505a4a8c | ||
|
|
ecfd8f6748 | ||
|
|
5bf1e2cf45 | ||
|
|
793525875f | ||
|
|
492aea166e | ||
|
|
83071ca7c2 | ||
|
|
6df330e62f | ||
|
|
66df00d038 | ||
|
|
4784e2de82 | ||
|
|
a43b6a5d32 | ||
|
|
48938c5e14 | ||
|
|
0e097b1fc6 | ||
|
|
56ba92b68b | ||
|
|
3ad376be44 | ||
|
|
ca6fbf024c | ||
|
|
3c1e7bdc6c | ||
|
|
b1dbc6a82b | ||
|
|
94ad477703 | ||
|
|
42496def98 | ||
|
|
8950613422 | ||
|
|
2faa1b10b1 | ||
|
|
ff69f82234 | ||
|
|
3317a8bfda | ||
|
|
94f3937f2f | ||
|
|
a3e0ed29b4 | ||
|
|
d3a4ed6ad3 | ||
|
|
bb363a7a3d | ||
|
|
2f95536b13 | ||
|
|
301a1e7664 | ||
|
|
662c3db7dc | ||
|
|
5b42ff746d | ||
|
|
c7f02bcc20 | ||
|
|
7617f6dfa7 | ||
|
|
8b08f263e5 | ||
|
|
d827cec5a7 | ||
|
|
e5e7cc914c | ||
|
|
ff72af52ad | ||
|
|
d24d227df4 | ||
|
|
5a75fe4b89 | ||
|
|
49d9467d3c | ||
|
|
065d329546 | ||
|
|
93b9481393 | ||
|
|
244b34b8d3 | ||
|
|
3e33f0fc2e | ||
|
|
3e33521796 | ||
|
|
79a08822ea | ||
|
|
85ad6495e6 | ||
|
|
04c2063791 | ||
|
|
dd0d1fc07a | ||
|
|
c64bc65359 | ||
|
|
8587a88723 | ||
|
|
e56226f046 | ||
|
|
6e48856bec | ||
|
|
51a012ff78 | ||
|
|
bd9f64b07e | ||
|
|
b1dd981537 | ||
|
|
553f154657 | ||
|
|
b6eb0745a3 | ||
|
|
f382291de4 | ||
|
|
df39aff5e9 | ||
|
|
20a92f533b | ||
|
|
b93d57cc9a | ||
|
|
2939bfae48 | ||
|
|
0d96d75b7a | ||
|
|
8f0672b8c5 | ||
|
|
9420dcf44d | ||
|
|
bde5729883 | ||
|
|
fa0ac2a9ab | ||
|
|
c037829b29 |
2
.github/README-de.md
vendored
2
.github/README-de.md
vendored
|
|
@ -10,7 +10,7 @@ Die folgenden Dateien werden unterstützt:
|
|||
* Einzelne Pokémon (.pk\*, \*.ck3, \*.xk3, \*.pb7, \*.sk2, \*.bk4, \*.rk4)
|
||||
* Wunderkarten (\*.pgt, \*.pcd, \*.pgf, .wc\*), inklusive Konvertierung zu .pk\*
|
||||
* Import von GO Park Pokémon (\*.gp1) inklusive Konvertierung zu .pb7
|
||||
* Import von Teams aus entschlüsselten 3DS Battle Videos.
|
||||
* Import von Teams aus entschlüsselten 3DS Kampfvideos.
|
||||
* Transfer von einer Generation zur anderen, mit automatischer Umwandlung des Formats.
|
||||
|
||||
Alle Daten werden so angezeigt, dass sie bearbeitet und gespeichert werden können.
|
||||
|
|
|
|||
4
.github/README-es.md
vendored
4
.github/README-es.md
vendored
|
|
@ -10,7 +10,7 @@ Soporta los siguientes archivos:
|
|||
* Archivos de entidades individuales de Pokémon (.pk\*, \*.ck3, \*.xk3, \*.pb7, \*.sk2, \*.bk4, \*.rk4)
|
||||
* Archivos de Regalos Misteriosos (\*.pgt, \*.pcd, \*.pgf, .wc\*) incluyendo conversión a .pk\*
|
||||
* Importar archivos de entidades de GO Park (\*.gp1) incluyendo conversión a .pb7
|
||||
* Importar equipos desde archivos Decrypted 3DS Battle Videos
|
||||
* Importar equipos desde archivos de Vídeos de Combate de 3DS desencriptados.
|
||||
* Pasar de una generación a la siguiente, convirtiendo los archivos en el proceso.
|
||||
|
||||
Los datos son visualizados en una forma que permite modificarlos y guardarlos.
|
||||
|
|
@ -42,7 +42,7 @@ La generación de códigos QR de PKHeX es la de [QRCoder](https://github.com/cod
|
|||
|
||||
La colección de sprites de Pokémons Shiny de PKHeX fue tomada de [pokesprite](https://github.com/msikma/pokesprite), licenciado bajo [la licencia MIT](https://github.com/msikma/pokesprite/blob/master/LICENSE).
|
||||
|
||||
PKHeX's Pokémon Legends: Arceus sprite collection is taken from the [National Pokédex - Icon Dex](https://www.deviantart.com/pikafan2000/art/National-Pokedex-Version-Delta-Icon-Dex-824897934) project and its abundance of collaborators and contributors.
|
||||
La colección de sprites de Leyendas Pokémon: Arceus de PKHeX proviene del proyecto [National Pokédex - Icon Dex](https://www.deviantart.com/pikafan2000/art/National-Pokedex-Version-Delta-Icon-Dex-824897934) y su gran cantidad de colaboradores y contribuyentes.
|
||||
|
||||
### IDE
|
||||
|
||||
|
|
|
|||
2
.github/README-it.md
vendored
2
.github/README-it.md
vendored
|
|
@ -9,7 +9,7 @@ Supporta i seguenti tipi di file:
|
|||
* File di Memory Card GameCube (\*.raw, \*.bin) contenenti File di Salvataggio Pokémon.
|
||||
* File di Entità Pokémon individuali (.pk\*, \*.ck3, \*.xk3, \*.pb7, \*.sk2, \*.bk4, \*.rk4)
|
||||
* File di Dono Segreto (\*.pgt, \*.pcd, \*.pgf, .wc\*) inclusa conversione in .pk\*
|
||||
* Importazione di Entità del Go Park (\*.gp1) inclusa conversione in .pb7
|
||||
* Importazione di Entità del GO Park (\*.gp1) inclusa conversione in .pb7
|
||||
* Importazione di squadre da Video Lotta del 3DS decriptati
|
||||
* Trasferimento da una generazione all'altra, convertendo i formati propriamente.
|
||||
|
||||
|
|
|
|||
4
.github/README-ko.md
vendored
4
.github/README-ko.md
vendored
|
|
@ -10,7 +10,7 @@ PKHeX(포케헥스)
|
|||
* 개별 포켓몬 엔티티 파일 (.pk\*, \*.ck3, \*.xk3, \*.pb7, \*.sk2, \*.bk4, \*.rk4)
|
||||
* 이상한소포 파일(\*.pgt, \*.pcd, \*.pgf, .wc\*)을 .pk로 변환하는 기능 포함
|
||||
* GO 파크 엔티티 가져오기 (\*.gp1) .pb7로 변환 포함
|
||||
* Decrypted 3DS Battle Videos에서 팀 가져오기
|
||||
* 복호화된 3DS 배틀비디오에서 팀 가져오기
|
||||
* 한 세대에서 다른 세대로 이동하면서 그 과정에서 형식이 변환됩니다.
|
||||
|
||||
데이터는 편집하고 저장할 수 있는 보기로 표시됩니다.
|
||||
|
|
@ -42,7 +42,7 @@ PKHeX의 QR 코드 생성 코드는 [the MIT license](https://github.com/codebud
|
|||
|
||||
PKHeX의 이로치(색이다른) 스프라이트 컬렉션은 [the MIT license](https://github.com/msikma/pokesprite/blob/master/LICENSE)에 따라 라이선스가 부여된 [pokesprite](https://github.com/msikma/pokesprite)에서 가져왔습니다.
|
||||
|
||||
PKheX의 Pokémon LEGENDS 아르세우스 스프라이트 컬렉션은 [National Pokédex - Icon Dex](https://www.deviantart.com/pikafan2000/art/National-Pokedex-Version-Delta-Icon-Dex-824897934) 프로젝트와 수많은 협력자 및 기여자의 도움을 받아 만들어졌습니다.
|
||||
PKHeX의 Pokémon LEGENDS 아르세우스 스프라이트 컬렉션은 [National Pokédex - Icon Dex](https://www.deviantart.com/pikafan2000/art/National-Pokedex-Version-Delta-Icon-Dex-824897934) 프로젝트와 수많은 협력자 및 기여자의 도움을 받아 만들어졌습니다.
|
||||
|
||||
### IDE(통합 개발 환경)
|
||||
|
||||
|
|
|
|||
2
.github/README-zh-Hans.md
vendored
2
.github/README-zh-Hans.md
vendored
|
|
@ -9,7 +9,7 @@ PKHeX
|
|||
* GameCube 宝可梦游戏存档包含 GameCube 记忆存档 (\*.raw, \*.bin)
|
||||
* 单个宝可梦实体文件 (.pk\*, \*.ck3, \*.xk3, \*.pb7, \*.sk2, \*.bk4, \*.rk4)
|
||||
* 神秘礼物文件 (\*.pgt, \*.pcd, \*.pgf, .wc\*) 并转换为 .pk\*
|
||||
* 导入 Go Park存档 (\*.gp1) 并转换为 .pb7
|
||||
* 导入 GO Park存档 (\*.gp1) 并转换为 .pb7
|
||||
* 从已破解的 3DS 对战视频中导入队伍
|
||||
* 支持宝可梦在不同世代的间转移,并转换文件格式
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>26.02.27</Version>
|
||||
<Version>26.04.11</Version>
|
||||
<LangVersion>14</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<NeutralLanguage>en</NeutralLanguage>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -70,4 +72,9 @@ public interface IBattleTemplate : ISpeciesForm, IGigantamaxReadOnly, IDynamaxLe
|
|||
/// <see cref="PKM.Moves"/> of the Set entity.
|
||||
/// </summary>
|
||||
ushort[] Moves { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the properties are probably from a Pokémon Champions set.
|
||||
/// </summary>
|
||||
bool IsChampions => Level == 50 && !IVs.ContainsAnyExcept(31) && EffortValues.IsChampions(EVs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 != Nature.Random && Nature != nature)
|
||||
if (Nature.IsFixed && 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 != Nature.Random) // specified in a separate Nature line
|
||||
if (Nature.IsFixed) // 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 != Nature.Random && currentNature != Nature)
|
||||
if (ampNature && currentNature.IsFixed && 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(IReadOnlyList<Type> types, int expectedMax)
|
||||
private static Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[] GetPropertyDictionaries(ReadOnlySpan<Type> types, int expectedMax)
|
||||
{
|
||||
var result = new Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[types.Count];
|
||||
for (int i = 0; i < types.Count; i++)
|
||||
var result = new Dictionary<string, PropertyInfo>.AlternateLookup<ReadOnlySpan<char>>[types.Length];
|
||||
for (int i = 0; i < types.Length; i++)
|
||||
result[i] = GetPropertyDictionary(types[i], ReflectUtil.GetAllPropertyInfoPublic, expectedMax).GetAlternateLookup<ReadOnlySpan<char>>();
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,10 @@ public void SetNickname(string nick)
|
|||
pk.ClearNickname();
|
||||
return;
|
||||
}
|
||||
pk.IsNicknamed = true;
|
||||
|
||||
pk.PrepareNickname();
|
||||
pk.Nickname = nick;
|
||||
pk.IsNicknamed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -137,7 +139,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;
|
||||
|
|
@ -193,6 +195,11 @@ public void ApplySetDetails(IBattleTemplate set)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Champions revises EV behavior to be /8.
|
||||
// If the user is requesting a Champions-like set import, apply EVs that way.
|
||||
if (set.IsChampions)
|
||||
pk.SetEVsChampions(evs);
|
||||
else
|
||||
pk.SetEVs(evs);
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +271,13 @@ public void ApplySetDetails(IBattleTemplate set)
|
|||
pk.RefreshChecksum();
|
||||
}
|
||||
|
||||
private void SetEVsChampions(ReadOnlySpan<int> evs)
|
||||
{
|
||||
Span<int> final = stackalloc int[6];
|
||||
EffortValues.ConvertFromChampions(evs, final);
|
||||
pk.SetEVs(final);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="PKM.HeldItem"/> value depending on the current format and the provided item index & format.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -100,7 +100,13 @@ public class EntitySummary : IFatefulEncounterReadOnly // do NOT seal, allow inh
|
|||
public string Relearn2 => Get(Strings.movelist, Entity.RelearnMove2);
|
||||
public string Relearn3 => Get(Strings.movelist, Entity.RelearnMove3);
|
||||
public string Relearn4 => Get(Strings.movelist, Entity.RelearnMove4);
|
||||
public ushort Checksum => Entity is ISanityChecksum s ? s.Checksum : Checksums.CRC16_CCITT(Entity.Data[Entity.SIZE_STORED..]);
|
||||
public ushort Checksum => Entity switch
|
||||
{
|
||||
ISanityChecksum s => s.Checksum,
|
||||
PK1 gb => gb.GetSingleListChecksum(),
|
||||
PK2 gb => gb.GetSingleListChecksum(),
|
||||
_ => Checksums.CRC16_CCITT(Entity.Data[..Entity.SIZE_STORED]),
|
||||
};
|
||||
public int Friendship => Entity.OriginalTrainerFriendship;
|
||||
public int EggYear => Entity.EggMetDate.GetValueOrDefault().Year;
|
||||
public int EggMonth => Entity.EggMetDate.GetValueOrDefault().Month;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ public static string GetMessage(PKM pk)
|
|||
return GetMessage(pk7);
|
||||
|
||||
var server = GetExploitURLPrefixPKM(pk.Format);
|
||||
var data = pk.EncryptedBoxData;
|
||||
Span<byte> data = stackalloc byte[pk.SIZE_STORED];
|
||||
pk.WriteEncryptedDataStored(data);
|
||||
return GetMessageBase64(data, server);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ public sealed class AdvancedSettings
|
|||
[LocalizedDescription("Folder path that contains dump(s) of block hash-names. If a specific dump file does not exist, only names defined within the program's code will be loaded.")]
|
||||
public string PathBlockKeyList { get; set; } = string.Empty;
|
||||
|
||||
[LocalizedDescription("Hide event variables below this event type value. Removes event values from the GUI that the user doesn't care to view.")]
|
||||
public NamedEventType HideEventTypeBelow { get; set; }
|
||||
|
||||
[LocalizedDescription("Hide event variable names for that contain any of the comma-separated substrings below. Removes event values from the GUI that the user doesn't care to view.")]
|
||||
public string HideEvent8Contains { get; set; } = string.Empty;
|
||||
|
||||
[LocalizedDescription("Minimum distance threshold that mouse movement must exceed before a drag operation is started from a slot.")]
|
||||
public int DragStartThreshold { get; set; } = 0;
|
||||
|
||||
[Browsable(false)]
|
||||
public string[] GetExclusionList8() => Array.ConvertAll(HideEvent8Contains.Split(',', StringSplitOptions.RemoveEmptyEntries), z => z.Trim());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ public sealed class SoundSettings
|
|||
{
|
||||
[LocalizedDescription("Play Sound when loading a new Save File")]
|
||||
public bool PlaySoundSAVLoad { get; set; } = true;
|
||||
|
||||
[LocalizedDescription("Play Sound when popping up Legality Report")]
|
||||
public bool PlaySoundLegalityCheck { get; set; } = true;
|
||||
|
||||
[LocalizedDescription("Play Sound when performing any other action that would be reasonable to sound alert.")]
|
||||
public bool PlaySoundOther { get; set; } = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,12 @@
|
|||
using System;
|
||||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for defining a manipulation of box data.
|
||||
/// </summary>
|
||||
public abstract class BoxManipBase : IBoxManip
|
||||
public abstract record BoxManipBase(BoxManipType Type, Func<SaveFile, bool> Usable) : 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 class BoxManipClear(BoxManipType Type, Func<PKM, bool> criteria, Func<SaveFile, bool> Usable) : BoxManipBase(Type, Usable)
|
||||
public sealed record 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 class BoxManipClearComplex(BoxManipType Type, Func<PKM, SaveFile, bool> criteria, Func<SaveFile, bool> Usable) : BoxManipBase(Type, Usable)
|
||||
public sealed record 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 class BoxManipClearDuplicate<T> : BoxManipBase
|
||||
public sealed record 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 class BoxManipModify(BoxManipType type, Action<PKM> Action, Func<SaveFile, bool> Usable)
|
||||
: BoxManipBase(type, Usable)
|
||||
public sealed record 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 class BoxManipModifyComplex(BoxManipType Type, Action<PKM, SaveFile> Action, Func<SaveFile, bool> Usable)
|
||||
public sealed record 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 class BoxManipSort(BoxManipType Type, Func<IEnumerable<PKM>, IEnumerable<PKM>> Sorter, Func<SaveFile, bool> Usable) : BoxManipBase(Type, Usable)
|
||||
public sealed record 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 class BoxManipSortComplex : BoxManipBase
|
||||
public sealed record 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) { }
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ public sealed class FakeSaveFile : SaveFile
|
|||
protected override void SetChecksums() { }
|
||||
public override GameVersion Version { get => GameVersion.R; set { } }
|
||||
public override Type PKMType => typeof(PK3);
|
||||
protected override PK3 GetPKM(byte[] data) => BlankPKM;
|
||||
protected override byte[] DecryptPKM(byte[] data) => data;
|
||||
protected override PK3 GetPKM(Memory<byte> data) => BlankPKM;
|
||||
protected override void DecryptPKM(Span<byte> data) { }
|
||||
public override PK3 BlankPKM => new();
|
||||
public override EntityContext Context => EntityContext.Gen3;
|
||||
protected override int SIZE_STORED => 0;
|
||||
protected override int SIZE_PARTY => 0;
|
||||
public override int SIZE_STORED => 0;
|
||||
public override int SIZE_PARTY => 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,9 @@ public static int Export(SaveFile sav, string destPath, IFileNamer<PKM> namer, B
|
|||
|
||||
int count = GetSlotCountForBox(boxSlotCount, box, total);
|
||||
int ctr = 0;
|
||||
// Export each slot in the box.
|
||||
// Export each slot in the box with party stats, to be nice to any external analysis.
|
||||
bool isPartyFormat = sav.SIZE_BOXSLOT == sav.SIZE_PARTY;
|
||||
Span<byte> data = stackalloc byte[sav.SIZE_PARTY];
|
||||
for (int slot = 0; slot < count; slot++)
|
||||
{
|
||||
var pk = sav.GetBoxSlotAtIndex(box, slot);
|
||||
|
|
@ -98,7 +100,13 @@ public static int Export(SaveFile sav, string destPath, IFileNamer<PKM> namer, B
|
|||
|
||||
var fileName = GetFileName(pk, settings.FileIndexPrefix, namer, box, slot, boxSlotCount);
|
||||
var fn = Path.Combine(destPath, fileName);
|
||||
File.WriteAllBytes(fn, pk.DecryptedPartyData);
|
||||
|
||||
// Assume that all PKM read for the loop all are the same shape; the if-else will always travel one path.
|
||||
// We don't have to worry about lingering party data from a previous loop iteration.
|
||||
if (!isPartyFormat)
|
||||
pk.ForcePartyData(); // Rather than export all-zero party stats, calculate what they would be.
|
||||
pk.WriteDecryptedDataParty(data);
|
||||
File.WriteAllBytes(fn, data);
|
||||
ctr++;
|
||||
}
|
||||
return ctr;
|
||||
|
|
|
|||
|
|
@ -61,11 +61,11 @@ private static List<SlotInfoMisc> GetExtraSlots2(SAV2 sav)
|
|||
|
||||
private static List<SlotInfoMisc> GetExtraSlots3(SAV3 sav)
|
||||
{
|
||||
if (sav is not SAV3FRLG)
|
||||
if (sav is not SAV3FRLG frlg)
|
||||
return None;
|
||||
return
|
||||
[
|
||||
new(sav.LargeBuffer[0x3C98..], 0) {Type = StorageSlotType.Daycare},
|
||||
new(frlg.LargeBlock.SingleDaycareRoute5, 0) {Type = StorageSlotType.Daycare},
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ private static List<SlotInfoMisc> GetExtraSlots4(SAV4 sav)
|
|||
if (sav.GTS > 0)
|
||||
list.Add(new SlotInfoMisc(sav.GeneralBuffer[sav.GTS..], 0) { Type = StorageSlotType.GTS });
|
||||
if (sav is SAV4HGSS hgss)
|
||||
list.Add(new SlotInfoMisc(hgss.GeneralBuffer[SAV4HGSS.WalkerPair..], 1) {Type = StorageSlotType.Misc});
|
||||
list.Add(new SlotInfoMisc(hgss.GeneralBuffer[SAV4HGSS.WalkerPair..], 1) {Type = StorageSlotType.Pokéwalker});
|
||||
return list;
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ private static List<SlotInfoMisc> GetExtraSlots5(SAV5 sav)
|
|||
var list = new List<SlotInfoMisc>
|
||||
{
|
||||
new(sav.GTS.Upload, 0) {Type = StorageSlotType.GTS},
|
||||
new(sav.GlobalLink.Upload, 0) { Type = StorageSlotType.Misc },
|
||||
new(sav.GlobalLink.Upload, 0) { Type = StorageSlotType.PGL },
|
||||
|
||||
new(sav.BattleBox[0], 0) {Type = StorageSlotType.BattleBox},
|
||||
new(sav.BattleBox[1], 1) {Type = StorageSlotType.BattleBox},
|
||||
|
|
@ -106,7 +106,7 @@ private static List<SlotInfoMisc> GetExtraSlots6XY(SAV6XY sav)
|
|||
[
|
||||
new(sav.GTS.Upload, 0) {Type = StorageSlotType.GTS},
|
||||
new(sav.Fused[0], 0) {Type = StorageSlotType.FusedKyurem},
|
||||
new(sav.SUBE.GiveSlot, 0, Mutable: true) {Type = StorageSlotType.Misc}, // Old Man
|
||||
new(sav.SUBE.GiveSlot, 0, Mutable: true) {Type = StorageSlotType.Scripted}, // Old Man
|
||||
|
||||
new(sav.BattleBox[0], 0) {Type = StorageSlotType.BattleBox},
|
||||
new(sav.BattleBox[1], 1) {Type = StorageSlotType.BattleBox},
|
||||
|
|
@ -123,7 +123,7 @@ private static List<SlotInfoMisc> GetExtraSlots6AO(SAV6AO sav)
|
|||
[
|
||||
new(sav.GTS.Upload, 0) { Type = StorageSlotType.GTS },
|
||||
new(sav.Fused[0], 0) { Type = StorageSlotType.FusedKyurem },
|
||||
new(sav.SUBE.GiveSlot, 0) {Type = StorageSlotType.Misc},
|
||||
new(sav.SUBE.GiveSlot, 0) {Type = StorageSlotType.Scripted},
|
||||
|
||||
new(sav.BattleBox[0], 0) {Type = StorageSlotType.BattleBox},
|
||||
new(sav.BattleBox[1], 1) {Type = StorageSlotType.BattleBox},
|
||||
|
|
@ -150,9 +150,9 @@ private static List<SlotInfoMisc> GetExtraSlots7(SAV7 sav, bool all)
|
|||
]);
|
||||
list.AddRange(
|
||||
[
|
||||
new SlotInfoMisc(uu.BattleAgency[0], 0) {Type = StorageSlotType.Misc},
|
||||
new SlotInfoMisc(uu.BattleAgency[1], 1) {Type = StorageSlotType.Misc},
|
||||
new SlotInfoMisc(uu.BattleAgency[2], 2) {Type = StorageSlotType.Misc},
|
||||
new SlotInfoMisc(uu.BattleAgency[0], 0) {Type = StorageSlotType.BattleAgency},
|
||||
new SlotInfoMisc(uu.BattleAgency[1], 1) {Type = StorageSlotType.BattleAgency},
|
||||
new SlotInfoMisc(uu.BattleAgency[2], 2) {Type = StorageSlotType.BattleAgency},
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -202,15 +202,15 @@ private static List<SlotInfoMisc> GetExtraSlots8b(SAV8BS sav)
|
|||
{
|
||||
return
|
||||
[
|
||||
new(sav.UgSaveData[0], 0, true) { Type = StorageSlotType.Misc, HideLegality = true },
|
||||
new(sav.UgSaveData[1], 1, true) { Type = StorageSlotType.Misc, HideLegality = true },
|
||||
new(sav.UgSaveData[2], 2, true) { Type = StorageSlotType.Misc, HideLegality = true },
|
||||
new(sav.UgSaveData[3], 3, true) { Type = StorageSlotType.Misc, HideLegality = true },
|
||||
new(sav.UgSaveData[4], 4, true) { Type = StorageSlotType.Misc, HideLegality = true },
|
||||
new(sav.UgSaveData[5], 5, true) { Type = StorageSlotType.Misc, HideLegality = true },
|
||||
new(sav.UgSaveData[6], 6, true) { Type = StorageSlotType.Misc, HideLegality = true },
|
||||
new(sav.UgSaveData[7], 7, true) { Type = StorageSlotType.Misc, HideLegality = true },
|
||||
new(sav.UgSaveData[8], 8, true) { Type = StorageSlotType.Misc, HideLegality = true },
|
||||
new(sav.UgSaveData[0], 0, true) { Type = StorageSlotType.Underground, HideLegality = true },
|
||||
new(sav.UgSaveData[1], 1, true) { Type = StorageSlotType.Underground, HideLegality = true },
|
||||
new(sav.UgSaveData[2], 2, true) { Type = StorageSlotType.Underground, HideLegality = true },
|
||||
new(sav.UgSaveData[3], 3, true) { Type = StorageSlotType.Underground, HideLegality = true },
|
||||
new(sav.UgSaveData[4], 4, true) { Type = StorageSlotType.Underground, HideLegality = true },
|
||||
new(sav.UgSaveData[5], 5, true) { Type = StorageSlotType.Underground, HideLegality = true },
|
||||
new(sav.UgSaveData[6], 6, true) { Type = StorageSlotType.Underground, HideLegality = true },
|
||||
new(sav.UgSaveData[7], 7, true) { Type = StorageSlotType.Underground, HideLegality = true },
|
||||
new(sav.UgSaveData[8], 8, true) { Type = StorageSlotType.Underground, HideLegality = true },
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -239,8 +239,8 @@ private static List<SlotInfoMisc> GetExtraSlots9(SAV9SV sav)
|
|||
|
||||
if (sav.Blocks.TryGetBlock(SaveBlockAccessor9SV.KSurpriseTrade, out var surprise))
|
||||
{
|
||||
list.Add(new(surprise.Raw[0x198..], 0) { Type = StorageSlotType.Misc }); // my upload
|
||||
list.Add(new(surprise.Raw[0x02C..], 1) { Type = StorageSlotType.Misc }); // received from others
|
||||
list.Add(new(surprise.Raw[0x198..], 0) { Type = StorageSlotType.SurpriseTrade }); // my upload
|
||||
list.Add(new(surprise.Raw[0x02C..], 1) { Type = StorageSlotType.SurpriseTrade }); // received from others
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
@ -254,7 +254,7 @@ private static List<SlotInfoMisc> GetExtraSlots9a(SAV9ZA sav)
|
|||
{
|
||||
const int size = 0x1F0;
|
||||
var ofs = (i * size) + 8;
|
||||
var entry = shinyCache.Raw.Slice(ofs, PokeCrypto.SIZE_9PARTY);
|
||||
var entry = shinyCache.Raw.Slice(ofs, PokeCrypto.SIZE_8PARTY);
|
||||
if (EntityDetection.IsPresent(entry.Span))
|
||||
list.Add(new(entry, i, true) { Type = StorageSlotType.Shiny, HideLegality = true }); // no OT info
|
||||
else
|
||||
|
|
@ -266,9 +266,9 @@ private static List<SlotInfoMisc> GetExtraSlots9a(SAV9ZA sav)
|
|||
{
|
||||
const int size = 0x1A8;
|
||||
var ofs = (i * size) + 8;
|
||||
var entry = giveAway.Raw.Slice(ofs, PokeCrypto.SIZE_9PARTY);
|
||||
var entry = giveAway.Raw.Slice(ofs, PokeCrypto.SIZE_8PARTY);
|
||||
if (EntityDetection.IsPresent(entry.Span))
|
||||
list.Add(new(entry, i, true, Mutable: true) { Type = StorageSlotType.Misc });
|
||||
list.Add(new(entry, i, true, Mutable: true) { Type = StorageSlotType.Scripted });
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,28 +7,106 @@ public enum StorageSlotType : byte
|
|||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Originated from Box
|
||||
/// </summary>
|
||||
Box,
|
||||
|
||||
/// <summary>
|
||||
/// Originated from Party
|
||||
/// </summary>
|
||||
Party,
|
||||
|
||||
/// <summary> Battle Box </summary>
|
||||
/// <summary>
|
||||
/// Battle Box
|
||||
/// </summary>
|
||||
BattleBox,
|
||||
/// <summary> Daycare </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Daycare
|
||||
/// </summary>
|
||||
Daycare,
|
||||
/// <summary> Global Trade Station (GTS) </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Miscellaneous Origin (usually in-game scripted event recollection)
|
||||
/// </summary>
|
||||
Scripted,
|
||||
|
||||
/// <summary>
|
||||
/// Global Trade Station (GTS)
|
||||
/// </summary>
|
||||
GTS,
|
||||
/// <summary> Shiny Overworld Cache </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Pokémon Global Link (PGL)
|
||||
/// </summary>
|
||||
PGL,
|
||||
|
||||
/// <summary>
|
||||
/// Surprise Trade Upload/Download
|
||||
/// </summary>
|
||||
SurpriseTrade,
|
||||
|
||||
/// <summary>
|
||||
/// Shiny Overworld Cache
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="GameVersion.ZA"/>
|
||||
/// </remarks>
|
||||
Shiny,
|
||||
|
||||
/// <summary> Fused Legendary Storage </summary>
|
||||
/// <summary>
|
||||
/// Underground area wild Pokémon cache
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="GameVersion.BD"/>
|
||||
/// <see cref="GameVersion.SP"/>
|
||||
/// </remarks>
|
||||
Underground,
|
||||
|
||||
/// <summary>
|
||||
/// Fused Legendary Storage
|
||||
/// </summary>
|
||||
Fused,
|
||||
|
||||
/// <summary>
|
||||
/// Sub-tag for <see cref="Species.Kyurem"/> differentiation.
|
||||
/// </summary>
|
||||
FusedKyurem,
|
||||
/// <summary>
|
||||
/// Sub-tag for <see cref="Species.Solgaleo"/> differentiation.
|
||||
/// </summary>
|
||||
FusedNecrozmaS,
|
||||
/// <summary>
|
||||
/// Sub-tag for <see cref="Species.Lunala"/> differentiation.
|
||||
/// </summary>
|
||||
FusedNecrozmaM,
|
||||
/// <summary>
|
||||
/// Sub-tag for <see cref="Species.Calyrex"/> differentiation.
|
||||
/// </summary>
|
||||
FusedCalyrex,
|
||||
|
||||
/// <summary> Miscellaneous </summary>
|
||||
Misc,
|
||||
/// <summary> Poké Pelago (Gen7) </summary>
|
||||
/// <summary>
|
||||
/// Poké Pelago (Gen7)
|
||||
/// </summary>
|
||||
Resort,
|
||||
/// <summary> Ride Legendary Slot (S/V) </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Ride Legendary Slot (S/V)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="GameVersion.SL"/>
|
||||
/// <see cref="GameVersion.VL"/>
|
||||
/// </remarks>
|
||||
Ride,
|
||||
|
||||
/// <summary>
|
||||
/// Battle Agency (Gen7)
|
||||
/// </summary>
|
||||
BattleAgency,
|
||||
|
||||
/// <summary>
|
||||
/// Gen4 HeartGold/SoulSilver pedometer accessory upload
|
||||
/// </summary>
|
||||
Pokéwalker,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ public GameDataSource(GameStrings s)
|
|||
/// <remarks>Most recent games are at the top, loosely following Generation groups.</remarks>
|
||||
private static ReadOnlySpan<byte> OrderedVersionArray =>
|
||||
[
|
||||
53, // Champions
|
||||
52, // 9 Z-A
|
||||
50, 51, // 9 S/V
|
||||
47, // 8 PLA
|
||||
|
|
|
|||
|
|
@ -448,6 +448,10 @@ private void SanitizeMetLocations()
|
|||
Gen6.Met4[35] += " (-)";
|
||||
Gen7.Met4[38] += " (-)";
|
||||
Gen7b.Met4[27] += " (-)";
|
||||
|
||||
// only a duplicate in LATAM Spanish
|
||||
if (Language is SpanishL)
|
||||
Gen5.Met4[47] += " (-)";
|
||||
}
|
||||
|
||||
if (Language is Korean)
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ private EntityContext GetContextInternal()
|
|||
BD or SP => EntityContext.Gen8b,
|
||||
SW or SH => EntityContext.Gen8,
|
||||
SL or VL => EntityContext.Gen9,
|
||||
ZA => EntityContext.Gen9a,
|
||||
ZA or CP => EntityContext.Gen9a,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
|
|
@ -248,7 +248,7 @@ public bool Contains(GameVersion g2)
|
|||
Gen8 => version1 is SW or SH or BD or SP or SWSH or BDSP or PLA,
|
||||
|
||||
SV => version1 is SL or VL,
|
||||
Gen9 => version1 is SL or VL or SV or ZA,
|
||||
Gen9 => version1 is SL or VL or SV or ZA or CP,
|
||||
|
||||
_ => false,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ 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;
|
||||
|
||||
|
|
@ -21,7 +19,7 @@ public sealed class PlayerBag3E : PlayerBag, IPlayerBag3
|
|||
new(0x000, 50, 999, info, PCItems),
|
||||
];
|
||||
|
||||
public PlayerBag3E(SAV3E sav) : this(sav.Large[BaseOffset..], sav.SecurityKey) { }
|
||||
public PlayerBag3E(SAV3E sav) : this(sav.LargeBlock.Inventory, sav.SmallBlock.SecurityKey) { }
|
||||
public PlayerBag3E(ReadOnlySpan<byte> data, uint security)
|
||||
{
|
||||
UpdateSecurityKey(security);
|
||||
|
|
@ -29,7 +27,7 @@ public PlayerBag3E(ReadOnlySpan<byte> data, uint security)
|
|||
}
|
||||
|
||||
public override void CopyTo(SaveFile sav) => CopyTo((SAV3E)sav);
|
||||
public void CopyTo(SAV3E sav) => CopyTo(sav.Large[BaseOffset..]);
|
||||
public void CopyTo(SAV3E sav) => CopyTo(sav.LargeBlock.Inventory);
|
||||
public void CopyTo(Span<byte> data) => Pouches.SaveAll(data);
|
||||
|
||||
public override int GetMaxCount(InventoryType type, int itemIndex)
|
||||
|
|
|
|||
|
|
@ -4,14 +4,13 @@
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public sealed class PlayerBag3FRLG : PlayerBag, IPlayerBag3
|
||||
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));
|
||||
|
||||
public override IReadOnlyList<InventoryPouch3> Pouches { get; } = GetPouches(ItemStorage3FRLG.Instance);
|
||||
public override ItemStorage3FRLG Info => ItemStorage3FRLG.Instance;
|
||||
|
||||
private static InventoryPouch3[] GetPouches(ItemStorage3FRLG info) =>
|
||||
private static InventoryPouch3[] GetPouches(IItemStorage info) =>
|
||||
[
|
||||
new(0x078, 42, 999, info, Items),
|
||||
new(0x120, 30, 001, info, KeyItems),
|
||||
|
|
@ -21,15 +20,15 @@ public sealed class PlayerBag3FRLG : PlayerBag, IPlayerBag3
|
|||
new(0x000, 30, 999, info, PCItems),
|
||||
];
|
||||
|
||||
public PlayerBag3FRLG(SAV3FRLG sav) : this(sav.Large[BaseOffset..], sav.SecurityKey) { }
|
||||
public PlayerBag3FRLG(ReadOnlySpan<byte> data, uint security)
|
||||
public PlayerBag3FRLG(SAV3FRLG sav) : this(sav.LargeBlock.Inventory, sav.SmallBlock.SecurityKey, sav.IsVirtualConsole) { }
|
||||
public PlayerBag3FRLG(ReadOnlySpan<byte> data, uint security, bool vc) : this(vc)
|
||||
{
|
||||
UpdateSecurityKey(security);
|
||||
Pouches.LoadAll(data);
|
||||
}
|
||||
|
||||
public override void CopyTo(SaveFile sav) => CopyTo((SAV3FRLG)sav);
|
||||
public void CopyTo(SAV3FRLG sav) => CopyTo(sav.Large[BaseOffset..]);
|
||||
public void CopyTo(SAV3FRLG sav) => CopyTo(sav.LargeBlock.Inventory);
|
||||
public void CopyTo(Span<byte> data) => Pouches.SaveAll(data);
|
||||
|
||||
public override int GetMaxCount(InventoryType type, int itemIndex)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ 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;
|
||||
|
||||
|
|
@ -21,11 +19,11 @@ public sealed class PlayerBag3RS : PlayerBag
|
|||
new(0x000, 50, 999, info, PCItems),
|
||||
];
|
||||
|
||||
public PlayerBag3RS(SAV3RS sav) : this(sav.Large[BaseOffset..]) { }
|
||||
public PlayerBag3RS(SAV3RS sav) : this(sav.LargeBlock.Inventory) { }
|
||||
public PlayerBag3RS(ReadOnlySpan<byte> data) => Pouches.LoadAll(data);
|
||||
|
||||
public override void CopyTo(SaveFile sav) => CopyTo((SAV3RS)sav);
|
||||
public void CopyTo(SAV3RS sav) => CopyTo(sav.Large[BaseOffset..]);
|
||||
public void CopyTo(SAV3RS sav) => CopyTo(sav.LargeBlock.Inventory);
|
||||
public void CopyTo(Span<byte> data) => Pouches.SaveAll(data);
|
||||
|
||||
public override int GetMaxCount(InventoryType type, int itemIndex)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public sealed class ItemStorage3Colo : IItemStorage
|
|||
540, 541, 542, 546, 547,
|
||||
];
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,17 +13,16 @@ 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, 276, 277, 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, 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,
|
||||
370, 371, 372,
|
||||
// E
|
||||
375, 376,
|
||||
];
|
||||
|
||||
private static readonly ushort[] PCItems = [.. General, .. Berry, .. Balls, .. Machine];
|
||||
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ public sealed class ItemStorage3FRLG : IItemStorage
|
|||
public static ReadOnlySpan<ushort> Key =>
|
||||
[
|
||||
// R/S
|
||||
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,
|
||||
260, 261, 262, 263, 264, 265,
|
||||
// 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,
|
||||
];
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
@ -31,3 +31,58 @@ public sealed class ItemStorage3FRLG : IItemStorage
|
|||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Item storage for <see cref="GameVersion.FR"/> and <see cref="GameVersion.LG"/> on <see cref="GameConsole.NX"/>.
|
||||
/// </summary>
|
||||
public sealed class ItemStorage3FRLG_VC : IItemStorage // TODO VC RSE: delete me and any usages as RSE gives the remainder of items.
|
||||
{
|
||||
public static readonly ItemStorage3FRLG_VC Instance = new();
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => ItemStorage3FRLG.Instance.GetItems(type);
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !IsUnreleasedHeld(itemIndex); // use VC unreleased list
|
||||
|
||||
public static bool IsUnreleasedHeld(int itemIndex) => Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
private static ReadOnlySpan<ushort> Unreleased =>
|
||||
[
|
||||
// Unobtainable
|
||||
005, // Safari
|
||||
|
||||
// TODO RSE VC: Remove these
|
||||
007, 012, // Dive Ball, Premier Ball (Unobtainable without trading from R/S/E)
|
||||
039, 041, 042, 043, // Flutes (Yellow is obtainable via Coins)
|
||||
|
||||
// Unobtainable
|
||||
044, // Berry Juice
|
||||
|
||||
// TODO RSE VC: Remove these
|
||||
046, 047, // Shoal Salt, Shoal Shell
|
||||
048, 049, 050, 051, // Shards
|
||||
081, // Fluffy Tail
|
||||
121, 122, 123, 124, 125, 126, 127, 128, 129, // Mail
|
||||
168, // Liechi Berry (Mirage Island)
|
||||
|
||||
// Event Berries (Unobtainable)
|
||||
169, // Ganlon Berry (Event)
|
||||
170, // Salac Berry (Event)
|
||||
171, // Petaya Berry (Event)
|
||||
172, // Apicot Berry (Event)
|
||||
173, // Lansat Berry (Event)
|
||||
174, // Starf Berry (Event)
|
||||
175, // Enigma Berry (Event)
|
||||
|
||||
// TODO RSE VC: Remove these
|
||||
179, // BrightPowder
|
||||
180, // White Herb
|
||||
185, // Mental Herb
|
||||
186, // Choice Band
|
||||
191, // Soul Dew
|
||||
192, // DeepSeaTooth
|
||||
193, // DeepSeaScale
|
||||
198, // Scope Lens
|
||||
202, // Light Ball
|
||||
219, // Shell Bell
|
||||
254, 255, 256, 257, 258, 259, // Scarves
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,13 +54,13 @@ public sealed class ItemStorage3RS : IItemStorage
|
|||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
];
|
||||
|
||||
internal static ReadOnlySpan<ushort> Unreleased => [005]; // Safari Ball
|
||||
internal static ReadOnlySpan<ushort> Unreleased => [005, 044]; // Safari Ball, Berry Juice
|
||||
|
||||
public static ushort[] GetAllHeld() => [..General, ..Balls, ..Berry, ..MachineOnlyTM];
|
||||
|
||||
private static readonly ushort[] PCItems = [..General, ..Key, .. Berry, ..Balls, ..Machine];
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public sealed class ItemStorage3XD : IItemStorage
|
|||
590, 591, 592, 593,
|
||||
];
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ public sealed class ItemStorage4DP : ItemStorage4, IItemStorage
|
|||
|
||||
public static ushort[] GetAllHeld() => [..GeneralDP, ..Mail, ..Medicine, ..Berry, ..BallsDPPt, ..Battle, ..Machine[..^8]];
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public sealed class ItemStorage4HGSS : ItemStorage4, IItemStorage
|
|||
492, 493, 494, 495, 496, 497, 498, 499, 500, // Apricorn Balls
|
||||
];
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public sealed class ItemStorage4Pt : ItemStorage4, IItemStorage
|
|||
|
||||
public static ushort[] GetAllHeld() => [..GeneralPt, ..Mail, ..Medicine, ..Berry, ..BallsDPPt, ..Battle, ..Machine[..^8]];
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public sealed class ItemStorage5B2W2 : ItemStorage5, IItemStorage
|
|||
616, 617, 621, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638,
|
||||
];
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public sealed class ItemStorage5BW : ItemStorage5, IItemStorage
|
|||
616, 617, 621, 623, 624, 625, 626,
|
||||
];
|
||||
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => true;
|
||||
public bool IsLegal(InventoryType type, int itemIndex, int itemCount) => !Unreleased.Contains((ushort)itemIndex);
|
||||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -168,7 +168,9 @@ public static InventoryType GetInventoryPouch(ushort itemIndex)
|
|||
}
|
||||
|
||||
public static bool IsMegaStone(ushort item) => MegaStones.Contains(item);
|
||||
public static bool IsUniqueHeldItem(ushort item) => IsMegaStone(item) || item is (0534 or 0535); // Primal Orbs
|
||||
public static bool IsUniqueHeldItem(ushort item) => IsMegaStone(item) || IsOrb(item);
|
||||
public static bool IsOrb(ushort item) => item is (0534 or 0535); // Primal Orbs
|
||||
|
||||
public static ushort[] GetAllUniqueHeldItems() => [..MegaStones, 0534, 0535];
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,20 @@ private static void AnalyzeInventory(BulkAnalysis input, SAV9ZA za)
|
|||
continue;
|
||||
|
||||
var item = items.GetItem(stone);
|
||||
if (ItemStorage9ZA.IsOrb(stone))
|
||||
{
|
||||
// Handled via Other items (give, unique), not Mega Stones (loan).
|
||||
if (item.IsNew) // Not acquired/given by the save file, thus not able to be held.
|
||||
input.AddLine(slot, Identifier, BulkCheckResult.NoIndex, BulkHeldItemInventoryNotAcquired_0, stone);
|
||||
else if (seenStones.TryGetValue(stone, out var otherIndex)) // Already given to another slot.
|
||||
input.AddLine(slot, input.AllData[otherIndex], Identifier, i, index2: otherIndex, BulkHeldItemInventoryMultipleSlots_0, stone);
|
||||
else // First time seeing this item, all good.
|
||||
seenStones[stone] = i;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mega Stone
|
||||
if (item.Count == 0) // Not acquired by the save file, thus not able to be held.
|
||||
input.AddLine(slot, Identifier, BulkCheckResult.NoIndex, BulkHeldItemInventoryNotAcquired_0, stone);
|
||||
else if (!item.IsHeld) // Not marked as held, so it's still "in the bag" (not given).
|
||||
|
|
|
|||
|
|
@ -95,15 +95,26 @@ internal static class Encounters2
|
|||
new(202, 15, C) { Location = 016 }, // Wobbuffet @ Goldenrod City (Game Corner)
|
||||
];
|
||||
|
||||
private static IndividualValueSet AllZero => new(00, 00, 00, 00, 00, 00);
|
||||
private static IndividualValueSet Shiny2 => new(00, 02, 10, 10, 10, 10);
|
||||
|
||||
public static readonly EncounterStatic2[] StaticOddEggC =
|
||||
[
|
||||
new(172, 05, C) { IsEgg = true, Moves = new((int)Move.ThunderShock,(int)Move.Charm, (int)Move.DizzyPunch)}, // Pichu
|
||||
new(173, 05, C) { IsEgg = true, Moves = new((int)Move.Pound, (int)Move.Charm, (int)Move.DizzyPunch)}, // Cleffa
|
||||
new(174, 05, C) { IsEgg = true, Moves = new((int)Move.Sing, (int)Move.Charm, (int)Move.DizzyPunch)}, // Igglybuff
|
||||
new(236, 05, C) { IsEgg = true, Moves = new((int)Move.Tackle, (int)Move.DizzyPunch)}, // Tyrogue
|
||||
new(238, 05, C) { IsEgg = true, Moves = new((int)Move.Pound, (int)Move.Lick, (int)Move.DizzyPunch)}, // Smoochum
|
||||
new(239, 05, C) { IsEgg = true, Moves = new((int)Move.QuickAttack, (int)Move.Leer, (int)Move.DizzyPunch)}, // Elekid
|
||||
new(240, 05, C) { IsEgg = true, Moves = new((int)Move.Ember, (int)Move.DizzyPunch)}, // Magby
|
||||
new(172, 05, C) { IsEgg = true, Gender = 1, IVs = AllZero, Shiny = Shiny.Never, Moves = new((int)Move.ThunderShock,(int)Move.Charm, (int)Move.DizzyPunch)}, // Pichu
|
||||
new(173, 05, C) { IsEgg = true, Gender = 1, IVs = AllZero, Shiny = Shiny.Never, Moves = new((int)Move.Pound, (int)Move.Charm, (int)Move.DizzyPunch)}, // Cleffa
|
||||
new(174, 05, C) { IsEgg = true, Gender = 1, IVs = AllZero, Shiny = Shiny.Never, Moves = new((int)Move.Sing, (int)Move.Charm, (int)Move.DizzyPunch)}, // Igglybuff
|
||||
new(236, 05, C) { IsEgg = true, Gender = 0, IVs = AllZero, Shiny = Shiny.Never, Moves = new((int)Move.Tackle, (int)Move.DizzyPunch)}, // Tyrogue
|
||||
new(238, 05, C) { IsEgg = true, Gender = 1, IVs = AllZero, Shiny = Shiny.Never, Moves = new((int)Move.Pound, (int)Move.Lick, (int)Move.DizzyPunch)}, // Smoochum
|
||||
new(239, 05, C) { IsEgg = true, Gender = 1, IVs = AllZero, Shiny = Shiny.Never, Moves = new((int)Move.QuickAttack, (int)Move.Leer, (int)Move.DizzyPunch)}, // Elekid
|
||||
new(240, 05, C) { IsEgg = true, Gender = 1, IVs = AllZero, Shiny = Shiny.Never, Moves = new((int)Move.Ember, (int)Move.DizzyPunch)}, // Magby
|
||||
|
||||
new(172, 05, C) { IsEgg = true, Gender = 1, IVs = Shiny2, Shiny = Shiny.Always, Moves = new((int)Move.ThunderShock,(int)Move.Charm, (int)Move.DizzyPunch)}, // Shiny Pichu
|
||||
new(173, 05, C) { IsEgg = true, Gender = 1, IVs = Shiny2, Shiny = Shiny.Always, Moves = new((int)Move.Pound, (int)Move.Charm, (int)Move.DizzyPunch)}, // Shiny Cleffa
|
||||
new(174, 05, C) { IsEgg = true, Gender = 1, IVs = Shiny2, Shiny = Shiny.Always, Moves = new((int)Move.Sing, (int)Move.Charm, (int)Move.DizzyPunch)}, // Shiny Igglybuff
|
||||
new(236, 05, C) { IsEgg = true, Gender = 0, IVs = Shiny2, Shiny = Shiny.Always, Moves = new((int)Move.Tackle, (int)Move.DizzyPunch)}, // Shiny Tyrogue
|
||||
new(238, 05, C) { IsEgg = true, Gender = 1, IVs = Shiny2, Shiny = Shiny.Always, Moves = new((int)Move.Pound, (int)Move.Lick, (int)Move.DizzyPunch)}, // Shiny Smoochum
|
||||
new(239, 05, C) { IsEgg = true, Gender = 1, IVs = Shiny2, Shiny = Shiny.Always, Moves = new((int)Move.QuickAttack, (int)Move.Leer, (int)Move.DizzyPunch)}, // Shiny Elekid
|
||||
new(240, 05, C) { IsEgg = true, Gender = 1, IVs = Shiny2, Shiny = Shiny.Always, Moves = new((int)Move.Ember, (int)Move.DizzyPunch)}, // Shiny Magby
|
||||
];
|
||||
|
||||
internal static readonly EncounterStatic2 CelebiVC = new(251, 30, C) { Location = 014 }; // Celebi @ Ilex Forest (VC)
|
||||
|
|
@ -121,7 +132,7 @@ internal static class Encounters2
|
|||
new(TradeNames, 7, 178, 15, 15616) { Gender = 0, IVs = new(08, 09, 06, 08, 06, 06) }, // Xatu @ Pewter City for Haunter [wild]
|
||||
new(TradeNames, 8, 082, 05, 50082) { Gender = 2, IVs = new(08, 09, 06, 06, 06, 06) }, // Magneton @ Power Plant for Dugtrio [traded for Lickitung]
|
||||
|
||||
new(TradeNames, 9, 021, 10, 01001), // Spearow @ Goldenrod City for free
|
||||
new(TradeNames, 10, 213, 15, 00518), // Shuckle @ Cianwood City for free
|
||||
new(TradeNames, 9, 021, 10, 01001) { Shiny = Shiny.Random }, // Spearow @ Goldenrod City for free
|
||||
new(TradeNames, 10, 213, 15, 00518) { Shiny = Shiny.Random }, // Shuckle @ Cianwood City for free
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,17 +77,12 @@ private static EncounterArea3[] GetRegular([ConstantExpected] string resource, [
|
|||
public static readonly EncounterStatic3[] StaticLG =
|
||||
[
|
||||
// Celadon City Game Corner
|
||||
new(063, 09, FR) { FixedBall = Ball.Poke, Location = 94 }, // Abra
|
||||
new(035, 08, FR) { FixedBall = Ball.Poke, Location = 94 }, // Clefairy
|
||||
new(123, 25, FR) { FixedBall = Ball.Poke, Location = 94 }, // Scyther
|
||||
new(147, 18, FR) { FixedBall = Ball.Poke, Location = 94 }, // Dratini
|
||||
new(137, 26, FR) { FixedBall = Ball.Poke, Location = 94 }, // Porygon
|
||||
|
||||
new(063, 07, LG) { FixedBall = Ball.Poke, Location = 94 }, // Abra
|
||||
new(035, 12, LG) { FixedBall = Ball.Poke, Location = 94 }, // Clefairy
|
||||
new(127, 18, LG) { FixedBall = Ball.Poke, Location = 94 }, // Pinsir
|
||||
new(147, 24, LG) { FixedBall = Ball.Poke, Location = 94 }, // Dratini
|
||||
new(137, 18, LG) { FixedBall = Ball.Poke, Location = 94 }, // Porygon
|
||||
|
||||
new(386, 30, LG) { Location = 187, FatefulEncounter = true, Form = 2 }, // Deoxys @ Birth Island
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ private static EncounterArea3[] GetSwarm([ConstantExpected] string resource, [Le
|
|||
// Stationary
|
||||
new(352, 30, RSE) { Location = 034 }, // Kecleon @ Route 119
|
||||
new(352, 30, RSE) { Location = 035 }, // Kecleon @ Route 120
|
||||
new(100, 25, RSE) { Location = 062 }, // Voltorb @ New Mauville
|
||||
|
||||
// Stationary Lengendary
|
||||
new(377, 40, RSE) { Location = 082 }, // Regirock @ Desert Ruins
|
||||
|
|
|
|||
|
|
@ -255,5 +255,9 @@ public static class EncounterServerDate
|
|||
{0102, new(2025, 10, 23, 2026, 02, 01, +2)}, // Slowpoke PokéCenter Gift
|
||||
{0101, new(2025, 10, 31, 2027, 02, 01)}, // PokéCenter Audino Birthday Gift
|
||||
{1607, new(2025, 12, 09, 2026, 01, 20)}, // Alpha Charizard
|
||||
|
||||
{9031, new(2026, 04, 02)}, // Alpha Chikorita
|
||||
{9032, new(2026, 04, 02)}, // Alpha Tepig
|
||||
{9033, new(2026, 04, 02)}, // Alpha Totodile
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 != Nature.Random || Mutations.IsComplexNature();
|
||||
public bool IsSpecifiedNature() => Nature.IsFixed || Mutations.IsComplexNature();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a level range is specified in the criteria.
|
||||
|
|
@ -126,6 +126,12 @@ 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>
|
||||
|
|
@ -183,6 +189,20 @@ 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>
|
||||
|
|
@ -191,7 +211,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);
|
||||
|
|
@ -300,7 +320,7 @@ public Nature GetNature(Nature encValue)
|
|||
/// </summary>
|
||||
public Nature GetNature()
|
||||
{
|
||||
if (Nature != Nature.Random)
|
||||
if (Nature.IsFixed)
|
||||
return Nature;
|
||||
var result = (Nature)Util.Rand.Next(25);
|
||||
if (Mutations.HasFlag(AllowOnlyNeutralNature))
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ public static class EncounterGenerator
|
|||
9 => version switch
|
||||
{
|
||||
GameVersion.ZA => EncounterGenerator9a.Instance,
|
||||
_ => EncounterGenerator9.Instance,
|
||||
GameVersion.SL or GameVersion.VL => EncounterGenerator9.Instance,
|
||||
_ => EncounterGeneratorDummy.Instance, // Champions
|
||||
},
|
||||
_ => EncounterGeneratorDummy.Instance,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ public enum PogoType : byte
|
|||
|
||||
// Pokémon captured in the wild.
|
||||
Wild,
|
||||
WildLevel20,
|
||||
WildLevel25,
|
||||
|
||||
// Pokémon hatched from Eggs.
|
||||
Egg,
|
||||
|
|
@ -137,6 +139,8 @@ public static class PogoTypeExtensions
|
|||
public byte LevelMin => encounterType switch
|
||||
{
|
||||
Wild => 1,
|
||||
WildLevel20 => 20,
|
||||
WildLevel25 => 25,
|
||||
Egg => 1,
|
||||
Egg12km => 8,
|
||||
Raid => 20,
|
||||
|
|
@ -204,6 +208,8 @@ public static class PogoTypeExtensions
|
|||
public int MinimumIV => encounterType switch
|
||||
{
|
||||
Wild => 0,
|
||||
WildLevel20 => 0,
|
||||
WildLevel25 => 0,
|
||||
RaidMythical => 10,
|
||||
RaidShadowMythical => 8,
|
||||
RaidShadowMythicalGOWA => 8,
|
||||
|
|
@ -324,6 +330,6 @@ public bool IsBallValid(Ball ball)
|
|||
_ => Ball.None, // Poké, Great, Ultra
|
||||
};
|
||||
|
||||
public bool IsSpecialResearch => encounterType is >= SpecialMythical and < TimedMythical;
|
||||
public bool IsSpecialResearch => encounterType is SpecialResearch or >= SpecialMythical and < TimedMythical;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,27 +48,25 @@ public EncounterTrade1(ReadOnlySpan<string[]> names, byte index, ushort species,
|
|||
LevelMinGSC = levelMinGSC;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When transferred to Gen7+ via Bank, the nickname for a Japanese Dugtrio in Hiragana changes from "ぐリお" to "ぐりお".
|
||||
/// </summary>
|
||||
public const string HiraganaDugtrio7 = "ぐりお";
|
||||
|
||||
private bool IsNicknameValid(PKM pk, ReadOnlySpan<char> nick)
|
||||
{
|
||||
if (pk.Format <= 2)
|
||||
return IsNicknameAnyMatch(nick);
|
||||
|
||||
// Converted string 1/2->7 to language specific value
|
||||
// Nicknames can be from any of the languages it can trade between.
|
||||
int lang = pk.Language;
|
||||
if (lang == 1)
|
||||
{
|
||||
// Special consideration for Hiragana strings that are transferred
|
||||
if (Version == GameVersion.YW && Species == (int)Core.Species.Dugtrio)
|
||||
return nick is "ぐりお";
|
||||
return nick.SequenceEqual(Nicknames.Span[(int)LanguageID.Japanese]);
|
||||
}
|
||||
if (!pk.Japanese)
|
||||
return DetectLanguage(nick, Nicknames.Span, 2) >= 2;
|
||||
|
||||
return GetNicknameIndex(nick) >= 2;
|
||||
// Converted Japanese strings 1/2->7 can mutate from an exact match.
|
||||
// Special consideration for Hiragana strings that are transferred: only Dugtrio's nickname changes when transferred to Gen7+.
|
||||
if (pk.Format > 2 && Version == GameVersion.YW && Species == (int)Core.Species.Dugtrio)
|
||||
return nick is HiraganaDugtrio7;
|
||||
// Otherwise, must match the Japanese nickname exactly.
|
||||
return Nicknames.Span[(int)LanguageID.Japanese].SequenceEqual(nick);
|
||||
}
|
||||
|
||||
private bool IsNicknameAnyMatch(ReadOnlySpan<char> current) => GetNicknameIndex(current) >= 0;
|
||||
|
||||
private static bool IsTrainerNameValid(PKM pk)
|
||||
{
|
||||
if (pk.Format <= 2)
|
||||
|
|
@ -83,12 +81,12 @@ private static bool IsTrainerNameValid(PKM pk)
|
|||
return trainer.SequenceEqual(expect);
|
||||
}
|
||||
|
||||
private int GetNicknameIndex(ReadOnlySpan<char> nickname) => GetIndex(nickname, Nicknames.Span);
|
||||
|
||||
private static int GetIndex(ReadOnlySpan<char> name, ReadOnlySpan<string> arr)
|
||||
private static int DetectLanguage(ReadOnlySpan<char> name, ReadOnlySpan<string> arr, int start = 1)
|
||||
{
|
||||
for (int i = 0; i < arr.Length; i++)
|
||||
for (int i = start; i < arr.Length; i++)
|
||||
{
|
||||
if (i == (int)LanguageID.UNUSED_6)
|
||||
continue;
|
||||
if (name.SequenceEqual(arr[i]))
|
||||
return i;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ public sealed record EncounterTrade2 : IEncounterable, IEncounterMatch, IEncount
|
|||
public bool IsEgg => false;
|
||||
public Ball FixedBall => Ball.Poke;
|
||||
public AbilityPermission Ability => AbilityPermission.OnlyHidden;
|
||||
public Shiny Shiny => Shiny.Random;
|
||||
public bool IsShiny => false;
|
||||
public ushort EggLocation => 0;
|
||||
public bool IsFixedTrainer => true;
|
||||
|
|
@ -33,6 +32,7 @@ public sealed record EncounterTrade2 : IEncounterable, IEncounterMatch, IEncount
|
|||
private readonly ReadOnlyMemory<string> TrainerNames;
|
||||
private readonly ReadOnlyMemory<string> Nicknames;
|
||||
|
||||
public Shiny Shiny { get; init; } = Shiny.Never;
|
||||
public byte Gender { get; init; }
|
||||
public byte OTGender { get; init; }
|
||||
public IndividualValueSet IVs { get; init; }
|
||||
|
|
@ -168,8 +168,8 @@ private int DetectLanguage(PKM pk, ReadOnlySpan<char> trainer, ReadOnlySpan<char
|
|||
return -1;
|
||||
return (int)LanguageID.Korean;
|
||||
}
|
||||
|
||||
for (int i = 2; i < TrainerNames.Length; i++)
|
||||
// Skip languages that are not-transferable to International games.
|
||||
for (int i = 2; i < (int)LanguageID.Korean; i++)
|
||||
{
|
||||
if (i == (int)LanguageID.UNUSED_6)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -58,12 +58,16 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
|
||||
// Force Hatch
|
||||
Language = language,
|
||||
OriginalTrainerName = tr.OT,
|
||||
Nickname = SpeciesName.GetSpeciesNameGeneration(Species, language, Generation),
|
||||
OriginalTrainerFriendship = 120,
|
||||
MetLevel = 0,
|
||||
MetLocation = Location,
|
||||
};
|
||||
// Copy from SaveFile's OT name. Trash bytes here should be pure, but our OT name might not always source from a PK3/SAV3.
|
||||
// Condition the buffer as if it came from a correct SAV3 named after the OT.
|
||||
var ot = pk.OriginalTrainerTrash;
|
||||
ot[..(language == 1 ? 6 : 7)].Fill(0xFF);
|
||||
pk.OriginalTrainerName = EncounterUtil.GetTrainerName(tr, language);
|
||||
|
||||
SetEncounterMoves(pk);
|
||||
|
||||
|
|
@ -75,14 +79,14 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
// Get a random PID that matches gender/nature/ability criteria
|
||||
var pi = PersonalTable.E[Species];
|
||||
var gr = pi.Gender;
|
||||
var pid = GetRandomPID(criteria, gr);
|
||||
var pid = GetRandomPID(criteria, gr, tr.ID32);
|
||||
pk.PID = pid;
|
||||
pk.RefreshAbility((int)(pid % 2));
|
||||
|
||||
return pk;
|
||||
}
|
||||
|
||||
private uint GetRandomPID(in EncounterCriteria criteria, byte gr)
|
||||
private uint GetRandomPID(in EncounterCriteria criteria, byte gr, uint id32)
|
||||
{
|
||||
var seed = Util.Rand32();
|
||||
while (true)
|
||||
|
|
@ -105,6 +109,10 @@ private uint GetRandomPID(in EncounterCriteria criteria, byte gr)
|
|||
if (!Daycare3.IsValidProcPID(pid, Version))
|
||||
continue; // 0-value PID is invalid
|
||||
|
||||
var shiny = ShinyUtil.GetIsShiny3(id32, pid);
|
||||
if (criteria.Shiny.IsShiny() != shiny)
|
||||
continue;
|
||||
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,11 +64,15 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
Ball = (byte)GetRequiredBall(Ball.Poke),
|
||||
|
||||
Language = language,
|
||||
OriginalTrainerName = tr.OT,
|
||||
OriginalTrainerGender = tr.Gender,
|
||||
ID32 = tr.ID32,
|
||||
Nickname = SpeciesName.GetSpeciesNameGeneration(Species, language, Generation),
|
||||
};
|
||||
// Copy from SaveFile's OT name. Trash bytes here should be pure, but our OT name might not always source from a PK3/SAV3.
|
||||
// Condition the buffer as if it came from a correct SAV3 named after the OT.
|
||||
var ot = pk.OriginalTrainerTrash;
|
||||
ot[..(language == 1 ? 6 : 7)].Fill(0xFF);
|
||||
pk.OriginalTrainerName = EncounterUtil.GetTrainerName(tr, language);
|
||||
|
||||
SetPINGA(pk, criteria, pi);
|
||||
SetEncounterMoves(pk);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public sealed record EncounterStatic3(ushort Species, byte Level, GameVersion Ve
|
|||
|
||||
public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
||||
{
|
||||
int lang = GetTemplateLanguage(tr);
|
||||
int language = GetTemplateLanguage(tr);
|
||||
var version = this.GetCompatibleVersion(tr.Version);
|
||||
var pi = PersonalTable.E[Species];
|
||||
var pk = new PK3
|
||||
|
|
@ -56,12 +56,16 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
Ball = (byte)(FixedBall != Ball.None ? FixedBall : Ball.Poke),
|
||||
FatefulEncounter = FatefulEncounter,
|
||||
|
||||
Language = lang,
|
||||
OriginalTrainerName = EncounterUtil.GetTrainerName(tr, lang),
|
||||
Language = language,
|
||||
OriginalTrainerGender = tr.Gender,
|
||||
ID32 = tr.ID32,
|
||||
Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation),
|
||||
Nickname = SpeciesName.GetSpeciesNameGeneration(Species, language, Generation),
|
||||
};
|
||||
// Copy from SaveFile's OT name. Trash bytes here should be pure, but our OT name might not always source from a PK3/SAV3.
|
||||
// Condition the buffer as if it came from a correct SAV3 named after the OT.
|
||||
var ot = pk.OriginalTrainerTrash;
|
||||
ot[..(language == 1 ? 6 : 7)].Fill(0xFF);
|
||||
pk.OriginalTrainerName = EncounterUtil.GetTrainerName(tr, language);
|
||||
|
||||
if (IsEgg)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
// Get a random PID that matches gender/nature/ability criteria
|
||||
var pi = PersonalTable.HGSS[Species];
|
||||
var gr = pi.Gender;
|
||||
var pid = GetRandomPID(criteria, gr, out var gender);
|
||||
var pid = GetRandomPID(criteria, gr, tr.ID32, out var gender);
|
||||
pk.PID = pid;
|
||||
pk.Gender = gender;
|
||||
pk.RefreshAbility((int)(pid & 1));
|
||||
|
|
@ -92,7 +92,7 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
return pk;
|
||||
}
|
||||
|
||||
private uint GetRandomPID(in EncounterCriteria criteria, byte gr, out byte gender)
|
||||
private uint GetRandomPID(in EncounterCriteria criteria, byte gr, uint id32, out byte gender)
|
||||
{
|
||||
var seed = Util.Rand32();
|
||||
while (true)
|
||||
|
|
@ -115,6 +115,10 @@ private uint GetRandomPID(in EncounterCriteria criteria, byte gr, out byte gende
|
|||
// PID is rolled forward upon picking up the egg.
|
||||
// Not worth skipping 0-value PIDs. Too rare to be worth trying again, since it can be a valid PID.
|
||||
|
||||
var shiny = ShinyUtil.GetIsShiny3(id32, pid);
|
||||
if (criteria.Shiny.IsShiny() != shiny)
|
||||
continue;
|
||||
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
var pi = PersonalTable.B2W2[Species];
|
||||
var gr = pi.Gender;
|
||||
var ability = criteria.GetAbilityFromNumber(Ability);
|
||||
var pid = GetRandomPID(criteria, gr, out var gender);
|
||||
var pid = GetRandomPID(criteria, gr, tr.ID32, out var gender);
|
||||
pid = (pid & 0xFFFEFFFFu) | (uint)(ability & 1) << 16; // 0x00000000 or 0x00010000
|
||||
pk.PID = pid;
|
||||
pk.Gender = gender;
|
||||
|
|
@ -81,7 +81,7 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
return pk;
|
||||
}
|
||||
|
||||
private static uint GetRandomPID(in EncounterCriteria criteria, byte gr, out byte gender)
|
||||
private static uint GetRandomPID(in EncounterCriteria criteria, byte gr, uint id32, out byte gender)
|
||||
{
|
||||
var seed = Util.Rand32();
|
||||
while (true)
|
||||
|
|
@ -91,6 +91,9 @@ private static uint GetRandomPID(in EncounterCriteria criteria, byte gr, out byt
|
|||
gender = EntityGender.GetFromPIDAndRatio(pid, gr);
|
||||
if (criteria.IsSpecifiedGender() && !criteria.IsSatisfiedGender(gender))
|
||||
continue;
|
||||
var shiny = ShinyUtil.GetIsShiny3(id32, pid);
|
||||
if (criteria.Shiny.IsShiny() != shiny)
|
||||
continue;
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ private bool IsMatchNatureGenderShiny(PKM pk)
|
|||
return false;
|
||||
if (Gender != FixedGenderUtil.GenderRandom && Gender != pk.Gender)
|
||||
return false;
|
||||
if (Nature != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && 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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && 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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && 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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && 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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && pk.Nature != Nature)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@ public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
|||
pk.SetMoves(Moves);
|
||||
else
|
||||
EncounterUtil.SetEncounterMoves(pk, version, Level);
|
||||
if (Relearn.HasMoves)
|
||||
pk.SetRelearnMoves(Relearn);
|
||||
|
||||
pk.ResetPartyStats();
|
||||
|
||||
return pk;
|
||||
|
|
|
|||
|
|
@ -122,8 +122,6 @@ 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,6 +57,10 @@ 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);
|
||||
|
|
@ -64,23 +68,22 @@ protected override void SetPINGA(PK8 pk, in EncounterCriteria criteria, Personal
|
|||
const int max = 100_000;
|
||||
do
|
||||
{
|
||||
if (TryApply(pk, seed = rand.Next(), iv, param, criteria))
|
||||
if (TryApply(pk, seed = rand.Next(), iv, param, iterCriteria))
|
||||
break;
|
||||
} while (++ctr < max);
|
||||
|
||||
if (ctr == max) // fail
|
||||
{
|
||||
if (!TryApply(pk, seed = rand.Next(), iv, param, criteria.WithoutIVs()))
|
||||
iterCriteria = iterCriteria.WithoutIVs();
|
||||
if (!TryApply(pk, seed = rand.Next(), iv, param, iterCriteria))
|
||||
{
|
||||
var tmp = EncounterCriteria.Unrestricted with { Shiny = ShinyMethod };
|
||||
while (!TryApply(pk, seed = rand.Next(), iv, param, tmp)) { }
|
||||
iterCriteria = EncounterCriteria.Unrestricted with { Shiny = ShinyMethod };
|
||||
while (!TryApply(pk, seed = rand.Next(), iv, param, iterCriteria)) { }
|
||||
}
|
||||
}
|
||||
|
||||
FinishCorrelation(pk, seed);
|
||||
if (criteria.IsSpecifiedNature() && criteria.Nature != pk.Nature && criteria.Nature.IsMint())
|
||||
pk.StatNature = criteria.Nature;
|
||||
if (criteria.Shiny.IsShiny())
|
||||
if (isShinyRequested)
|
||||
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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && pk.Nature != Nature)
|
||||
return false;
|
||||
if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -199,7 +199,9 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo)
|
|||
if (pk is not IScaledSize s)
|
||||
return true;
|
||||
|
||||
// 3 of the Alpha statics were mistakenly set as 127 scale. If they enter HOME on 3.0.1, they'll get bumped to 255.
|
||||
// 3 of the Alpha statics were mistakenly set as 127 height/weight/scale.
|
||||
// Depositing them from any game into HOME 3.0.1 or later bumps all 3 values to 255.
|
||||
// The handling is server-sided and checks specifically for origin game, species, form, and Alpha Mark.
|
||||
// Defer scale match to downstream checks; we are sufficiently confident this is the best-match.
|
||||
if (IsAlpha127) // Average Size Alphas
|
||||
{
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ private void SetPINGA(PK9 pk, in EncounterCriteria criteria, PersonalInfo9SV pi)
|
|||
|
||||
if (Gender != FixedGenderUtil.GenderRandom)
|
||||
pk.Gender = Gender;
|
||||
if (Nature != Nature.Random)
|
||||
if (Nature.IsFixed)
|
||||
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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && 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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && 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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && 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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && 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 != Nature.Random && pk.Nature != Nature)
|
||||
if (Nature.IsFixed && 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);
|
||||
pk.PID = GetAdaptedPID(ref rand, pk, enc);
|
||||
|
||||
if (enc.Shiny is Shiny.Random && criteria.Shiny.IsShiny() != pk.IsShiny)
|
||||
var pid = GetAdaptedPID(ref rand, pk, enc);
|
||||
if (enc.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(ShinyUtil.GetShinyXor(pid, pk.ID32), 16))
|
||||
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 != Nature.Random ? enc.Nature
|
||||
var nature = enc.Nature.IsFixed ? 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 != Nature.Random ? enc.Nature
|
||||
var nature = enc.Nature.IsFixed ? 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 != Nature.Random;
|
||||
bool IsFixedNature => Nature.IsFixed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,14 @@ public static class EncounterVerifier
|
|||
private static CheckResult VerifyEncounter(PKM pk, IEncounterTemplate enc) => enc switch
|
||||
{
|
||||
EncounterShadow3Colo { IsEReader: true } when pk.Language != (int)LanguageID.Japanese => GetInvalid(G3EReader),
|
||||
EncounterStatic3 { Species: (int)Species.Mew } when pk.Language != (int)LanguageID.Japanese => GetInvalid(EncUnreleasedEMewJP),
|
||||
EncounterStatic3 { Species: (int)Species.Deoxys, Location: 200 } when pk.Language == (int)LanguageID.Japanese => GetInvalid(EncUnreleased),
|
||||
|
||||
// Mew @ Faraway Island (Emerald)
|
||||
EncounterStatic3 { Species: (int)Species.Mew } when pk.Language != (int)LanguageID.Japanese
|
||||
=> GetInvalid(EncUnreleasedEMewJP),
|
||||
// Deoxys @ Birth Island (FireRed/LeafGreen) - Never distributed in Japan during GBA Cart era. NX virtual console added for all.
|
||||
EncounterStatic3 { Species: (int)Species.Deoxys, Location: 200 } when pk.Language == (int)LanguageID.Japanese && !ParseSettings.AllowGen3EventTicketsAll(pk)
|
||||
=> GetInvalid(EncUnreleased),
|
||||
|
||||
EncounterStatic4 { Species: (int)Species.Shaymin } when pk.Language == (int)LanguageID.Korean => GetInvalid(EncUnreleased),
|
||||
EncounterStatic4 { IsRoaming: true } when pk is G4PKM { MetLocation: 193, GroundTile: GroundTileType.Water } => GetInvalid(G4InvalidTileR45Surf),
|
||||
MysteryGift g => VerifyEncounterEvent(pk, g),
|
||||
|
|
@ -146,6 +152,8 @@ private static CheckResult VerifyEncounterEgg3(PKM pk)
|
|||
return GetValid(EggLocation);
|
||||
|
||||
// Version isn't updated when hatching on a different game. Check any game.
|
||||
if (!ParseSettings.AllowGBACrossTransferRSE(pk)) // Must match the origin game (Nintendo Switch VC)
|
||||
return GetInvalid(EggLocationInvalid);
|
||||
if (EggHatchLocation3.IsValidMet3Any(met))
|
||||
return GetValid(EggLocationTrade);
|
||||
return GetInvalid(EggLocationInvalid);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public sealed class EvolutionGroup3 : IEvolutionGroup
|
|||
private static PersonalTable3 Personal => PersonalTable.E;
|
||||
private static EvolutionRuleTweak Tweak => EvolutionRuleTweak.Default;
|
||||
|
||||
public IEvolutionGroup? GetNext(PKM pk, EvolutionOrigin enc) => pk.Format > Generation ? EvolutionGroup4.Instance : null;
|
||||
public IEvolutionGroup? GetNext(PKM pk, EvolutionOrigin enc) => pk.Format > Generation ? EvolutionGroup4.Instance : null; // TODO HOME FR/LG
|
||||
public IEvolutionGroup? GetPrevious(PKM pk, EvolutionOrigin enc) => null;
|
||||
public void DiscardForOrigin(Span<EvoCriteria> result, PKM pk, EvolutionOrigin enc) => EvolutionUtil.Discard(result, Personal);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,10 +15,9 @@ public sealed class EvolutionGroupHOME : IEvolutionGroup
|
|||
|
||||
public IEvolutionGroup? GetNext(PKM pk, EvolutionOrigin enc)
|
||||
{
|
||||
return null; // TODO HOME ZA2: Re-enable when we have more info.
|
||||
// if (pk.Format <= 9 && pk.Context is not EntityContext.Gen9a)
|
||||
// return null;
|
||||
// return EvolutionGroupHOME.Instance;
|
||||
if (pk is { Format: <= 9, Context: not EntityContext.Gen9a })
|
||||
return null;
|
||||
return EvolutionGroupHOME2.Instance;
|
||||
}
|
||||
|
||||
public IEvolutionGroup? GetPrevious(PKM pk, EvolutionOrigin enc)
|
||||
|
|
@ -50,7 +49,16 @@ public void DiscardForOrigin(Span<EvoCriteria> result, PKM pk, EvolutionOrigin e
|
|||
/// </summary>
|
||||
/// <returns>True if we should check all adjacent evolution sources.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool CheckAllAdjacent(PKM pk, EvolutionOrigin enc) => enc.SkipChecks || pk is IHomeTrack { HasTracker: true } || !ParseSettings.IgnoreTransferIfNoTracker;
|
||||
private static bool CheckAllAdjacent(PKM pk, EvolutionOrigin enc)
|
||||
{
|
||||
if (enc.SkipChecks)
|
||||
return true;
|
||||
if (IsOutsideContext(pk.Context))
|
||||
return true; // transferred through HOME already
|
||||
return pk is IHomeTrack { HasTracker: true } || !ParseSettings.IgnoreTransferIfNoTracker;
|
||||
}
|
||||
|
||||
private static bool IsOutsideContext(EntityContext context) => context is not (EntityContext.Gen8 or EntityContext.Gen8a or EntityContext.Gen8b or EntityContext.Gen9);
|
||||
|
||||
public int Devolve(Span<EvoCriteria> result, PKM pk, EvolutionOrigin enc)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,15 +15,14 @@ public sealed class EvolutionGroupHOME2 : IEvolutionGroup
|
|||
|
||||
public IEvolutionGroup? GetPrevious(PKM pk, EvolutionOrigin enc)
|
||||
{
|
||||
return null; // TODO HOME ZA2: Re-enable when we have more info.
|
||||
// if (enc.Generation > 9 || enc.Context is EntityContext.Gen9a)
|
||||
// return null;
|
||||
// return EvolutionGroupHOME.Instance;
|
||||
if (enc is { Generation: > 9} or { Context: EntityContext.Gen9a })
|
||||
return null;
|
||||
return EvolutionGroupHOME.Instance;
|
||||
}
|
||||
|
||||
public void DiscardForOrigin(Span<EvoCriteria> result, PKM pk, EvolutionOrigin enc)
|
||||
{
|
||||
if (pk.ZA) // TODO HOME ZA2: did they force realign everything and fix their bug?
|
||||
if (pk.ZA)
|
||||
{
|
||||
var table = PersonalTable.ZA;
|
||||
if (enc.Options.HasFlag(OriginOptions.SkipChecks))
|
||||
|
|
@ -33,8 +32,10 @@ public void DiscardForOrigin(Span<EvoCriteria> result, PKM pk, EvolutionOrigin e
|
|||
}
|
||||
|
||||
// Check if ability was possibly realigned by form change; if not, discard anything that doesn't have the ability.
|
||||
// If touched by HOME, HOME realigns tracker, so we can't discard in that case.
|
||||
|
||||
var index = pk.AbilityNumber >> 1;
|
||||
if (index is 0 or 1)
|
||||
if (index is 0 or 1 && pk is not IHomeTrack { HasTracker: true })
|
||||
{
|
||||
var didRealignAbility = false;
|
||||
var ability = pk.Ability;
|
||||
|
|
|
|||
|
|
@ -138,4 +138,22 @@ private static int GetSpeciesIndex(ReadOnlySpan<EvoCriteria> array, ushort speci
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public bool HasVisitedExcept(params ReadOnlySpan<EntityContext> context)
|
||||
{
|
||||
if (HasVisitedZA && !context.Contains(EntityContext.Gen9a)) return true;
|
||||
if (HasVisitedGen9 && !context.Contains(EntityContext.Gen9)) return true;
|
||||
if (HasVisitedBDSP && !context.Contains(EntityContext.Gen8a)) return true;
|
||||
if (HasVisitedPLA && !context.Contains(EntityContext.Gen8b)) return true;
|
||||
if (HasVisitedSWSH && !context.Contains(EntityContext.Gen8)) return true;
|
||||
if (HasVisitedLGPE && !context.Contains(EntityContext.Gen7b)) return true;
|
||||
if (HasVisitedGen7 && !context.Contains(EntityContext.Gen7)) return true;
|
||||
if (HasVisitedGen6 && !context.Contains(EntityContext.Gen6)) return true;
|
||||
if (HasVisitedGen5 && !context.Contains(EntityContext.Gen5)) return true;
|
||||
if (HasVisitedGen4 && !context.Contains(EntityContext.Gen4)) return true;
|
||||
if (HasVisitedGen3 && !context.Contains(EntityContext.Gen3)) return true;
|
||||
if (HasVisitedGen2 && !context.Contains(EntityContext.Gen2)) return true;
|
||||
if (HasVisitedGen1 && !context.Contains(EntityContext.Gen1)) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,12 @@ private static void CheckEncounterMoves(Span<MoveResult> result, ReadOnlySpan<us
|
|||
|
||||
private static void Check(Span<MoveResult> result, ReadOnlySpan<ushort> current, PKM pk, EvoCriteria evo, int stage, MoveSourceType types)
|
||||
{
|
||||
if (!ParseSettings.AllowGBACrossTransferRSE(pk))
|
||||
{
|
||||
CheckNX(result, current, pk, evo, stage, types);
|
||||
return;
|
||||
}
|
||||
|
||||
var rs = LearnSource3RS.Instance;
|
||||
var species = evo.Species;
|
||||
if (!rs.TryGetPersonal(species, evo.Form, out var rp))
|
||||
|
|
@ -137,6 +143,48 @@ private static void Check(Span<MoveResult> result, ReadOnlySpan<ushort> current,
|
|||
}
|
||||
}
|
||||
|
||||
private static void CheckNX(Span<MoveResult> result, ReadOnlySpan<ushort> current, PKM pk, EvoCriteria evo, int stage, MoveSourceType types)
|
||||
{
|
||||
var species = evo.Species;
|
||||
var fr = LearnSource3FR.Instance;
|
||||
if (!fr.TryGetPersonal(species, evo.Form, out var fp))
|
||||
return; // should never happen.
|
||||
var lg = LearnSource3LG.Instance;
|
||||
var lp = lg[species];
|
||||
|
||||
var isFireRed = pk.Version == GameVersion.FR;
|
||||
ILearnSource<PersonalInfo3> primaryLS = isFireRed ? fr : lg;
|
||||
ILearnSource<PersonalInfo3> secondaryLS = !isFireRed ? fr : lg;
|
||||
var primaryPI = isFireRed ? fp : lp;
|
||||
var secondaryPI = !isFireRed ? fp : lp;
|
||||
var primaryEnv = isFireRed ? LearnEnvironment.FR : LearnEnvironment.LG;
|
||||
|
||||
for (int i = result.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (result[i].Valid)
|
||||
continue;
|
||||
|
||||
// Level Up moves are different for each game, but TM/HM is shared.
|
||||
var move = current[i];
|
||||
var chk = primaryLS.GetCanLearn(pk, primaryPI, evo, move, types);
|
||||
if (chk != default)
|
||||
{
|
||||
result[i] = new(chk, (byte)stage, Context);
|
||||
continue;
|
||||
}
|
||||
chk = secondaryLS.GetCanLearn(pk, secondaryPI, evo, move, types & MoveSourceType.LevelUp); // Tutors same as FR
|
||||
if (chk != default)
|
||||
{
|
||||
result[i] = new(chk, (byte)stage, Context);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Tutors are indexes 0-14, same as Emerald.
|
||||
if (LearnSource3E.GetIsTutorFRLG(evo.Species, move))
|
||||
result[i] = new(new(LearnMethod.Tutor, primaryEnv));
|
||||
}
|
||||
}
|
||||
|
||||
public void GetAllMoves(Span<bool> result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current)
|
||||
{
|
||||
if (types.HasFlag(MoveSourceType.Encounter) && enc.Context == Context)
|
||||
|
|
@ -158,6 +206,16 @@ public void GetAllMoves(Span<bool> result, PKM pk, EvolutionHistory history, IEn
|
|||
|
||||
private static void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceType types)
|
||||
{
|
||||
if (!ParseSettings.AllowGBACrossTransferRSE(pk)) // NX
|
||||
{
|
||||
LearnSource3FR.Instance.GetAllMoves(result, pk, evo, types);
|
||||
LearnSource3LG.Instance.GetAllMoves(result, pk, evo, types & (MoveSourceType.LevelUp));
|
||||
|
||||
// Tutors are indexes 0-14, same as Emerald.
|
||||
if (types.HasFlag(MoveSourceType.EnhancedTutor))
|
||||
LearnSource3E.GetAllTutorMovesFRLG(result, evo.Species);
|
||||
return;
|
||||
}
|
||||
LearnSource3E.Instance.GetAllMoves(result, pk, evo, types);
|
||||
LearnSource3RS.Instance.GetAllMoves(result, pk, evo, types & (MoveSourceType.LevelUp | MoveSourceType.AllTutors));
|
||||
LearnSource3FR.Instance.GetAllMoves(result, pk, evo, types & (MoveSourceType.LevelUp | MoveSourceType.AllTutors));
|
||||
|
|
|
|||
|
|
@ -144,10 +144,33 @@ public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceTy
|
|||
}
|
||||
}
|
||||
|
||||
// TODO RSE VC: Remove these.
|
||||
internal static bool GetIsTutorFRLG(ushort species, ushort move)
|
||||
{
|
||||
var info = Personal[species];
|
||||
var index = Tutor_E.IndexOf(move);
|
||||
if ((uint)index >= 15)
|
||||
return false;
|
||||
return info.TypeTutors[index];
|
||||
}
|
||||
|
||||
internal static void GetAllTutorMovesFRLG(Span<bool> result, ushort species)
|
||||
{
|
||||
var pi = Personal[species];
|
||||
var flags = pi.TypeTutors;
|
||||
var moves = Tutor_E;
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
if (flags[i])
|
||||
result[moves[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<ushort> Tutor_E =>
|
||||
[
|
||||
005, 014, 025, 034, 038, 068, 069, 102, 118, 135,
|
||||
138, 086, 153, 157, 164, 223, 205, 244, 173, 196,
|
||||
203, 189, 008, 207, 214, 129, 111, 009, 007, 210,
|
||||
// Introduced in FR/LG
|
||||
005, 014, 025, 034, 038, 068, 069, 102, 118, 135, 138, 086, 153, 157, 164,
|
||||
// Introduced in Emerald
|
||||
223, 205, 244, 173, 196, 203, 189, 008, 207, 214, 129, 111, 009, 007, 210,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
|
|
@ -19,7 +20,8 @@ public static class Legal
|
|||
|
||||
internal const int MaxSpeciesID_3 = 386;
|
||||
internal const int MaxMoveID_3 = 354;
|
||||
internal const int MaxItemID_3 = 374;
|
||||
internal const int MaxItemID_3_RS = 346;
|
||||
internal const int MaxItemID_3_FRLG = 374;
|
||||
internal const int MaxItemID_3_E = 376;
|
||||
internal const int MaxItemID_3_COLO = 547;
|
||||
internal const int MaxItemID_3_XD = 593;
|
||||
|
|
@ -150,7 +152,7 @@ public static class Legal
|
|||
internal const int MaxAbilityID_9a_MD = MaxAbilityID_9a_IK;
|
||||
|
||||
internal const int MaxBallID_9 = (int)Ball.LAOrigin;
|
||||
internal const GameVersion MaxGameID_HOME = GameVersion.VL; // TODO HOME ZA - Replace with ZA when HOME; if backwards transfer is allowed. If prevented, rename epoch as HOME1.
|
||||
internal const GameVersion MaxGameID_HOME = GameVersion.VL;
|
||||
internal const GameVersion MaxGameID_HOME2 = GameVersion.ZA;
|
||||
|
||||
internal static readonly ushort[] HeldItems_GSC = ItemStorage2.GetAllHeld();
|
||||
|
|
@ -302,4 +304,40 @@ public static bool GetIsFixedIVSequenceValidNoRand(in IndividualValueSet IVs, PK
|
|||
if (IVs.SPD != pk.IV_SPD) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For a species with a potentially valid FR/LG origin encounter, flag if not permitted.
|
||||
/// </summary>
|
||||
public static bool IsForeignFRLG(ushort species) => IsForeign(ForeignFRLG, species, ShiftFRLG);
|
||||
|
||||
private static bool IsForeign(ReadOnlySpan<byte> bitSet, int species, [ConstantExpected] int shift)
|
||||
{
|
||||
species -= shift;
|
||||
var offset = species >> 3;
|
||||
if ((uint)offset >= bitSet.Length)
|
||||
return false;
|
||||
|
||||
var bit = species & 7;
|
||||
if ((bitSet[offset] & (1 << bit)) != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private const ushort ShiftFRLG = 151; // First unavailable Species (Mew)
|
||||
|
||||
/// <summary>
|
||||
/// Bitset representing species that are considered unobtainable in FR/LG.
|
||||
/// Includes foreign transfers and time-of-day evolutions.
|
||||
/// First species is Mew (151), last is Deoxys (386).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Source: https://www.serebii.net/fireredleafgreen/unobtainable.shtml
|
||||
/// </remarks>
|
||||
private static ReadOnlySpan<byte> ForeignFRLG =>
|
||||
[
|
||||
0xFF, 0x33, 0x18, 0x60, 0x04, 0x63, 0x50, 0x0D,
|
||||
0x84, 0x40, 0x00, 0x04, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0x07,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,450 +18,446 @@ public sealed class LegalityCheckLocalization
|
|||
#region General Strings
|
||||
|
||||
/// <summary>Default text for indicating validity.</summary>
|
||||
public string Valid { get; set; } = "Valid.";
|
||||
public string Valid { get; init; } = "Valid.";
|
||||
|
||||
/// <summary>Default text for indicating legality.</summary>
|
||||
public string Legal { get; set; } = "Legal!";
|
||||
public string Legal { get; init; } = "Legal!";
|
||||
|
||||
/// <summary>Default text for indicating an error has occurred.</summary>
|
||||
public string Error { get; set; } = "Internal error.";
|
||||
public string Error { get; init; } = "Internal error.";
|
||||
|
||||
/// <summary>Analysis not available for the <see cref="PKM"/></summary>
|
||||
public string AnalysisUnavailable { get; set; } = "Analysis not available for this Pokémon.";
|
||||
public string AnalysisUnavailable { get; init; } = "Analysis not available for this Pokémon.";
|
||||
|
||||
/// <summary>Format text for exporting a legality check result.</summary>
|
||||
public string F0_1 { get; set; } = "{0}: {1}";
|
||||
public string F0_1 { get; init; } = "{0}: {1}";
|
||||
|
||||
/// <summary>Severity string for <see cref="Severity.Invalid"/></summary>
|
||||
public string SInvalid { get; set; } = "Invalid";
|
||||
public string SInvalid { get; init; } = "Invalid";
|
||||
|
||||
/// <summary>Severity string for <see cref="Severity.Fishy"/></summary>
|
||||
public string SFishy { get; set; } = "Fishy";
|
||||
public string SFishy { get; init; } = "Fishy";
|
||||
|
||||
/// <summary>Severity string for <see cref="Severity.Valid"/></summary>
|
||||
public string SValid { get; set; } = "Valid";
|
||||
public string SValid { get; init; } = "Valid";
|
||||
|
||||
/// <summary>Severity string for anything not implemented.</summary>
|
||||
public string NotImplemented { get; set; } = "Not Implemented";
|
||||
public string NotImplemented { get; init; } = "Not Implemented";
|
||||
|
||||
public string AbilityCapsuleUsed { get; set; } = "Ability available with Ability Capsule.";
|
||||
public string AbilityPatchUsed { get; set; } = "Ability available with Ability Patch.";
|
||||
public string AbilityPatchRevertUsed { get; set; } = "Ability available with Ability Patch Revert.";
|
||||
public string AbilityFlag { get; set; } = "Ability matches ability number.";
|
||||
public string AbilityHiddenFail { get; set; } = "Hidden Ability mismatch for encounter type.";
|
||||
public string AbilityHiddenUnavailable { get; set; } = "Hidden Ability not available.";
|
||||
public string AbilityMismatch { get; set; } = "Ability mismatch for encounter.";
|
||||
public string AbilityMismatch3 { get; set; } = "Ability does not match Generation 3 species ability.";
|
||||
public string AbilityMismatchFlag { get; set; } = "Ability does not match ability number.";
|
||||
public string AbilityMismatchGift { get; set; } = "Ability does not match Mystery Gift.";
|
||||
public string AbilityMismatchPID { get; set; } = "Ability does not match PID.";
|
||||
public string AbilityUnexpected { get; set; } = "Ability is not valid for species/form.";
|
||||
public string AbilityCapsuleUsed { get; init; } = "Ability available with Ability Capsule.";
|
||||
public string AbilityPatchUsed { get; init; } = "Ability available with Ability Patch.";
|
||||
public string AbilityPatchRevertUsed { get; init; } = "Ability available with Ability Patch Revert.";
|
||||
public string AbilityFlag { get; init; } = "Ability matches ability number.";
|
||||
public string AbilityHiddenFail { get; init; } = "Hidden Ability mismatch for encounter type.";
|
||||
public string AbilityHiddenUnavailable { get; init; } = "Hidden Ability not available.";
|
||||
public string AbilityMismatch { get; init; } = "Ability mismatch for encounter.";
|
||||
public string AbilityMismatch3 { get; init; } = "Ability does not match Generation 3 species ability.";
|
||||
public string AbilityMismatchFlag { get; init; } = "Ability does not match ability number.";
|
||||
public string AbilityMismatchGift { get; init; } = "Ability does not match Mystery Gift.";
|
||||
public string AbilityMismatchPID { get; init; } = "Ability does not match PID.";
|
||||
public string AbilityUnexpected { get; init; } = "Ability is not valid for species/form.";
|
||||
|
||||
public string AwakenedCap { get; set; } = "Individual AV cannot be greater than {0}.";
|
||||
public string AwakenedShouldBeValue { get; set; } = "{1} AV should be greater than {0}.";
|
||||
public string AwakenedCap { get; init; } = "Individual AV cannot be greater than {0}.";
|
||||
public string AwakenedShouldBeValue { get; init; } = "{1} AV should be greater than {0}.";
|
||||
|
||||
public string BallAbility { get; set; } = "Can't obtain Hidden Ability with Ball.";
|
||||
public string BallEggCherish { get; set; } = "Can't have Cherish Ball for regular Egg.";
|
||||
public string BallEggMaster { get; set; } = "Can't have Master Ball for regular Egg.";
|
||||
public string BallEnc { get; set; } = "Correct ball for encounter type.";
|
||||
public string BallEncMismatch { get; set; } = "Can't have ball for encounter type.";
|
||||
public string BallHeavy { get; set; } = "Can't have Heavy Ball for light, low-catch rate species (Gen VII).";
|
||||
public string BallSpecies { get; set; } = "Can't obtain species in Ball.";
|
||||
public string BallSpeciesPass { get; set; } = "Ball possible for species.";
|
||||
public string BallUnavailable { get; set; } = "Ball unobtainable in origin Generation.";
|
||||
public string BallG4Sinnoh { get; set; } = "Ball value for D/P/Pt (0x83) is not within range.";
|
||||
public string BallG4Johto { get; set; } = "Extended Ball value for HG/SS (0x86) is not within range.";
|
||||
public string BallAbility { get; init; } = "Can't obtain Hidden Ability with Ball.";
|
||||
public string BallEggCherish { get; init; } = "Can't have Cherish Ball for regular Egg.";
|
||||
public string BallEggMaster { get; init; } = "Can't have Master Ball for regular Egg.";
|
||||
public string BallEnc { get; init; } = "Correct ball for encounter type.";
|
||||
public string BallEncMismatch { get; init; } = "Can't have ball for encounter type.";
|
||||
public string BallHeavy { get; init; } = "Can't have Heavy Ball for light, low-catch rate species (Gen VII).";
|
||||
public string BallSpecies { get; init; } = "Can't obtain species in Ball.";
|
||||
public string BallSpeciesPass { get; init; } = "Ball possible for species.";
|
||||
public string BallUnavailable { get; init; } = "Ball unobtainable in origin Generation.";
|
||||
public string BallG4Sinnoh { get; init; } = "Ball value for D/P/Pt (0x83) is not within range.";
|
||||
public string BallG4Johto { get; init; } = "Extended Ball value for HG/SS (0x86) is not within range.";
|
||||
|
||||
public string ContestZero { get; set; } = "Contest Stats should be 0.";
|
||||
public string ContestZeroSheen { get; set; } = "Contest Stat Sheen should be 0.";
|
||||
public string ContestSheenGEQ_0 { get; set; } = "Contest Stat Sheen should be >= {0}.";
|
||||
public string ContestSheenLEQ_0 { get; set; } = "Contest Stat Sheen should be <= {0}.";
|
||||
public string ContestZero { get; init; } = "Contest Stats should be 0.";
|
||||
public string ContestZeroSheen { get; init; } = "Contest Stat Sheen should be 0.";
|
||||
public string ContestSheenGEQ_0 { get; init; } = "Contest Stat Sheen should be >= {0}.";
|
||||
public string ContestSheenLEQ_0 { get; init; } = "Contest Stat Sheen should be <= {0}.";
|
||||
|
||||
public string DateCalendarInvalidMet { get; set; } = "Met Date is not a valid calendar date.";
|
||||
public string DateCalendarInvalidEgg { get; set; } = "Egg Met Date is not a valid calendar date.";
|
||||
public string DateLocalInvalidDate { get; set; } = "Local Date is outside of console's local time window.";
|
||||
public string DateLocalInvalidTime { get; set; } = "Local Time is not a valid timestamp.";
|
||||
public string DateOutsideDistributionWindow { get; set; } = "Met Date is outside of distribution window.";
|
||||
public string DateCalendarInvalidMet { get; init; } = "Met Date is not a valid calendar date.";
|
||||
public string DateCalendarInvalidEgg { get; init; } = "Egg Met Date is not a valid calendar date.";
|
||||
public string DateLocalInvalidDate { get; init; } = "Local Date is outside of console's local time window.";
|
||||
public string DateLocalInvalidTime { get; init; } = "Local Time is not a valid timestamp.";
|
||||
public string DateOutsideDistributionWindow { get; init; } = "Met Date is outside of distribution window.";
|
||||
|
||||
public string EggContest { get; set; } = "Cannot increase Contest Stats of an Egg.";
|
||||
public string EggEXP { get; set; } = "Eggs cannot receive experience.";
|
||||
public string EggFMetLevel_0 { get; set; } = "Invalid Met Level, expected {0}.";
|
||||
public string EggHatchCycles { get; set; } = "Invalid Egg hatch cycles.";
|
||||
public string EggLocation { get; set; } = "Able to hatch an Egg at Met Location.";
|
||||
public string EggLocationInvalid { get; set; } = "Can't hatch an Egg at Met Location.";
|
||||
public string EggLocationNone { get; set; } = "Invalid Egg Location, expected none.";
|
||||
public string EggLocationPalPark { get; set; } = "Invalid Met Location, expected Pal Park.";
|
||||
public string EggLocationTrade { get; set; } = "Able to hatch a traded Egg at Met Location.";
|
||||
public string EggLocationTradeFail { get; set; } = "Invalid Egg Location, shouldn't be 'traded' while an Egg.";
|
||||
public string EggMetLocationFail { get; set; } = "Can't obtain Egg from Egg Location.";
|
||||
public string EggNature { get; set; } = "Eggs cannot have their Stat Nature changed.";
|
||||
public string EggPP { get; set; } = "Eggs cannot have modified move PP counts.";
|
||||
public string EggPPUp { get; set; } = "Cannot apply PP Ups to an Egg.";
|
||||
public string EggRelearnFlags { get; set; } = "Expected no Relearn Move Flags.";
|
||||
public string EggShinyPokeStar { get; set; } = "Eggs cannot be a Pokéstar Studios star.";
|
||||
public string EggSpecies { get; set; } = "Can't obtain Egg for this species.";
|
||||
public string EggUnhatched { get; set; } = "Valid un-hatched Egg.";
|
||||
public string EggContest { get; init; } = "Cannot increase Contest Stats of an Egg.";
|
||||
public string EggEXP { get; init; } = "Eggs cannot receive experience.";
|
||||
public string EggFMetLevel_0 { get; init; } = "Invalid Met Level, expected {0}.";
|
||||
public string EggHatchCycles { get; init; } = "Invalid Egg hatch cycles.";
|
||||
public string EggLocation { get; init; } = "Able to hatch an Egg at Met Location.";
|
||||
public string EggLocationInvalid { get; init; } = "Can't hatch an Egg at Met Location.";
|
||||
public string EggLocationNone { get; init; } = "Invalid Egg Location, expected none.";
|
||||
public string EggLocationPalPark { get; init; } = "Invalid Met Location, expected Pal Park.";
|
||||
public string EggLocationTrade { get; init; } = "Able to hatch a traded Egg at Met Location.";
|
||||
public string EggLocationTradeFail { get; init; } = "Invalid Egg Location, shouldn't be 'traded' while an Egg.";
|
||||
public string EggMetLocationFail { get; init; } = "Can't obtain Egg from Egg Location.";
|
||||
public string EggNature { get; init; } = "Eggs cannot have their Stat Nature changed.";
|
||||
public string EggPP { get; init; } = "Eggs cannot have modified move PP counts.";
|
||||
public string EggPPUp { get; init; } = "Cannot apply PP Ups to an Egg.";
|
||||
public string EggRelearnFlags { get; init; } = "Expected no Relearn Move Flags.";
|
||||
public string EggShinyPokeStar { get; init; } = "Eggs cannot be a Pokéstar Studios star.";
|
||||
public string EggSpecies { get; init; } = "Can't obtain Egg for this species.";
|
||||
public string EggUnhatched { get; init; } = "Valid un-hatched Egg.";
|
||||
|
||||
public string EncCondition { get; set; } = "Valid Wild Encounter at location.";
|
||||
public string EncConditionBadRNGFrame { get; set; } = "Unable to match encounter conditions to a possible RNG frame.";
|
||||
public string EncConditionBadSpecies { get; set; } = "Species does not exist in origin game.";
|
||||
public string EncCondition { get; init; } = "Valid Wild Encounter at location.";
|
||||
public string EncConditionBadRNGFrame { get; init; } = "Unable to match encounter conditions to a possible RNG frame.";
|
||||
public string EncConditionBadSpecies { get; init; } = "Species does not exist in origin game.";
|
||||
|
||||
public string EncGift { get; set; } = "Unable to match a gift Egg encounter from origin game.";
|
||||
public string EncGiftEggEvent { get; set; } = "Unable to match an event Egg encounter from origin game.";
|
||||
public string EncGiftIVMismatch { get; set; } = "IVs do not match Mystery Gift Data.";
|
||||
public string EncGiftNicknamed { get; set; } = "Event gift has been nicknamed.";
|
||||
public string EncGiftNotFound { get; set; } = "Unable to match to a Mystery Gift in the database.";
|
||||
public string EncGiftPIDMismatch { get; set; } = "Mystery Gift fixed PID mismatch.";
|
||||
public string EncGiftShinyMismatch { get; set; } = "Mystery Gift shiny mismatch.";
|
||||
public string EncGiftVersionNotDistributed { get; set; } = "Mystery Gift cannot be received by this version.";
|
||||
public string EncGift { get; init; } = "Unable to match a gift Egg encounter from origin game.";
|
||||
public string EncGiftEggEvent { get; init; } = "Unable to match an event Egg encounter from origin game.";
|
||||
public string EncGiftIVMismatch { get; init; } = "IVs do not match Mystery Gift Data.";
|
||||
public string EncGiftNicknamed { get; init; } = "Event gift has been nicknamed.";
|
||||
public string EncGiftNotFound { get; init; } = "Unable to match to a Mystery Gift in the database.";
|
||||
public string EncGiftPIDMismatch { get; init; } = "Mystery Gift fixed PID mismatch.";
|
||||
public string EncGiftShinyMismatch { get; init; } = "Mystery Gift shiny mismatch.";
|
||||
public string EncGiftVersionNotDistributed { get; init; } = "Mystery Gift cannot be received by this version.";
|
||||
|
||||
public string EncInvalid { get; set; } = "Unable to match an encounter from origin game.";
|
||||
public string EncMasteryInitial { get; set; } = "Initial move mastery flags do not match the encounter's expected state.";
|
||||
public string EncInvalid { get; init; } = "Unable to match an encounter from origin game.";
|
||||
public string EncMasteryInitial { get; init; } = "Initial move mastery flags do not match the encounter's expected state.";
|
||||
|
||||
public string EncTradeChangedNickname { get; set; } = "In-game Trade Nickname has been altered.";
|
||||
public string EncTradeChangedOT { get; set; } = "In-game Trade OT has been altered.";
|
||||
public string EncTradeIndexBad { get; set; } = "In-game Trade invalid index?";
|
||||
public string EncTradeMatch { get; set; } = "Valid In-game trade.";
|
||||
public string EncTradeUnchanged { get; set; } = "In-game Trade OT and Nickname have not been altered.";
|
||||
public string EncTradeChangedNickname { get; init; } = "In-game Trade Nickname has been altered.";
|
||||
public string EncTradeChangedOT { get; init; } = "In-game Trade OT has been altered.";
|
||||
public string EncTradeIndexBad { get; init; } = "In-game Trade invalid index?";
|
||||
public string EncTradeMatch { get; init; } = "Valid In-game trade.";
|
||||
public string EncTradeUnchanged { get; init; } = "In-game Trade OT and Nickname have not been altered.";
|
||||
|
||||
public string EncStaticPIDShiny { get; set; } = "Encounter shiny mismatch.";
|
||||
public string EncTypeMatch { get; set; } = "Encounter Type matches encounter.";
|
||||
public string EncTypeMismatch { get; set; } = "Encounter Type does not match encounter.";
|
||||
public string EncUnreleased { get; set; } = "Unreleased event.";
|
||||
public string EncUnreleasedEMewJP { get; set; } = "Non japanese Mew from Faraway Island. Unreleased event.";
|
||||
public string EncStaticPIDShiny { get; init; } = "Encounter shiny mismatch.";
|
||||
public string EncTypeMatch { get; init; } = "Encounter Type matches encounter.";
|
||||
public string EncTypeMismatch { get; init; } = "Encounter Type does not match encounter.";
|
||||
public string EncUnreleased { get; init; } = "Unreleased event.";
|
||||
public string EncUnreleasedEMewJP { get; init; } = "Non japanese Mew from Faraway Island. Unreleased event.";
|
||||
|
||||
public string EReaderAmerica { get; set; } = "American E-Reader Berry in Japanese save file.";
|
||||
public string EReaderInvalid { get; set; } = "Invalid E-Reader Berry.";
|
||||
public string EReaderJapan { get; set; } = "Japanese E-Reader Berry in international save file.";
|
||||
public string EReaderAmerica { get; init; } = "American E-Reader Berry in Japanese save file.";
|
||||
public string EReaderInvalid { get; init; } = "Invalid E-Reader Berry.";
|
||||
public string EReaderJapan { get; init; } = "Japanese E-Reader Berry in international save file.";
|
||||
|
||||
public string Effort2Remaining { get; set; } = "2 EVs remaining.";
|
||||
public string EffortAbove252 { get; set; } = "EVs cannot go above 252.";
|
||||
public string EffortAbove510 { get; set; } = "EV total cannot be above 510.";
|
||||
public string EffortAllEqual { get; set; } = "EVs are all equal.";
|
||||
public string EffortCap100 { get; set; } = "Individual EV for a level 100 encounter in Generation 4 cannot be greater than 100.";
|
||||
public string EffortEgg { get; set; } = "Eggs cannot receive EVs.";
|
||||
public string EffortShouldBeZero { get; set; } = "Cannot receive EVs.";
|
||||
public string EffortEXPIncreased { get; set; } = "All EVs are zero, but leveled above Met Level.";
|
||||
public string EffortUntrainedCap { get; set; } = "Individual EV without changing EXP cannot be greater than {0}.";
|
||||
public string Effort2Remaining { get; init; } = "2 EVs remaining.";
|
||||
public string EffortAbove252 { get; init; } = "EVs cannot go above 252.";
|
||||
public string EffortAbove510 { get; init; } = "EV total cannot be above 510.";
|
||||
public string EffortAllEqual { get; init; } = "EVs are all equal.";
|
||||
public string EffortCap100 { get; init; } = "Individual EV for a level 100 encounter in Generation 4 cannot be greater than 100.";
|
||||
public string EffortEgg { get; init; } = "Eggs cannot receive EVs.";
|
||||
public string EffortShouldBeZero { get; init; } = "Cannot receive EVs.";
|
||||
public string EffortEXPIncreased { get; init; } = "All EVs are zero, but leveled above Met Level.";
|
||||
public string EffortUntrainedCap { get; init; } = "Individual EV without changing EXP cannot be greater than {0}.";
|
||||
|
||||
public string EvoInvalid { get; set; } = "Evolution not valid (or level/trade evolution unsatisfied).";
|
||||
public string EvoTradeReqOutsider { get; set; } = "Outsider {0} should have evolved into {1}.";
|
||||
public string EvoTradeRequired { get; set; } = "Version Specific evolution requires a trade to opposite version. A Handling Trainer is required.";
|
||||
public string EvoInvalid { get; init; } = "Evolution not valid (or level/trade evolution unsatisfied).";
|
||||
public string EvoTradeReqOutsider { get; init; } = "Outsider {0} should have evolved into {1}.";
|
||||
public string EvoTradeRequired { get; init; } = "Version Specific evolution requires a trade to opposite version. A Handling Trainer is required.";
|
||||
|
||||
public string FatefulGiftMissing { get; set; } = "Fateful Encounter with no matching Encounter. Has the Mystery Gift data been contributed?";
|
||||
public string FatefulInvalid { get; set; } = "Fateful Encounter should not be checked.";
|
||||
public string FatefulMissing { get; set; } = "Special In-game Fateful Encounter flag missing.";
|
||||
public string FatefulMystery { get; set; } = "Mystery Gift Fateful Encounter.";
|
||||
public string FatefulMysteryMissing { get; set; } = "Mystery Gift Fateful Encounter flag missing.";
|
||||
public string FatefulGiftMissing { get; init; } = "Fateful Encounter with no matching Encounter. Has the Mystery Gift data been contributed?";
|
||||
public string FatefulInvalid { get; init; } = "Fateful Encounter should not be checked.";
|
||||
public string FatefulMissing { get; init; } = "Special In-game Fateful Encounter flag missing.";
|
||||
public string FatefulMystery { get; init; } = "Mystery Gift Fateful Encounter.";
|
||||
public string FatefulMysteryMissing { get; init; } = "Mystery Gift Fateful Encounter flag missing.";
|
||||
|
||||
public string FavoriteMarkingUnavailable { get; set; } = "Favorite Marking is not available.";
|
||||
public string FavoriteMarkingUnavailable { get; init; } = "Favorite Marking is not available.";
|
||||
|
||||
public string FormArgumentLEQ_0 { get; set; } = "Form argument is too high for current form.";
|
||||
public string FormArgumentGEQ_0 { get; set; } = "Form argument is too low for current form.";
|
||||
public string FormArgumentNotAllowed { get; set; } = "Form argument is not allowed for this encounter.";
|
||||
public string FormArgumentValid { get; set; } = "Form argument is valid.";
|
||||
public string FormArgumentInvalid { get; set; } = "Form argument is not valid.";
|
||||
public string FormBattle { get; set; } = "Form cannot exist outside of a battle.";
|
||||
public string FormEternal { get; set; } = "Valid Eternal Flower encounter.";
|
||||
public string FormEternalInvalid { get; set; } = "Invalid Eternal Flower encounter.";
|
||||
public string FormInvalidGame { get; set; } = "Form cannot be obtained in origin game.";
|
||||
public string FormInvalidNature { get; set; } = "Form cannot have this nature.";
|
||||
public string FormItem { get; set; } = "Held item matches Form.";
|
||||
public string FormItemInvalid { get; set; } = "Held item does not match Form.";
|
||||
public string FormParty { get; set; } = "Form cannot exist outside of Party.";
|
||||
public string FormPikachuCosplay { get; set; } = "Only Cosplay Pikachu can have this form.";
|
||||
public string FormPikachuCosplayInvalid { get; set; } = "Cosplay Pikachu cannot have the default form.";
|
||||
public string FormPikachuEventInvalid { get; set; } = "Event Pikachu cannot have the default form.";
|
||||
public string FormInvalidExpect_0 { get; set; } = "Form is invalid, expected form index {0}.";
|
||||
public string FormValid { get; set; } = "Form is Valid.";
|
||||
public string FormVivillon { get; set; } = "Valid Vivillon pattern.";
|
||||
public string FormVivillonEventPre { get; set; } = "Event Vivillon pattern on pre-evolution.";
|
||||
public string FormVivillonInvalid { get; set; } = "Invalid Vivillon pattern.";
|
||||
public string FormVivillonNonNative { get; set; } = "Non-native Vivillon pattern.";
|
||||
public string FormArgumentLEQ_0 { get; init; } = "Form argument is too high for current form.";
|
||||
public string FormArgumentGEQ_0 { get; init; } = "Form argument is too low for current form.";
|
||||
public string FormArgumentNotAllowed { get; init; } = "Form argument is not allowed for this encounter.";
|
||||
public string FormArgumentValid { get; init; } = "Form argument is valid.";
|
||||
public string FormArgumentInvalid { get; init; } = "Form argument is not valid.";
|
||||
public string FormBattle { get; init; } = "Form cannot exist outside of a battle.";
|
||||
public string FormInvalidGame { get; init; } = "Form cannot be obtained in origin game.";
|
||||
public string FormInvalidNature { get; init; } = "Form cannot have this nature.";
|
||||
public string FormItem { get; init; } = "Held item matches Form.";
|
||||
public string FormItemInvalid { get; init; } = "Held item does not match Form.";
|
||||
public string FormParty { get; init; } = "Form cannot exist outside of Party.";
|
||||
public string FormInvalidExpect_0 { get; init; } = "Form is invalid, expected form index {0}.";
|
||||
public string FormValid { get; init; } = "Form is Valid.";
|
||||
public string FormVivillon { get; init; } = "Valid Vivillon pattern.";
|
||||
public string FormVivillonEventPre { get; init; } = "Event Vivillon pattern on pre-evolution.";
|
||||
public string FormVivillonInvalid { get; init; } = "Invalid Vivillon pattern.";
|
||||
public string FormVivillonNonNative { get; init; } = "Non-native Vivillon pattern.";
|
||||
|
||||
public string G1CatchRateChain { get; set; } = "Catch rate does not match any species from Pokémon evolution chain.";
|
||||
public string G1CatchRateEvo { get; set; } = "Catch rate match species without encounters. Expected a preevolution catch rate.";
|
||||
public string G1CatchRateItem { get; set; } = "Catch rate does not match a valid held item from Generation 2.";
|
||||
public string G1CatchRateMatchPrevious { get; set; } = "Catch Rate matches a species from Pokémon evolution chain.";
|
||||
public string G1CatchRateMatchTradeback { get; set; } = "Catch rate matches a valid held item from Generation 2.";
|
||||
public string G1CatchRateNone { get; set; } = "Catch rate does not match any species from Pokémon evolution chain or any Generation 2 held items.";
|
||||
public string G1CharNick { get; set; } = "Nickname from Generation 1/2 uses unavailable characters.";
|
||||
public string G1CharOT { get; set; } = "OT from Generation 1/2 uses unavailable characters.";
|
||||
public string G1OTGender { get; set; } = "Female OT from Generation 1/2 is invalid.";
|
||||
public string G1Stadium { get; set; } = "Incorrect Stadium OT.";
|
||||
public string G1Type1Fail { get; set; } = "Invalid Type A, does not match species type.";
|
||||
public string G1Type2Fail { get; set; } = "Invalid Type B, does not match species type.";
|
||||
public string G1TypeMatch1 { get; set; } = "Valid Type A, matches species type.";
|
||||
public string G1TypeMatch2 { get; set; } = "Valid Type B, matches species type.";
|
||||
public string G1TypeMatchPorygon { get; set; } = "Porygon with valid Type A and B values.";
|
||||
public string G1TypePorygonFail { get; set; } = "Porygon with invalid Type A and B values. Does not a match a valid type combination.";
|
||||
public string G1TypePorygonFail1 { get; set; } = "Porygon with invalid Type A value.";
|
||||
public string G1TypePorygonFail2 { get; set; } = "Porygon with invalid Type B value.";
|
||||
public string G2InvalidTileTreeNotFound { get; set; } = "Could not find a tree for Crystal headbutt encounter that matches OTID.";
|
||||
public string G2TreeID { get; set; } = "Found a tree for Crystal headbutt encounter that matches OTID.";
|
||||
public string G2OTGender { get; set; } = "OT from Virtual Console games other than Crystal cannot be female.";
|
||||
public string G1CatchRateChain { get; init; } = "Catch rate does not match any species from Pokémon evolution chain.";
|
||||
public string G1CatchRateEvo { get; init; } = "Catch rate match species without encounters. Expected a pre-evolution catch rate.";
|
||||
public string G1CatchRateItem { get; init; } = "Catch rate does not match a valid held item from Generation 2.";
|
||||
public string G1CatchRateMatchPrevious { get; init; } = "Catch Rate matches a species from Pokémon evolution chain.";
|
||||
public string G1CatchRateMatchTradeback { get; init; } = "Catch rate matches a valid held item from Generation 2.";
|
||||
public string G1CatchRateNone { get; init; } = "Catch rate does not match any species from Pokémon evolution chain or any Generation 2 held items.";
|
||||
public string G1CharNick { get; init; } = "Nickname from Generation 1/2 uses unavailable characters.";
|
||||
public string G1CharOT { get; init; } = "OT from Generation 1/2 uses unavailable characters.";
|
||||
public string G1OTGender { get; init; } = "Female OT from Generation 1/2 is invalid.";
|
||||
public string G1Stadium { get; init; } = "Incorrect Stadium OT.";
|
||||
public string G1Type1Fail { get; init; } = "Invalid Type A, does not match species type.";
|
||||
public string G1Type2Fail { get; init; } = "Invalid Type B, does not match species type.";
|
||||
public string G1TypeMatch1 { get; init; } = "Valid Type A, matches species type.";
|
||||
public string G1TypeMatch2 { get; init; } = "Valid Type B, matches species type.";
|
||||
public string G1TypeMatchPorygon { get; init; } = "Porygon with valid Type A and B values.";
|
||||
public string G1TypePorygonFail { get; init; } = "Porygon with invalid Type A and B values. Does not a match a valid type combination.";
|
||||
public string G1TypePorygonFail1 { get; init; } = "Porygon with invalid Type A value.";
|
||||
public string G1TypePorygonFail2 { get; init; } = "Porygon with invalid Type B value.";
|
||||
public string G2InvalidTileTreeNotFound { get; init; } = "Could not find a tree for Crystal headbutt encounter that matches OTID.";
|
||||
public string G2TreeID { get; init; } = "Found a tree for Crystal headbutt encounter that matches OTID.";
|
||||
public string G2OTGender { get; init; } = "OT from Virtual Console games other than Crystal cannot be female.";
|
||||
|
||||
public string G3EReader { get; set; } = "Non Japanese Shadow E-reader Pokémon. Unreleased encounter.";
|
||||
public string G3OTGender { get; set; } = "OT from Colosseum/XD cannot be female.";
|
||||
public string G4InvalidTileR45Surf { get; set; } = "Johto Route 45 surfing encounter. Unreachable Water tiles.";
|
||||
public string G4PartnerMoodEgg { get; set; } = "Eggs cannot have an Mood stat value.";
|
||||
public string G4PartnerMoodZero { get; set; } = "Mood stat value should be zero when not in the player's party.";
|
||||
public string G4ShinyLeafBitsInvalid { get; set; } = "Shiny Leaf/Crown bits are not valid.";
|
||||
public string G4ShinyLeafBitsEgg { get; set; } = "Eggs cannot have Shiny Leaf/Crown.";
|
||||
public string G5IVAll30 { get; set; } = "All IVs of N's Pokémon should be 30.";
|
||||
public string G5PIDShinyGrotto { get; set; } = "Hidden Grotto captures cannot be shiny.";
|
||||
public string G5SparkleInvalid { get; set; } = "Special In-game N's Sparkle flag should not be checked.";
|
||||
public string G5SparkleRequired { get; set; } = "Special In-game N's Sparkle flag missing.";
|
||||
public string G5PokeStarMustBeZero { get; set; } = "Pokéstar Studios fame must be zero, cannot participate.";
|
||||
public string G5PokeStarImpossibleValue { get; set; } = "Pokéstar Studios fame value is unreachable.";
|
||||
public string G7BSocialShouldBe100Spirit { get; set; } = "Spirit should be 100 for Pokémon not in the player's party.";
|
||||
public string G7BSocialShouldBe100Mood { get; set; } = "Mood should be 100 for Pokémon not in the player's party.";
|
||||
public string G3EReader { get; init; } = "Non Japanese Shadow E-reader Pokémon. Unreleased encounter.";
|
||||
public string G3OTGender { get; init; } = "OT from Colosseum/XD cannot be female.";
|
||||
public string G4InvalidTileR45Surf { get; init; } = "Johto Route 45 surfing encounter. Unreachable Water tiles.";
|
||||
public string G4PartnerMoodEgg { get; init; } = "Eggs cannot have an Mood stat value.";
|
||||
public string G4PartnerMoodZero { get; init; } = "Mood stat value should be zero when not in the player's party.";
|
||||
public string G4ShinyLeafBitsInvalid { get; init; } = "Shiny Leaf/Crown bits are not valid.";
|
||||
public string G4ShinyLeafBitsEgg { get; init; } = "Eggs cannot have Shiny Leaf/Crown.";
|
||||
public string G5IVAll30 { get; init; } = "All IVs of N's Pokémon should be 30.";
|
||||
public string G5PIDShinyGrotto { get; init; } = "Hidden Grotto captures cannot be shiny.";
|
||||
public string G5SparkleInvalid { get; init; } = "Special In-game N's Sparkle flag should not be checked.";
|
||||
public string G5SparkleRequired { get; init; } = "Special In-game N's Sparkle flag missing.";
|
||||
public string G5PokeStarMustBeZero { get; init; } = "Pokéstar Studios fame must be zero, cannot participate.";
|
||||
public string G5PokeStarImpossibleValue { get; init; } = "Pokéstar Studios fame value is unreachable.";
|
||||
public string G7BSocialShouldBe100Spirit { get; init; } = "Spirit should be 100 for Pokémon not in the player's party.";
|
||||
public string G7BSocialShouldBe100Mood { get; init; } = "Mood should be 100 for Pokémon not in the player's party.";
|
||||
|
||||
public string GanbaruStatTooHigh { get; set; } = "One or more Ganbaru Value is above the natural limit of (10 - IV bonus).";
|
||||
public string GanbaruStatTooHigh { get; init; } = "One or more Ganbaru Value is above the natural limit of (10 - IV bonus).";
|
||||
|
||||
public string GenderInvalidNone { get; set; } = "Genderless Pokémon should not have a gender.";
|
||||
public string GeoBadOrder { get; set; } = "GeoLocation Memory: Gap/Blank present.";
|
||||
public string GeoHardwareInvalid { get; set; } = "Geolocation: Country is not in 3DS region.";
|
||||
public string GeoHardwareRange { get; set; } = "Invalid Console Region.";
|
||||
public string GeoHardwareValid { get; set; } = "Geolocation: Country is in 3DS region.";
|
||||
public string GeoMemoryMissing { get; set; } = "GeoLocation Memory: Memories should be present.";
|
||||
public string GeoNoCountryHT { get; set; } = "GeoLocation Memory: HT Name present but has no previous Country.";
|
||||
public string GeoNoRegion { get; set; } = "GeoLocation Memory: Region without Country.";
|
||||
public string GenderInvalidNone { get; init; } = "Genderless Pokémon should not have a gender.";
|
||||
public string GeoBadOrder { get; init; } = "GeoLocation Memory: Gap/Blank present.";
|
||||
public string GeoHardwareInvalid { get; init; } = "Geolocation: Country is not in 3DS region.";
|
||||
public string GeoHardwareRange { get; init; } = "Invalid Console Region.";
|
||||
public string GeoHardwareValid { get; init; } = "Geolocation: Country is in 3DS region.";
|
||||
public string GeoMemoryMissing { get; init; } = "GeoLocation Memory: Memories should be present.";
|
||||
public string GeoNoCountryHT { get; init; } = "GeoLocation Memory: HT Name present but has no previous Country.";
|
||||
public string GeoNoRegion { get; init; } = "GeoLocation Memory: Region without Country.";
|
||||
|
||||
public string HyperTrainLevelGEQ_0 { get; set; } = "Can't Hyper Train a Pokémon that isn't level {0}.";
|
||||
public string HyperPerfectAll { get; set; } = "Can't Hyper Train a Pokémon with perfect IVs.";
|
||||
public string HyperPerfectOne { get; set; } = "Can't Hyper Train a perfect IV.";
|
||||
public string HyperPerfectUnavailable { get; set; } = "Can't Hyper Train any IV(s).";
|
||||
public string HyperTrainLevelGEQ_0 { get; init; } = "Can't Hyper Train a Pokémon that isn't level {0}.";
|
||||
public string HyperPerfectAll { get; init; } = "Can't Hyper Train a Pokémon with perfect IVs.";
|
||||
public string HyperPerfectOne { get; init; } = "Can't Hyper Train a perfect IV.";
|
||||
public string HyperPerfectUnavailable { get; init; } = "Can't Hyper Train any IV(s).";
|
||||
|
||||
public string ItemEgg { get; set; } = "Eggs cannot hold items.";
|
||||
public string ItemUnreleased { get; set; } = "Held item is unreleased.";
|
||||
public string ItemEgg { get; init; } = "Eggs cannot hold items.";
|
||||
public string ItemUnreleased { get; init; } = "Held item is unreleased.";
|
||||
|
||||
public string IVAllEqual_0 { get; set; } = "All IVs are {0}.";
|
||||
public string IVNotCorrect { get; set; } = "IVs do not match encounter requirements.";
|
||||
public string IVFlawlessCountGEQ_0 { get; set; } = "Should have at least {0} IVs = 31.";
|
||||
public string IVAllEqual_0 { get; init; } = "All IVs are {0}.";
|
||||
public string IVNotCorrect { get; init; } = "IVs do not match encounter requirements.";
|
||||
public string IVFlawlessCountGEQ_0 { get; init; } = "Should have at least {0} IVs = 31.";
|
||||
|
||||
public string LevelBoostNotZero { get; set; } = "Level Boost should be zero.";
|
||||
public string LevelEXPThreshold { get; set; } = "Current experience matches level threshold.";
|
||||
public string LevelEXPTooHigh { get; set; } = "Current experience exceeds maximum amount for level 100.";
|
||||
public string LevelMetBelow { get; set; } = "Current level is below met level.";
|
||||
public string LevelMetGift { get; set; } = "Met Level does not match Mystery Gift level.";
|
||||
public string LevelMetGiftFail { get; set; } = "Current Level below Mystery Gift level.";
|
||||
public string LevelMetSane { get; set; } = "Current level is not below met level.";
|
||||
public string LevelBoostNotZero { get; init; } = "Level Boost should be zero.";
|
||||
public string LevelEXPThreshold { get; init; } = "Current experience matches level threshold.";
|
||||
public string LevelEXPTooHigh { get; init; } = "Current experience exceeds maximum amount for level 100.";
|
||||
public string LevelMetBelow { get; init; } = "Current level is below met level.";
|
||||
public string LevelMetGift { get; init; } = "Met Level does not match Mystery Gift level.";
|
||||
public string LevelMetGiftFail { get; init; } = "Current Level below Mystery Gift level.";
|
||||
public string LevelMetSane { get; init; } = "Current level is not below met level.";
|
||||
|
||||
public string MarkValueOutOfRange_0 { get; set; } = "Individual marking at index {0} is not within the allowed value range.";
|
||||
public string MarkValueShouldBeZero { get; set; } = "Marking flags cannot be set.";
|
||||
public string MarkValueUnusedBitsPresent { get; set; } = "Marking flags uses bits beyond the accessible range.";
|
||||
public string MarkValueOutOfRange_0 { get; init; } = "Individual marking at index {0} is not within the allowed value range.";
|
||||
public string MarkValueShouldBeZero { get; init; } = "Marking flags cannot be set.";
|
||||
public string MarkValueUnusedBitsPresent { get; init; } = "Marking flags uses bits beyond the accessible range.";
|
||||
|
||||
public string MemoryArgBadCatch_H { get; set; } = "{0} Memory: {0} did not catch this.";
|
||||
public string MemoryArgBadHatch_H { get; set; } = "{0} Memory: {0} did not hatch this.";
|
||||
public string MemoryArgBadHT { get; set; } = "Memory: Can't have Handling Trainer Memory as Egg.";
|
||||
public string MemoryArgBadID_H { get; set; } = "{0} Memory: Can't obtain Memory on {0} Version.";
|
||||
public string MemoryArgBadItem_H1 { get; set; } = "{0} Memory: Species can't hold this item.";
|
||||
public string MemoryArgBadLocation_H { get; set; } = "{0} Memory: Can't obtain Location on {0} Version.";
|
||||
public string MemoryArgBadMove_H1 { get; set; } = "{0} Memory: Species can't learn {1}.";
|
||||
public string MemoryArgBadOTEgg_H { get; set; } = "{0} Memory: Link Trade is not a valid first memory.";
|
||||
public string MemoryArgBadSpecies_H1 { get; set; } = "{0} Memory: Can't capture species in game.";
|
||||
public string MemoryArgSpecies_H { get; set; } = "{0} Memory: Species can be captured in game.";
|
||||
public string MemoryCleared_H { get; set; } = "Memory: Not cleared properly.";
|
||||
public string MemoryValid_H { get; set; } = "{0} Memory is valid.";
|
||||
public string MemoryFeelInvalid_H { get; set; } = "{0} Memory: Invalid Feeling.";
|
||||
public string MemoryHTFlagInvalid { get; set; } = "Untraded: Current handler should not be the Handling Trainer.";
|
||||
public string MemoryHTGender_0 { get; set; } = "HT Gender invalid: {0}";
|
||||
public string MemoryHTLanguage { get; set; } = "HT Language is missing.";
|
||||
public string MemoryArgBadCatch_H { get; init; } = "{0} Memory: {0} did not catch this.";
|
||||
public string MemoryArgBadHatch_H { get; init; } = "{0} Memory: {0} did not hatch this.";
|
||||
public string MemoryArgBadHT { get; init; } = "Memory: Can't have Handling Trainer Memory as Egg.";
|
||||
public string MemoryArgBadID_H { get; init; } = "{0} Memory: Can't obtain Memory on {0} Version.";
|
||||
public string MemoryArgBadItem_H1 { get; init; } = "{0} Memory: Species can't hold this item.";
|
||||
public string MemoryArgBadLocation_H { get; init; } = "{0} Memory: Can't obtain Location on {0} Version.";
|
||||
public string MemoryArgBadMove_H1 { get; init; } = "{0} Memory: Species can't learn {1}.";
|
||||
public string MemoryArgBadOTEgg_H { get; init; } = "{0} Memory: Link Trade is not a valid first memory.";
|
||||
public string MemoryArgBadSpecies_H1 { get; init; } = "{0} Memory: Can't capture species in game.";
|
||||
public string MemoryArgSpecies_H { get; init; } = "{0} Memory: Species can be captured in game.";
|
||||
public string MemoryCleared_H { get; init; } = "Memory: Not cleared properly.";
|
||||
public string MemoryValid_H { get; init; } = "{0} Memory is valid.";
|
||||
public string MemoryFeelInvalid_H { get; init; } = "{0} Memory: Invalid Feeling.";
|
||||
public string MemoryHTFlagInvalid { get; init; } = "Untraded: Current handler should not be the Handling Trainer.";
|
||||
public string MemoryHTGender_0 { get; init; } = "HT Gender invalid: {0}";
|
||||
public string MemoryHTLanguage { get; init; } = "HT Language is missing.";
|
||||
|
||||
public string MemoryIndexArgHT { get; set; } = "Should have a HT Memory TextVar value (somewhere).";
|
||||
public string MemoryIndexFeel_H1 { get; set; } = "{0} Memory: Feeling should be index {1}.";
|
||||
public string MemoryIndexFeelHTLEQ9 { get; set; } = "Should have a HT Memory Feeling value 0-9.";
|
||||
public string MemoryIndexID_H1 { get; set; } = "{0} Memory: Should be index {1}.";
|
||||
public string MemoryIndexIntensity_H1 { get; set; } = "{0} Memory: Intensity should be index {1}.";
|
||||
public string MemoryIndexIntensityHT1 { get; set; } = "Should have a HT Memory Intensity value (1st).";
|
||||
public string MemoryIndexIntensityMin_H1 { get; set; } = "{0} Memory: Intensity should be at least {1}.";
|
||||
public string MemoryIndexLinkHT { get; set; } = "Should have a Link Trade HT Memory.";
|
||||
public string MemoryIndexVar { get; set; } = "{0} Memory: TextVar should be index {1}.";
|
||||
public string MemoryMissingHT { get; set; } = "Memory: Handling Trainer Memory missing.";
|
||||
public string MemoryMissingOT { get; set; } = "Memory: Original Trainer Memory missing.";
|
||||
public string MemoryIndexArgHT { get; init; } = "Should have a HT Memory TextVar value (somewhere).";
|
||||
public string MemoryIndexFeel_H1 { get; init; } = "{0} Memory: Feeling should be index {1}.";
|
||||
public string MemoryIndexFeelHTLEQ9 { get; init; } = "Should have a HT Memory Feeling value 0-9.";
|
||||
public string MemoryIndexID_H1 { get; init; } = "{0} Memory: Should be index {1}.";
|
||||
public string MemoryIndexIntensity_H1 { get; init; } = "{0} Memory: Intensity should be index {1}.";
|
||||
public string MemoryIndexIntensityHT1 { get; init; } = "Should have a HT Memory Intensity value (1st).";
|
||||
public string MemoryIndexIntensityMin_H1 { get; init; } = "{0} Memory: Intensity should be at least {1}.";
|
||||
public string MemoryIndexLinkHT { get; init; } = "Should have a Link Trade HT Memory.";
|
||||
public string MemoryIndexVar { get; init; } = "{0} Memory: TextVar should be index {1}.";
|
||||
public string MemoryMissingHT { get; init; } = "Memory: Handling Trainer Memory missing.";
|
||||
public string MemoryMissingOT { get; init; } = "Memory: Original Trainer Memory missing.";
|
||||
|
||||
public string MemorySocialZero { get; set; } = "Social Stat should be zero.";
|
||||
public string MemoryStatSocialLEQ_0 { get; set; } = "Social Stat should be <= {0}";
|
||||
public string MemorySocialZero { get; init; } = "Social Stat should be zero.";
|
||||
public string MemoryStatSocialLEQ_0 { get; init; } = "Social Stat should be <= {0}";
|
||||
|
||||
public string MemoryStatAffectionHT0 { get; set; } = "Untraded: Handling Trainer Affection should be 0.";
|
||||
public string MemoryStatAffectionOT0 { get; set; } = "OT Affection should be 0.";
|
||||
public string MemoryStatFriendshipHT0 { get; set; } = "Untraded: Handling Trainer Friendship should be 0.";
|
||||
public string MemoryStatFriendshipOTBaseEvent_0 { get; set; } = "Event OT Friendship does not match base friendship ({0}).";
|
||||
public string MemoryStatAffectionHT0 { get; init; } = "Untraded: Handling Trainer Affection should be 0.";
|
||||
public string MemoryStatAffectionOT0 { get; init; } = "OT Affection should be 0.";
|
||||
public string MemoryStatFriendshipHT0 { get; init; } = "Untraded: Handling Trainer Friendship should be 0.";
|
||||
public string MemoryStatFriendshipOTBaseEvent_0 { get; init; } = "Event OT Friendship does not match base friendship ({0}).";
|
||||
|
||||
public string MetDetailTimeOfDay { get; set; } = "Met Time of Day value is not within the expected range.";
|
||||
public string MoveEvoFCombination_0 { get; set; } = "Moves combinations is not compatible with {0} evolution.";
|
||||
public string MoveFExpectSingle_0 { get; set; } = "Expected: {0}";
|
||||
public string MoveKeldeoMismatch { get; set; } = "Keldeo Move/Form mismatch.";
|
||||
public string MovePPExpectHealed_01 { get; set; } = "Move {0} PP is below the amount expected ({1}).";
|
||||
public string MovePPTooHigh_01 { get; set; } = "Move {0} PP is above the amount allowed ({1}).";
|
||||
public string MovePPUpsTooHigh_01 { get; set; } = "Move {0} PP Ups is above the amount allowed ({1}).";
|
||||
public string MetDetailTimeOfDay { get; init; } = "Met Time of Day value is not within the expected range.";
|
||||
public string MoveEvoFCombination_0 { get; init; } = "Moves combinations is not compatible with {0} evolution.";
|
||||
public string MoveFExpectSingle_0 { get; init; } = "Expected: {0}";
|
||||
public string MoveKeldeoMismatch { get; init; } = "Keldeo Move/Form mismatch.";
|
||||
public string MovePPExpectHealed_01 { get; init; } = "Move {0} PP is below the amount expected ({1}).";
|
||||
public string MovePPTooHigh_01 { get; init; } = "Move {0} PP is above the amount allowed ({1}).";
|
||||
public string MovePPUpsTooHigh_01 { get; init; } = "Move {0} PP Ups is above the amount allowed ({1}).";
|
||||
|
||||
public string MoveShopAlphaMoveShouldBeMastered_0 { get; set; } = "Alpha Move should be marked as mastered.";
|
||||
public string MoveShopAlphaMoveShouldBeOther { get; set; } = "Alpha encounter cannot be found with this Alpha Move.";
|
||||
public string MoveShopAlphaMoveShouldBeZero { get; set; } = "Only Alphas may have an Alpha Move set.";
|
||||
public string MoveShopMasterInvalid_0 { get; set; } = "Cannot manually master {0}: not permitted to master.";
|
||||
public string MoveShopMasterNotLearned_0 { get; set; } = "Cannot manually master {0}: not in possible learned level up moves.";
|
||||
public string MoveShopPurchaseInvalid_0 { get; set; } = "Cannot purchase {0} from the move shop.";
|
||||
public string MoveShopAlphaMoveShouldBeMastered_0 { get; init; } = "Alpha Move should be marked as mastered.";
|
||||
public string MoveShopAlphaMoveShouldBeOther { get; init; } = "Alpha encounter cannot be found with this Alpha Move.";
|
||||
public string MoveShopAlphaMoveShouldBeZero { get; init; } = "Only Alphas may have an Alpha Move set.";
|
||||
public string MoveShopMasterInvalid_0 { get; init; } = "Cannot manually master {0}: not permitted to master.";
|
||||
public string MoveShopMasterNotLearned_0 { get; init; } = "Cannot manually master {0}: not in possible learned level up moves.";
|
||||
public string MoveShopPurchaseInvalid_0 { get; init; } = "Cannot purchase {0} from the move shop.";
|
||||
|
||||
public string MoveTechRecordFlagMissing_0 { get; set; } = "Unexpected Technical Record Learned flag: {0}";
|
||||
public string MoveTechRecordFlagMissing_0 { get; init; } = "Unexpected Technical Record Learned flag: {0}";
|
||||
|
||||
public string NickFlagEggNo { get; set; } = "Egg must be not nicknamed.";
|
||||
public string NickFlagEggYes { get; set; } = "Egg must be nicknamed.";
|
||||
public string NickInvalidChar { get; set; } = "Cannot be given this Nickname.";
|
||||
public string NickLengthLong { get; set; } = "Nickname too long.";
|
||||
public string NickLengthShort { get; set; } = "Nickname is empty.";
|
||||
public string NickMatchLanguage { get; set; } = "Nickname matches species name.";
|
||||
public string NickMatchLanguageEgg { get; set; } = "Egg matches language Egg name.";
|
||||
public string NickMatchLanguageEggFail { get; set; } = "Egg name does not match language Egg name.";
|
||||
public string NickMatchLanguageFail { get; set; } = "Nickname does not match species name.";
|
||||
public string NickMatchLanguageFlag { get; set; } = "Nickname flagged, matches species name.";
|
||||
public string NickMatchNoOthers { get; set; } = "Nickname does not match another species name.";
|
||||
public string NickMatchNoOthersFail { get; set; } = "Nickname matches another species name (+language).";
|
||||
public string NickFlagEggNo { get; init; } = "Egg must be not nicknamed.";
|
||||
public string NickFlagEggYes { get; init; } = "Egg must be nicknamed.";
|
||||
public string NickInvalidChar { get; init; } = "Cannot be given this Nickname.";
|
||||
public string NickLengthLong { get; init; } = "Nickname too long.";
|
||||
public string NickLengthShort { get; init; } = "Nickname is empty.";
|
||||
public string NickMatchLanguage { get; init; } = "Nickname matches species name.";
|
||||
public string NickMatchLanguageEgg { get; init; } = "Egg matches language Egg name.";
|
||||
public string NickMatchLanguageEggFail { get; init; } = "Egg name does not match language Egg name.";
|
||||
public string NickMatchLanguageFail { get; init; } = "Nickname does not match species name.";
|
||||
public string NickMatchLanguageFlag { get; init; } = "Nickname flagged, matches species name.";
|
||||
public string NickMatchNoOthers { get; init; } = "Nickname does not match another species name.";
|
||||
public string NickMatchNoOthersFail { get; init; } = "Nickname matches another species name (+language).";
|
||||
|
||||
public string OTLanguage { get; set; } = "Language ID should be {0}, not {1}.";
|
||||
public string OTLong { get; set; } = "OT Name too long.";
|
||||
public string OTShort { get; set; } = "OT Name too short.";
|
||||
public string OTSuspicious { get; set; } = "Suspicious Original Trainer details.";
|
||||
public string OTLanguage { get; init; } = "Language ID should be {0}, not {1}.";
|
||||
public string OTLong { get; init; } = "OT Name too long.";
|
||||
public string OTShort { get; init; } = "OT Name too short.";
|
||||
public string OTSuspicious { get; init; } = "Suspicious Original Trainer details.";
|
||||
|
||||
public string OT_IDEqual { get; set; } = "TID16 and SID16 are equal.";
|
||||
public string OT_IDs0 { get; set; } = "TID16 and SID16 are 0.";
|
||||
public string OT_SID0 { get; set; } = "SID16 is zero.";
|
||||
public string OT_SID0Invalid { get; set; } = "SID16 should be 0.";
|
||||
public string OT_TID0 { get; set; } = "TID16 is zero.";
|
||||
public string OT_IDInvalid { get; set; } = "TID16 and SID16 combination is not possible.";
|
||||
public string OT_IDEqual { get; init; } = "TID16 and SID16 are equal.";
|
||||
public string OT_IDs0 { get; init; } = "TID16 and SID16 are 0.";
|
||||
public string OT_SID0 { get; init; } = "SID16 is zero.";
|
||||
public string OT_SID0Invalid { get; init; } = "SID16 should be 0.";
|
||||
public string OT_TID0 { get; init; } = "TID16 is zero.";
|
||||
public string OT_IDInvalid { get; init; } = "TID16 and SID16 combination is not possible.";
|
||||
|
||||
public string PIDEncryptWurmple { get; set; } = "Wurmple evolution Encryption Constant mismatch.";
|
||||
public string PIDEncryptZero { get; set; } = "Encryption Constant is not set.";
|
||||
public string PIDEqualsEC { get; set; } = "Encryption Constant matches PID.";
|
||||
public string PIDGenderMatch { get; set; } = "Gender matches PID.";
|
||||
public string PIDGenderMismatch { get; set; } = "PID-Gender mismatch.";
|
||||
public string PIDNatureMatch { get; set; } = "Nature matches PID.";
|
||||
public string PIDNatureMismatch { get; set; } = "PID-Nature mismatch.";
|
||||
public string PIDTypeMismatch { get; set; } = "PID+ correlation does not match what was expected for the Encounter's type.";
|
||||
public string PIDZero { get; set; } = "PID is not set.";
|
||||
public string PIDEncryptWurmple { get; init; } = "Wurmple evolution Encryption Constant mismatch.";
|
||||
public string PIDEncryptZero { get; init; } = "Encryption Constant is not set.";
|
||||
public string PIDEqualsEC { get; init; } = "Encryption Constant matches PID.";
|
||||
public string PIDGenderMatch { get; init; } = "Gender matches PID.";
|
||||
public string PIDGenderMismatch { get; init; } = "PID-Gender mismatch.";
|
||||
public string PIDNatureMatch { get; init; } = "Nature matches PID.";
|
||||
public string PIDNatureMismatch { get; init; } = "PID-Nature mismatch.";
|
||||
public string PIDTypeMismatch { get; init; } = "PID+ correlation does not match what was expected for the Encounter's type.";
|
||||
public string PIDZero { get; init; } = "PID is not set.";
|
||||
|
||||
public string PlusMoveAlphaMissing_0 { get; set; } = "Expected to have mastered the move {0} when encountered as an alpha.";
|
||||
public string PlusMoveMultipleInvalid { get; set; } = "Multiple Plus Move flags are invalid.";
|
||||
public string PlusMoveInvalid_0 { get; set; } = "{0} cannot be learned and set as a Plus Move.";
|
||||
public string PlusMoveSufficientLevelMissing_0 { get; set; } = "Plus Move flag for {0} must be set."; // as the Pokémon's current level is above the level it becomes available for use as a Plus Move.
|
||||
public string PlusMoveCountInvalid { get; set; } = "Out of range Plus Move flag index is set.";
|
||||
public string PlusMoveAlphaMissing_0 { get; init; } = "Expected to have mastered the move {0} when encountered as an alpha.";
|
||||
public string PlusMoveMultipleInvalid { get; init; } = "Multiple Plus Move flags are invalid.";
|
||||
public string PlusMoveInvalid_0 { get; init; } = "{0} cannot be learned and set as a Plus Move.";
|
||||
public string PlusMoveSufficientLevelMissing_0 { get; init; } = "Plus Move flag for {0} must be set."; // as the Pokémon's current level is above the level it becomes available for use as a Plus Move.
|
||||
public string PlusMoveCountInvalid { get; init; } = "Out of range Plus Move flag index is set.";
|
||||
|
||||
public string PokerusDaysTooHigh_0 { get; set; } = "Pokérus Days Remaining value is too high; expected <= {0}.";
|
||||
public string PokerusStrainUnobtainable_0 { get; set; } = "Pokérus Strain {0} cannot be obtained.";
|
||||
public string PokerusDaysTooHigh_0 { get; init; } = "Pokérus Days Remaining value is too high; expected <= {0}.";
|
||||
public string PokerusStrainUnobtainable_0 { get; init; } = "Pokérus Strain {0} cannot be obtained.";
|
||||
|
||||
public string RibbonAllValid { get; set; } = "All ribbons accounted for.";
|
||||
public string RibbonEgg { get; set; } = "Can't receive Ribbon(s) as an Egg.";
|
||||
public string RibbonsInvalid_0 { get; set; } = "Invalid Ribbons: {0}";
|
||||
public string RibbonsMissing_0 { get; set; } = "Missing Ribbons: {0}";
|
||||
public string RibbonMarkingInvalid_0 { get; set; } = "Invalid Marking: {0}";
|
||||
public string RibbonMarkingMissing_0 { get; set; } = "Missing Marking: {0}";
|
||||
public string RibbonMarkingAffixed_0 { get; set; } = "Invalid Affixed Ribbon/Marking: {0}";
|
||||
public string RibbonAllValid { get; init; } = "All ribbons accounted for.";
|
||||
public string RibbonEgg { get; init; } = "Can't receive Ribbon(s) as an Egg.";
|
||||
public string RibbonsInvalid_0 { get; init; } = "Invalid Ribbons: {0}";
|
||||
public string RibbonsMissing_0 { get; init; } = "Missing Ribbons: {0}";
|
||||
public string RibbonMarkingInvalid_0 { get; init; } = "Invalid Marking: {0}";
|
||||
public string RibbonMarkingMissing_0 { get; init; } = "Missing Marking: {0}";
|
||||
public string RibbonMarkingAffixed_0 { get; init; } = "Invalid Affixed Ribbon/Marking: {0}";
|
||||
|
||||
public string StatDynamaxInvalid { get; set; } = "Dynamax Level is not within the expected range.";
|
||||
public string StatIncorrectHeight { get; set; } = "Calculated Height does not match stored value.";
|
||||
public string StatIncorrectWeight { get; set; } = "Calculated Weight does not match stored value.";
|
||||
public string StatIncorrectHeightValue_0 { get; set; } = "Height should be {0}.";
|
||||
public string StatIncorrectWeightValue_0 { get; set; } = "Weight should be {0}.";
|
||||
public string StatIncorrectScaleValue_0 { get; set; } = "Scale should be {0}.";
|
||||
public string StatInvalidHeightWeight { get; set; } = "Height / Weight values are statistically improbable.";
|
||||
public string StatIncorrectCP { get; set; } = "Calculated CP does not match stored value.";
|
||||
public string StatGigantamaxInvalid { get; set; } = "Gigantamax Flag mismatch.";
|
||||
public string StatGigantamaxValid { get; set; } = "Gigantamax Flag was changed via Max Soup.";
|
||||
public string StatNatureInvalid { get; set; } = "Stat Nature is not within the expected range.";
|
||||
public string StatBattleVersionInvalid { get; set; } = "Battle Version is not within the expected range.";
|
||||
public string StatNobleInvalid { get; set; } = "Noble Flag mismatch.";
|
||||
public string StatAlphaInvalid { get; set; } = "Alpha Flag mismatch.";
|
||||
public string StatDynamaxInvalid { get; init; } = "Dynamax Level is not within the expected range.";
|
||||
public string StatIncorrectHeight { get; init; } = "Calculated Height does not match stored value.";
|
||||
public string StatIncorrectWeight { get; init; } = "Calculated Weight does not match stored value.";
|
||||
public string StatIncorrectHeightValue_0 { get; init; } = "Height should be {0}.";
|
||||
public string StatIncorrectWeightValue_0 { get; init; } = "Weight should be {0}.";
|
||||
public string StatIncorrectScaleValue_0 { get; init; } = "Scale should be {0}.";
|
||||
public string StatInvalidHeightWeight { get; init; } = "Height / Weight values are statistically improbable.";
|
||||
public string StatIncorrectCP { get; init; } = "Calculated CP does not match stored value.";
|
||||
public string StatGigantamaxInvalid { get; init; } = "Gigantamax Flag mismatch.";
|
||||
public string StatGigantamaxValid { get; init; } = "Gigantamax Flag was changed via Max Soup.";
|
||||
public string StatNatureInvalid { get; init; } = "Stat Nature is not within the expected range.";
|
||||
public string StatBattleVersionInvalid { get; init; } = "Battle Version is not within the expected range.";
|
||||
public string StatNobleInvalid { get; init; } = "Noble Flag mismatch.";
|
||||
public string StatAlphaInvalid { get; init; } = "Alpha Flag mismatch.";
|
||||
|
||||
public string StoredSourceEgg { get; set; } = "Egg must be in Box or Party.";
|
||||
public string StoredSlotSourceInvalid_0 { get; set; } = "Invalid Stored Source: {0}";
|
||||
public string StoredSourceEgg { get; init; } = "Egg must be in Box or Party.";
|
||||
public string StoredSlotSourceInvalid_0 { get; init; } = "Invalid Stored Source: {0}";
|
||||
|
||||
public string SuperComplete { get; set; } = "Super Training complete flag mismatch.";
|
||||
public string SuperDistro { get; set; } = "Distribution Super Training missions are not released.";
|
||||
public string SuperEgg { get; set; } = "Can't Super Train an Egg.";
|
||||
public string SuperNoComplete { get; set; } = "Can't have active Super Training complete flag for origins.";
|
||||
public string SuperNoUnlocked { get; set; } = "Can't have active Super Training unlocked flag for origins.";
|
||||
public string SuperUnavailable { get; set; } = "Super Training missions are not available in games visited.";
|
||||
public string SuperUnused { get; set; } = "Unused Super Training Flag is flagged.";
|
||||
public string G6SuperTrainEggBag { get; set; } = "Egg cannot use a Training Bag.";
|
||||
public string G6SuperTrainEggHits { get; set; } = "Eggs cannot hit Training Bags.";
|
||||
public string G6SuperTrainBagInvalid_0 { get; set; } = "Unrecognized Training Bag ID: {0}";
|
||||
public string G6SuperTrainBagHitsInvalid_012 { get; set; } = "Training bag cannot have {0} hits; expected value within [{1},{2}].";
|
||||
public string SuperComplete { get; init; } = "Super Training complete flag mismatch.";
|
||||
public string SuperDistro { get; init; } = "Distribution Super Training missions are not released.";
|
||||
public string SuperEgg { get; init; } = "Can't Super Train an Egg.";
|
||||
public string SuperNoComplete { get; init; } = "Can't have active Super Training complete flag for origins.";
|
||||
public string SuperNoUnlocked { get; init; } = "Can't have active Super Training unlocked flag for origins.";
|
||||
public string SuperUnavailable { get; init; } = "Super Training missions are not available in games visited.";
|
||||
public string SuperUnused { get; init; } = "Unused Super Training Flag is flagged.";
|
||||
public string G6SuperTrainEggBag { get; init; } = "Egg cannot use a Training Bag.";
|
||||
public string G6SuperTrainEggHits { get; init; } = "Eggs cannot hit Training Bags.";
|
||||
public string G6SuperTrainBagInvalid_0 { get; init; } = "Unrecognized Training Bag ID: {0}";
|
||||
public string G6SuperTrainBagHitsInvalid_012 { get; init; } = "Training bag cannot have {0} hits; expected value within [{1},{2}].";
|
||||
|
||||
public string TeraTypeIncorrect { get; set; } = "Tera Type does not match the expected value.";
|
||||
public string TeraTypeMismatch { get; set; } = "Tera Type does not match either of the default types.";
|
||||
public string TeraTypeIncorrect { get; init; } = "Tera Type does not match the expected value.";
|
||||
public string TeraTypeMismatch { get; init; } = "Tera Type does not match either of the default types.";
|
||||
|
||||
public string TradeNotAvailable { get; set; } = "Encounter cannot be traded to the active trainer.";
|
||||
public string TradeNotAvailable { get; init; } = "Encounter cannot be traded to the active trainer.";
|
||||
|
||||
public string TrainerIDNoSeed { get; set; } = "Trainer ID is not obtainable from any RNG seed.";
|
||||
public string TrainerIDNoSeed { get; init; } = "Trainer ID is not obtainable from any RNG seed.";
|
||||
|
||||
public string TransferBad { get; set; } = "Incorrectly transferred from previous generation.";
|
||||
public string TransferBad { get; init; } = "Incorrectly transferred from previous generation.";
|
||||
|
||||
public string TransferCurrentHandlerInvalid { get; set; } = "Invalid Current handler value, trainer details for save file expected another value.";
|
||||
public string TransferEgg { get; set; } = "Can't transfer Eggs between Generations.";
|
||||
public string TransferEggLocationTransporter { get; set; } = "Invalid Met Location, expected Poké Transfer.";
|
||||
public string TransferEggMetLevel { get; set; } = "Invalid Met Level for transfer.";
|
||||
public string TransferEggVersion { get; set; } = "Can't transfer Eggs to this game.";
|
||||
public string TransferFlagIllegal { get; set; } = "Flagged as illegal by the game (glitch abuse).";
|
||||
public string TransferHTFlagRequired { get; set; } = "Current handler cannot be the OT.";
|
||||
public string TransferHTMismatchName { get; set; } = "Handling trainer does not match the expected trainer name.";
|
||||
public string TransferHTMismatchGender { get; set; } = "Handling trainer does not match the expected trainer gender.";
|
||||
public string TransferHTMismatchLanguage { get; set; } = "Handling trainer does not match the expected trainer language.";
|
||||
public string TransferKoreanGen4 { get; set; } = "Korean Generation 4 games cannot interact with International Generation 4 games.";
|
||||
public string TransferMet { get; set; } = "Invalid Met Location, expected Poké Transfer or Crown.";
|
||||
public string TransferNotPossible { get; set; } = "Unable to transfer into current format from origin format.";
|
||||
public string TransferMetLocation { get; set; } = "Invalid Transfer Met Location.";
|
||||
public string TransferNature { get; set; } = "Invalid Nature for transfer Experience.";
|
||||
public string TransferObedienceLevel { get; set; } = "Invalid Obedience Level.";
|
||||
public string TransferPIDECBitFlip { get; set; } = "PID should be equal to EC [with top bit flipped]!";
|
||||
public string TransferPIDECEquals { get; set; } = "PID should be equal to EC!";
|
||||
public string TransferPIDECXor { get; set; } = "Encryption Constant matches shinyxored PID.";
|
||||
public string TransferTrackerMissing { get; set; } = "Pokémon HOME Transfer Tracker is missing.";
|
||||
public string TransferTrackerShouldBeZero { get; set; } = "Pokémon HOME Transfer Tracker should be 0.";
|
||||
public string TransferCurrentHandlerInvalid { get; init; } = "Invalid Current handler value, trainer details for save file expected another value.";
|
||||
public string TransferEgg { get; init; } = "Can't transfer Eggs between Generations.";
|
||||
public string TransferEggLocationTransporter { get; init; } = "Invalid Met Location, expected Poké Transfer.";
|
||||
public string TransferEggMetLevel { get; init; } = "Invalid Met Level for transfer.";
|
||||
public string TransferEggVersion { get; init; } = "Can't transfer Eggs to this game.";
|
||||
public string TransferFlagIllegal { get; init; } = "Flagged as illegal by the game (glitch abuse).";
|
||||
public string TransferHTFlagRequired { get; init; } = "Current handler cannot be the OT.";
|
||||
public string TransferHTMismatchName { get; init; } = "Handling trainer does not match the expected trainer name.";
|
||||
public string TransferHTMismatchGender { get; init; } = "Handling trainer does not match the expected trainer gender.";
|
||||
public string TransferHTMismatchLanguage { get; init; } = "Handling trainer does not match the expected trainer language.";
|
||||
public string TransferKoreanGen4 { get; init; } = "Korean Generation 4 games cannot interact with International Generation 4 games.";
|
||||
public string TransferMet { get; init; } = "Invalid Met Location, expected Poké Transfer or Crown.";
|
||||
public string TransferNotPossible { get; init; } = "Unable to transfer into current format from origin format.";
|
||||
public string TransferMetLocation { get; init; } = "Invalid Transfer Met Location.";
|
||||
public string TransferNature { get; init; } = "Invalid Nature for transfer Experience.";
|
||||
public string TransferObedienceLevel { get; init; } = "Invalid Obedience Level.";
|
||||
public string TransferPIDECBitFlip { get; init; } = "PID should be equal to EC [with top bit flipped]!";
|
||||
public string TransferPIDECEquals { get; init; } = "PID should be equal to EC!";
|
||||
public string TransferPIDECXor { get; init; } = "Encryption Constant matches shiny-xor'd PID.";
|
||||
public string TransferTrackerMissing { get; init; } = "Pokémon HOME Transfer Tracker is missing.";
|
||||
public string TransferTrackerShouldBeZero { get; init; } = "Pokémon HOME Transfer Tracker should be 0.";
|
||||
|
||||
public string TrashBytesExpected { get; set; } = "Expected Trash Bytes.";
|
||||
public string TrashBytesMismatchInitial { get; set; } = "Expected initial trash bytes to match the encounter.";
|
||||
public string TrashBytesMissingTerminator { get; set; } = "Final terminator missing.";
|
||||
public string TrashBytesShouldBeEmpty { get; set; } = "Trash Bytes should be cleared.";
|
||||
public string TrashBytesExpected { get; init; } = "Expected Trash Bytes.";
|
||||
public string TrashBytesMismatchInitial { get; init; } = "Expected initial trash bytes to match the encounter.";
|
||||
public string TrashBytesMissingTerminatorFinal { get; init; } = "Final terminator missing.";
|
||||
public string TrashBytesShouldBeEmpty { get; init; } = "Trash Bytes should be cleared.";
|
||||
public string TrashBytesResetViaTransfer { get; init; } = "Trash Bytes were reset via transfer.";
|
||||
|
||||
#endregion
|
||||
|
||||
public string EncTradeShouldHaveEvolvedToSpecies_0 { get; set; } = "Trade Encounter should have evolved to species: {0}.";
|
||||
public string EncGiftLanguageNotDistributed { get; set; } = "Gift Encounter was never distributed with this language.";
|
||||
public string EncGiftRegionNotDistributed { get; set; } = "Gift Encounter was never distributed to this Console Region.";
|
||||
public string FormInvalidRangeLEQ_0F { get; set; } = "Form Count is out of range. Expected <= {0}, got {1}.";
|
||||
public string MovesShouldMatchRelearnMoves { get; set; } = "Moves should exactly match Relearn Moves.";
|
||||
public string MemoryStatEnjoyment_0 { get; set; } = "Enjoyment should be {0}.";
|
||||
public string MemoryStatFullness_0 { get; set; } = "Fullness should be {0}.";
|
||||
public string MemoryStatFullnessLEQ_0 { get; set; } = "Fullness should be <= {0}.";
|
||||
public string OTLanguageShouldBe_0 { get; set; } = "Language ID should be {0}, not {1}.";
|
||||
public string OTLanguageShouldBe_0or1 { get; set; } = "Language ID should be {0} or {1}, not {2}.";
|
||||
public string OTLanguageShouldBeLeq_0 { get; set; } = "Language ID should be <= {0}, not {1}.";
|
||||
public string OTLanguageCannotPlayOnVersion_0 { get; set; } = "Language ID {0} cannot be played on this version.";
|
||||
public string OTLanguageCannotTransferToConsoleRegion_0 { get; set; } = "Language ID {0} cannot be transferred to this Console Region.";
|
||||
public string EncTradeShouldHaveEvolvedToSpecies_0 { get; init; } = "Trade Encounter should have evolved to species: {0}.";
|
||||
public string EncGiftLanguageNotDistributed { get; init; } = "Gift Encounter was never distributed with this language.";
|
||||
public string EncGiftRegionNotDistributed { get; init; } = "Gift Encounter was never distributed to this Console Region.";
|
||||
public string FormInvalidRangeLEQ_0F { get; init; } = "Form Count is out of range. Expected <= {0}, got {1}.";
|
||||
public string MovesShouldMatchRelearnMoves { get; init; } = "Moves should exactly match Relearn Moves.";
|
||||
public string MemoryStatEnjoyment_0 { get; init; } = "Enjoyment should be {0}.";
|
||||
public string MemoryStatFullness_0 { get; init; } = "Fullness should be {0}.";
|
||||
public string MemoryStatFullnessLEQ_0 { get; init; } = "Fullness should be <= {0}.";
|
||||
public string OTLanguageShouldBe_0 { get; init; } = "Language ID should be {0}, not {1}.";
|
||||
public string OTLanguageShouldBe_0or1 { get; init; } = "Language ID should be {0} or {1}, not {2}.";
|
||||
public string OTLanguageShouldBeLeq_0 { get; init; } = "Language ID should be <= {0}, not {1}.";
|
||||
public string OTLanguageCannotPlayOnVersion_0 { get; init; } = "Language ID {0} cannot be played on this version.";
|
||||
public string OTLanguageCannotTransferToConsoleRegion_0 { get; init; } = "Language ID {0} cannot be transferred to this Console Region.";
|
||||
|
||||
public string WordFilterInvalidCharacter_0 { get; set; } = "Word Filter: Invalid character '{0}' (0x{1}).";
|
||||
public string WordFilterFlaggedPattern_01 { get; set; } = "Word Filter ({1}): Flagged pattern '{0}'.";
|
||||
public string WordFilterTooManyNumbers_0 { get; set; } = "Word Filter: Too many numbers (>{0}).";
|
||||
public string BulkCloneDetectedDetails { get; set; } = "Clone detected (Details).";
|
||||
public string BulkCloneDetectedTracker { get; set; } = "Clone detected (Duplicate Tracker).";
|
||||
public string HintEvolvesToSpecies_0 { get; set; } = "Evolves to species: {0}.";
|
||||
public string HintEvolvesToRareForm_0 { get; set; } = "Evolves to rare form: {0}.";
|
||||
public string BulkSharingEncryptionConstantGenerationDifferent { get; set; } = "Detected sharing of Encryption Constant across generations.";
|
||||
public string BulkSharingEncryptionConstantGenerationSame { get; set; } = "Detected sharing of Encryption Constant.";
|
||||
public string BulkSharingEncryptionConstantRNGType { get; set; } = "Detected sharing of Encryption Constant sharing for different RNG encounters.";
|
||||
public string BulkSharingPIDGenerationDifferent { get; set; } = "Detected sharing of PID across generations.";
|
||||
public string BulkSharingPIDGenerationSame { get; set; } = "Detected sharing of PID.";
|
||||
public string BulkSharingPIDRNGType { get; set; } = "Detected sharing of PID for different RNG encounters.";
|
||||
public string BulkDuplicateMysteryGiftEggReceived { get; set; } = "Detected multiple redemptions of the same non-repeatable Mystery Gift Egg.";
|
||||
public string BulkSharingTrainerID { get; set; } = "Detected sharing of Trainer ID across multiple trainer names.";
|
||||
public string BulkSharingTrainerVersion { get; set; } = "Detected sharing of Trainer ID across multiple versions.";
|
||||
public string BulkDuplicateFusionSlot { get; set; } = "Detected multiple fusions of the same fusion stored slot species.";
|
||||
public string BulkHeldItemInventoryAssignedNoneHeld_0 { get; set; } = "{0} is marked as held player inventory, but no Pokémon found in slots checked.";
|
||||
public string BulkHeldItemInventoryMultipleSlots_0 { get; set; } = "{0} is a unique item and cannot be held by multiple Pokémon.";
|
||||
public string BulkHeldItemInventoryNotAcquired_0 { get; set; } = "{0} has not been acquired in player inventory.";
|
||||
public string BulkHeldItemInventoryUnassigned_0 { get; set; } = "{0} is not marked as assigned in player inventory.";
|
||||
public string BulkFusionSourceInvalid { get; set; } = "The subsumed Species-Form stored in the save file does not match the expected Species-Form of the fused slot.";
|
||||
public string WordFilterInvalidCharacter_0 { get; init; } = "Word Filter: Invalid character '{0}' (0x{1}).";
|
||||
public string WordFilterFlaggedPattern_01 { get; init; } = "Word Filter ({1}): Flagged pattern '{0}'.";
|
||||
public string WordFilterTooManyNumbers_0 { get; init; } = "Word Filter: Too many numbers (>{0}).";
|
||||
public string BulkCloneDetectedDetails { get; init; } = "Clone detected (Details).";
|
||||
public string BulkCloneDetectedTracker { get; init; } = "Clone detected (Duplicate Tracker).";
|
||||
public string HintEvolvesToSpecies_0 { get; init; } = "Evolves to species: {0}.";
|
||||
public string HintEvolvesToRareForm_0 { get; init; } = "Evolves to rare form: {0}.";
|
||||
public string BulkSharingEncryptionConstantGenerationDifferent { get; init; } = "Detected sharing of Encryption Constant across generations.";
|
||||
public string BulkSharingEncryptionConstantGenerationSame { get; init; } = "Detected sharing of Encryption Constant.";
|
||||
public string BulkSharingEncryptionConstantRNGType { get; init; } = "Detected sharing of Encryption Constant sharing for different RNG encounters.";
|
||||
public string BulkSharingPIDGenerationDifferent { get; init; } = "Detected sharing of PID across generations.";
|
||||
public string BulkSharingPIDGenerationSame { get; init; } = "Detected sharing of PID.";
|
||||
public string BulkSharingPIDRNGType { get; init; } = "Detected sharing of PID for different RNG encounters.";
|
||||
public string BulkDuplicateMysteryGiftEggReceived { get; init; } = "Detected multiple redemptions of the same non-repeatable Mystery Gift Egg.";
|
||||
public string BulkSharingTrainerID { get; init; } = "Detected sharing of Trainer ID across multiple trainer names.";
|
||||
public string BulkSharingTrainerVersion { get; init; } = "Detected sharing of Trainer ID across multiple versions.";
|
||||
public string BulkDuplicateFusionSlot { get; init; } = "Detected multiple fusions of the same fusion stored slot species.";
|
||||
public string BulkHeldItemInventoryAssignedNoneHeld_0 { get; init; } = "{0} is marked as held player inventory, but no Pokémon found in slots checked.";
|
||||
public string BulkHeldItemInventoryMultipleSlots_0 { get; init; } = "{0} is a unique item and cannot be held by multiple Pokémon.";
|
||||
public string BulkHeldItemInventoryNotAcquired_0 { get; init; } = "{0} has not been acquired in player inventory.";
|
||||
public string BulkHeldItemInventoryUnassigned_0 { get; init; } = "{0} is not marked as assigned in player inventory.";
|
||||
public string BulkFusionSourceInvalid { get; init; } = "The subsumed Species-Form stored in the save file does not match the expected Species-Form of the fused slot.";
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(LegalityCheckLocalization))]
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ public static class LegalityCheckResultCodeExtensions
|
|||
|
||||
// Evolution
|
||||
EvoInvalid => localization.EvoInvalid,
|
||||
EvoTradeReqOutsider_0 => localization.EvoTradeReqOutsider,
|
||||
EvoTradeReqOutsider_01 => localization.EvoTradeReqOutsider,
|
||||
EvoTradeRequired => localization.EvoTradeRequired,
|
||||
|
||||
// Form
|
||||
|
|
@ -144,16 +144,11 @@ public static class LegalityCheckResultCodeExtensions
|
|||
FormArgumentValid => localization.FormArgumentValid,
|
||||
FormArgumentInvalid => localization.FormArgumentInvalid,
|
||||
FormBattle => localization.FormBattle,
|
||||
FormEternal => localization.FormEternal,
|
||||
FormEternalInvalid => localization.FormEternalInvalid,
|
||||
FormInvalidGame => localization.FormInvalidGame,
|
||||
FormInvalidNature => localization.FormInvalidNature,
|
||||
FormItemMatches => localization.FormItem,
|
||||
FormItemInvalid => localization.FormItemInvalid,
|
||||
FormParty => localization.FormParty,
|
||||
FormPikachuCosplay => localization.FormPikachuCosplay,
|
||||
FormPikachuCosplayInvalid => localization.FormPikachuCosplayInvalid,
|
||||
FormPikachuEventInvalid => localization.FormPikachuEventInvalid,
|
||||
FormInvalidExpect_0 => localization.FormInvalidExpect_0,
|
||||
FormValid => localization.FormValid,
|
||||
FormVivillon => localization.FormVivillon,
|
||||
|
|
@ -410,8 +405,9 @@ public static class LegalityCheckResultCodeExtensions
|
|||
TransferTrackerShouldBeZero => localization.TransferTrackerShouldBeZero,
|
||||
TrashBytesExpected => localization.TrashBytesExpected,
|
||||
TrashBytesMismatchInitial => localization.TrashBytesMismatchInitial,
|
||||
TrashBytesMissingTerminator => localization.TrashBytesMissingTerminator,
|
||||
TrashBytesMissingTerminatorFinal => localization.TrashBytesMissingTerminatorFinal,
|
||||
TrashBytesShouldBeEmpty => localization.TrashBytesShouldBeEmpty,
|
||||
TrashBytesResetViaTransfer => localization.TrashBytesResetViaTransfer,
|
||||
WordFilterInvalidCharacter_0 => localization.WordFilterInvalidCharacter_0,
|
||||
WordFilterFlaggedPattern_01 => localization.WordFilterFlaggedPattern_01,
|
||||
WordFilterTooManyNumbers_0 => localization.WordFilterTooManyNumbers_0,
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ private string GetMemory(CheckResult chk, string template, LegalityCheckResultCo
|
|||
EncTradeShouldHaveEvolvedToSpecies_0 => string.Format(format, GetSpeciesName(chk.Argument)),
|
||||
MoveEvoFCombination_0 => string.Format(format, GetSpeciesName(chk.Argument)),
|
||||
HintEvolvesToSpecies_0 => string.Format(format, GetSpeciesName(chk.Argument)),
|
||||
EvoTradeReqOutsider_01 => string.Format(format, GetSpeciesName(chk.Argument), GetSpeciesName(chk.Argument2)),
|
||||
|
||||
RibbonMarkingInvalid_0 => string.Format(format, GetRibbonName((RibbonIndex)chk.Argument)),
|
||||
RibbonMarkingMissing_0 => string.Format(format, GetRibbonName((RibbonIndex)chk.Argument)),
|
||||
|
|
|
|||
|
|
@ -68,14 +68,15 @@ public static void Generate(PK5 pk, in EncounterCriteria criteria, byte gr, ulon
|
|||
if (type is Shiny.Never)
|
||||
{
|
||||
if (ShinyUtil.GetIsShiny3(id32, pid))
|
||||
pid ^= 0x1000_0000; // force not shiny. the wild xor is never true.
|
||||
pid ^= 0x1000_0000; // force not shiny. the wild xor never undoes this fixing.
|
||||
}
|
||||
else if (type is Shiny.Always)
|
||||
{
|
||||
// inlined GetShinyPID without ability force (done later)
|
||||
var gval = (byte)pid;
|
||||
var trainerXor = (id32 >> 16) ^ (ushort)id32;
|
||||
pid = ((gval ^ trainerXor) << 16) | gval;
|
||||
// retain the random gender value, then ensure top16 bits yield a shiny.
|
||||
// this results in xor = 0.
|
||||
pid &= 0xFF;
|
||||
pid |= ShinyUtil.GetShinyXor(pid, id32) << 16;
|
||||
}
|
||||
|
||||
if (isSingleAbility)
|
||||
|
|
@ -89,8 +90,11 @@ public static void Generate(PK5 pk, in EncounterCriteria criteria, byte gr, ulon
|
|||
|
||||
if (wildXor)
|
||||
{
|
||||
// great job checking the wrong bits to give 2x shiny chance for wild stuff.
|
||||
var corr = (pid >> 31) ^ (pid & 1) ^ bitXor;
|
||||
// Attempt to nullify the top bit of the shiny xor?
|
||||
// It seems this was an attempt by the game developer to give 2x shiny chance for wild encounters...
|
||||
// Checks and flips bits inconsistently?
|
||||
// Possibly due to ability being moved to bit16 from bit0, thus shifting the anti-shiny to msb?
|
||||
var corr = (pid >> 31) ^ (pid & 1) ^ bitXor; // msb, lsb, lsb of tid^sid
|
||||
if (corr != 0)
|
||||
pid ^= 0x8000_0000;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ 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 != Nature.Random ? param.Nature
|
||||
var nature = param.Nature.IsFixed ? param.Nature
|
||||
: param.Species == (int)Species.Toxtricity
|
||||
? ToxtricityUtil.GetRandomNature(ref rng, pk.Form)
|
||||
: (Nature)rng.NextInt(25);
|
||||
|
|
@ -160,6 +160,8 @@ 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)
|
||||
|
|
@ -167,9 +169,8 @@ 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))
|
||||
|
|
@ -181,6 +182,8 @@ 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;
|
||||
|
|
@ -236,7 +239,7 @@ public static bool TryApply(PK8 pk, ulong seed, Span<int> ivs, in GenerateParam8
|
|||
return false;
|
||||
pk.Gender = gender;
|
||||
|
||||
var nature = param.Nature != Nature.Random ? param.Nature
|
||||
var nature = param.Nature.IsFixed ? param.Nature
|
||||
: param.Species == (int)Species.Toxtricity
|
||||
? ToxtricityUtil.GetRandomNature(ref rng, pk.Form)
|
||||
: (Nature)rng.NextInt(25);
|
||||
|
|
|
|||
|
|
@ -129,6 +129,8 @@ 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];
|
||||
|
|
@ -172,6 +174,8 @@ 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
|
||||
|
|
@ -179,16 +183,10 @@ 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)));
|
||||
|
||||
if (pk is IScaledSize s)
|
||||
{
|
||||
s.HeightScalar = height;
|
||||
s.WeightScalar = weight;
|
||||
if (pk is IScaledSizeValue a)
|
||||
{
|
||||
a.ResetHeight();
|
||||
a.ResetWeight();
|
||||
}
|
||||
}
|
||||
pk.HeightScalar = height;
|
||||
pk.WeightScalar = weight;
|
||||
pk.ResetHeight();
|
||||
pk.ResetWeight();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ 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,6 +65,8 @@ 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);
|
||||
pk.PID = GetAdaptedPID(ref rand, pk, enc);
|
||||
|
||||
if (enc.Shiny is Shiny.Random && criteria.Shiny.IsShiny() != pk.IsShiny)
|
||||
var pid = GetAdaptedPID(ref rand, pk, enc);
|
||||
if (enc.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
|
||||
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 != Nature.Random ? enc.Nature : enc.Species == (int)Species.Toxtricity
|
||||
var nature = enc.Nature.IsFixed ? 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 != Nature.Random ? enc.Nature : enc.Species == (int)Species.Toxtricity
|
||||
var nature = enc.Nature.IsFixed ? 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.</param>
|
||||
/// <param name="GenderRatio">Gender ratio byte from Personal Info.</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>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public static bool IsRequired(IEncounterTemplate enc, EntityContext current)
|
|||
WB8 { IsHOMEGift: true } => true,
|
||||
WA8 { IsHOMEGift: true } => true,
|
||||
WC9 { IsHOMEGift: true } => true,
|
||||
WA9 { IsHOMEGift: true } => true,
|
||||
_ => enc.Generation < 8,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, HeldItems_RS, ItemStorage3RS.Unreleased); // Safari Ball
|
||||
private static readonly bool[] ReleasedHeldItems_3 = GetPermitList(MaxItemID_3_RS, 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);
|
||||
|
|
|
|||
|
|
@ -20,9 +20,8 @@ public static MemorySource GetPossibleSources(EvolutionHistory history)
|
|||
sources |= MemorySource.Bank; // Trade encounters from Gen7 also come with hardcoded memories.
|
||||
if (history.HasVisitedSWSH)
|
||||
sources |= MemorySource.Gen8;
|
||||
if (history.HasVisitedGen9)
|
||||
if (history.HasVisitedGen9 || history.HasVisitedZA)
|
||||
sources |= MemorySource.Deleted;
|
||||
// TODO HOME ZA
|
||||
return sources;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,17 @@ public static class ParseSettings
|
|||
/// Setting to specify if an analysis should permit data sourced from the physical cartridge era of Game Boy games.
|
||||
/// </summary>
|
||||
/// <remarks>If false, indicates to use Virtual Console rules (which are transferable to Gen7+)</remarks>
|
||||
public static bool AllowGBCartEra { private get; set; }
|
||||
public static bool AllowEraCartGB { private get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Setting to specify if an analysis should permit data sourced from the physical cartridge era of Game Boy Advance games.
|
||||
/// </summary>
|
||||
public static bool AllowEraCartGBA { private get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Setting to specify if an analysis should permit data sourced from the Nintendo Switch Virtual Console era of Game Boy Advance games.
|
||||
/// </summary>
|
||||
public static bool AllowEraSwitchGBA { private get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Setting to specify if an analysis should permit trading a Generation 1 origin file to Generation 2, then back. Useful for checking RBY Metagame rules.
|
||||
|
|
@ -55,27 +65,35 @@ public static class ParseSettings
|
|||
/// <returns>True if Crystal data is allowed</returns>
|
||||
public static bool AllowGen2MoveReminder(PKM pk) => !pk.Korean && AllowGBStadium2;
|
||||
|
||||
public static bool AllowGen2OddEgg(PKM pk) => !pk.Japanese || AllowGBCartEra;
|
||||
public static bool AllowGen2OddEgg(PKM pk) => !pk.Japanese || AllowEraCartGB;
|
||||
|
||||
public static bool AllowGBVirtualConsole3DS => !AllowGBCartEra;
|
||||
public static bool AllowGBEraEvents => AllowGBCartEra;
|
||||
public static bool AllowGBStadium2 => AllowGBCartEra;
|
||||
public static bool AllowGBVirtualConsole3DS => !AllowEraCartGB;
|
||||
public static bool AllowGBEraEvents => AllowEraCartGB;
|
||||
public static bool AllowGBStadium2 => AllowEraCartGB;
|
||||
|
||||
// This logic will likely need to change (format check): TODO HOME FR/LG
|
||||
public static bool AllowGBACrossTransferXD(PKM pk) => AllowEraCartGBA;
|
||||
public static bool AllowGBACrossTransferRSE(PKM pk) => AllowEraCartGBA;
|
||||
public static bool AllowGen3EventTicketsAll(PKM pk) => AllowEraSwitchGBA;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes certain settings
|
||||
/// </summary>
|
||||
/// <param name="sav">Newly loaded save file</param>
|
||||
/// <returns>Save file is Physical GB cartridge save file (not Virtual Console)</returns>
|
||||
public static bool InitFromSaveFileData(SaveFile sav)
|
||||
public static void InitFromSaveFileData(SaveFile sav)
|
||||
{
|
||||
ActiveTrainer = sav;
|
||||
return AllowGBCartEra = sav switch
|
||||
AllowEraCartGB = sav switch
|
||||
{
|
||||
SAV1 { IsVirtualConsole: true } => false,
|
||||
SAV2 { IsVirtualConsole: true } => false,
|
||||
{ Generation: 1 or 2 } => true,
|
||||
_ => false,
|
||||
};
|
||||
var isVirtual3 = sav is SAV3 { IsVirtualConsole: true };
|
||||
AllowEraSwitchGBA = isVirtual3;
|
||||
AllowEraCartGBA = !isVirtual3; // sav.Generation >= 8; TODO HOME FR/LG
|
||||
}
|
||||
|
||||
internal static bool IgnoreTransferIfNoTracker => Settings.HOMETransfer.HOMETransferTrackerNotPresent == Severity.Invalid;
|
||||
|
|
|
|||
|
|
@ -138,16 +138,11 @@ public enum LegalityCheckResultCode : ushort
|
|||
FormArgumentValid,
|
||||
FormArgumentInvalid,
|
||||
FormBattle,
|
||||
FormEternal,
|
||||
FormEternalInvalid,
|
||||
FormInvalidGame,
|
||||
FormInvalidNature,
|
||||
FormItemMatches,
|
||||
FormItemInvalid,
|
||||
FormParty,
|
||||
FormPikachuCosplay,
|
||||
FormPikachuCosplayInvalid,
|
||||
FormPikachuEventInvalid,
|
||||
FormValid,
|
||||
FormVivillon,
|
||||
FormVivillonEventPre,
|
||||
|
|
@ -363,10 +358,13 @@ public enum LegalityCheckResultCode : ushort
|
|||
TransferEncryptGen6Xor,
|
||||
TransferTrackerMissing,
|
||||
TransferTrackerShouldBeZero,
|
||||
|
||||
// Trash Bytes
|
||||
TrashBytesExpected,
|
||||
TrashBytesMismatchInitial,
|
||||
TrashBytesMissingTerminator,
|
||||
TrashBytesMissingTerminatorFinal,
|
||||
TrashBytesShouldBeEmpty,
|
||||
TrashBytesResetViaTransfer,
|
||||
|
||||
// Bulk Cross-Comparison
|
||||
BulkCloneDetectedDetails,
|
||||
|
|
@ -390,7 +388,6 @@ public enum LegalityCheckResultCode : ushort
|
|||
ContestSheenLEQ_0,
|
||||
EggFMetLevel_0,
|
||||
EffortUntrainedCap_0,
|
||||
EvoTradeReqOutsider_0,
|
||||
FormArgumentLEQ_0,
|
||||
FormArgumentGEQ_0,
|
||||
FormInvalidExpect_0,
|
||||
|
|
@ -476,6 +473,7 @@ public enum LegalityCheckResultCode : ushort
|
|||
EncTradeShouldHaveEvolvedToSpecies_0, // species
|
||||
MoveEvoFCombination_0, // species
|
||||
HintEvolvesToSpecies_0, // species
|
||||
EvoTradeReqOutsider_01, // species, species
|
||||
|
||||
RibbonMarkingInvalid_0, // ribbon
|
||||
RibbonMarkingMissing_0, // ribbon
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ public static bool IsFormChangeable(ushort species, byte oldForm, byte newForm,
|
|||
{
|
||||
EntityContext.Gen6 => false,
|
||||
EntityContext.Gen7 => newForm >= 2 || (oldForm == 1 && newForm == 0),
|
||||
EntityContext.Gen9a => newForm >= 2,
|
||||
EntityContext.Gen9a when origin is EntityContext.Gen9a => newForm >= 2,
|
||||
_ => true,
|
||||
};
|
||||
}
|
||||
|
|
@ -420,7 +420,7 @@ public static bool IsLordForm(ushort species, byte form, EntityContext context)
|
|||
/// <param name="pi">Game specific personal info</param>
|
||||
/// <param name="species"><see cref="Species"/> ID</param>
|
||||
/// <param name="format"><see cref="PKM.Form"/> ID</param>
|
||||
/// <returns>True if it has forms that can be provided by <see cref="FormConverter.GetFormList"/>, otherwise false for none.</returns>
|
||||
/// <returns>True if it has forms that can be provided by <see cref="FormConverter"/>, otherwise false for none.</returns>
|
||||
public static bool HasFormSelection(IPersonalFormInfo pi, ushort species, byte format)
|
||||
{
|
||||
if (format <= 3 && species != (int)Unown)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user