mirror of
https://github.com/kwsch/pkNX.git
synced 2026-10-01 13:47:47 -05:00
Add changes for ZA DLC (Mega Dimension) (#407)
This commit is contained in:
13
FlatBuffers/ZA/Battle/Schemas/ItemTableArray.fbs
Normal file
13
FlatBuffers/ZA/Battle/Schemas/ItemTableArray.fbs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
attribute "fs_serializer";
|
||||
|
||||
table ItemTable {
|
||||
ItemID:int;
|
||||
PlibID:int;
|
||||
}
|
||||
|
||||
table ItemTableArray (fs_serializer) {
|
||||
Table:[ItemTable] (required);
|
||||
}
|
||||
|
||||
root_type ItemTableArray;
|
||||
18
FlatBuffers/ZA/Misc/Schemas/ConditionRareDBArray.fbs
Normal file
18
FlatBuffers/ZA/Misc/Schemas/ConditionRareDBArray.fbs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table ConditionRareDB {
|
||||
Table:[ConditionRare] (required);
|
||||
}
|
||||
|
||||
table ConditionRareDBArray (fs_serializer) {
|
||||
Table:[ConditionRareDB] (required);
|
||||
}
|
||||
|
||||
table ConditionRare {
|
||||
Version:float;
|
||||
TriggerID:int;
|
||||
ComparisonOperatorType:int;
|
||||
}
|
||||
root_type ConditionRareDBArray;
|
||||
22
FlatBuffers/ZA/Misc/Schemas/Donut/BerryDetailArray.fbs
Normal file
22
FlatBuffers/ZA/Misc/Schemas/Donut/BerryDetailArray.fbs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table BerryDetail {
|
||||
ItemID:uint;
|
||||
DonutIndex:uint;
|
||||
IsHyperspace:bool;
|
||||
Spicy:uint;
|
||||
Fresh:uint;
|
||||
Sweet:uint;
|
||||
Bitter:uint;
|
||||
Sour:uint;
|
||||
LevelBoost:uint;
|
||||
Calories:uint;
|
||||
}
|
||||
|
||||
table BerryDetailArray (fs_serializer) {
|
||||
Table:[BerryDetail] (required);
|
||||
}
|
||||
|
||||
root_type BerryDetailArray;
|
||||
17
FlatBuffers/ZA/Misc/Schemas/Donut/DonutDetailArray.fbs
Normal file
17
FlatBuffers/ZA/Misc/Schemas/Donut/DonutDetailArray.fbs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DonutDetail {
|
||||
Index:uint;
|
||||
FlavorDominant:uint;
|
||||
BerryBase:uint;
|
||||
Name:string (required);
|
||||
Info:string (required);
|
||||
}
|
||||
|
||||
table DonutDetailArray (fs_serializer) {
|
||||
Table:[DonutDetail] (required);
|
||||
}
|
||||
|
||||
root_type DonutDetailArray;
|
||||
26
FlatBuffers/ZA/Misc/Schemas/Donut/DonutFlavorArray.fbs
Normal file
26
FlatBuffers/ZA/Misc/Schemas/Donut/DonutFlavorArray.fbs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DonutFlavor {
|
||||
Flavor:string (required); // power granted
|
||||
FlavorName:int;
|
||||
UniqueEffect:int;
|
||||
BoostArg:int; // type to boost, or which variant of the flavor
|
||||
Field04:int;
|
||||
Category2:int; // does this prevent multiple in same category?
|
||||
IsBattleStatBoost:bool;
|
||||
Level:int;
|
||||
LevelVariance:int; // mostly matches level, besides shiny power (3) and legends (1)
|
||||
IsSpecial:bool;
|
||||
Name:string (required);
|
||||
Info:string (required);
|
||||
PrefixAdj:string (required); // based on the primary power
|
||||
Detail:string (required);
|
||||
}
|
||||
|
||||
table DonutFlavorArray (fs_serializer) {
|
||||
Table:[DonutFlavor] (required);
|
||||
}
|
||||
|
||||
root_type DonutFlavorArray;
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DonutFlavorLottery {
|
||||
Count:uint;
|
||||
Lv1:uint;
|
||||
Lv2:uint;
|
||||
Lv3:uint;
|
||||
}
|
||||
|
||||
table DonutFlavorLotteryArray (fs_serializer) {
|
||||
Table:[DonutFlavorLottery] (required);
|
||||
}
|
||||
|
||||
root_type DonutFlavorLotteryArray;
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DonutFlavorParameter {
|
||||
Index:uint;
|
||||
Lv1:float;
|
||||
Lv2:float;
|
||||
Lv3:float;
|
||||
}
|
||||
|
||||
table DonutFlavorParameterArray (fs_serializer) {
|
||||
Table:[DonutFlavorParameter] (required);
|
||||
}
|
||||
|
||||
root_type DonutFlavorParameterArray;
|
||||
20
FlatBuffers/ZA/Misc/Schemas/Donut/DonutOneWordArray.fbs
Normal file
20
FlatBuffers/ZA/Misc/Schemas/Donut/DonutOneWordArray.fbs
Normal file
@@ -0,0 +1,20 @@
|
||||
include "Shared/ActivationCondition.fbs";
|
||||
include "Shared/ActivationConditionElement.fbs";
|
||||
include "Shared/ActivationConditionParam.fbs";
|
||||
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DonutOneWord {
|
||||
Text:string (required);
|
||||
State:uint; // start=0, working=1, max=2, leave=3
|
||||
Other:uint; // only used by oneword_max_*
|
||||
Condition:[ActivationCondition] (required);
|
||||
}
|
||||
|
||||
table DonutOneWordArray (fs_serializer) {
|
||||
Table:[DonutOneWord] (required);
|
||||
}
|
||||
|
||||
root_type DonutOneWordArray;
|
||||
26
FlatBuffers/ZA/Misc/Schemas/Donut/DonutRecipeArray.fbs
Normal file
26
FlatBuffers/ZA/Misc/Schemas/Donut/DonutRecipeArray.fbs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
// special donut recipe
|
||||
table DonutRecipe {
|
||||
Index:uint;
|
||||
SweetMin:uint;
|
||||
SweetMax:uint;
|
||||
SpicyMin:uint;
|
||||
SpicyMax:uint;
|
||||
SourMin:uint;
|
||||
SourMax:uint;
|
||||
BitterMin:uint;
|
||||
BitterMax:uint;
|
||||
FreshMin:uint;
|
||||
FreshMax:uint;
|
||||
DonutName:uint;
|
||||
RecipeName:string (required);
|
||||
}
|
||||
|
||||
table DonutRecipeArray (fs_serializer) {
|
||||
Table:[DonutRecipe] (required);
|
||||
}
|
||||
|
||||
root_type DonutRecipeArray;
|
||||
@@ -1,5 +1 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<Content Remove="Schemas\WeatherHappeningParamArray.fbs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk" />
|
||||
|
||||
@@ -54,6 +54,8 @@ public void AddDump(List<string> lines, PersonalTable9ZA table, ushort speciesIn
|
||||
if (form != 0)
|
||||
name += $"-{form}";
|
||||
name += $" #{entry.DexIndex:000}";
|
||||
// if (entry.DexIndex != 0) // every group is 0, don't bother emitting. The game does -232 to check >=1 for Hyperspace Dex.
|
||||
// name += $" [{entry.DexGroup}]";
|
||||
AddDump(lines, entry, index, name, speciesInternal, form);
|
||||
}
|
||||
|
||||
@@ -366,6 +368,20 @@ public static class Plib9
|
||||
{ 0094, 2403 }, // Unremarkable Teacup
|
||||
{ 0095, 2404 }, // Masterpiece Teacup
|
||||
{ 0096, 2402 }, // Syrupy Apple
|
||||
{ 0097, 0000 },
|
||||
{ 0098, 0000 },
|
||||
{ 0099, 0000 },
|
||||
{ 0100, 0000 },
|
||||
{ 0101, 0000 },
|
||||
{ 0102, 0765 }, // Prison Bottle
|
||||
{ 0103, 0000 },
|
||||
{ 0104, 0000 },
|
||||
{ 0105, 0000 },
|
||||
{ 0106, 0000 },
|
||||
{ 0107, 0000 },
|
||||
{ 0108, 0000 },
|
||||
{ 0109, 0000 },
|
||||
{ 0110, 0000 },
|
||||
{ 0111, 0537 }, // Prism Scale
|
||||
{ 0112, 0325 }, // Reaper Cloth
|
||||
{ 0113, 0252 }, // Upgrade
|
||||
@@ -375,5 +391,8 @@ public static class Plib9
|
||||
{ 0117, 0321 }, // Protector
|
||||
{ 0118, 0235 }, // Dragon Scale
|
||||
{ 0119, 2482 }, // Metal Alloy
|
||||
{ 0121, 0847 }, // Zygarde Cube
|
||||
{ 0120, 0000 },
|
||||
{ 1691, 1691 }, // Black Augurite -- yeah, they gave up having unique indexes
|
||||
};
|
||||
}
|
||||
|
||||
@@ -53,10 +53,27 @@ public int Gender
|
||||
|
||||
public ushort Form { get => FB.Info.Form; set => FB.Info.Form = value; }
|
||||
|
||||
public ushort DexIndex
|
||||
public int DexGroup
|
||||
{
|
||||
get => FB.Dex;
|
||||
set => FB.Dex = value;
|
||||
get => FB.Dex?.Group ?? 0;
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
FB.Dex = null;
|
||||
else
|
||||
(FB.Dex ??= new PersonalInfoDex()).Group = (byte)value;
|
||||
}
|
||||
}
|
||||
public int DexIndex
|
||||
{
|
||||
get => FB.Dex?.Index ?? 0;
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
FB.Dex = null;
|
||||
else
|
||||
(FB.Dex ??= new PersonalInfoDex()).Index = (byte)value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Item1 { get => 0; set { } }
|
||||
@@ -98,7 +115,7 @@ public void Write(BinaryWriter bw)
|
||||
bw.Write(FB.Info.Color);
|
||||
bw.Write(FB.IsPresentInGame);
|
||||
|
||||
bw.Write((byte)0);
|
||||
bw.Write((byte)DexGroup);
|
||||
bw.Write((ushort)DexIndex);
|
||||
bw.Write(FB.Info.Height);
|
||||
bw.Write(FB.Info.Weight);
|
||||
@@ -144,5 +161,12 @@ private static ushort GetEXP(int bst, byte evoStage, short add)
|
||||
404, 369, 417, 430, 164, 528, 231, 191, 390, 399,
|
||||
174, 605, 200, 018, 269, 056, 377, 127, 118, 441,
|
||||
527, 411, 526, 394, 059, 087, 370,
|
||||
// ZA DLC
|
||||
004, 263, 886,
|
||||
047, 491, 490, 488, 885, 006, 318, 325, 466, 246,
|
||||
259, 206, 305, 706, 102, 443, 138, 402, 509, 451,
|
||||
409, 458, 299, 814, 530, 815, 480, 524, 207, 330,
|
||||
252, 660, 799, 813, 013, 130, 161, 503, 333, 410,
|
||||
080, 669, 143, 090, 329, 800, 796, 307, 308, 338,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -11,10 +11,8 @@ attribute "fs_serializer";
|
||||
table PersonalInfo {
|
||||
Info:PersonalInfoDetail (required);
|
||||
IsPresentInGame:bool;
|
||||
Dex:ushort; // No need to group. Changed from SV.
|
||||
// Dex:PersonalInfoDex; // not required
|
||||
// KitakamiDex:ushort; // NOT USED IN DATA
|
||||
// BlueberryDex:ushort; // NOT USED IN DATA
|
||||
// Dex:ushort; // base game was just a ushort; extended to 2+1 struct in Mega Dimension DLC
|
||||
Dex:PersonalInfoDex; // not required
|
||||
Type1:ubyte;
|
||||
Type2:ubyte;
|
||||
Ability1:ushort;
|
||||
@@ -40,6 +38,11 @@ table PersonalInfo {
|
||||
Learnset:[PersonalInfoMove] (required);
|
||||
}
|
||||
|
||||
struct PersonalInfoDex { // give me a class, not struct.
|
||||
Index:ushort;
|
||||
Group:ubyte;
|
||||
}
|
||||
|
||||
table PersonalTable (fs_serializer) {
|
||||
Table:[PersonalInfo] (required);
|
||||
}
|
||||
|
||||
@@ -31,4 +31,5 @@ table PokeDataBattle {
|
||||
EffortValue:ParamSet (required);
|
||||
RareType:RareType;
|
||||
ScaleValue:short;
|
||||
IsOybn:bool;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,10 @@ enum ItemID : int
|
||||
ITEMID_HIKARINOISI = 107,
|
||||
ITEMID_YAMINOISI = 108,
|
||||
ITEMID_MEZAMEISI = 109,
|
||||
ITEMID_AKUAKASETTO = 116,
|
||||
ITEMID_INAZUMAKASETTO = 117,
|
||||
ITEMID_BUREIZUKASETTO = 118,
|
||||
ITEMID_HURIIZUKASETTO = 119,
|
||||
ITEMID_KURABONOMI = 149,
|
||||
ITEMID_KAGONOMI = 150,
|
||||
ITEMID_MOMONNOMI = 151,
|
||||
@@ -145,7 +149,10 @@ enum ItemID : int
|
||||
ITEMID_MOKUTAN = 249,
|
||||
ITEMID_RYUUNOKIBA = 250,
|
||||
ITEMID_SIRUKUNOSUKAAHU = 251,
|
||||
ITEMID_APPUGUREEDO = 252,
|
||||
ITEMID_KAIGARANOSUZU = 253,
|
||||
ITEMID_HUTOIHONE = 258,
|
||||
ITEMID_NAGANEGI = 259,
|
||||
ITEMID_KOUKAKURENZU = 265,
|
||||
ITEMID_TIKARANOHATIMAKI = 266,
|
||||
ITEMID_MONOSIRIMEGANE = 267,
|
||||
@@ -174,6 +181,7 @@ enum ItemID : int
|
||||
ITEMID_KIREINANUKEGARA = 295,
|
||||
ITEMID_OOKINANEKKO = 296,
|
||||
ITEMID_KODAWARIMEGANE = 297,
|
||||
ITEMID_AYASIIPATTI = 324,
|
||||
ITEMID_WAZAMASIN01 = 328,
|
||||
ITEMID_WAZAMASIN02 = 329,
|
||||
ITEMID_WAZAMASIN03 = 330,
|
||||
@@ -274,6 +282,9 @@ enum ItemID : int
|
||||
ITEMID_HURENDOBOORU = 497,
|
||||
ITEMID_MUUNBOORU = 498,
|
||||
ITEMID_KONPEBOORU = 499,
|
||||
ITEMID_BENIIRONOTAMA = 534,
|
||||
ITEMID_AIIRONOTAMA = 535,
|
||||
ITEMID_KIREINAUROKO = 537,
|
||||
ITEMID_SINKANOKISEKI = 538,
|
||||
ITEMID_KARUISI = 539,
|
||||
ITEMID_GOTUGOTUMETTO = 540,
|
||||
@@ -408,16 +419,20 @@ enum ItemID : int
|
||||
ITEMID_YOUKIMINTO = 1249,
|
||||
ITEMID_MUJYAKIMINTO = 1250,
|
||||
ITEMID_MAZIMEMINTO = 1251,
|
||||
ITEMID_ROTOMUNOKATAROGU = 1278,
|
||||
ITEMID_GARANATUBURESU = 1582,
|
||||
ITEMID_AKASINOOMAMORI = 1589,
|
||||
ITEMID_GARANATURIISU = 1592,
|
||||
ITEMID_TOKUSEIPATTI = 1606,
|
||||
ITEMID_KURONOKISEKI = 1691,
|
||||
ITEMID_NOROINOYOROI = 1861,
|
||||
ITEMID_SENTOUBAFFA1 = 1881,
|
||||
ITEMID_SENTOUBAFFA2 = 1882,
|
||||
ITEMID_SENTOUBAFFA3 = 1883,
|
||||
ITEMID_SENTOUBAFFA4 = 1884,
|
||||
ITEMID_SENTOUBAFFA5 = 1885,
|
||||
ITEMID_SENTOUBAFFA6 = 1886,
|
||||
ITEMID_SOZAI182 = 2137,
|
||||
ITEMID_WAZAMASIN100 = 2160,
|
||||
ITEMID_WAZAMASIN101 = 2161,
|
||||
ITEMID_WAZAMASIN102 = 2162,
|
||||
@@ -490,6 +505,7 @@ enum ItemID : int
|
||||
ITEMID_WAZAMASIN169 = 2229,
|
||||
ITEMID_WAZAMASIN170 = 2230,
|
||||
ITEMID_WAZAMASIN171 = 2231,
|
||||
ITEMID_IWAINOYOROI = 2344,
|
||||
ITEMID_YOUSEINOHANE = 2401,
|
||||
ITEMID_KAIDENNOTANE = 2558,
|
||||
ITEMID_PIKUSINAITO = 2559,
|
||||
@@ -534,19 +550,19 @@ enum ItemID : int
|
||||
ITEMID_OISHIIGOMI = 2598,
|
||||
ITEMID_GENKINOKOEDA = 2599,
|
||||
ITEMID_DEURONOWASUREMONO = 2600,
|
||||
ITEMID_DAIZINAMONO14 = 2601,
|
||||
ITEMID_DAIZINAMONO15 = 2602,
|
||||
ITEMID_DAIZINAMONO16 = 2603,
|
||||
ITEMID_DAIZINAMONO17 = 2604,
|
||||
ITEMID_DAIZINAMONO18 = 2605,
|
||||
ITEMID_DAIZINAMONO19 = 2606,
|
||||
ITEMID_DAIZINAMONO20 = 2607,
|
||||
ITEMID_DAIZINAMONO21 = 2608,
|
||||
ITEMID_DAIZINAMONO22 = 2609,
|
||||
ITEMID_DAIZINAMONO23 = 2610,
|
||||
ITEMID_DAIZINAMONO24 = 2611,
|
||||
ITEMID_DAIZINAMONO25 = 2612,
|
||||
ITEMID_DAIZINAMONO26 = 2613,
|
||||
ITEMID_BEIKINGUPAUDAA = 2601,
|
||||
ITEMID_IJIGENPAUDAA1 = 2602,
|
||||
ITEMID_IJIGENPAUDAA2 = 2603,
|
||||
ITEMID_IJIGENPAUDAA3 = 2604,
|
||||
ITEMID_IJIGENPAUDAA4 = 2605,
|
||||
ITEMID_IJIGENPAUDAA5 = 2606,
|
||||
ITEMID_HOUENNOARAJIO = 2607,
|
||||
ITEMID_SUPAISUBURAKKU = 2608,
|
||||
ITEMID_ORIIBUAOIRU = 2609,
|
||||
ITEMID_PACHIPACHIKYANDII = 2610,
|
||||
ITEMID_TAISETSUNATEGAMI = 2611,
|
||||
ITEMID_OMOIDENOYUBIWA2 = 2612,
|
||||
ITEMID_YOGORETASUKAAHU = 2613,
|
||||
ITEMID_DAIZINAMONO27 = 2614,
|
||||
ITEMID_DAIZINAMONO28 = 2615,
|
||||
ITEMID_DAIZINAMONO29 = 2616,
|
||||
@@ -568,4 +584,54 @@ enum ItemID : int
|
||||
ITEMID_AONOKANARYINUI1 = 2632,
|
||||
ITEMID_AONOKANARYINUI2 = 2633,
|
||||
ITEMID_AONOKANARYINUI3 = 2634,
|
||||
ITEMID_RAITYUUNAITOx = 2635,
|
||||
ITEMID_RAITYUUNAITOy = 2636,
|
||||
ITEMID_TIRIINNAITO = 2637,
|
||||
ITEMID_ABUSORUNAITOz = 2638,
|
||||
ITEMID_MUKUHOOKUNAITO = 2639,
|
||||
ITEMID_GABURIASUNAITOz = 2640,
|
||||
ITEMID_RUKARIONAITOz = 2641,
|
||||
ITEMID_GORUUGUNAITO = 2642,
|
||||
ITEMID_NYAONIKUSUNAITO = 2643,
|
||||
ITEMID_KEKENKANINAITO = 2644,
|
||||
ITEMID_GUSOKUMUSYANAITO = 2645,
|
||||
ITEMID_MAGIANAITO = 2646,
|
||||
ITEMID_SUKOBUIRANAITO = 2647,
|
||||
ITEMID_SEGUREIBUNAITO = 2648,
|
||||
ITEMID_SHARITATSUNAITO = 2649,
|
||||
ITEMID_KIRAHURORUNAITO = 2650,
|
||||
ITEMID_IJIGENKURABONOMI = 2651,
|
||||
ITEMID_IJIGENKAGONOMI = 2652,
|
||||
ITEMID_IJIGENMOMONNOMI = 2653,
|
||||
ITEMID_IJIGENTIIGONOMI = 2654,
|
||||
ITEMID_IJIGENNANASINOMI = 2655,
|
||||
ITEMID_IJIGENORENNOMI = 2656,
|
||||
ITEMID_IJIGENKIINOMI = 2657,
|
||||
ITEMID_IJIGENRAMUNOMI = 2658,
|
||||
ITEMID_IJIGENOBONNOMI = 2659,
|
||||
ITEMID_IJIGENZAROKUNOMI = 2660,
|
||||
ITEMID_IJIGENNEKOBUNOMI = 2661,
|
||||
ITEMID_IJIGENTAPORUNOMI = 2662,
|
||||
ITEMID_IJIGENROMENOMI = 2663,
|
||||
ITEMID_IJIGENUBUNOMI = 2664,
|
||||
ITEMID_IJIGENMATOMANOMI = 2665,
|
||||
ITEMID_IJIGENOKKANOMI = 2666,
|
||||
ITEMID_IJIGENITOKENOMI = 2667,
|
||||
ITEMID_IJIGENSOKUNONOMI = 2668,
|
||||
ITEMID_IJIGENRINDONOMI = 2669,
|
||||
ITEMID_IJIGENYATHENOMI = 2670,
|
||||
ITEMID_IJIGENYOPUNOMI = 2671,
|
||||
ITEMID_IJIGENBIAANOMI = 2672,
|
||||
ITEMID_IJIGENSYUKANOMI = 2673,
|
||||
ITEMID_IJIGENBAKOUNOMI = 2674,
|
||||
ITEMID_IJIGENUTANNOMI = 2675,
|
||||
ITEMID_IJIGENTANGANOMI = 2676,
|
||||
ITEMID_IJIGENYOROGINOMI = 2677,
|
||||
ITEMID_IJIGENKASIBUNOMI = 2678,
|
||||
ITEMID_IJIGENHABANNOMI = 2679,
|
||||
ITEMID_IJIGENNAMONOMI = 2680,
|
||||
ITEMID_IJIGENRIRIBANOMI = 2681,
|
||||
ITEMID_IJIGENHOZUNOMI = 2682,
|
||||
ITEMID_IJIGENROZERUNOMI = 2683,
|
||||
ITEMID_KANARIIPAN = 2684,
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ table TrainerBattleDetail {
|
||||
|
||||
table TrainerBattleData {
|
||||
Type:string (required);
|
||||
TrainerBattleID:string;
|
||||
NPCAssetID:string;
|
||||
Field03:string;
|
||||
Field04:string;
|
||||
TrainerBattleID1:string;
|
||||
NPCAssetID1:string;
|
||||
TrainerBattleID2:string;
|
||||
NPCAssetID2:string;
|
||||
Field05:string;
|
||||
Field06:string;
|
||||
Field07:string;
|
||||
@@ -28,7 +28,8 @@ table TrainerBattleData {
|
||||
Field16:string;
|
||||
Field17:string;
|
||||
Field18:string;
|
||||
Field19:[TrainerBattleDetail] (required);
|
||||
Field19:string; // one field was inserted in 2.0.0, not sure which but it was after Field13
|
||||
Field20:[TrainerBattleDetail] (required);
|
||||
}
|
||||
|
||||
table TrainerBattleGlobalDBArray (fs_serializer) {
|
||||
|
||||
@@ -17,6 +17,7 @@ table FieldAreaInfo {
|
||||
ProhibitReadyBallThrow:bool;
|
||||
ProhibitPartnerPutout:bool;
|
||||
IsOptimizeWaterLight:bool;
|
||||
CanEvolveToPoke0867:bool; // Runerigus, inserted in 2.0.0
|
||||
DefaultStartPosition:PackedVec3f;
|
||||
DefaultStartYaw:float;
|
||||
Music:string;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
include "Shared/ActivationCondition.fbs";
|
||||
include "Shared/ActivationConditionElement.fbs";
|
||||
include "Shared/ActivationConditionParam.fbs";
|
||||
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DimensionBossLottery {
|
||||
BossLotteryId:string;
|
||||
BattleId:string;
|
||||
Rank:int;
|
||||
EstimateLevel:int;
|
||||
ExtensionLevel:int;
|
||||
IsRematch:bool;
|
||||
DevNo:int;
|
||||
FormNo:int;
|
||||
GateObjectType:int;
|
||||
GateSpawnerId:string;
|
||||
StartPointObjectName:string;
|
||||
Condition:[ActivationCondition];
|
||||
ReturnGateCondition:[ActivationCondition];
|
||||
}
|
||||
|
||||
table DimensionBossLotteryDB {
|
||||
Table:[DimensionBossLottery] (required);
|
||||
}
|
||||
|
||||
table DimensionBossLotteryDBArray (fs_serializer) {
|
||||
Table:[DimensionBossLotteryDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionBossLotteryDBArray;
|
||||
18
FlatBuffers/ZA/World/Schemas/Dimension/DimensionConfigDB.fbs
Normal file
18
FlatBuffers/ZA/World/Schemas/Dimension/DimensionConfigDB.fbs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DimensionConfig {
|
||||
SpecialLotteryForceWinChainCount:int;
|
||||
GateObjectStreamingActivateDistance:float;
|
||||
GateObjectStreamingDeactivateDistance:float;
|
||||
DummyZoneAreaId:string;
|
||||
DummyZoneExtensionLevel:int;
|
||||
BonusLotteryRandomThresholdDistance:float;
|
||||
}
|
||||
|
||||
table DimensionConfigDB (fs_serializer) {
|
||||
Table:DimensionConfig (required);
|
||||
}
|
||||
|
||||
root_type DimensionConfigDB;
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DimensionGateObject {
|
||||
GateObjectType:int;
|
||||
ObjectTemplatePath:string;
|
||||
}
|
||||
|
||||
table DimensionGateObjectDB {
|
||||
Table:[DimensionGateObject] (required);
|
||||
}
|
||||
|
||||
table DimensionGateObjectDBArray (fs_serializer) {
|
||||
Table:[DimensionGateObjectDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionGateObjectDBArray;
|
||||
@@ -0,0 +1,23 @@
|
||||
include "Shared/ActivationCondition.fbs";
|
||||
include "Shared/ActivationConditionElement.fbs";
|
||||
include "Shared/ActivationConditionParam.fbs";
|
||||
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DimensionGateSpawner {
|
||||
GateSpawnerId:string;
|
||||
IsDynamicCondition:bool;
|
||||
Condition:[ActivationCondition];
|
||||
}
|
||||
|
||||
table DimensionGateSpawnerDB {
|
||||
Table:[DimensionGateSpawner] (required);
|
||||
}
|
||||
|
||||
table DimensionGateSpawnerDBArray (fs_serializer) {
|
||||
Table:[DimensionGateSpawnerDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionGateSpawnerDBArray;
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table RankItem {
|
||||
Rank:int;
|
||||
ItemTableId:string (required);
|
||||
}
|
||||
|
||||
table DimensionGimmickItem {
|
||||
GimmickId:string;
|
||||
RankItems:[RankItem] (required);
|
||||
}
|
||||
|
||||
table DimensionGimmickItemDB {
|
||||
Table:[DimensionGimmickItem] (required);
|
||||
}
|
||||
|
||||
table DimensionGimmickItemDBArray (fs_serializer) {
|
||||
Table:[DimensionGimmickItemDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionGimmickItemDBArray;
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table StartPointItem {
|
||||
ObjectName:string (required);
|
||||
}
|
||||
|
||||
table DimensionMap {
|
||||
MapId:string;
|
||||
MapSize:int;
|
||||
TaskRandomPopItemLimit:int;
|
||||
WildTypeCount:int;
|
||||
BattleTypeCount:int;
|
||||
StartPointItems:[StartPointItem] (required);
|
||||
}
|
||||
|
||||
table DimensionMapDB {
|
||||
Table:[DimensionMap] (required);
|
||||
}
|
||||
|
||||
table DimensionMapDBArray (fs_serializer) {
|
||||
Table:[DimensionMapDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionMapDBArray;
|
||||
@@ -0,0 +1,40 @@
|
||||
include "Shared/ActivationCondition.fbs";
|
||||
include "Shared/ActivationConditionElement.fbs";
|
||||
include "Shared/ActivationConditionParam.fbs";
|
||||
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DimensionProgressRankItem {
|
||||
Rank:int;
|
||||
LotteryWeight:int;
|
||||
MinCount:int;
|
||||
MaxCount:int;
|
||||
}
|
||||
|
||||
table DimensionProgress {
|
||||
ProgressId:string;
|
||||
WildMinCount:int;
|
||||
WildMaxCount:int;
|
||||
BattleMinCount:int;
|
||||
BattleMaxCount:int;
|
||||
EventMinCount:int;
|
||||
EventMaxCount:int;
|
||||
AreaGateMinCount:int;
|
||||
AreaGateMaxCount:int;
|
||||
TotalGateMinCount:int;
|
||||
TotalGateMaxCount:int;
|
||||
RankItems:[DimensionProgressRankItem] (required);
|
||||
Condition:[ActivationCondition];
|
||||
}
|
||||
|
||||
table DimensionProgressDB {
|
||||
Table:[DimensionProgress] (required);
|
||||
}
|
||||
|
||||
table DimensionProgressDBArray (fs_serializer) {
|
||||
Table:[DimensionProgressDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionProgressDBArray;
|
||||
@@ -0,0 +1,32 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table PokeTypeItem {
|
||||
PokeType:int;
|
||||
LotteryWeight:int;
|
||||
}
|
||||
|
||||
table MapItem {
|
||||
MapId:string;
|
||||
LotteryWeight:int;
|
||||
}
|
||||
|
||||
table DimensionRank {
|
||||
Rank:int;
|
||||
ExtensionLevel:int;
|
||||
EstimateLevel:int;
|
||||
LimitReductionSpeed:float;
|
||||
MapItems:[MapItem] (required);
|
||||
BattlePokeTypeItems:[PokeTypeItem] (required);
|
||||
}
|
||||
|
||||
table DimensionRankDB {
|
||||
Table:[DimensionRank] (required);
|
||||
}
|
||||
|
||||
table DimensionRankDBArray (fs_serializer) {
|
||||
Table:[DimensionRankDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionRankDBArray;
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DimensionSpecialLottery {
|
||||
SpecialLotteryId:string (required);
|
||||
Rank:int;
|
||||
ZoneType:int;
|
||||
MapId:string (required);
|
||||
PatternSceneName:string; // not required
|
||||
LotteryTableType:int;
|
||||
LotteryWeight:int;
|
||||
}
|
||||
|
||||
table DimensionSpecialLotteryDB {
|
||||
Table:[DimensionSpecialLottery] (required);
|
||||
}
|
||||
|
||||
table DimensionSpecialLotteryDBArray (fs_serializer) {
|
||||
Table:[DimensionSpecialLotteryDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionSpecialLotteryDBArray;
|
||||
@@ -0,0 +1,36 @@
|
||||
include "Shared/ActivationCondition.fbs";
|
||||
include "Shared/ActivationConditionElement.fbs";
|
||||
include "Shared/ActivationConditionParam.fbs";
|
||||
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DimensionUniqueLottery {
|
||||
UniqueLotteryId:string;
|
||||
UseLimit:bool;
|
||||
Rank:int;
|
||||
EstimateLevel:int;
|
||||
MapId:string;
|
||||
StartPointObjectName:string;
|
||||
PatternSceneName:string;
|
||||
ZoneType:int;
|
||||
WildPokeType_0:int;
|
||||
WildPokePatternNo_0:int;
|
||||
WildPokeType_1:int;
|
||||
WildPokePatternNo_1:int;
|
||||
WildPokeType_2:int;
|
||||
WildPokePatternNo_2:int;
|
||||
GateSpawnerId:string;
|
||||
Condition:[ActivationCondition];
|
||||
}
|
||||
|
||||
table DimensionUniqueLotteryDB {
|
||||
Table:[DimensionUniqueLottery] (required);
|
||||
}
|
||||
|
||||
table DimensionUniqueLotteryDBArray (fs_serializer) {
|
||||
Table:[DimensionUniqueLotteryDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionUniqueLotteryDBArray;
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DimensionWildSpawnerItem {
|
||||
SpawnerDataId:string (required);
|
||||
LotteryWeight:int;
|
||||
}
|
||||
|
||||
table DimensionWildPatternItem {
|
||||
PatternNo:int;
|
||||
LotteryWeight:int;
|
||||
SpawnerItems:[DimensionWildSpawnerItem];
|
||||
}
|
||||
|
||||
table DimensionWildRankItem {
|
||||
Rank:int;
|
||||
PatternItems:[DimensionWildPatternItem];
|
||||
}
|
||||
|
||||
table DimensionWildPokemon {
|
||||
PokeType:int;
|
||||
RankItems:[DimensionWildRankItem] (required);
|
||||
}
|
||||
|
||||
table DimensionWildPokemonDB {
|
||||
Table:[DimensionWildPokemon] (required);
|
||||
}
|
||||
|
||||
table DimensionWildPokemonDBArray (fs_serializer) {
|
||||
Table:[DimensionWildPokemonDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionWildPokemonDBArray;
|
||||
@@ -0,0 +1,40 @@
|
||||
include "Shared/ActivationCondition.fbs";
|
||||
include "Shared/ActivationConditionElement.fbs";
|
||||
include "Shared/ActivationConditionParam.fbs";
|
||||
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table DimensionZoneEventItem {
|
||||
EventId:string;
|
||||
EventKind:int;
|
||||
LotteryWeight:int;
|
||||
EstimateLevel:int;
|
||||
Condition:[ActivationCondition];
|
||||
}
|
||||
|
||||
table DimensionZoneRankItem {
|
||||
Rank:int;
|
||||
WildLotteryWeight:int;
|
||||
BattleLotteryWeight:int;
|
||||
EventLotteryWeight:int;
|
||||
WildSceneNames:[string];
|
||||
BattleSceneNames:[string];
|
||||
EventItems:[DimensionZoneEventItem];
|
||||
}
|
||||
|
||||
table DimensionZoneLottery {
|
||||
MapId:string;
|
||||
RankItems:[DimensionZoneRankItem] (required);
|
||||
}
|
||||
|
||||
table DimensionZoneLotteryDB {
|
||||
Table:[DimensionZoneLottery] (required);
|
||||
}
|
||||
|
||||
table DimensionZoneLotteryDBArray (fs_serializer) {
|
||||
Table:[DimensionZoneLotteryDB] (required);
|
||||
}
|
||||
|
||||
root_type DimensionZoneLotteryDBArray;
|
||||
@@ -0,0 +1,26 @@
|
||||
include "Shared/ActivationCondition.fbs";
|
||||
include "Shared/ActivationConditionElement.fbs";
|
||||
include "Shared/ActivationConditionParam.fbs";
|
||||
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table ItemTableInfo {
|
||||
TableId:string;
|
||||
Condition:[ActivationCondition];
|
||||
}
|
||||
|
||||
table WazagimmickItemSpawner {
|
||||
Id:string;
|
||||
ObjectNameList:[string] (required);
|
||||
MinCount:int;
|
||||
MaxCount:int;
|
||||
ItemTableInfoList:[ItemTableInfo] (required);
|
||||
}
|
||||
|
||||
table WazagimmickItemSpawnerDB (fs_serializer) {
|
||||
Table:[WazagimmickItemSpawner] (required);
|
||||
}
|
||||
|
||||
root_type WazagimmickItemSpawnerDB;
|
||||
@@ -0,0 +1,30 @@
|
||||
include "Shared/ActivationCondition.fbs";
|
||||
include "Shared/ActivationConditionElement.fbs";
|
||||
include "Shared/ActivationConditionParam.fbs";
|
||||
|
||||
namespace pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
attribute "fs_serializer";
|
||||
|
||||
table ItemTableItemLotteryData {
|
||||
ItemId:string (required);
|
||||
Weight:int;
|
||||
MaxCount:int;
|
||||
Type:int;
|
||||
Condition:[ActivationCondition];
|
||||
}
|
||||
|
||||
table WazagimmickItemTable {
|
||||
Id:string (required);
|
||||
ItemLotteryDataList:[ItemTableItemLotteryData] (required);
|
||||
}
|
||||
|
||||
table WazagimmickItemTableDB {
|
||||
Table:[WazagimmickItemTable] (required);
|
||||
}
|
||||
|
||||
table WazagimmickItemTableDBArray (fs_serializer) {
|
||||
Table:[WazagimmickItemTableDB] (required);
|
||||
}
|
||||
|
||||
root_type WazagimmickItemTableDBArray;
|
||||
@@ -23,10 +23,12 @@ The following games are supported:
|
||||
* Sword / Shield
|
||||
* Legends: Arceus
|
||||
* Scarlet / Violet **(Only for dumping data, not to edit files!)**
|
||||
* Legends: Z-A **(Only for dumping data, not to edit files!)**
|
||||
|
||||
pkNX operates under the assumption that your dumped ROM includes the latest available update data for the following games:
|
||||
* Sword / Shield (Ver. 1.3.2)
|
||||
* Scarlet / Violet (Ver. 3.0.1)
|
||||
* Scarlet / Violet (Ver. 4.0.0)
|
||||
* Legends: Z-A (Ver. 2.0.0)
|
||||
|
||||
## Features
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ private static GameVersion GetGameFromPath(string romfs, string? exefs)
|
||||
private const int FILECOUNT_SV_300 = 30; // Ver. 3.0.0 (Indigo Disk)
|
||||
private const int FILECOUNT_ZA_100 = 22; // Ver. 1.0.0
|
||||
private const int FILECOUNT_ZA_102 = 21; // Ver. 1.0.2
|
||||
private const int FILECOUNT_ZA_200 = 22; // Ver. 2.0.0 (Mega Dimension)
|
||||
|
||||
private static ulong GetTitleID(string? exefs)
|
||||
{
|
||||
@@ -114,7 +115,7 @@ private static ulong GetTitleID(string? exefs)
|
||||
FILECOUNT_SV or FILECOUNT_SV_101 or FILECOUNT_SV_120 or FILECOUNT_SV_130 or FILECOUNT_SV_201 or FILECOUNT_SV_300
|
||||
=> DetectGen9(exefs),
|
||||
|
||||
FILECOUNT_ZA_100 or FILECOUNT_ZA_102
|
||||
FILECOUNT_ZA_100 or FILECOUNT_ZA_102 or FILECOUNT_ZA_200
|
||||
=> GameVersion.ZA,
|
||||
|
||||
_ => GameVersion.Invalid
|
||||
|
||||
@@ -73,6 +73,8 @@ public enum EvolutionType : byte
|
||||
|
||||
Hisui = 61,
|
||||
|
||||
UseMoveBarbBarrage = 62, // ZA
|
||||
|
||||
UseItemFullMoon = 90, // Ursaluna
|
||||
UseMoveAgileStyle = 91, // Wyrdeer
|
||||
UseMoveStrongStyle = 92, // Overqwil
|
||||
@@ -158,6 +160,7 @@ public static class EvolutionTypeExtensions
|
||||
LevelUpRecoilDamageMale => true,
|
||||
LevelUpRecoilDamageFemale => true,
|
||||
Hisui => false,
|
||||
UseMoveBarbBarrage => false,
|
||||
|
||||
UseItemFullMoon => false,
|
||||
UseMoveAgileStyle => false,
|
||||
@@ -237,6 +240,7 @@ public static class EvolutionTypeExtensions
|
||||
[LevelUpKnowMoveECElse] = Moves, // Dudunsparce 0
|
||||
[LevelUpKnowMoveEC25] = Moves, // Dudunsparce 1
|
||||
[Hisui] = NoArg,
|
||||
[UseMoveBarbBarrage] = NoArg,
|
||||
};
|
||||
|
||||
public static EvolutionTypeArgumentType GetArgType(this EvolutionType t) => ArgType[t];
|
||||
|
||||
48
pkNX.WinForms/Dumping/Gen9a/Dumper9a.Designer.cs
generated
48
pkNX.WinForms/Dumping/Gen9a/Dumper9a.Designer.cs
generated
@@ -51,13 +51,15 @@ private void InitializeComponent()
|
||||
B_Misc = new System.Windows.Forms.Button();
|
||||
B_Scrubbed = new System.Windows.Forms.Button();
|
||||
B_DumpTriggers = new System.Windows.Forms.Button();
|
||||
B_DumpConfig = new System.Windows.Forms.Button();
|
||||
Tab_PKHeX = new System.Windows.Forms.TabPage();
|
||||
flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
B_Locations = new System.Windows.Forms.Button();
|
||||
B_DonutText = new System.Windows.Forms.Button();
|
||||
Tab_Future = new System.Windows.Forms.TabPage();
|
||||
flowLayoutPanel4 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
B_OpenFolder = new System.Windows.Forms.Button();
|
||||
B_DumpConfig = new System.Windows.Forms.Button();
|
||||
B_Dimension = new System.Windows.Forms.Button();
|
||||
TC_Options.SuspendLayout();
|
||||
Tab_General.SuspendLayout();
|
||||
flowLayoutPanel1.SuspendLayout();
|
||||
@@ -235,6 +237,7 @@ private void InitializeComponent()
|
||||
flowLayoutPanel3.Controls.Add(B_Scrubbed);
|
||||
flowLayoutPanel3.Controls.Add(B_DumpTriggers);
|
||||
flowLayoutPanel3.Controls.Add(B_DumpConfig);
|
||||
flowLayoutPanel3.Controls.Add(B_Dimension);
|
||||
flowLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
flowLayoutPanel3.Location = new System.Drawing.Point(4, 3);
|
||||
flowLayoutPanel3.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
@@ -341,6 +344,17 @@ private void InitializeComponent()
|
||||
B_DumpTriggers.UseVisualStyleBackColor = true;
|
||||
B_DumpTriggers.Click += B_Triggers_Click;
|
||||
//
|
||||
// B_DumpConfig
|
||||
//
|
||||
B_DumpConfig.Location = new System.Drawing.Point(4, 234);
|
||||
B_DumpConfig.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
B_DumpConfig.Name = "B_DumpConfig";
|
||||
B_DumpConfig.Size = new System.Drawing.Size(144, 71);
|
||||
B_DumpConfig.TabIndex = 28;
|
||||
B_DumpConfig.Text = "Config";
|
||||
B_DumpConfig.UseVisualStyleBackColor = true;
|
||||
B_DumpConfig.Click += B_DumpConfig_Click;
|
||||
//
|
||||
// Tab_PKHeX
|
||||
//
|
||||
Tab_PKHeX.Controls.Add(flowLayoutPanel2);
|
||||
@@ -355,6 +369,7 @@ private void InitializeComponent()
|
||||
// flowLayoutPanel2
|
||||
//
|
||||
flowLayoutPanel2.Controls.Add(B_Locations);
|
||||
flowLayoutPanel2.Controls.Add(B_DonutText);
|
||||
flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
flowLayoutPanel2.Location = new System.Drawing.Point(3, 3);
|
||||
flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
@@ -373,6 +388,17 @@ private void InitializeComponent()
|
||||
B_Locations.UseVisualStyleBackColor = true;
|
||||
B_Locations.Click += B_Locations_Click;
|
||||
//
|
||||
// B_DonutText
|
||||
//
|
||||
B_DonutText.Location = new System.Drawing.Point(156, 3);
|
||||
B_DonutText.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
B_DonutText.Name = "B_DonutText";
|
||||
B_DonutText.Size = new System.Drawing.Size(144, 71);
|
||||
B_DonutText.TabIndex = 22;
|
||||
B_DonutText.Text = "Donut Text";
|
||||
B_DonutText.UseVisualStyleBackColor = true;
|
||||
B_DonutText.Click += B_DonutLocalization_Click;
|
||||
//
|
||||
// Tab_Future
|
||||
//
|
||||
Tab_Future.Controls.Add(flowLayoutPanel4);
|
||||
@@ -405,16 +431,16 @@ private void InitializeComponent()
|
||||
B_OpenFolder.UseVisualStyleBackColor = true;
|
||||
B_OpenFolder.Click += B_OpenFolder_Click;
|
||||
//
|
||||
// B_DumpConfig
|
||||
// B_Dimension
|
||||
//
|
||||
B_DumpConfig.Location = new System.Drawing.Point(4, 234);
|
||||
B_DumpConfig.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
B_DumpConfig.Name = "B_DumpConfig";
|
||||
B_DumpConfig.Size = new System.Drawing.Size(144, 71);
|
||||
B_DumpConfig.TabIndex = 28;
|
||||
B_DumpConfig.Text = "Config";
|
||||
B_DumpConfig.UseVisualStyleBackColor = true;
|
||||
B_DumpConfig.Click += B_DumpConfig_Click;
|
||||
B_Dimension.Location = new System.Drawing.Point(156, 234);
|
||||
B_Dimension.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
B_Dimension.Name = "B_Dimension";
|
||||
B_Dimension.Size = new System.Drawing.Size(144, 71);
|
||||
B_Dimension.TabIndex = 29;
|
||||
B_Dimension.Text = "Dimension";
|
||||
B_Dimension.UseVisualStyleBackColor = true;
|
||||
B_Dimension.Click += B_DumpDimension_Click;
|
||||
//
|
||||
// Dumper9a
|
||||
//
|
||||
@@ -471,5 +497,7 @@ private void InitializeComponent()
|
||||
private System.Windows.Forms.Button B_Scrubbed;
|
||||
private System.Windows.Forms.Button B_DumpTriggers;
|
||||
private System.Windows.Forms.Button B_DumpConfig;
|
||||
private System.Windows.Forms.Button B_DonutText;
|
||||
private System.Windows.Forms.Button B_Dimension;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,12 @@ private void B_DumpMisc_Click(object sender, EventArgs e)
|
||||
System.Media.SystemSounds.Asterisk.Play();
|
||||
}
|
||||
|
||||
private void B_DumpDimension_Click(object sender, EventArgs e)
|
||||
{
|
||||
Dumper.DumpDimension();
|
||||
System.Media.SystemSounds.Asterisk.Play();
|
||||
}
|
||||
|
||||
private void B_DumpScrubbed_Click(object sender, EventArgs e)
|
||||
{
|
||||
Dumper.DumpScrubbedInfo();
|
||||
@@ -190,4 +196,10 @@ private void B_Triggers_Click(object sender, EventArgs e)
|
||||
Dumper.DumpEventTriggers();
|
||||
System.Media.SystemSounds.Asterisk.Play();
|
||||
}
|
||||
|
||||
private void B_DonutLocalization_Click(object sender, EventArgs e)
|
||||
{
|
||||
Dumper.DumpDonutData();
|
||||
System.Media.SystemSounds.Asterisk.Play();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public void DumpStrings()
|
||||
{
|
||||
var textConfig = new TextConfig(GameVersion.ZA);
|
||||
ReadOnlySpan<string> groups = ["ik_messagedat"];
|
||||
ReadOnlySpan<string> types = ["script", "common"];
|
||||
ReadOnlySpan<string> types = ["script", "common", "sk"];
|
||||
foreach (var group in groups)
|
||||
{
|
||||
foreach (var type in types)
|
||||
@@ -512,6 +512,7 @@ public void DumpArchives()
|
||||
|
||||
public void DumpMisc()
|
||||
{
|
||||
Dump<ItemTableArray, ItemTable>("world/ik_data/battle/plib_item_conversion/plib_item_conversion_array.bfbs", z => z.Table);
|
||||
Dump<RankBattleRewardArray, RankBattleReward>("world/ik_data/rank_battle/reward/reward_array.bfbs", z => z.Table);
|
||||
Dump<PokedexBlackListMainArray, PokedexBlackListMain>("world/ik_data/ui/pokedex/black_list_main/black_list_main_array.bfbs", z => z.Table);
|
||||
|
||||
@@ -520,6 +521,7 @@ public void DumpMisc()
|
||||
DumpJson<CaptureZARankData>("world/ik_data/capture/capture_zarank_data/capture_zarank_data.bin");
|
||||
|
||||
Dump<ZARewardItemDataArray, ZARewardItemData>("ik_event/bin/za_reward_item_data/za_reward_item_data.bin", z => z.Table);
|
||||
Dump<NpcAssetDataDBArray, NpcAssetData>("world/ik_data/field/npc/npc_asset_data/npc_asset_data/npc_asset_data.bfbs", z => z.Table);
|
||||
Dump<TrainerBattleGlobalDBArray, TrainerBattleData>("ik_event/bin/event_trainer_battle_data/trainer_btl_data_global.bin", z => z.Table);
|
||||
Dump<ShopLineupArray, ShopLineup>("world/exl/shop/shop_item_lineup/shop_item_lineup.bin", z => z.Table);
|
||||
Dump<ItemTableDataDBArray, ItemTableDataDB>("world/ik_data/field/random_pop_item/random_pop_item_table/random_pop_item_table_data/random_pop_item_table_data_array.bfbs", z => z.Table);
|
||||
@@ -538,6 +540,27 @@ public void DumpMisc()
|
||||
Dump<WeatherHappeningParamArray, WeatherHappeningParam>("world/ik_data/field/weather/weather_happening/weather_happening_array.bin", z => z.Table);
|
||||
|
||||
DumpDressUp();
|
||||
|
||||
const string pst = "world/ik_data/field/spawner_transform_data/placement_npc_spawner_transform/placement_npc_spawner_transform/placement_npc_spawner_transform_array.bfbs";
|
||||
var spawnerT = Dump<SpawnerTransformDataDBArray, SpawnerTransformDataDB>(pst, z => z.Table);
|
||||
for (var i = 0; i < spawnerT.Table.Count; i++)
|
||||
{
|
||||
var table = spawnerT.Table[i];
|
||||
var lines = TableUtil.GetTable(table.Table);
|
||||
var path = GetRawPath(pst);
|
||||
var fileName = Path.ChangeExtension(path, $".{i:00}.txt");
|
||||
File.WriteAllText(fileName, lines);
|
||||
}
|
||||
|
||||
DumpJson<ConditionRareDBArray>("param_ai/data/ai/trigger/condition_rare/condition_rare_array.bin");
|
||||
|
||||
Dump<DonutFlavorArray, DonutFlavor>("world/exl/donut/flavor/flavor.bin", z => z.Table);
|
||||
Dump<DonutRecipeArray, DonutRecipe>("world/exl/donut/donut_recipe/donut_recipe.bin", z => z.Table);
|
||||
Dump<BerryDetailArray, BerryDetail>("world/exl/donut/berry/berry.bin", z => z.Table);
|
||||
Dump<DonutDetailArray, DonutDetail>("world/exl/donut/donut/donut.bin", z => z.Table);
|
||||
Dump<DonutFlavorLotteryArray, DonutFlavorLottery>("world/exl/donut/flavor_lottery/flavor_lottery.bin", z => z.Table);
|
||||
Dump<DonutFlavorParameterArray, DonutFlavorParameter>("world/exl/donut/flavor_parameter/flavor_parameter.bin", z => z.Table);
|
||||
Dump<DonutOneWordArray, DonutOneWord>("world/exl/donut/oneword/oneword.bin", z => z.Table);
|
||||
}
|
||||
|
||||
private void DumpDressUp()
|
||||
@@ -965,10 +988,18 @@ public void DumpPersonal()
|
||||
var alphaMoves = Dump<OyabunWazaDB, OyabunWaza>(alphaMovesPath, z => z.Table)
|
||||
.Table;
|
||||
|
||||
// Only acknowledge the first set of entries.
|
||||
foreach (var alpha in alphaMoves)
|
||||
{
|
||||
foreach (var form in alpha.FormTableList)
|
||||
pt[SpeciesConverterZA.GetNational9(alpha.DevNo), (byte)form.FormNo].AlphaMove = form.WazaNo;
|
||||
{
|
||||
var pi = pt[SpeciesConverterZA.GetNational9(alpha.DevNo), (byte)form.FormNo];
|
||||
if (pi.AlphaMove == 0)
|
||||
pi.AlphaMove = form.WazaNo;
|
||||
// don't throw an exception if already non-zero -- Raichu's mega forms were incorrectly configured as 1/2 rather than 2/3.
|
||||
// The Alpha Move search returns on first match.
|
||||
// the only clash is Raichu-1, which needs to stay as Iron Tail (not Play Rough).
|
||||
}
|
||||
}
|
||||
|
||||
var bin = pt.Write();
|
||||
@@ -1000,6 +1031,54 @@ public void DumpPersonal()
|
||||
RipPersonal(pt, lang);
|
||||
}
|
||||
|
||||
public void DumpDimension()
|
||||
{
|
||||
const string dimWild = "world/ik_data/field/dimension/dimension_wild_pokemon/dimension_wild_pokemon/dimension_wild_pokemon_array.bfbs";
|
||||
Dump<DimensionWildPokemonDBArray, DimensionWildPokemonDB>(dimWild, z => z.Table);
|
||||
DumpSel<DimensionWildPokemonDBArray, DimensionWildPokemon>(dimWild, z => z.Table.SelectMany(x => x.Table), "x");
|
||||
|
||||
const string dimSpecialLottery = "world/ik_data/field/dimension/dimension_special_lottery/dimension_special_lottery/dimension_special_lottery_array.bfbs";
|
||||
Dump<DimensionSpecialLotteryDBArray, DimensionSpecialLotteryDB>(dimSpecialLottery, z => z.Table);
|
||||
|
||||
const string dimItem = "world/ik_data/field/dimension/dimension_gimmick_item/dimension_gimmick_item/dimension_gimmick_item_array.bfbs";
|
||||
Dump<DimensionGimmickItemDBArray, DimensionGimmickItemDB>(dimItem, z => z.Table);
|
||||
|
||||
const string dimUniqueLottery = "world/ik_data/field/dimension/dimension_unique_lottery/dimension_unique_lottery/dimension_unique_lottery_array.bfbs";
|
||||
Dump<DimensionUniqueLotteryDBArray, DimensionUniqueLotteryDB>(dimUniqueLottery, z => z.Table);
|
||||
|
||||
const string dimZoneLottery = "world/ik_data/field/dimension/dimension_zone_lottery/dimension_zone_lottery/dimension_zone_lottery_array.bfbs";
|
||||
Dump<DimensionZoneLotteryDBArray, DimensionZoneLotteryDB>(dimZoneLottery, z => z.Table);
|
||||
|
||||
const string dimBossLottery = "world/ik_data/field/dimension/dimension_boss_lottery/dimension_boss_lottery/dimension_boss_lottery_array.bfbs";
|
||||
Dump<DimensionBossLotteryDBArray, DimensionBossLotteryDB>(dimBossLottery, z => z.Table);
|
||||
|
||||
const string dimGateSpawner = "world/ik_data/field/dimension/dimension_gate_spawner/dimension_gate_spawner/dimension_gate_spawner_array.bfbs";
|
||||
Dump<DimensionGateSpawnerDBArray, DimensionGateSpawnerDB>(dimGateSpawner, z => z.Table);
|
||||
|
||||
const string dimGateArray = "world/ik_data/field/dimension/dimension_gate_object/dimension_gate_object/dimension_gate_object_array.bfbs";
|
||||
Dump<DimensionGateObjectDBArray, DimensionGateObjectDB>(dimGateArray, z => z.Table);
|
||||
|
||||
const string dimProgress = "world/ik_data/field/dimension/dimension_progress/dimension_progress/dimension_progress_array.bfbs";
|
||||
Dump<DimensionProgressDBArray, DimensionProgressDB>(dimProgress, z => z.Table);
|
||||
|
||||
const string dimMapArray = "world/ik_data/field/dimension/dimension_map/dimension_map/dimension_map_array.bfbs";
|
||||
Dump<DimensionMapDBArray, DimensionMapDB>(dimMapArray, z => z.Table);
|
||||
|
||||
const string dimRankArray = "world/ik_data/field/dimension/dimension_rank/dimension_rank/dimension_rank_array.bfbs";
|
||||
Dump<DimensionRankDBArray, DimensionRankDB>(dimRankArray, z => z.Table);
|
||||
|
||||
const string dimConfig = "world/ik_data/field/dimension/dimension_config/dimension_config/dimension_config.bfbs";
|
||||
DumpJson<DimensionConfigDB>(dimConfig);
|
||||
|
||||
const string wazaConfig = "world/ik_data/field/wazagimmick_item_spawner/wazagimmick_item_spawner/wazagimmick_item_spawner.bfbs";
|
||||
Dump<WazagimmickItemSpawnerDB, WazagimmickItemSpawner>(wazaConfig, z => z.Table);
|
||||
|
||||
const string itemTable = "world/ik_data/field/wazagimmick_item_table/wazagimmick_item_table/wazagimmick_item_table_array.bfbs";
|
||||
Dump<WazagimmickItemTableDBArray, WazagimmickItemTableDB>(itemTable, z => z.Table);
|
||||
|
||||
DumpDimensionGates();
|
||||
}
|
||||
|
||||
private void RipPersonal(PersonalTable9ZA pt, string lang)
|
||||
{
|
||||
var cfg = new TextConfig(rom.Game);
|
||||
@@ -1035,16 +1114,16 @@ private void RipPersonal(PersonalTable9ZA pt, string lang)
|
||||
File.WriteAllLines(GetPath(lang, "MovePerPokemon.txt"), moveLines);
|
||||
|
||||
var dexOrder = pt.Table
|
||||
.Where(z => z.FB.Dex != 0 && z.FB.IsPresentInGame)
|
||||
.OrderBy(z => z.FB.Dex)
|
||||
.Where(z => z.FB.Dex != null && z.FB.IsPresentInGame)
|
||||
.OrderBy(z => z.FB.Dex!.Index)
|
||||
.GroupBy(z => z.FB.Info.SpeciesNational)
|
||||
.Select(z => z.First());
|
||||
|
||||
var pc = dexOrder.Select(z => $"{z.FB.Dex:000}\t{specNames[z.FB.Info.SpeciesInternal]}");
|
||||
var pc = dexOrder.Select(z => $"{z.FB.Dex!.Index:000}\t{specNames[z.FB.Info.SpeciesInternal]}");
|
||||
File.WriteAllText(GetPath(lang, "dex.txt"), string.Join(Environment.NewLine, pc));
|
||||
|
||||
var foreign = pt.Table
|
||||
.Where(z => z.FB.Dex == 0 && z.IsPresentInGame)
|
||||
.Where(z => z.FB.Dex == null && z.IsPresentInGame)
|
||||
.GroupBy(z => z.FB.Info.SpeciesNational)
|
||||
.Select(z => z.First());
|
||||
|
||||
@@ -1066,7 +1145,6 @@ private void RipPersonal(PersonalTable9ZA pt, string lang)
|
||||
File.WriteAllText(GetPath(lang, "tm.txt"), string.Join(Environment.NewLine, tmNames));
|
||||
}
|
||||
|
||||
|
||||
private static byte[][] SerializeU16Pickle(PersonalTable9ZA pt, Func<PersonalInfo, IList<ushort>> sel)
|
||||
{
|
||||
var t = pt.Table;
|
||||
@@ -1106,14 +1184,18 @@ static byte[] GetPickle(PersonalInfo9ZA e)
|
||||
return Write(e.FB.Info.SpeciesNational, e.FB.Evolutions);
|
||||
}
|
||||
|
||||
static byte[] Write(int species, IEnumerable<PersonalInfoEvolution> evos)
|
||||
static byte[] Write(int species, IList<PersonalInfoEvolution> evos)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
|
||||
var list = evos.ToArray();
|
||||
if (species == (int)Species.Crabrawler)
|
||||
Array.Reverse(list); // put the levelup evo last.
|
||||
var list = evos;
|
||||
if (species is (int)Species.Crabrawler or (int)Species.Feebas)
|
||||
{
|
||||
var tmp = evos.ToArray();
|
||||
Array.Reverse(tmp); // put the levelup evo last.
|
||||
list = tmp;
|
||||
}
|
||||
|
||||
foreach (var m in list) // just in case
|
||||
{
|
||||
@@ -1227,7 +1309,8 @@ public void DumpTrainers()
|
||||
var classes = Get<TrainerTypeArray>(trt);
|
||||
var npcs = Get<NpcAssetDataDBArray>(npc).Table;
|
||||
var trBtlData = Get<TrainerBattleGlobalDBArray>(btl).Table;
|
||||
List<(string TrainerBattleID, string NPCAssetID)> trBtls = trBtlData.Select(z => (z.TrainerBattleID, z.NPCAssetID)).ToList()!;
|
||||
List<(string TrainerBattleID1, string NPCAssetID1)> trBtls1 = trBtlData.Select(z => (z.TrainerBattleID1, z.NPCAssetID1)).ToList()!;
|
||||
List<(string TrainerBattleID2, string NPCAssetID2)> trBtls2 = trBtlData.Select(z => (z.TrainerBattleID2, z.NPCAssetID2)).ToList()!;
|
||||
|
||||
// pretty
|
||||
List<string> result = [];
|
||||
@@ -1276,6 +1359,7 @@ public void DumpTrainers()
|
||||
var gender = pk.Sex is 0 ? string.Empty : pk.Sex is SexType.MALE ? " (♂)" : " (♀)";
|
||||
|
||||
var level = $" (Lv. {pk.Level})";
|
||||
var alpha = pk.IsOybn ? " (Alpha)" : string.Empty;
|
||||
var item = pk.Item is 0 ? string.Empty : $" (Held Item: {items[(int)pk.Item]})";
|
||||
var rare = pk.RareType is RareType.RARE ? " ★" : string.Empty;
|
||||
var move1 = PrettyDumpUtil.GetMoveText(pk.Waza1, moves);
|
||||
@@ -1306,7 +1390,7 @@ public void DumpTrainers()
|
||||
var eff = pk.EffortValue;
|
||||
ReadOnlySpan<int> evs = [eff.HP, eff.ATK, eff.DEF, eff.SPA, eff.SPD, eff.SPE];
|
||||
var textEVs = evs.ContainsAnyExcept(0) ? $" (EVs: {PrettyDumpUtil.GetEVSpread(evs)})" : string.Empty;
|
||||
var line = $"- {name}{form}{gender}{rare}{level}{item}{ability}{nature}{ball}{moveOutput}{textIVs}{textEVs}";
|
||||
var line = $"- {name}{form}{gender}{rare}{level}{alpha}{item}{ability}{nature}{ball}{moveOutput}{textIVs}{textEVs}";
|
||||
result.Add(line);
|
||||
}
|
||||
|
||||
@@ -1327,7 +1411,7 @@ static string GetTrainerNameFormatted(string type, string name, ushort flags)
|
||||
var format = ((flags >> 7) & 0b11);
|
||||
var display = format switch
|
||||
{
|
||||
0 when name is "Corbeau" or "Philippe" => "{1} of the {0}", // no clue how they differentiate these two from Grunts, hardcode it
|
||||
0 when type is "Rust Syndicate" && name is "Corbeau" or "Philippe" => "{1} of the {0}", // no clue how they differentiate these two from Grunts, hardcode it
|
||||
0 => "{0} {1}",
|
||||
1 when article => "{1} of the {0}",
|
||||
1 => "{1} of {0}",
|
||||
@@ -1339,6 +1423,10 @@ static string GetTrainerNameFormatted(string type, string name, ushort flags)
|
||||
if (name is "representative")
|
||||
display = display.Insert(0, "The ");
|
||||
|
||||
// no unique name
|
||||
if (type is "Alpha Trainer" or "Hyperspace Trainer")
|
||||
return type;
|
||||
|
||||
return string.Format(display, type, name);
|
||||
}
|
||||
|
||||
@@ -1361,21 +1449,51 @@ string GetTrainerName(string id)
|
||||
return $"{rivalF}/{rivalM}";
|
||||
}
|
||||
|
||||
var (trainerBattleId, npcAssetId) = trBtls.FirstOrDefault(z => z.TrainerBattleID == id);
|
||||
if (trainerBattleId is null)
|
||||
// no unique name
|
||||
if (id.StartsWith("dim_rank_"))
|
||||
return string.Empty;
|
||||
|
||||
var (trainerBattleId1, npcAssetId1) = trBtls1.FirstOrDefault(z => z.TrainerBattleID1 == id);
|
||||
var (trainerBattleId2, npcAssetId2) = trBtls2.FirstOrDefault(z => z.TrainerBattleID2 == id);
|
||||
var btlToCheck = trainerBattleId2 is null ? trainerBattleId1 : trainerBattleId2;
|
||||
var npcToCheck = npcAssetId2 is null ? npcAssetId1 : npcAssetId2;
|
||||
|
||||
if (btlToCheck is null || id is "Ev_sub_123_010" || id.Contains("Ev_sub_124"))
|
||||
{
|
||||
// not in trname
|
||||
if (id is "Ev_sub_145_010_multi")
|
||||
return "Marcia";
|
||||
|
||||
var fallback = GetFallbackTrainerName(id);
|
||||
return ahtbNames.GetString(FnvHash.HashFnv1a_64(fallback), trNames);
|
||||
}
|
||||
|
||||
// special name format
|
||||
if (npcAssetId.Contains("rest_trainer"))
|
||||
if (npcToCheck.Contains("rest_trainer"))
|
||||
{
|
||||
var restName = ahtbNames.GetString(FnvHash.HashFnv1a_64(npcAssetId.Replace("_trainer", "")), trNames);
|
||||
var restName = ahtbNames.GetString(FnvHash.HashFnv1a_64(npcToCheck.Replace("_trainer", "")), trNames);
|
||||
return restName;
|
||||
}
|
||||
|
||||
var target = npcs.FirstOrDefault(z => z.AssetId == npcAssetId)!;
|
||||
if (npcToCheck.StartsWith("2on2_"))
|
||||
npcToCheck = npcToCheck[5..];
|
||||
|
||||
var target = npcs.FirstOrDefault(z => z.AssetId == npcToCheck)!;
|
||||
|
||||
if (target is null)
|
||||
{
|
||||
var startQuest = npcToCheck.Length is 15 ? 8 : 7;
|
||||
var startSub = npcToCheck.Length is 15 ? 12 : 11;
|
||||
var questID = int.Parse(npcToCheck[startQuest..(startQuest + 3)]);
|
||||
var subID = int.Parse(npcToCheck[startSub..(startSub + 3)]);
|
||||
|
||||
// this is off-by-two for some reason?
|
||||
if (questID == 180)
|
||||
subID += 2;
|
||||
|
||||
target = npcs.FirstOrDefault(z => z.AssetId == $"npc_sub{questID}_{subID:0000}")!;
|
||||
}
|
||||
|
||||
var name = target.NpcInfoList.Where(z => !string.IsNullOrWhiteSpace(z.Name)).ToArray()[0].Name;
|
||||
return ahtbNames.GetString(FnvHash.HashFnv1a_64(name), trNames);
|
||||
}
|
||||
@@ -1394,6 +1512,26 @@ string GetTrainerName(string id)
|
||||
"Ev_m09_2400_multi_02" => "executive05", // Griselle
|
||||
"Ev_sub_103_multi" => "alias01", // Andi
|
||||
"Ev_sub_114_multi" => "battleg", // Josée
|
||||
|
||||
// DLC
|
||||
"Ev_d02_0010" or "Ev_sub_161_010_multi" => "friend_01", // Naveen
|
||||
"Ev_d00_2100_multi" or "Ev_d04_1100" or "Ev_sub_164_010_multi" => "friend_02", // Lida
|
||||
"Ev_d01_3100" or "Ev_d02_2200" or "Ev_d03_1300" or "Ev_d04_2100" or "Ev_d05_1200" or "Ev_d06_1020" or "Ev_d07_1000" or "Ev_d07_1100" or "Ev_d07_2000" or "Ev_sub_162_010_multi" or "Ev_sub_203_010_multi_02" => "xyleader3_01", // Korrina
|
||||
"Ev_d05_0100" => "boss03", // Corbeau
|
||||
//"Ev_sub_145_010_multi" => "sub_145", // Marcia
|
||||
"Ev_sub_148_020_client" => "sub_148", // Dixan
|
||||
"Ev_sub_165_010_multi" or "Ev_sub_203_010_multi_01" => "detective", // Emma
|
||||
"Ev_sub_166_010_multi" => "executive02", // Gwynn
|
||||
"Ev_sub_167_010_multi" => "executive04", // Lebanne
|
||||
"Ev_sub_168_010_multi" => "secretary", // Vinnie
|
||||
"Ev_sub_169_010_multi" => "boss04", // Jacinthe
|
||||
"Ev_sub_170_010_multi" => "executive03", // Philippe
|
||||
|
||||
// Some DLC Side Missions with NPCs from past Side Missions are, annoyingly, not mapped as such in the NPC db array
|
||||
"Ev_sub_123_010" => "sub_002", // Trevelle
|
||||
_ when id.Contains("megax") => "sub_001", // Tracie
|
||||
_ when id.Contains("megay") => "sub_072", // Griddella
|
||||
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(id), id, null),
|
||||
};
|
||||
}
|
||||
@@ -1511,6 +1649,8 @@ public void ScanPatterns()
|
||||
("rnd_", true),
|
||||
("TITLE_", true),
|
||||
("itd_", true),
|
||||
("donut", true),
|
||||
("dim_", true),
|
||||
|
||||
("rso_", false), // royale card spawn
|
||||
("t1_", false),
|
||||
@@ -1559,7 +1699,7 @@ private void CreateSaveHashDump(IEnumerable<string> saveHashHits, string outPath
|
||||
..FromFile<EventLabelArray>("ik_event/bin/flag/temp_flag.bin").Table.Select(z => z.Name),
|
||||
..FromFile<EventLabelArray>("ik_event/bin/flag/temp_work.bin").Table.Select(z => z.Name),
|
||||
|
||||
..FromFile<EventLabelArray>("ik_event/bin/title/title.bin").Table.Select(z => z.Name),
|
||||
..FromFile<TitleArray>("ik_event/bin/title/title.bin").Table.Select(z => z.Name),
|
||||
|
||||
// works to grab first field of object as string, even though this isn't the right schema to parse as
|
||||
..FromFile<EventLabelArray>("ik_event/bin/momiji_count/momiji_count.bin").Table.Select(z => z.Name),
|
||||
@@ -1838,7 +1978,7 @@ private void DumpPokemonPKHeX(PokemonDataDBArray pokemon)
|
||||
|
||||
var names = GetCommonText("monsname", lang, cfg);
|
||||
var natures = GetCommonText("seikaku", lang, cfg);
|
||||
ReadOnlySpan<string> Trades = ["sub_addpoke_araichu", "sub_tradepoke_riolu", "sub_addpoke_gyadon", "sub_tradepoke_heracros"];
|
||||
ReadOnlySpan<string> Trades = ["sub_addpoke_araichu", "sub_tradepoke_riolu", "sub_addpoke_gyadon", "sub_tradepoke_heracros", "sub_tradepoke_poligon2"];
|
||||
|
||||
foreach (var enc in pokemon.Table)
|
||||
{
|
||||
@@ -1963,6 +2103,7 @@ public void DumpEncountData()
|
||||
var outPath = GetPath("spawner");
|
||||
var dumper = new SpawnRipper9a(rom, "English", outPath);
|
||||
dumper.ExportRippedMaps();
|
||||
dumper.ExportHyperspacePickle();
|
||||
}
|
||||
|
||||
private void DumpEncountPretty(EncountDataDBArray pokemon, PokemonDropItemTableDataDBArray drops)
|
||||
@@ -2098,13 +2239,19 @@ private void DumpEncountPretty(EncountDataDBArray pokemon, PokemonDropItemTableD
|
||||
{
|
||||
foreach (var slot in encDropData.Where(z => z.ItemTableId == i.Id))
|
||||
{
|
||||
float totalWeight = 0;
|
||||
foreach (var dropped in i.ItemLotteryDataList!)
|
||||
totalWeight += dropped.Weight;
|
||||
|
||||
foreach (var dropped in i.ItemLotteryDataList!)
|
||||
{
|
||||
var itemID = int.TryParse(dropped.ItemId, out var id);
|
||||
var weight = dropped.Weight;
|
||||
var maxCount = dropped.MaxCount;
|
||||
var type = dropped.Type;
|
||||
result.Add($"- {weight}% {items[id]} (×{maxCount})");
|
||||
float rate = (float)(Math.Round((weight / totalWeight) * 100f, 2));
|
||||
var countDisplay = maxCount == 1 ? $"×{maxCount}" : $"×1-{maxCount}";
|
||||
result.Add($"- {rate:00.00}% {items[id]} ({countDisplay})");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2200,10 +2347,13 @@ private void DumpTradeNames()
|
||||
result.Add(names[415]); // Riolouie (Riolu)
|
||||
result.Add(names[416]); // Spicy (Slowpoke)
|
||||
result.Add(names[417]); // Floffy (Raichu)
|
||||
result.Add(names[496]); // Alias (Porygon)
|
||||
|
||||
result.Add(names[293]); // Tracie
|
||||
result.Add(names[306]); // Bond
|
||||
result.Add(names[310]); // Quille
|
||||
result.Add(names[362]); // Griddella
|
||||
result.Add(names[431]); // Trian
|
||||
|
||||
File.WriteAllLines(GetPath("pkhex", "trades", $"text_tradeza_{l}.txt"), result);
|
||||
}
|
||||
@@ -2444,7 +2594,7 @@ public void DumpEventTriggers()
|
||||
|
||||
private IEnumerable<string> GetTriggerFileList()
|
||||
{
|
||||
for (int i = 0; i <= 9; i++)
|
||||
for (int i = 0; i <= 10; i++)
|
||||
{
|
||||
const string main = "ik_event/bin/trigger/main/trigger_main_{0:00}.bin";
|
||||
var file = string.Format(main, i);
|
||||
@@ -2458,6 +2608,106 @@ private IEnumerable<string> GetTriggerFileList()
|
||||
if (rom.HasFile(file))
|
||||
yield return file;
|
||||
}
|
||||
|
||||
yield return "ik_event/bin/trigger/map/trigger_map_t2.bin";
|
||||
yield return "ik_event/bin/trigger/global/trigger_global.bin";
|
||||
yield return "ik_event/bin/trigger/trainer_battle/trigger_trainer_battle_global.bin";
|
||||
yield return "ik_event/bin/trigger/wild_battle/trigger_wild_battle_global.bin";
|
||||
yield return "ik_event/bin/trigger/last_battle/trigger_last_battle_global.bin";
|
||||
yield return "ik_event/bin/trigger/boss_battle/trigger_boss_battle_global.bin";
|
||||
yield return "ik_event/bin/trigger/athletic_time_attack/trigger_athletic_time_attack.bin";
|
||||
}
|
||||
|
||||
public void DumpDonutData()
|
||||
{
|
||||
var textConfig = new TextConfig(GameVersion.ZA);
|
||||
|
||||
foreach (var language in LanguageEnglishNames)
|
||||
{
|
||||
var code = GetLanguageCode(language);
|
||||
|
||||
// Get Donut Names
|
||||
// Skip index 0, only keep 203 entries
|
||||
var donuts = GetText("donut_name", language).AsSpan(1, 203);
|
||||
foreach (ref var name in donuts)
|
||||
{
|
||||
// remove string format. don't care for now.
|
||||
name = name.Replace("[VAR 01D9(0001)][VAR 0133(0000)] ", ""); // english
|
||||
name = name.Replace("[VAR 0133(0000)]", ""); // otherwise, before & after
|
||||
name = name.Replace("[VAR 01D9(0001)]", "");
|
||||
|
||||
}
|
||||
WriteText("donutName", code, donuts.ToArray());
|
||||
|
||||
// Get Flavor Names
|
||||
var flavors = GetText("donut_flavor", language).AsSpan(205, 290);
|
||||
// Need to skip over the unused entries.
|
||||
// Skip 3,4,5 and 147-152
|
||||
var flavorNames = new List<string>();
|
||||
for (int i = 0; i < flavors.Length; i++)
|
||||
{
|
||||
if (i is 3 or 4 or 5 or >= 147 and <= 152)
|
||||
continue;
|
||||
flavorNames.Add(flavors[i]);
|
||||
}
|
||||
WriteText("donutFlavor", code, flavorNames);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
void WriteText(string name, string code, IEnumerable<string> lines)
|
||||
{
|
||||
var path = GetPath("pkhex", "donut");
|
||||
Directory.CreateDirectory(path);
|
||||
var fileName = $"text_{name}_{code}.txt";
|
||||
File.WriteAllText(Path.Combine(path, fileName), string.Join('\n', lines));
|
||||
}
|
||||
|
||||
string[] GetText(string name, string lang)
|
||||
{
|
||||
var data = rom.GetPackedFile($"{message}/dat/{lang}/sk/{name}.dat");
|
||||
return new TextFile(data, textConfig).Lines;
|
||||
}
|
||||
}
|
||||
|
||||
public void DumpDimensionGates()
|
||||
{
|
||||
var files = new[]
|
||||
{
|
||||
"world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_dim_gate_spawner/t1_dim_gate_spawner_blue_/t1_dim_gate_spawner_blue_0.trscn",
|
||||
"world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_dim_gate_spawner/t1_dim_gate_spawner_jaune_/t1_dim_gate_spawner_jaune_0.trscn",
|
||||
"world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_dim_gate_spawner/t1_dim_gate_spawner_rose_/t1_dim_gate_spawner_rose_0.trscn",
|
||||
"world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_dim_gate_spawner/t1_dim_gate_spawner_rouge_/t1_dim_gate_spawner_rouge_0.trscn",
|
||||
"world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_dim_gate_spawner/t1_dim_gate_spawner_veil_/t1_dim_gate_spawner_veil_0.trscn",
|
||||
"world/ik_scene/field/area/t1_i011/sub_scene/t1_i011_gimmick/t1_i011_dim_gate_spawner_/t1_i011_dim_gate_spawner_0.trscn",
|
||||
"world/ik_scene/field/area/t1_i012_1/sub_scene/t1_i012_1_gimmick/t1_i012_1_dim_gate_spawner_/t1_i012_1_dim_gate_spawner_0.trscn",
|
||||
"world/ik_scene/field/area/t1_i012_2/sub_scene/t1_i012_2_gimmick/t1_i012_2_dim_gate_spawner_/t1_i012_2_dim_gate_spawner_0.trscn",
|
||||
"world/ik_scene/field/area/t1_i014_1/sub_scene/t1_i014_1_gimmick/t1_i014_1_dim_gate_spawner_/t1_i014_1_dim_gate_spawner_0.trscn",
|
||||
"world/ik_scene/field/area/t2/sub_scene/t2_gimmick/t2_dim_gate_spawner_/t2_dim_gate_spawner_0.trscn",
|
||||
"world/ik_scene/field/area/t3/sub_scene/t3_gimmick/t3_dim_gate_spawner_/t3_dim_gate_spawner_0.trscn",
|
||||
};
|
||||
|
||||
List<string> Result = [];
|
||||
foreach (var t in files)
|
||||
{
|
||||
var data = rom.GetPackedFile(t);
|
||||
var obj = FlatBufferConverter.DeserializeFrom<TrinitySceneObjectTemplate>(data);
|
||||
Result.Add(obj.ObjectTemplateName);
|
||||
|
||||
foreach (var o in obj.Objects.Where(z => z.Type is "trinity_ObjectTemplate"))
|
||||
{
|
||||
var sceneObject = FlatBufferConverter.DeserializeFrom<TrinitySceneObjectTemplateData>(o.Data);
|
||||
var scenePoint = FlatBufferConverter.DeserializeFrom<TrinityScenePoint>(sceneObject.Data);
|
||||
var dim = sceneObject.ObjectTemplateName;
|
||||
var pos = scenePoint.Position;
|
||||
|
||||
Result.Add($"{dim}\t{pos.X}\t{pos.Y}\t{pos.Z}");
|
||||
}
|
||||
|
||||
Result.Add("");
|
||||
}
|
||||
|
||||
File.WriteAllLines(GetPath("dim_gate", "dim_gate.txt"), Result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ public sealed class SpawnGlobalInfo
|
||||
private readonly GameManager9a _rom;
|
||||
|
||||
public readonly Dictionary<string, EncountData> Encounters;
|
||||
public readonly Dictionary<string, SpawnerTransformData> SpawnerTransforms;
|
||||
public readonly Dictionary<string, List<SpawnerTransformData>> SpawnerTransforms;
|
||||
public readonly List<string> HyperspaceSpawnSets;
|
||||
|
||||
public readonly PokemonSpawnerDataDBArray SpawnerDatabase;
|
||||
|
||||
@@ -26,10 +27,45 @@ public SpawnGlobalInfo(GameManager9a rom)
|
||||
|
||||
const string pst = "world/ik_data/field/spawner_transform_data/pokemon_spawner_transform/pokemon_spawner_transform/pokemon_spawner_transform_array.bin";
|
||||
var spawnerT = Get<SpawnerTransformDataDBArray>(pst);
|
||||
SpawnerTransforms = spawnerT.Table.SelectMany(z => z.Table).ToDictionary(z => z.Name ?? "", z => z);
|
||||
// Build multimap of Name -> List<SpawnerTransformData>; skip null/empty names to avoid collisions.
|
||||
SpawnerTransforms = spawnerT.Table
|
||||
.SelectMany(z => z.Table)
|
||||
.Where(x => !string.IsNullOrEmpty(x.Name))
|
||||
.GroupBy(x => x.Name)
|
||||
.ToDictionary(g => g.Key!, g => g.ToList());
|
||||
|
||||
const string psp = "world/ik_data/field/pokemon_spawner/pokemon_spawner_data/pokemon_spawner_data_array.bin";
|
||||
SpawnerDatabase = Get<PokemonSpawnerDataDBArray>(psp);
|
||||
|
||||
const string dimWild = "world/ik_data/field/dimension/dimension_wild_pokemon/dimension_wild_pokemon/dimension_wild_pokemon_array.bin";
|
||||
var dim = Get<DimensionWildPokemonDBArray>(dimWild);
|
||||
|
||||
// Since we don't care about the star count requirements (since distortions can be 1-5 regardless of game progress), we can lump them all together.
|
||||
HyperspaceSpawnSets = GetHyperspaceSpawnSets(dim);
|
||||
}
|
||||
|
||||
private static List<string> GetHyperspaceSpawnSets(DimensionWildPokemonDBArray dim)
|
||||
{
|
||||
List<string> result = [];
|
||||
foreach (var a in dim.Table)
|
||||
{
|
||||
foreach (var b in a.Table)
|
||||
{
|
||||
foreach (var c in b.RankItems)
|
||||
{
|
||||
if (c.PatternItems is null) // no encounters for this type-set
|
||||
continue;
|
||||
foreach (var set in c.PatternItems)
|
||||
{
|
||||
if (set.SpawnerItems is not { } si)
|
||||
continue;
|
||||
result.AddRange(si.Select(x => x.SpawnerDataId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private T Get<T>(string path) where T : class, IFlatBufferSerializable<T>
|
||||
|
||||
@@ -80,11 +80,11 @@ public static void WritePickle(IReadOnlyList<EncounterArea9a> slotSets, string p
|
||||
File.WriteAllBytes(path, mini);
|
||||
}
|
||||
|
||||
public static void AddSlots(List<EncounterSlot9a> list, EncountData slot, EncountDataInfo enc)
|
||||
public static void AddSlots(List<EncounterSlot9a> list, EncountData slot, EncountDataInfo enc, bool hyperspaceBoost = false)
|
||||
{
|
||||
var species = SpeciesConverterZA.GetNational9((ushort)slot.DevNo);
|
||||
var form = (byte)slot.FormNo;
|
||||
const int boost = 0; // enc.AdditionalLevel; // field is unused; assumed to be similar to Kitakami post-game level boost, but there is none applicable in Z-A.
|
||||
int boost = !hyperspaceBoost ? 0 : enc.AdditionalLevel; // level boost used in hyperspace, applicable in Z-A.
|
||||
var minLevel = (byte)(slot.MinLevel + boost);
|
||||
var maxLevel = (byte)(slot.MaxLevel + boost);
|
||||
var gender = (sbyte)slot.Sex;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using pkNX.Structures.FlatBuffers.ZA;
|
||||
|
||||
namespace pkNX.WinForms;
|
||||
@@ -6,4 +8,18 @@ namespace pkNX.WinForms;
|
||||
public sealed class MapSpawnerSet
|
||||
{
|
||||
public required Dictionary<string, PokemonSpawnerData> SpawnerInfo { get; init; }
|
||||
|
||||
public bool TryGetSpawnerFromEncounter(string encId, [NotNullWhen(true)] out PokemonSpawnerData? spawnerData)
|
||||
{
|
||||
foreach (var (key, value) in SpawnerInfo)
|
||||
{
|
||||
if (value.EncountDataInfoList.All(x => x.EncountDataId != encId))
|
||||
continue;
|
||||
|
||||
spawnerData = value;
|
||||
return true;
|
||||
}
|
||||
spawnerData = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using pkNX.Structures;
|
||||
|
||||
namespace pkNX.WinForms;
|
||||
|
||||
@@ -19,6 +20,7 @@ public sealed class SpawnRipper9a
|
||||
public readonly LumioseMap Overworld;
|
||||
public const byte LocationLabs = 234;
|
||||
public const byte LocationSewer = 235;
|
||||
public const ushort LocationHyperspace = 273;
|
||||
|
||||
public readonly SpawnNameResolver Resolver;
|
||||
public readonly SpawnGlobalInfo Shared;
|
||||
@@ -60,7 +62,6 @@ private void FindAllPointsOnMaps()
|
||||
RippedMaps.Add(SimulateScene(SceneInfo9a.ScenePathsT3, "t3", _ => LocationSewer));
|
||||
}
|
||||
|
||||
|
||||
public void DumpSceneToPickle(List<SimulatedAreaSet> rip)
|
||||
{
|
||||
var sets = rip.SelectMany(z => z.ToAreas()).ToArray();
|
||||
@@ -106,7 +107,7 @@ public void ExportRippedMaps()
|
||||
foreach (var obj in spawn.Table)
|
||||
{
|
||||
foreach (var sub in obj.AppearanceSpawnerObjectInfoList)
|
||||
result.Add(sub.ObjectName, obj);
|
||||
result.TryAdd(sub.ObjectName, obj);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -136,6 +137,79 @@ private SpawnSceneSimulation SimulateScene(string[] scenePaths, string map, Func
|
||||
public string GetLocationName(int locationIndex) => Resolver.LocationNames[locationIndex];
|
||||
public bool TryGetSpawner(string name, [NotNullWhen(true)] out PokemonSpawnerData? spawnerData) => RipInfo.SpawnerInfo.TryGetValue(name, out spawnerData);
|
||||
public bool TryGetEncounter(string id, [NotNullWhen(true)] out EncountData? slot) => Shared.Encounters.TryGetValue(id, out slot);
|
||||
|
||||
public void ExportHyperspacePickle()
|
||||
{
|
||||
var list = new List<EncounterSlot9a>();
|
||||
var locationTable = new EncounterArea9a[] { new() { Location = LocationHyperspace, Slots = list } };
|
||||
|
||||
// Random set of spawns can appear at any spawner. All we care about is the encounters within that set.
|
||||
AddRandomSpawns(list);
|
||||
|
||||
// Special Distortion boss spawners come with a pack of encounters to act as nuisance. We need them.
|
||||
// ect_zdm40X_sp0Y_Z
|
||||
// bosses are the special spawn with fixed IVs. Don't need them.
|
||||
var band = Shared.Encounters.Select(z => z.Value)
|
||||
.Where(z => IsHyperspaceBandSp(z.Id));
|
||||
|
||||
foreach (var enc in band)
|
||||
{
|
||||
// Need to get the spawner that has this encounter, for the relevant level boost.
|
||||
if (!RipInfo.TryGetSpawnerFromEncounter(enc.Id, out var spawner))
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Could not find spawner for hyperspace band encounter {enc.Id} - {(Species)enc.DevNo}");
|
||||
continue;
|
||||
}
|
||||
AddSpawner(list, spawner);
|
||||
}
|
||||
|
||||
foreach (var set in locationTable)
|
||||
set.CondenseList();
|
||||
|
||||
var path = Path.Combine(_outDir, "encounter_hyperspace_za.pkl");
|
||||
EncounterSlot9a.WritePickle(locationTable, path);
|
||||
|
||||
// Write a concatenated array of slots for visual pattern inspection.
|
||||
EncounterSlot9a.WritePickleWithoutLocations(locationTable.SelectMany(z => z.Slots), path);
|
||||
}
|
||||
|
||||
private static bool IsHyperspaceBandSp(string name) => name.StartsWith("ect_zdm40") && !name.EndsWith("_sp");
|
||||
|
||||
private void AddRandomSpawns(List<EncounterSlot9a> list)
|
||||
{
|
||||
foreach (var set in Shared.HyperspaceSpawnSets)
|
||||
{
|
||||
foreach (var info in RipInfo.SpawnerInfo)
|
||||
{
|
||||
if (info.Value.Id != set)
|
||||
continue;
|
||||
AddSpawner(list, info.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSpawner(List<EncounterSlot9a> list, PokemonSpawnerData spawner)
|
||||
{
|
||||
foreach (var info in spawner.AppearanceSpawnerObjectInfoList)
|
||||
{
|
||||
var appearInfo = info.Appearance;
|
||||
if (appearInfo.MinCount == 0)
|
||||
continue;
|
||||
|
||||
var encounters = spawner.EncountDataInfoList;
|
||||
// don't care about randomness of the list of encounters. just add them.
|
||||
|
||||
foreach (var enc in encounters)
|
||||
{
|
||||
if (enc.EncountDataId is not { } id)
|
||||
continue;
|
||||
if (!TryGetEncounter(id, out var slot))
|
||||
continue;
|
||||
EncounterSlot9a.AddSlots(list, slot, enc, hyperspaceBoost: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record PointDump
|
||||
|
||||
Reference in New Issue
Block a user