From 0936c08eb14ed08eb9042c008404b24bf60e088a Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 16 Nov 2025 15:56:12 -0600 Subject: [PATCH] LZA 1.0.2 Cumulative changes from the team. Co-Authored-By: Matt <17801814+sora10pls@users.noreply.github.com> Co-Authored-By: SciresM <8676005+SciresM@users.noreply.github.com> Co-Authored-By: Lusamine <30205550+Lusamine@users.noreply.github.com> --- .../Personal/Wrapper/PersonalInfo9SV.cs | 2 +- .../Archive/TrinityFileSystemManager.cs | 23 +- FlatBuffers/SV/Trinity/Archive/TrinityPak.cs | 41 +- .../SV/Trinity/Archive/TrinityPakExtractor.cs | 108 +- FlatBuffers/SV/Trinity/Scene/SceneDumper.cs | 10 +- FlatBuffers/SV/Trinity/Schemas/TrinityPak.fbs | 9 +- .../ZA/Battle/Schemas/BattleSetting.fbs | 57 + FlatBuffers/ZA/Battle/Schemas/LockonDesc.fbs | 27 + .../ZA/Battle/Schemas/PlayerDamage.fbs | 28 + ...NX.Structures.FlatBuffers.ZA.Battle.csproj | 1 + FlatBuffers/ZA/Directory.Build.props | 26 + .../ZA/Item/Schemas/Enums/ItemType.fbs | 14 + .../FieldWazaGimmickPrivateDBArray.fbs | 33 + .../ZA/Item/Schemas/HudLineupArray.fbs | 21 + FlatBuffers/ZA/Item/Schemas/ItemDataArray.fbs | 64 + .../ZA/Item/Schemas/ItemTableDataDBArray.fbs | 27 + .../RandomPopItemSpawnerDataDBArray.fbs | 35 + .../ZA/Item/Schemas/ShopLineupArray.fbs | 33 + .../ZA/Item/Schemas/ZARewardItemDataArray.fbs | 22 + ...pkNX.Structures.FlatBuffers.ZA.Item.csproj | 2 + .../ZA/Misc/Schemas/DressUpDataArray.fbs | 25 + .../Misc/Schemas/DressUpEnsembleDataArray.fbs | 23 + .../ZA/Misc/Schemas/DressUpGroupDataArray.fbs | 15 + FlatBuffers/ZA/Misc/Schemas/EventConst.fbs | 14 + FlatBuffers/ZA/Misc/Schemas/EventControl.fbs | 36 + FlatBuffers/ZA/Misc/Schemas/EventLabel.fbs | 13 + .../ZA/Misc/Schemas/FieldWeatherTable.fbs | 100 + .../ZA/Misc/Schemas/FieldWeatherType.fbs | 19 + .../ZA/Misc/Schemas/HairMakeDataArray.fbs | 21 + FlatBuffers/ZA/Misc/Schemas/TitleArray.fbs | 29 + .../ZA/Misc/Schemas/TitleCountArray.fbs | 17 + .../Schemas/WeatherHappeningParamArray.fbs | 38 + ...pkNX.Structures.FlatBuffers.ZA.Misc.csproj | 5 + .../ZA/Personal/Dumpers/PersonalDumper9a.cs | 379 +++ .../Personal/Types/PersonalInfoDex.cs | 3 + .../Personal/Types/PersonalInfoEvolution.cs | 3 + .../Personal/Types/PersonalInfoGender.cs | 24 + .../Personal/Types/PersonalInfoStats.cs | 6 + .../Personal/Wrapper/PersonalInfo9ZA.cs | 148 + .../Personal/Wrapper/PersonalTable9ZA.cs | 123 + .../Personal/Schemas/PersonalInfoDetail.fbs | 30 + .../Schemas/PersonalInfoEvolution.fbs | 13 + .../Personal/Schemas/PersonalInfoGender.fbs | 14 + .../ZA/Personal/Schemas/PersonalInfoHatch.fbs | 9 + .../ZA/Personal/Schemas/PersonalInfoMove.fbs | 8 + .../ZA/Personal/Schemas/PersonalInfoStats.fbs | 11 + .../ZA/Personal/Schemas/PersonalTable.fbs | 47 + ....Structures.FlatBuffers.ZA.Personal.csproj | 2 + .../ZA/Shared/Gen9/PokeData/ParamSet.cs | 8 + .../ZA/Shared/Gen9/PokeData/PokeDataBattle.cs | 26 + .../ZA/Shared/Gen9/SpeciesConverterZA.cs | 88 + .../Shared/Schemas/Entity/CollisionShape.fbs | 8 + .../Schemas/Entity/ComparisonOperatorType.fbs | 10 + ...ditionSimpleAutoBattleHecklerAreaArray.fbs | 14 + .../ZA/Shared/Schemas/Entity/OwnerInfo.fbs | 12 + .../ZA/Shared/Schemas/Entity/ParamSet.fbs | 11 + .../ZA/Shared/Schemas/Entity/PokeObjArray.fbs | 61 + .../Schemas/Entity/PokemonTriggerID.fbs | 1005 +++++++ .../Schemas/Entity/PokemonUniquePathData.fbs | 1105 +++++++ .../Shared/Schemas/Misc/CaptureBallData.fbs | 35 + .../ZA/Shared/Schemas/Misc/CaptureData.fbs | 40 + .../Shared/Schemas/Misc/CaptureZARankData.fbs | 32 + .../ZA/Shared/Schemas/Misc/MegaEvoArray.fbs | 21 + .../Schemas/PokeData/PokeDataBattle.fbs | 34 + .../Schemas/PokeData/PokeDataDLCGift.fbs | 43 + .../Schemas/PokeData/PokeDataEventBattle.fbs | 41 + .../Shared/Schemas/PokeData/PokeDataFull.fbs | 64 + .../Schemas/PokeData/PokeDataSymbol.fbs | 31 + .../Shared/Schemas/PokeData/PokeDataTrade.fbs | 45 + .../ZA/Shared/Schemas/PokeData/WazaSet.fbs | 9 + .../Shared/Schemas/PokeData/WazaSetBattle.fbs | 8 + .../Schemas/Shared/ActivationCondition.fbs | 9 + .../Shared/ActivationConditionElement.fbs | 7 + .../Shared/ActivationConditionParam.fbs | 7 + .../Shared/Schemas/Shared/AppearanceInfo.fbs | 6 + .../ZA/Shared/Schemas/Shared/BallID.fbs | 43 + .../ZA/Shared/Schemas/Shared/BattleType.fbs | 7 + .../ZA/Shared/Schemas/Shared/ClerkType.fbs | 6 + .../ZA/Shared/Schemas/Shared/CondEnum.fbs | 8 + .../ZA/Shared/Schemas/Shared/CoolTimeInfo.fbs | 5 + .../ZA/Shared/Schemas/Shared/DataType.fbs | 8 + .../ZA/Shared/Schemas/Shared/DevID.fbs | 1031 +++++++ .../ZA/Shared/Schemas/Shared/HoldItem.fbs | 5 + .../ZA/Shared/Schemas/Shared/ItemID.fbs | 571 ++++ .../ZA/Shared/Schemas/Shared/LangType.fbs | 14 + .../Shared/Schemas/Shared/MahoippuViewID.fbs | 11 + .../ZA/Shared/Schemas/Shared/MoveType.fbs | 23 + .../ZA/Shared/Schemas/Shared/PayType.fbs | 7 + .../ZA/Shared/Schemas/Shared/PokeMemoType.fbs | 14 + .../ZA/Shared/Schemas/Shared/RareType.fbs | 6 + .../ZA/Shared/Schemas/Shared/RibbonType.fbs | 116 + .../ZA/Shared/Schemas/Shared/SeikakuType.fbs | 30 + .../ZA/Shared/Schemas/Shared/SellType.fbs | 6 + FlatBuffers/ZA/Shared/Schemas/Shared/Sex.fbs | 8 + .../ZA/Shared/Schemas/Shared/SexType.fbs | 8 + .../ZA/Shared/Schemas/Shared/ShopKind.fbs | 22 + .../ZA/Shared/Schemas/Shared/SizeType.fbs | 11 + .../ZA/Shared/Schemas/Shared/TalentType.fbs | 7 + .../ZA/Shared/Schemas/Shared/TokuseiID.fbs | 311 ++ .../ZA/Shared/Schemas/Shared/TokuseiType.fbs | 9 + .../Shared/Schemas/Shared/TriggerCommand.fbs | 10 + .../ZA/Shared/Schemas/Shared/TriggerTable.fbs | 21 + .../ZA/Shared/Schemas/Shared/WazaID.fbs | 925 ++++++ .../ZA/Shared/Schemas/Shared/WazaList.fbs | 10 + .../ZA/Shared/Schemas/Shared/WazaType.fbs | 6 + .../ZA/Shared/Schemas/Shared/ZARank.fbs | 32 + .../ZA/Shared/Schemas/Shared/ZoneInfo.fbs | 6 + ...NX.Structures.FlatBuffers.ZA.Shared.csproj | 2 + .../Schemas/MedalRateDefeatBonusArray.fbs | 13 + .../Trainers/Schemas/NpcAssetDataDBArray.fbs | 22 + .../ZA/Trainers/Schemas/TrDataMainArray.fbs | 42 + .../Schemas/TrainerBattleDataGlobal.fbs | 38 + .../ZA/Trainers/Schemas/TrainerBodySize.fbs | 8 + .../ZA/Trainers/Schemas/TrainerCategory.fbs | 6 + .../ZA/Trainers/Schemas/TrainerEnvArray.fbs | 88 + .../ZA/Trainers/Schemas/TrainerTypeArray.fbs | 28 + ....Structures.FlatBuffers.ZA.Trainers.csproj | 2 + .../Trinity/Archive/TrinityFileDescriptors.cs | 38 + .../Archive/TrinityFileSystemManager.cs | 99 + .../Archive/TrinityFileSystemMetadata.cs | 33 + FlatBuffers/ZA/Trinity/Archive/TrinityPak.cs | 72 + .../ZA/Trinity/Archive/TrinityPakExtractor.cs | 106 + FlatBuffers/ZA/Trinity/Scene/SceneDumper.cs | 526 ++++ .../ZA/Trinity/Schemas/LogicExpression.fbs | 34 + .../ZA/Trinity/Schemas/PlacementRegistry.fbs | 64 + .../Schemas/TIAIPerceptualComponent.fbs | 8 + .../Schemas/TIDynamicExclusionComponent.fbs | 8 + .../Schemas/TIModelDitherFadeComponent.fbs | 12 + .../ZA/Trinity/Schemas/TrinityComponent.fbs | 57 + .../Schemas/TrinityEnvironmentParameter.fbs | 9 + .../Schemas/TrinityFileDescriptors.fbs | 23 + .../Schemas/TrinityFileSystemMetadata.fbs | 9 + .../Schemas/TrinityGroundPlaceComponent.fbs | 8 + .../Trinity/Schemas/TrinityModelComponent.fbs | 30 + .../Schemas/TrinityOverrideSensorData.fbs | 11 + FlatBuffers/ZA/Trinity/Schemas/TrinityPak.fbs | 28 + .../Schemas/TrinityParticleComponent.fbs | 12 + .../Trinity/Schemas/TrinityPropertySheet.fbs | 40 + .../ZA/Trinity/Schemas/TrinitySceneObject.fbs | 50 + .../Schemas/TrinitySceneObjectTemplate.fbs | 29 + .../ZA/Trinity/Schemas/TrinityScenePoint.fbs | 12 + ...X.Structures.FlatBuffers.ZA.Trinity.csproj | 5 + .../Waza/Schemas/PersonalWazaParamDBArray.fbs | 55 + FlatBuffers/ZA/Waza/Schemas/TokuseiArray.fbs | 20 + FlatBuffers/ZA/Waza/Schemas/Waza.fbs | 97 + FlatBuffers/ZA/Waza/Schemas/WazaAffinity.fbs | 10 + .../ZA/Waza/Schemas/WazaEntityStat.fbs | 14 + FlatBuffers/ZA/Waza/Schemas/WazaInflict.fbs | 10 + .../ZA/Waza/Schemas/WazaParamDBArray.fbs | 51 + ...pkNX.Structures.FlatBuffers.ZA.Waza.csproj | 2 + .../ZA/World/Schemas/Area/AreaConfig.fbs | 9 + .../ZA/World/Schemas/Area/AreaLayer.fbs | 12 + .../ZA/World/Schemas/Area/AreaType.fbs | 9 + .../ZA/World/Schemas/Area/CacheOption.fbs | 6 + .../Schemas/Area/DungeonMapUIDataArray.fbs | 16 + .../ZA/World/Schemas/Area/FieldAreaInfo.fbs | 37 + .../Schemas/Area/FieldBattleZoneArray.fbs | 17 + .../ZA/World/Schemas/Area/FieldConfig.fbs | 26 + .../Schemas/Area/FieldDataConfigArray.fbs | 79 + .../World/Schemas/Area/FieldLocationArray.fbs | 16 + .../World/Schemas/Area/FieldMainAreaArray.fbs | 16 + .../ZA/World/Schemas/Area/FieldPlayer.fbs | 259 ++ .../Schemas/Area/FieldSceneAreaArray.fbs | 20 + .../ZA/World/Schemas/Area/FieldShadowInfo.fbs | 7 + .../ZA/World/Schemas/Area/FieldSubArea.fbs | 16 + .../World/Schemas/Area/FieldWildZoneArray.fbs | 17 + .../ZA/World/Schemas/Area/OyabunSetting.fbs | 10 + .../ZA/World/Schemas/Area/StreamingConfig.fbs | 10 + .../Schemas/Encount/EncountDataDBArray.fbs | 47 + .../Schemas/Encount/PokemonDataDBArray.fbs | 39 + .../PokemonDropItemTableDataDBArray.fbs | 30 + .../ZA/World/Schemas/Oyabun/OyabunWazaDB.fbs | 19 + .../Spawner/PokemonSpawnerDataDBArray.fbs | 76 + .../Schemas/Spawner/SpawnerDataDBArray.fbs | 49 + .../Spawner/SpawnerTransformDataDBArray.fbs | 21 + .../Spawner/WazaGimmickSpawnerDataDBArray.fbs | 45 + FlatBuffers/ZA/World/World/IAreaLayer.cs | 20 + ...kNX.Structures.FlatBuffers.ZA.World.csproj | 1 + .../Schemas/PokedexBlackListMainArray.fbs | 14 + .../Zukan/Schemas/RankBattleRewardArray.fbs | 39 + ...kNX.Structures.FlatBuffers.ZA.Zukan.csproj | 2 + .../ReflectionDumpSchema.cs | 7 +- .../SchemaDumpSettings.cs | 1 + .../Data/Color3f.cs | 2 +- .../FlatBufferConverter.cs | 13 +- .../Math/PackedVec3f.cs | 2 + .../Schemas/Geometry/SRT.fbs | 9 + .../Util/FlatDumper.cs | 2 +- pkNX.Containers/FileMitm.cs | 2 +- pkNX.Containers/FolderContainer.cs | 16 +- pkNX.Containers/Mini/MiniUtil.cs | 111 + pkNX.Containers/Misc/AHTB.cs | 116 +- pkNX.Containers/Misc/AHTBEntry.cs | 44 +- pkNX.Containers/Misc/BinaryRWExtensions.cs | 44 - pkNX.Containers/Misc/GFPack.cs | 75 +- pkNX.Containers/Misc/Oodle.cs | 181 +- pkNX.Containers/Misc/StructConverter.cs | 19 - pkNX.Containers/Misc/Zlib.cs | 109 + pkNX.Containers/NX/NSO.cs | 7 +- pkNX.Containers/Trinity/TrinityUtil.cs | 25 + pkNX.Game/Editors/DataCache.cs | 10 +- pkNX.Game/Editors/TMEditorGG.cs | 4 +- pkNX.Game/Editors/TypeChartEditor.cs | 23 +- pkNX.Game/File/GameFileMapping.cs | 13 + pkNX.Game/GameLocation.cs | 135 +- pkNX.Game/GameManager.cs | 1 + pkNX.Game/GameManager9a.cs | 102 + pkNX.Game/GameManagerGG.cs | 8 +- pkNX.Game/GameManagerSV.cs | 4 +- pkNX.Game/GameManagerSWSH.cs | 9 +- pkNX.Game/Text/TextManager.cs | 6 +- pkNX.Game/Text/TextMapping.cs | 27 + .../Randomizers/FormRandomizer.cs | 6 +- .../Randomizers/MoveRandomizer.cs | 4 +- .../Personal/PersonalRandomizer.cs | 4 +- pkNX.Structures/CodePattern.cs | 66 +- pkNX.Structures/EggMove/EggMoves2.cs | 26 - pkNX.Structures/EggMove/EggMoves6.cs | 30 - pkNX.Structures/Encounter/EncounterStatic.cs | 7 +- .../Encounter/Gen6/EncounterGift6AO.cs | 46 - .../Encounter/Gen6/EncounterGift6XY.cs | 35 - .../Encounter/Gen6/EncounterStatic6.cs | 49 - .../Encounter/Gen7/EncounterGift7.cs | 32 - .../Encounter/Gen7/EncounterStatic7.cs | 133 - .../Encounter/Gen7/EncounterStatic7b.cs | 61 +- pkNX.Structures/Evolution/EvolutionSet6.cs | 52 - pkNX.Structures/Evolution/EvolutionType.cs | 2 +- pkNX.Structures/Evolution/SeedPokeTable.cs | 4 +- .../Evolution/ZukanEvolutionTable.cs | 9 +- pkNX.Structures/GameUtil.cs | 75 +- pkNX.Structures/GameVersion.cs | 4 + pkNX.Structures/Havok/HavokCollision.cs | 212 +- pkNX.Structures/Item/Item.cs | 212 +- pkNX.Structures/Item/Item8.cs | 67 +- pkNX.Structures/Item/Item8a.cs | 56 +- pkNX.Structures/Learnset/Learnset6.cs | 21 +- pkNX.Structures/Learnset/Learnset8.cs | 61 +- pkNX.Structures/Legality/GameInfo.cs | 62 +- pkNX.Structures/Legality/Legal.cs | 9 - pkNX.Structures/Legality/Tables/Tables6.cs | 549 ---- pkNX.Structures/Legality/Tables/Tables7.cs | 276 -- pkNX.Structures/Legality/Tables/Tables7b.cs | 131 - pkNX.Structures/Legality/Tables/Tables8.cs | 136 - pkNX.Structures/Legality/Tables/Tables9.cs | 7 + pkNX.Structures/Maison/Maison6.cs | 90 - .../MegaEvolution/MegaEvolutionSet.cs | 58 +- pkNX.Structures/Move/Move.cs | 8 +- pkNX.Structures/Move/Move6.cs | 9 +- pkNX.Structures/Move/Move7.cs | 18 +- .../Personal/Info/PersonalInfo5B2W2.cs | 83 +- .../Personal/Info/PersonalInfo7SM.cs | 50 +- .../Personal/Table/PersonalTable5B2W2.cs | 70 - .../Personal/Table/PersonalTable5BW.cs | 70 - .../Personal/Table/PersonalTable6AO.cs | 74 - .../Personal/Table/PersonalTable6XY.cs | 74 - pkNX.Structures/StringSearch.cs | 63 + pkNX.Structures/StructConverter.cs | 45 - pkNX.Structures/TableUtil.cs | 16 +- pkNX.Structures/Text/TextFile.cs | 2 +- pkNX.Structures/Util.cs | 58 +- pkNX.Structures/VsTrainer/3DS/TrData6.cs | 46 - pkNX.Structures/VsTrainer/3DS/TrData6AO.cs | 24 - pkNX.Structures/VsTrainer/3DS/TrData6XY.cs | 23 - pkNX.Structures/VsTrainer/3DS/TrPoke6.cs | 63 - .../VsTrainer/3DS/TrainerClass6.cs | 6 - pkNX.Structures/VsTrainer/Base/TrainerData.cs | 8 +- pkNX.Structures/VsTrainer/GG/TrainerData7b.cs | 20 +- pkNX.Structures/VsTrainer/GG/TrainerData8.cs | 22 +- .../pkNX.Tests.FileSystem.csproj | 4 +- .../pkNX.Tests.SourceGen.csproj | 4 +- .../pkNX.Tests.Trinity.csproj | 4 +- .../Dumping/{ => Gen8}/DumperSWSH.Designer.cs | 0 .../Dumping/{ => Gen8}/DumperSWSH.cs | 0 .../Dumping/{ => Gen8}/DumperSWSH.resx | 0 .../Dumping/{ => Gen8}/GameDumperSWSH.cs | 11 +- .../Dumping/{ => Gen8a}/DumperPLA.Designer.cs | 0 .../Dumping/{ => Gen8a}/DumperPLA.cs | 0 .../Dumping/{ => Gen8a}/DumperPLA.resx | 0 .../Dumping/{ => Gen8a}/GameDumperPLA.cs | 11 +- .../Dumping/{SV => Gen9}/BoxCollision9.cs | 0 .../Dumping/{ => Gen9}/DumperSV.Designer.cs | 0 pkNX.WinForms/Dumping/{ => Gen9}/DumperSV.cs | 0 .../Dumping/{ => Gen9}/DumperSV.resx | 0 .../Encounter/EncounterDumpConfigSV.cs | 0 .../Encounter/EncounterDumperSV.cs | 13 - .../Encounter/EncounterExtensions9.cs | 0 .../Encounter/EncounterSlotDumper9.cs | 0 .../Encounter/FixedSymbolDumper9.cs | 0 .../Encounter/GimmighoulDumper.cs | 0 .../{SV => Gen9}/Encounter/PaldeaEncounter.cs | 0 .../Dumping/{ => Gen9}/GameDumperSV.cs | 22 +- .../{SV => Gen9}/Location/AreaWeather9.cs | 0 .../{SV => Gen9}/Location/LocationDatabase.cs | 0 .../Location/LocationPointDetail.cs | 0 .../{SV => Gen9}/Location/LocationStorage.cs | 0 .../Dumping/{ => Gen9}/MassOutbreakRipper.cs | 20 +- .../Models/PaldeaCoinSymbolModel.cs | 0 .../Models/PaldeaCoinSymbolPoint.cs | 0 .../{SV => Gen9}/Models/PaldeaFieldModel.cs | 0 .../Models/PaldeaFixedSymbolModel.cs | 0 .../Models/PaldeaFixedSymbolPoint.cs | 0 .../{SV => Gen9}/Models/PaldeaSceneModel.cs | 0 .../{SV => Gen9}/Models/PaldeaSpawnModel.cs | 0 .../Dumping/{ => Gen9}/TeraRaidRipper.cs | 15 +- pkNX.WinForms/Dumping/Gen9a/DumpHelper9a.cs | 47 + .../Dumping/Gen9a/Dumper9a.Designer.cs | 475 +++ pkNX.WinForms/Dumping/Gen9a/Dumper9a.cs | 193 ++ pkNX.WinForms/Dumping/Gen9a/Dumper9a.resx | 120 + .../Gen9a/Encounter/EncounterDumper9a.cs | 31 + pkNX.WinForms/Dumping/Gen9a/GameDumper9a.cs | 2673 +++++++++++++++++ pkNX.WinForms/Dumping/TextInput.cs | 4 +- pkNX.WinForms/Main.cs | 10 +- pkNX.WinForms/MainEditor/EditUtil.cs | 3 +- pkNX.WinForms/MainEditor/Editor9a.cs | 66 + pkNX.WinForms/MainEditor/EditorGG.cs | 4 +- pkNX.WinForms/MainEditor/EditorProvider.cs | 1 + pkNX.WinForms/MainEditor/EditorSWSH.cs | 20 +- pkNX.WinForms/Program.cs | 4 + pkNX.WinForms/ProgramSettings.cs | 1 - pkNX.WinForms/Subforms/{ => Gen7b}/BTTE.cs | 0 .../Subforms/{ => Gen7b}/BTTE.designer.cs | 0 pkNX.WinForms/Subforms/{ => Gen7b}/BTTE.resx | 0 .../Subforms/{ => Gen7b}/GGWE.Designer.cs | 0 pkNX.WinForms/Subforms/{ => Gen7b}/GGWE.cs | 0 pkNX.WinForms/Subforms/{ => Gen7b}/GGWE.resx | 0 .../{ => Gen7b}/PokeDataUI.Designer.cs | 0 .../Subforms/{ => Gen7b}/PokeDataUI.cs | 0 .../Subforms/{ => Gen7b}/PokeDataUI.resx | 0 .../{ => Gen7b}/ShinyRate.Designer.cs | 0 .../Subforms/{ => Gen7b}/ShinyRate.cs | 0 .../Subforms/{ => Gen7b}/ShinyRate.resx | 0 .../Subforms/{ => Gen7b}/TMList.Designer.cs | 0 pkNX.WinForms/Subforms/{ => Gen7b}/TMList.cs | 0 .../Subforms/{ => Gen7b}/TMList.resx | 0 .../{ => Gen7b}/TypeChart.Designer.cs | 0 .../Subforms/{ => Gen7b}/TypeChart.cs | 24 +- .../Subforms/{ => Gen7b}/TypeChart.resx | 0 .../Subforms/{ => Gen8}/SSWE.Designer.cs | 0 pkNX.WinForms/Subforms/{ => Gen8}/SSWE.cs | 0 pkNX.WinForms/Subforms/{ => Gen8}/SSWE.resx | 0 .../{ => Gen8a}/AreaEditor8a.Designer.cs | 0 .../Subforms/{ => Gen8a}/AreaEditor8a.cs | 0 .../Subforms/{ => Gen8a}/AreaEditor8a.resx | 0 .../{ => Gen8a}/MapViewer8a.Designer.cs | 0 .../Subforms/{ => Gen8a}/MapViewer8a.cs | 0 .../Subforms/{ => Gen8a}/MapViewer8a.resx | 0 .../{ => Gen8a}/PokeDataUI8a.Designer.cs | 0 .../Subforms/{ => Gen8a}/PokeDataUI8a.cs | 0 .../Subforms/{ => Gen8a}/PokeDataUI8a.resx | 0 .../{ => Gen9}/MapViewer9.Designer.cs | 0 .../Subforms/{ => Gen9}/MapViewer9.cs | 2 +- .../Subforms/{ => Gen9}/MapViewer9.resx | 0 .../Subforms/{ => Gen9}/PaldeaMap.cs | 0 .../Map/Dumping/ActivationConditionUtil9a.cs | 42 + .../Gen9a/Map/Dumping/FlatBufferSource.cs | 14 + .../Gen9a/Map/Dumping/SceneSpawner.cs | 14 + .../Gen9a/Map/Dumping/SpawnGlobalInfo.cs | 37 + .../Gen9a/Map/Dumping/SpawnNameResolver.cs | 44 + .../Gen9a/Map/Dumping/SpawnSceneSimulation.cs | 93 + .../Gen9a/Map/Exports/DetailedSpawn9a.cs | 57 + .../Gen9a/Map/Exports/EncounterArea9a.cs | 31 + .../Gen9a/Map/Exports/EncounterSlot9a.cs | 108 + .../Gen9a/Map/Exports/FakeSpawner9a.cs | 25 + .../Gen9a/Map/Exports/SimulatedAreaSet.cs | 104 + .../Gen9a/Map/Exports/SpawnExporter.cs | 93 + .../Subforms/Gen9a/Map/Info/AreaDef9a.cs | 11 + .../Gen9a/Map/Info/LumioseFieldIndex.cs | 9 + .../Subforms/Gen9a/Map/Info/LumioseMap.cs | 428 +++ .../Subforms/Gen9a/Map/Info/MapTransform.cs | 23 + .../Subforms/Gen9a/Map/Info/SceneInfo9a.cs | 47 + .../Subforms/Gen9a/Map/Info/TransformUI9a.cs | 49 + .../Subforms/Gen9a/Map/MapSpawnerSet.cs | 9 + .../Subforms/Gen9a/Map/SpawnRipper9a.cs | 1395 +++++++++ pkNX.WinForms/Subforms/Gen9a/Map/World9a.cs | 63 + .../Subforms/Gen9a/MapViewer9a.Designer.cs | 261 ++ pkNX.WinForms/Subforms/Gen9a/MapViewer9a.cs | 445 +++ pkNX.WinForms/Subforms/Gen9a/MapViewer9a.resx | 120 + .../Subforms/GenericEditor/GenericEditor.cs | 1 - .../{ => GenericEditor}/GenericEditor.resx | 0 pkNX.WinForms/Subforms/ModelConverter.cs | 4 +- pkNX.WinForms/UI/MainWindow.xaml.cs | 8 +- pkNX.WinForms/UI/UIStaticSources.cs | 2 +- pkNX.WinForms/UI/WPFTextEditor.xaml.cs | 6 +- pkNX.WinForms/Utils/FormsIconHelper.cs | 18 +- pkNX.WinForms/WinFormsUtil.cs | 8 +- pkNX.WinForms/pkNX.WinForms.csproj | 16 +- pkNX.sln | 546 ++-- 387 files changed, 19631 insertions(+), 3503 deletions(-) create mode 100644 FlatBuffers/ZA/Battle/Schemas/BattleSetting.fbs create mode 100644 FlatBuffers/ZA/Battle/Schemas/LockonDesc.fbs create mode 100644 FlatBuffers/ZA/Battle/Schemas/PlayerDamage.fbs create mode 100644 FlatBuffers/ZA/Battle/pkNX.Structures.FlatBuffers.ZA.Battle.csproj create mode 100644 FlatBuffers/ZA/Directory.Build.props create mode 100644 FlatBuffers/ZA/Item/Schemas/Enums/ItemType.fbs create mode 100644 FlatBuffers/ZA/Item/Schemas/FieldWazaGimmickPrivateDBArray.fbs create mode 100644 FlatBuffers/ZA/Item/Schemas/HudLineupArray.fbs create mode 100644 FlatBuffers/ZA/Item/Schemas/ItemDataArray.fbs create mode 100644 FlatBuffers/ZA/Item/Schemas/ItemTableDataDBArray.fbs create mode 100644 FlatBuffers/ZA/Item/Schemas/RandomPopItemSpawnerDataDBArray.fbs create mode 100644 FlatBuffers/ZA/Item/Schemas/ShopLineupArray.fbs create mode 100644 FlatBuffers/ZA/Item/Schemas/ZARewardItemDataArray.fbs create mode 100644 FlatBuffers/ZA/Item/pkNX.Structures.FlatBuffers.ZA.Item.csproj create mode 100644 FlatBuffers/ZA/Misc/Schemas/DressUpDataArray.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/DressUpEnsembleDataArray.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/DressUpGroupDataArray.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/EventConst.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/EventControl.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/EventLabel.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/FieldWeatherTable.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/FieldWeatherType.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/HairMakeDataArray.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/TitleArray.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/TitleCountArray.fbs create mode 100644 FlatBuffers/ZA/Misc/Schemas/WeatherHappeningParamArray.fbs create mode 100644 FlatBuffers/ZA/Misc/pkNX.Structures.FlatBuffers.ZA.Misc.csproj create mode 100644 FlatBuffers/ZA/Personal/Dumpers/PersonalDumper9a.cs create mode 100644 FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoDex.cs create mode 100644 FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoEvolution.cs create mode 100644 FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoGender.cs create mode 100644 FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoStats.cs create mode 100644 FlatBuffers/ZA/Personal/Personal/Wrapper/PersonalInfo9ZA.cs create mode 100644 FlatBuffers/ZA/Personal/Personal/Wrapper/PersonalTable9ZA.cs create mode 100644 FlatBuffers/ZA/Personal/Schemas/PersonalInfoDetail.fbs create mode 100644 FlatBuffers/ZA/Personal/Schemas/PersonalInfoEvolution.fbs create mode 100644 FlatBuffers/ZA/Personal/Schemas/PersonalInfoGender.fbs create mode 100644 FlatBuffers/ZA/Personal/Schemas/PersonalInfoHatch.fbs create mode 100644 FlatBuffers/ZA/Personal/Schemas/PersonalInfoMove.fbs create mode 100644 FlatBuffers/ZA/Personal/Schemas/PersonalInfoStats.fbs create mode 100644 FlatBuffers/ZA/Personal/Schemas/PersonalTable.fbs create mode 100644 FlatBuffers/ZA/Personal/pkNX.Structures.FlatBuffers.ZA.Personal.csproj create mode 100644 FlatBuffers/ZA/Shared/Gen9/PokeData/ParamSet.cs create mode 100644 FlatBuffers/ZA/Shared/Gen9/PokeData/PokeDataBattle.cs create mode 100644 FlatBuffers/ZA/Shared/Gen9/SpeciesConverterZA.cs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Entity/CollisionShape.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Entity/ComparisonOperatorType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Entity/ConditionSimpleAutoBattleHecklerAreaArray.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Entity/OwnerInfo.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Entity/ParamSet.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Entity/PokeObjArray.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Entity/PokemonTriggerID.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Entity/PokemonUniquePathData.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Misc/CaptureBallData.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Misc/CaptureData.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Misc/CaptureZARankData.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Misc/MegaEvoArray.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataBattle.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataDLCGift.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataEventBattle.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataFull.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataSymbol.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataTrade.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/PokeData/WazaSet.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/PokeData/WazaSetBattle.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/ActivationCondition.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/ActivationConditionElement.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/ActivationConditionParam.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/AppearanceInfo.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/BallID.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/BattleType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/ClerkType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/CondEnum.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/CoolTimeInfo.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/DataType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/DevID.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/HoldItem.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/ItemID.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/LangType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/MahoippuViewID.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/MoveType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/PayType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/PokeMemoType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/RareType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/RibbonType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/SeikakuType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/SellType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/Sex.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/SexType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/ShopKind.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/SizeType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/TalentType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/TokuseiID.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/TokuseiType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/TriggerCommand.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/TriggerTable.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/WazaID.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/WazaList.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/WazaType.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/ZARank.fbs create mode 100644 FlatBuffers/ZA/Shared/Schemas/Shared/ZoneInfo.fbs create mode 100644 FlatBuffers/ZA/Shared/pkNX.Structures.FlatBuffers.ZA.Shared.csproj create mode 100644 FlatBuffers/ZA/Trainers/Schemas/MedalRateDefeatBonusArray.fbs create mode 100644 FlatBuffers/ZA/Trainers/Schemas/NpcAssetDataDBArray.fbs create mode 100644 FlatBuffers/ZA/Trainers/Schemas/TrDataMainArray.fbs create mode 100644 FlatBuffers/ZA/Trainers/Schemas/TrainerBattleDataGlobal.fbs create mode 100644 FlatBuffers/ZA/Trainers/Schemas/TrainerBodySize.fbs create mode 100644 FlatBuffers/ZA/Trainers/Schemas/TrainerCategory.fbs create mode 100644 FlatBuffers/ZA/Trainers/Schemas/TrainerEnvArray.fbs create mode 100644 FlatBuffers/ZA/Trainers/Schemas/TrainerTypeArray.fbs create mode 100644 FlatBuffers/ZA/Trainers/pkNX.Structures.FlatBuffers.ZA.Trainers.csproj create mode 100644 FlatBuffers/ZA/Trinity/Archive/TrinityFileDescriptors.cs create mode 100644 FlatBuffers/ZA/Trinity/Archive/TrinityFileSystemManager.cs create mode 100644 FlatBuffers/ZA/Trinity/Archive/TrinityFileSystemMetadata.cs create mode 100644 FlatBuffers/ZA/Trinity/Archive/TrinityPak.cs create mode 100644 FlatBuffers/ZA/Trinity/Archive/TrinityPakExtractor.cs create mode 100644 FlatBuffers/ZA/Trinity/Scene/SceneDumper.cs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/LogicExpression.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/PlacementRegistry.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TIAIPerceptualComponent.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TIDynamicExclusionComponent.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TIModelDitherFadeComponent.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityComponent.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityEnvironmentParameter.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityFileDescriptors.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityFileSystemMetadata.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityGroundPlaceComponent.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityModelComponent.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityOverrideSensorData.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityPak.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityParticleComponent.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityPropertySheet.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinitySceneObject.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinitySceneObjectTemplate.fbs create mode 100644 FlatBuffers/ZA/Trinity/Schemas/TrinityScenePoint.fbs create mode 100644 FlatBuffers/ZA/Trinity/pkNX.Structures.FlatBuffers.ZA.Trinity.csproj create mode 100644 FlatBuffers/ZA/Waza/Schemas/PersonalWazaParamDBArray.fbs create mode 100644 FlatBuffers/ZA/Waza/Schemas/TokuseiArray.fbs create mode 100644 FlatBuffers/ZA/Waza/Schemas/Waza.fbs create mode 100644 FlatBuffers/ZA/Waza/Schemas/WazaAffinity.fbs create mode 100644 FlatBuffers/ZA/Waza/Schemas/WazaEntityStat.fbs create mode 100644 FlatBuffers/ZA/Waza/Schemas/WazaInflict.fbs create mode 100644 FlatBuffers/ZA/Waza/Schemas/WazaParamDBArray.fbs create mode 100644 FlatBuffers/ZA/Waza/pkNX.Structures.FlatBuffers.ZA.Waza.csproj create mode 100644 FlatBuffers/ZA/World/Schemas/Area/AreaConfig.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/AreaLayer.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/AreaType.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/CacheOption.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/DungeonMapUIDataArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldAreaInfo.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldBattleZoneArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldConfig.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldDataConfigArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldLocationArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldMainAreaArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldPlayer.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldSceneAreaArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldShadowInfo.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldSubArea.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/FieldWildZoneArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/OyabunSetting.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Area/StreamingConfig.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Encount/EncountDataDBArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Encount/PokemonDataDBArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Encount/PokemonDropItemTableDataDBArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Oyabun/OyabunWazaDB.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Spawner/PokemonSpawnerDataDBArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Spawner/SpawnerDataDBArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Spawner/SpawnerTransformDataDBArray.fbs create mode 100644 FlatBuffers/ZA/World/Schemas/Spawner/WazaGimmickSpawnerDataDBArray.fbs create mode 100644 FlatBuffers/ZA/World/World/IAreaLayer.cs create mode 100644 FlatBuffers/ZA/World/pkNX.Structures.FlatBuffers.ZA.World.csproj create mode 100644 FlatBuffers/ZA/Zukan/Schemas/PokedexBlackListMainArray.fbs create mode 100644 FlatBuffers/ZA/Zukan/Schemas/RankBattleRewardArray.fbs create mode 100644 FlatBuffers/ZA/Zukan/pkNX.Structures.FlatBuffers.ZA.Zukan.csproj create mode 100644 FlatBuffers/pkNX.Structures.FlatBuffers/Schemas/Geometry/SRT.fbs delete mode 100644 pkNX.Containers/Misc/BinaryRWExtensions.cs create mode 100644 pkNX.Containers/Misc/Zlib.cs create mode 100644 pkNX.Containers/Trinity/TrinityUtil.cs create mode 100644 pkNX.Game/GameManager9a.cs delete mode 100644 pkNX.Structures/EggMove/EggMoves2.cs delete mode 100644 pkNX.Structures/EggMove/EggMoves6.cs delete mode 100644 pkNX.Structures/Encounter/Gen6/EncounterGift6AO.cs delete mode 100644 pkNX.Structures/Encounter/Gen6/EncounterGift6XY.cs delete mode 100644 pkNX.Structures/Encounter/Gen6/EncounterStatic6.cs delete mode 100644 pkNX.Structures/Encounter/Gen7/EncounterGift7.cs delete mode 100644 pkNX.Structures/Encounter/Gen7/EncounterStatic7.cs delete mode 100644 pkNX.Structures/Evolution/EvolutionSet6.cs delete mode 100644 pkNX.Structures/Maison/Maison6.cs delete mode 100644 pkNX.Structures/Personal/Table/PersonalTable5B2W2.cs delete mode 100644 pkNX.Structures/Personal/Table/PersonalTable5BW.cs delete mode 100644 pkNX.Structures/Personal/Table/PersonalTable6AO.cs delete mode 100644 pkNX.Structures/Personal/Table/PersonalTable6XY.cs create mode 100644 pkNX.Structures/StringSearch.cs delete mode 100644 pkNX.Structures/StructConverter.cs delete mode 100644 pkNX.Structures/VsTrainer/3DS/TrData6.cs delete mode 100644 pkNX.Structures/VsTrainer/3DS/TrData6AO.cs delete mode 100644 pkNX.Structures/VsTrainer/3DS/TrData6XY.cs delete mode 100644 pkNX.Structures/VsTrainer/3DS/TrPoke6.cs delete mode 100644 pkNX.Structures/VsTrainer/3DS/TrainerClass6.cs rename pkNX.WinForms/Dumping/{ => Gen8}/DumperSWSH.Designer.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen8}/DumperSWSH.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen8}/DumperSWSH.resx (100%) rename pkNX.WinForms/Dumping/{ => Gen8}/GameDumperSWSH.cs (99%) rename pkNX.WinForms/Dumping/{ => Gen8a}/DumperPLA.Designer.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen8a}/DumperPLA.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen8a}/DumperPLA.resx (100%) rename pkNX.WinForms/Dumping/{ => Gen8a}/GameDumperPLA.cs (99%) rename pkNX.WinForms/Dumping/{SV => Gen9}/BoxCollision9.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen9}/DumperSV.Designer.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen9}/DumperSV.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen9}/DumperSV.resx (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Encounter/EncounterDumpConfigSV.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Encounter/EncounterDumperSV.cs (91%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Encounter/EncounterExtensions9.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Encounter/EncounterSlotDumper9.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Encounter/FixedSymbolDumper9.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Encounter/GimmighoulDumper.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Encounter/PaldeaEncounter.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen9}/GameDumperSV.cs (99%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Location/AreaWeather9.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Location/LocationDatabase.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Location/LocationPointDetail.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Location/LocationStorage.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen9}/MassOutbreakRipper.cs (98%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Models/PaldeaCoinSymbolModel.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Models/PaldeaCoinSymbolPoint.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Models/PaldeaFieldModel.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Models/PaldeaFixedSymbolModel.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Models/PaldeaFixedSymbolPoint.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Models/PaldeaSceneModel.cs (100%) rename pkNX.WinForms/Dumping/{SV => Gen9}/Models/PaldeaSpawnModel.cs (100%) rename pkNX.WinForms/Dumping/{ => Gen9}/TeraRaidRipper.cs (99%) create mode 100644 pkNX.WinForms/Dumping/Gen9a/DumpHelper9a.cs create mode 100644 pkNX.WinForms/Dumping/Gen9a/Dumper9a.Designer.cs create mode 100644 pkNX.WinForms/Dumping/Gen9a/Dumper9a.cs create mode 100644 pkNX.WinForms/Dumping/Gen9a/Dumper9a.resx create mode 100644 pkNX.WinForms/Dumping/Gen9a/Encounter/EncounterDumper9a.cs create mode 100644 pkNX.WinForms/Dumping/Gen9a/GameDumper9a.cs create mode 100644 pkNX.WinForms/MainEditor/Editor9a.cs rename pkNX.WinForms/Subforms/{ => Gen7b}/BTTE.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/BTTE.designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/BTTE.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/GGWE.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/GGWE.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/GGWE.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/PokeDataUI.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/PokeDataUI.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/PokeDataUI.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/ShinyRate.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/ShinyRate.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/ShinyRate.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/TMList.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/TMList.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/TMList.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/TypeChart.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen7b}/TypeChart.cs (84%) rename pkNX.WinForms/Subforms/{ => Gen7b}/TypeChart.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen8}/SSWE.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen8}/SSWE.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen8}/SSWE.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen8a}/AreaEditor8a.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen8a}/AreaEditor8a.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen8a}/AreaEditor8a.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen8a}/MapViewer8a.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen8a}/MapViewer8a.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen8a}/MapViewer8a.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen8a}/PokeDataUI8a.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen8a}/PokeDataUI8a.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen8a}/PokeDataUI8a.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen9}/MapViewer9.Designer.cs (100%) rename pkNX.WinForms/Subforms/{ => Gen9}/MapViewer9.cs (98%) rename pkNX.WinForms/Subforms/{ => Gen9}/MapViewer9.resx (100%) rename pkNX.WinForms/Subforms/{ => Gen9}/PaldeaMap.cs (100%) create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Dumping/ActivationConditionUtil9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Dumping/FlatBufferSource.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SceneSpawner.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnGlobalInfo.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnNameResolver.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnSceneSimulation.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Exports/DetailedSpawn9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Exports/EncounterArea9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Exports/EncounterSlot9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Exports/FakeSpawner9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Exports/SimulatedAreaSet.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Exports/SpawnExporter.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Info/AreaDef9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Info/LumioseFieldIndex.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Info/LumioseMap.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Info/MapTransform.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Info/SceneInfo9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/Info/TransformUI9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/MapSpawnerSet.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/SpawnRipper9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/Map/World9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/MapViewer9a.Designer.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/MapViewer9a.cs create mode 100644 pkNX.WinForms/Subforms/Gen9a/MapViewer9a.resx rename pkNX.WinForms/Subforms/{ => GenericEditor}/GenericEditor.resx (100%) diff --git a/FlatBuffers/SV/Personal/Personal/Wrapper/PersonalInfo9SV.cs b/FlatBuffers/SV/Personal/Personal/Wrapper/PersonalInfo9SV.cs index 78d65f5d..9a6589b2 100644 --- a/FlatBuffers/SV/Personal/Personal/Wrapper/PersonalInfo9SV.cs +++ b/FlatBuffers/SV/Personal/Personal/Wrapper/PersonalInfo9SV.cs @@ -1,7 +1,7 @@ namespace pkNX.Structures.FlatBuffers.SV; /// -/// Personal Info class with values from the games. +/// Personal Info class with values from the games. /// public sealed class PersonalInfo9SV(PersonalInfo fb) : IPersonalInfo { diff --git a/FlatBuffers/SV/Trinity/Archive/TrinityFileSystemManager.cs b/FlatBuffers/SV/Trinity/Archive/TrinityFileSystemManager.cs index 1181f0b5..c8fa96af 100644 --- a/FlatBuffers/SV/Trinity/Archive/TrinityFileSystemManager.cs +++ b/FlatBuffers/SV/Trinity/Archive/TrinityFileSystemManager.cs @@ -56,22 +56,27 @@ public byte[] GetData(ulong offset, ulong length) return Reader.ReadBytes((int)length); } + public void GetData(ulong offset, ulong length, Span data) + { + Reader.BaseStream.Seek((long)offset, SeekOrigin.Begin); + _ = Reader.Read(data[..(int)length]); + } + public TrinityPak GetPak(int index) { var data = GetPakData(index); return TrinityPak.Serializer.Parse(data, FlatBufferDeserializationOption.GreedyMutable); } + public ulong GetPakHash(int index) => FnvHash.HashFnv1a_64(GetPackPath(index)); + public ulong GetPakLength(int index) => FileData.FileInfos[index].FileSize; + public ulong GetPakOffset(ulong hash) => Meta.GetFileOffset(hash); + public byte[] GetPakData(int index) { - var path = GetPackPath(index); - var hash = FnvHash.HashFnv1a_64(path); - var offset = Meta.GetFileOffset(hash); - var info = FileData.FileInfos[index]; - var size = info.FileSize; - - //Debug.WriteLine($"Found {index} at 0x{offset:X12}, Size={info.FileSize:X}, SubFileCount={info.FileCount}"); - + var size = GetPakLength(index); + var hash = GetPakHash(index); + var offset = GetPakOffset(hash); return GetData(offset, size); } @@ -80,7 +85,7 @@ public byte[] GetPackedFile(ulong hash) var index = FileData.GetSubFileIndex(hash); var pak = GetPak((int)index); var file = pak.GetFileData(hash); - return file.GetUncompressedData(); + return file.Decompress(); } public byte[] GetPackedFile(string path) => GetPackedFile(FnvHash.HashFnv1a_64(path)); diff --git a/FlatBuffers/SV/Trinity/Archive/TrinityPak.cs b/FlatBuffers/SV/Trinity/Archive/TrinityPak.cs index b5314f56..bd9b9d9d 100644 --- a/FlatBuffers/SV/Trinity/Archive/TrinityPak.cs +++ b/FlatBuffers/SV/Trinity/Archive/TrinityPak.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using pkNX.Containers; +using System.IO.Compression; // Added for Zlib support namespace pkNX.Structures.FlatBuffers.SV.Trinity; @@ -34,17 +35,39 @@ private int BinarySearch(ulong hash) public partial class TrinityPakFileData { - public byte[] GetUncompressedData() => CompressionType switch - { // TODO: What specific ID is zlib? - 3 => Oodle.Decompress(Data.Span, (long)UncompressedSize)!, // Oodle - 0xFF => Data.ToArray(), // Uncompressed + public byte[] Decompress() => CompressionType switch + { + DataCompressionType.None => Data.ToArray(), // Uncompressed + DataCompressionType.Zlib => Zlib.Decompress(Data.Span, (int)UncompressedSize), + DataCompressionType.Lz4 => LZ4.Decode(Data.Span, (int)UncompressedSize), + >= DataCompressionType.OodleKraken and <= DataCompressionType.OodleHydra => Oodle.Decompress(Data.Span, (long)UncompressedSize)!, // Oodle _ => throw new ArgumentException($"Unknown compression type {CompressionType}"), }; - public ReadOnlySpan GetUncompressedDataReadOnly() => CompressionType switch - { // TODO: What specific ID is zlib? - 3 => Oodle.Decompress(Data.Span, (long)UncompressedSize)!, // Oodle - 0xFF => Data.ToArray(), // Uncompressed - _ => throw new ArgumentException($"Unknown compression type {CompressionType}"), + public void DecompressTo(Span result) + { + if (CompressionType == DataCompressionType.None) + Data.Span.CopyTo(result); // Uncompressed + else if (CompressionType == DataCompressionType.Zlib) + Zlib.Decompress(Data.Span, result); + else if (CompressionType == DataCompressionType.Lz4) + LZ4.Decode(Data.Span, result); + else if (CompressionType is >= DataCompressionType.OodleKraken and <= DataCompressionType.OodleHydra) + Oodle.TryDecompress(Data.Span, result, out _); + else + throw new ArgumentException($"Unknown compression type {CompressionType}"); + } + + public static ReadOnlySpan Compress(ReadOnlySpan data, DataCompressionType type, OodleCompressionLevel level = OodleCompressionLevel.Optimal2) => type switch + { + DataCompressionType.None => data, + DataCompressionType.Zlib => Zlib.Compress(data), + DataCompressionType.Lz4 => LZ4.Encode(data), + DataCompressionType.OodleKraken => Oodle.Compress(data, out _, OodleFormat.Kraken, level), + DataCompressionType.OodleLeviathan => Oodle.Compress(data, out _, OodleFormat.Leviathan, level), + DataCompressionType.OodleMermaid => Oodle.Compress(data, out _, OodleFormat.Mermaid, level), + DataCompressionType.OodleSelkie => Oodle.Compress(data, out _, OodleFormat.Selkie, level), + DataCompressionType.OodleHydra => Oodle.Compress(data, out _, OodleFormat.Hydra, level), + _ => throw new NotImplementedException($"Compression type {type} is not implemented."), }; } diff --git a/FlatBuffers/SV/Trinity/Archive/TrinityPakExtractor.cs b/FlatBuffers/SV/Trinity/Archive/TrinityPakExtractor.cs index 46518e2a..6e8cc14e 100644 --- a/FlatBuffers/SV/Trinity/Archive/TrinityPakExtractor.cs +++ b/FlatBuffers/SV/Trinity/Archive/TrinityPakExtractor.cs @@ -1,5 +1,5 @@ using pkNX.Containers; -using static System.Buffers.Binary.BinaryPrimitives; +using System.Buffers; namespace pkNX.Structures.FlatBuffers.SV.Trinity; @@ -8,44 +8,69 @@ public static class TrinityPakExtractor public const string DumpArchiveExtracted = "extracted"; private const string DumpArchivePak = "paks"; - public static void DumpArchives(string pathRomFS, string outbasedir) + public static void DumpArchives(string pathRomFS, string dirRootDump) { var pathFs = Path.Combine(pathRomFS, "arc", "data.trpfs"); var pathFd = Path.Combine(pathRomFS, "arc", "data.trpfd"); var reader = new TrinityFileSystemManager(pathFs, pathFd); - Extract(outbasedir, reader); + Extract(dirRootDump, reader); reader.Dispose(); } - private static void Extract(string outbasedir, TrinityFileSystemManager manager) + private static void Extract(string dirRoot, TrinityFileSystemManager manager) { - var outpakdir = Path.Combine(outbasedir, DumpArchivePak); - var outexdir = Path.Combine(outbasedir, DumpArchiveExtracted); - Directory.CreateDirectory(outbasedir); - Directory.CreateDirectory(outpakdir); - Directory.CreateDirectory(outexdir); + Directory.CreateDirectory(dirRoot); + + var dirPak = Path.Combine(dirRoot, DumpArchivePak); + Directory.CreateDirectory(dirPak); + + var dirExtract = Path.Combine(dirRoot, DumpArchiveExtracted); + Directory.CreateDirectory(dirExtract); var count = manager.FileCount; for (var i = 0; i < count; i++) - ExportArc(manager, i, outpakdir, outexdir); + ExportArc(manager, i, dirPak, dirExtract); } - private static void ExportArc(TrinityFileSystemManager reader, int packIndex, string outpakdir, string outexdir) + private static void ExportArc(TrinityFileSystemManager reader, int packIndex, string dirPak, string dirExtract) { - var packFilePath = reader.GetPackPath(packIndex); - var outpakpath = Path.Combine(outpakdir, packFilePath); - var dirName = Path.GetDirectoryName(outpakpath); + var pool = ArrayPool.Shared; + var hash = reader.GetPakHash(packIndex); + var length = reader.GetPakLength(packIndex); + var offset = reader.GetPakOffset(hash); + var rent = pool.Rent((int)length); + var data = rent.AsMemory(0, (int)length); + try + { + reader.GetData(offset, length, data.Span); + var packFilePath = reader.GetPackPath(packIndex); + ExportPackFile(data.Span, dirPak, packFilePath); + ExportPackExtract(data, dirExtract, packFilePath); + } + finally + { + data.Span.Clear(); + pool.Return(rent); + } + } + + private static void ExportPackFile(ReadOnlySpan data, string dir, string pakFilePath) + { + var fileName = Path.Combine(dir, pakFilePath); + var dirName = Path.GetDirectoryName(fileName); if (string.IsNullOrEmpty(dirName)) - throw new Exception($"{outpakpath} directory name is null"); + throw new Exception($"{fileName} directory name is null"); Directory.CreateDirectory(dirName); - var data = reader.GetPakData(packIndex); - File.WriteAllBytes(outpakpath, data); + File.WriteAllBytes(fileName, data); + } - var outexpakdir = Path.Combine(outexdir, packFilePath); - Directory.CreateDirectory(outexpakdir); - var trpak = FlatBufferConverter.DeserializeFrom(data); - ExtractPack(trpak, outexpakdir); + private static void ExportPackExtract(Memory data, string dir, string pakFilePath) + { + var folder = Path.Combine(dir, pakFilePath); + Directory.CreateDirectory(folder); + var obj = FlatBufferConverter.DeserializeFrom(data); + ExtractPack(obj, folder); } private static void ExtractPack(TrinityPak trpak, string outexpakdir) @@ -54,33 +79,28 @@ private static void ExtractPack(TrinityPak trpak, string outexpakdir) WriteFile(trpak.Files[i], trpak.Hashes[i], outexpakdir, i); } - private static void WriteFile(TrinityPakFileData file, ulong hash, string outexpakdir, int fileIndex) + private static void WriteFile(TrinityPakFileData file, ulong hash, string dir, int fileIndex) { - var decompressed = file.GetUncompressedDataReadOnly(); - var ext = GuessExtension(decompressed); + if (file.CompressionType is DataCompressionType.None) + { + WriteFile(file.Data.Span, hash, dir, fileIndex); + return; + } - var filepath = Path.Combine(outexpakdir, $"{fileIndex:0000} - {hash:X16}.{ext}"); - //Debug.WriteLine($" * File, CompressionType={file.CompressionType}, CompressedSize={file.Data.Length:X}, UncompressedSize={file.UncompressedSize}, Field_00={file.Field_00}, Field_01={file.Field_01}"); - - using var fs = File.Create(filepath); - fs.Write(decompressed); + var pool = ArrayPool.Shared; + var length = (int)file.UncompressedSize; + var rent = pool.Rent(length); + var decompressed = rent.AsSpan(0, length); + file.DecompressTo(decompressed); + WriteFile(decompressed, hash, dir, fileIndex); + decompressed.Clear(); + pool.Return(rent); } - private static string GuessExtension(ReadOnlySpan data) + private static void WriteFile(ReadOnlySpan decompressed, ulong hash, string dir, int fileIndex) { - const string defaultExtension = "bin"; - if (data.Length < 8) - return defaultExtension; - var u32 = ReadUInt32LittleEndian(data); - if (ReadUInt32LittleEndian(data[4..8]) == 0x53424642) - return "bfbs"; - return u32 switch - { - AHTB.Magic => "ahtb", - 0x43524153 => "sarc", - 0x58544E42 => "bntx", - 0x63726173 => "sarc", - _ => defaultExtension, - }; + var ext = TrinityUtil.GuessExtension(decompressed); + var filepath = Path.Combine(dir, $"{fileIndex:0000} - {hash:X16}.{ext}"); + File.WriteAllBytes(filepath, decompressed); } } diff --git a/FlatBuffers/SV/Trinity/Scene/SceneDumper.cs b/FlatBuffers/SV/Trinity/Scene/SceneDumper.cs index 733c45a1..e64c7dee 100644 --- a/FlatBuffers/SV/Trinity/Scene/SceneDumper.cs +++ b/FlatBuffers/SV/Trinity/Scene/SceneDumper.cs @@ -259,8 +259,8 @@ private static void DumpParticleComponent(Memory data, TextWriter tw, int { var props = FlatBufferConverter.DeserializeFrom(data); Write(tw, depth, $"{nameof(props.ParticleFile)}: {props.ParticleFile}"); - Write(tw, depth, $"{nameof(props.ParticleName)}: {props.ParticleName}"); - Write(tw, depth, $"{nameof(props.ParticleParent)}: {props.ParticleParent}"); + Write(tw, depth, $"{nameof(props.ParticleName)}: {props.ParticleName} ({FnvHash.HashFnv1a_64(props.ParticleName):X16})"); + Write(tw, depth, $"{nameof(props.ParticleParent)}: {props.ParticleParent} ({FnvHash.HashFnv1a_64(props.ParticleParent):X16})"); } private static void DumpCollisionComponent(Memory data, TextWriter tw, int depth) @@ -321,7 +321,7 @@ private static void DumpObjectSwitcher(Memory data, TextWriter tw, int dep private static void DumpObjectTemplate(Memory data, TextWriter tw, int depth) { var props = FlatBufferConverter.DeserializeFrom(data); - Write(tw, depth, $"{nameof(props.ObjectTemplateName)}: {props.ObjectTemplateName}"); + Write(tw, depth, $"{nameof(props.ObjectTemplateName)}: {props.ObjectTemplateName} ({FnvHash.HashFnv1a_64(props.ObjectTemplateName):X16})"); Write(tw, depth, $"{nameof(props.ObjectTemplatePath)}: {props.ObjectTemplatePath}"); Write(tw, depth, $"{nameof(props.ObjectTemplateExtra)}: {props.ObjectTemplateExtra}"); Write(tw, depth, $"{nameof(props.Field03)}: {props.Field03}"); @@ -331,7 +331,7 @@ private static void DumpObjectTemplate(Memory data, TextWriter tw, int dep private static void DumpScenePoint(Memory data, TextWriter tw, int depth) { var props = FlatBufferConverter.DeserializeFrom(data); - Write(tw, depth, $"{nameof(props.Name)}: {props.Name}"); + Write(tw, depth, $"{nameof(props.Name)}: {props.Name} ({FnvHash.HashFnv1a_64(props.Name):X16})"); Write(tw, depth, $"{nameof(props.Position)}: {props.Position}"); Write(tw, depth, $"{nameof(props.Field02)}: {props.Field02}"); } @@ -339,7 +339,7 @@ private static void DumpScenePoint(Memory data, TextWriter tw, int depth) private static void DumpSceneObject(Memory data, TextWriter tw, int depth) { var props = FlatBufferConverter.DeserializeFrom(data); - Write(tw, depth, $"{nameof(props.ObjectName)}: {props.ObjectName}"); + Write(tw, depth, $"{nameof(props.ObjectName)}: {props.ObjectName} ({FnvHash.HashFnv1a_64(props.ObjectName):X16})"); Write(tw, depth, $"{nameof(props.ObjectPosition)}:"); Dump(props.ObjectPosition, tw, depth + 1); Write(tw, depth, $"{nameof(props.Field02)}: {props.Field02}"); diff --git a/FlatBuffers/SV/Trinity/Schemas/TrinityPak.fbs b/FlatBuffers/SV/Trinity/Schemas/TrinityPak.fbs index 7c0af30a..841b6d92 100644 --- a/FlatBuffers/SV/Trinity/Schemas/TrinityPak.fbs +++ b/FlatBuffers/SV/Trinity/Schemas/TrinityPak.fbs @@ -1,9 +1,10 @@ namespace pkNX.Structures.FlatBuffers.SV.Trinity; attribute "fs_serializer"; -enum CompressionType : ushort +enum DataCompressionType : byte { - None = 0, + None = -1, + Invalid = 0, Zlib = 1, Lz4 = 2, OodleKraken = 3, @@ -15,8 +16,8 @@ enum CompressionType : ushort table TrinityPakFileData { Field_00:uint; - CompressionType:ubyte; - Field_02:ubyte; + CompressionType:DataCompressionType; + CompressionLevel:ubyte; UncompressedSize:ulong; Data:[ubyte] (required); } diff --git a/FlatBuffers/ZA/Battle/Schemas/BattleSetting.fbs b/FlatBuffers/ZA/Battle/Schemas/BattleSetting.fbs new file mode 100644 index 00000000..6867d9bd --- /dev/null +++ b/FlatBuffers/ZA/Battle/Schemas/BattleSetting.fbs @@ -0,0 +1,57 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_vector"; +attribute "fs_serializer"; +attribute "fs_valueStruct"; +attribute "fs_nonVirtual"; +attribute "fs_unsafeStructVector"; + +struct StealthRockDamageRatio { + DemonType_1:int; + DemonType_1_2:int; + DemonType_1_4:int; + DemonType_1_8:int; + DemonType_1_16:int; + DemonType_1_32:int; + DemonType_2:int; + DemonType_4:int; + DemonType_8:int; + DemonType_16:int; + DemonType_32:int; +} + +struct DamagePerTypeAff { + PerType_1_8:int; + PerType_1_4:int; + PerType_1_2:int; + PerType_1:int; + PerType_2:int; + PerType_4:int; + PerType_8:int; +} + +table BattleSetting (fs_serializer) { + Damage_Per_Mega_Aura:int; + Damage_Per_Random_Amplitude:int; + Damage_Per_Trainer_Battle:int; + Damage_Per_Wild_Battle:int; + Damage_Per_Weather_Advantage:int; + Damage_Per_Weather_Disadvantage:int; + Damage_Per_Critical:int; + Damage_Per_Critical_Plus:int; + Damage_Per_Type_Match:int; + Damage_Per_Type_Match_Plus:int; + Damage_Per_Mamoru_Through_Plus:int; + Damage_Per_Type_Aff:DamagePerTypeAff; + Damage_Per_Type_Aff_Plus:DamagePerTypeAff; + Damage_Per_Mega_Type_Aff:DamagePerTypeAff; + Damage_Per_Mega_Type_Aff_Plus:DamagePerTypeAff; + Reflector_Damage_Cut_Ratio:int; + Hikarinokabe_Damage_Cut_Ratio:int; + Needle_Guard_Damage_Demon:int; + Stealth_Rock_Damage_Demon:StealthRockDamageRatio; + Stealth_Rock_Damage_Demon_Plus:StealthRockDamageRatio; + Critical_Rank_Ratio:[int] (required); +} + +root_type BattleSetting; diff --git a/FlatBuffers/ZA/Battle/Schemas/LockonDesc.fbs b/FlatBuffers/ZA/Battle/Schemas/LockonDesc.fbs new file mode 100644 index 00000000..4ccc1299 --- /dev/null +++ b/FlatBuffers/ZA/Battle/Schemas/LockonDesc.fbs @@ -0,0 +1,27 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +struct LockonDescRange { + Width:float; + Top:float; + Bottom:float; + Near:float; + Far:float; +} + +struct LockonDescRangePreset { + Enter:LockonDescRange; + Change:LockonDescRange; + Leave:LockonDescRange; +} + +table LockonDesc (fs_serializer) { + Presets:[LockonDescRangePreset] (required); + ReticleRange:float; + UpdateCycle:ubyte; + Target:ulong; + UnlockDelay:float; +} + +root_type LockonDesc; diff --git a/FlatBuffers/ZA/Battle/Schemas/PlayerDamage.fbs b/FlatBuffers/ZA/Battle/Schemas/PlayerDamage.fbs new file mode 100644 index 00000000..c904d17c --- /dev/null +++ b/FlatBuffers/ZA/Battle/Schemas/PlayerDamage.fbs @@ -0,0 +1,28 @@ +include "Shared/DevID.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +struct WazaDamage { + WazaPower:uint; + Damage:uint; +} + +struct PokemonDamageRatio { + TotalPower:uint; + Ratio:float; +} + +table MegaPokemonRatio { + DevNo:DevID; + Ratio:float; +} + +table PlayerDamage (fs_serializer) { + Move:[WazaDamage] (required); + PokemonRatio:[PokemonDamageRatio] (required); + MegaPokemon:[MegaPokemonRatio] (required); +} + +root_type PlayerDamage; diff --git a/FlatBuffers/ZA/Battle/pkNX.Structures.FlatBuffers.ZA.Battle.csproj b/FlatBuffers/ZA/Battle/pkNX.Structures.FlatBuffers.ZA.Battle.csproj new file mode 100644 index 00000000..6b512ec9 --- /dev/null +++ b/FlatBuffers/ZA/Battle/pkNX.Structures.FlatBuffers.ZA.Battle.csproj @@ -0,0 +1 @@ + diff --git a/FlatBuffers/ZA/Directory.Build.props b/FlatBuffers/ZA/Directory.Build.props new file mode 100644 index 00000000..16b126ef --- /dev/null +++ b/FlatBuffers/ZA/Directory.Build.props @@ -0,0 +1,26 @@ + + + + + + + + ..\..\pkNX.Structures.FlatBuffers\Schemas\ + + + + + + + + + ..\Shared\Schemas\ + + + + + + + + + diff --git a/FlatBuffers/ZA/Item/Schemas/Enums/ItemType.fbs b/FlatBuffers/ZA/Item/Schemas/Enums/ItemType.fbs new file mode 100644 index 00000000..82d677a5 --- /dev/null +++ b/FlatBuffers/ZA/Item/Schemas/Enums/ItemType.fbs @@ -0,0 +1,14 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum ItemType : int { + ITEMTYPE_0 = 0, + ITEMTYPE_1 = 1, + ITEMTYPE_2 = 2, + ITEMTYPE_3 = 3, + ITEMTYPE_4 = 4, + ITEMTYPE_5 = 5, + ITEMTYPE_6 = 6, + ITEMTYPE_7 = 7, + ITEMTYPE_8 = 8, + ITEMTYPE_9 = 9, +} diff --git a/FlatBuffers/ZA/Item/Schemas/FieldWazaGimmickPrivateDBArray.fbs b/FlatBuffers/ZA/Item/Schemas/FieldWazaGimmickPrivateDBArray.fbs new file mode 100644 index 00000000..b0280475 --- /dev/null +++ b/FlatBuffers/ZA/Item/Schemas/FieldWazaGimmickPrivateDBArray.fbs @@ -0,0 +1,33 @@ +include "Shared/ActivationConditionParam.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table ExtensionParam { + PokemonPopId:string (required); + ItemPopId:string; + QuestId:string; + WarpParamId:string; + ImpactAroundId:string; +} + +table FieldWazaGimmickPrivate { + GroupId:string; + ObjectName:[string] (required); + GimmickId:string; + RepopInterval:int; + RepopOffset:int; + Spawner:bool; + Extension:ExtensionParam (required); + ActivationConditionParamList:[ActivationConditionParam]; +} + +table FieldWazaGimmickPrivateDB { + Table:[FieldWazaGimmickPrivate] (required); +} + +table FieldWazaGimmickPrivateDBArray (fs_serializer) { + Table:[FieldWazaGimmickPrivateDB] (required); +} + +root_type FieldWazaGimmickPrivateDBArray; diff --git a/FlatBuffers/ZA/Item/Schemas/HudLineupArray.fbs b/FlatBuffers/ZA/Item/Schemas/HudLineupArray.fbs new file mode 100644 index 00000000..90400024 --- /dev/null +++ b/FlatBuffers/ZA/Item/Schemas/HudLineupArray.fbs @@ -0,0 +1,21 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table HudInventory { + Field00:uint; + Items:[uint] (required); +} + +table HudLineup { + Name:string (required); + Field01:uint; + Field02:uint; + Inventory:[HudInventory] (required); +} + +table HudLineupArray (fs_serializer) { + Table:[HudLineup] (required); +} + +root_type HudLineupArray; diff --git a/FlatBuffers/ZA/Item/Schemas/ItemDataArray.fbs b/FlatBuffers/ZA/Item/Schemas/ItemDataArray.fbs new file mode 100644 index 00000000..cca8dd1f --- /dev/null +++ b/FlatBuffers/ZA/Item/Schemas/ItemDataArray.fbs @@ -0,0 +1,64 @@ +include "Shared/WazaID.fbs"; +include "Enums/ItemType.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table ItemData { + Id:int (key); + ItemType:ItemType; + InternalName:string (required); + IconName:string (required); + Price:int; + Pocket:int; + SlotMaxNum:int; + SortNum:int; + PriceMegaShard:int; + PriceColorfulScrew:int; + CanNotHold:bool; + MachineWaza:WazaID; + MachineIndex:int; + WorkRecvSleep:bool; + WorkRecvPoison:bool; + WorkRecvBurn:bool; + WorkRecvFreeze:bool; + WorkRecvParalyze:bool; + WorkRecvConfuse:bool; + WorkRecvMero:bool; + WorkAttack:int; + WorkDefense:int; + WorkSpAttack:int; + WorkSpDefense:int; + WorkSpeed:int; + WorkAccuracy:int; + WorkCritical:int; + WorkEffectGuard:int; + MintNature:int; + WorkRecvPower:int; + HealPercentage:int; + WorkRevival:int; + RevivePercentage:int; + ExpPointGain:int; + MaxUseLevel:int; // 100 for Rare Candy, otherwise 0 + WorkFriendly1:int; + WorkFriendly2:int; + WorkFriendly3:int; + WorkEvolutional:bool; + WorkFormChange:bool; + WorkStatusHp:int; + WorkStatusAtk:int; + WorkStatusDef:int; + WorkStatusSpd:int; + WorkStatusSAtk:int; + WorkStatusSDef:int; + EquipPower:int; + AutoHealPriority:int; + CanUseInBattle:bool; + SwapIntoId:int; // only used for Pebble -> Zygardite +} + +table ItemDataArray (fs_serializer) { + Table:[ItemData] (required); +} + +root_type ItemDataArray; diff --git a/FlatBuffers/ZA/Item/Schemas/ItemTableDataDBArray.fbs b/FlatBuffers/ZA/Item/Schemas/ItemTableDataDBArray.fbs new file mode 100644 index 00000000..2c897b3b --- /dev/null +++ b/FlatBuffers/ZA/Item/Schemas/ItemTableDataDBArray.fbs @@ -0,0 +1,27 @@ +include "Shared/ActivationCondition.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table ItemLotteryData { + ItemId:string (required); + Weight:int; + MaxCount:int; + Type:int; + ActivationConditionArray:[ActivationCondition]; +} + +table ItemTableData { + Id:string (required); + ItemLotteryDataList:[ItemLotteryData] (required); +} + +table ItemTableDataDB { + Data:[ItemTableData] (required); +} + +table ItemTableDataDBArray (fs_serializer) { + Table:[ItemTableDataDB] (required); +} + +root_type ItemTableDataDBArray; diff --git a/FlatBuffers/ZA/Item/Schemas/RandomPopItemSpawnerDataDBArray.fbs b/FlatBuffers/ZA/Item/Schemas/RandomPopItemSpawnerDataDBArray.fbs new file mode 100644 index 00000000..8c4bc0ca --- /dev/null +++ b/FlatBuffers/ZA/Item/Schemas/RandomPopItemSpawnerDataDBArray.fbs @@ -0,0 +1,35 @@ +include "Shared/ActivationCondition.fbs"; +include "Shared/AppearanceInfo.fbs"; +include "Shared/CoolTimeInfo.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table RandomPopItemTableInfo { + TableId:string (required); + TableInfoActivationConditionArray:[ActivationCondition]; +} + +table AppearanceSpawnerObjectInfo { + ObjectName:string (required); + CreateScenePath:string; + AppearanceInfoData:AppearanceInfo; +} + +table RandomPopItemSpawnerData { + Id:string (required); + AppearanceSpawnerObjectInfoList:[AppearanceSpawnerObjectInfo] (required); + CoolTime:CoolTimeInfo; + ActivationConditionArray:[ActivationCondition] (required); + TableInfoList:[RandomPopItemTableInfo] (required); +} + +table RandomPopItemSpawnerDataDB { + Table:[RandomPopItemSpawnerData] (required); +} + +table RandomPopItemSpawnerDataDBArray (fs_serializer) { + Table:[RandomPopItemSpawnerDataDB] (required); +} + +root_type RandomPopItemSpawnerDataDBArray; diff --git a/FlatBuffers/ZA/Item/Schemas/ShopLineupArray.fbs b/FlatBuffers/ZA/Item/Schemas/ShopLineupArray.fbs new file mode 100644 index 00000000..005d6b4a --- /dev/null +++ b/FlatBuffers/ZA/Item/Schemas/ShopLineupArray.fbs @@ -0,0 +1,33 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table ShopLineupArray (fs_serializer) { + Table:[ShopLineup] (required); +} + +table ShopLineup { + Name:string (required); + Inventory:[ShopInventory] (required); +} + +table ShopInventory { + Item:uint; + DisplayIndex:uint; + Conditions:[ShopInventoryCondition] (required); +} + +table ShopInventoryCondition { + Table:[ShopInventoryConditionHolder] (required); +} + +table ShopInventoryConditionHolder { + Table:[ShopInventoryAppearConditionsHolder] (required); +} + +table ShopInventoryAppearConditionsHolder { + Condition:string; + Comparison:uint; + Arguments:[string]; +} + +root_type ShopLineupArray; diff --git a/FlatBuffers/ZA/Item/Schemas/ZARewardItemDataArray.fbs b/FlatBuffers/ZA/Item/Schemas/ZARewardItemDataArray.fbs new file mode 100644 index 00000000..964682ab --- /dev/null +++ b/FlatBuffers/ZA/Item/Schemas/ZARewardItemDataArray.fbs @@ -0,0 +1,22 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table ZARewardItem { + ItemID:string (required); + Quantity:uint; + Weight:uint; +} + +table ZARewardItemData { + ID:string (required); + MinWinStreak:uint; + MaxWinStreak:uint; + Field03:byte; + RewardItem:[ZARewardItem] (required); +} + +table ZARewardItemDataArray (fs_serializer) { + Table:[ZARewardItemData] (required); +} + +root_type ZARewardItemDataArray; diff --git a/FlatBuffers/ZA/Item/pkNX.Structures.FlatBuffers.ZA.Item.csproj b/FlatBuffers/ZA/Item/pkNX.Structures.FlatBuffers.ZA.Item.csproj new file mode 100644 index 00000000..35e3d842 --- /dev/null +++ b/FlatBuffers/ZA/Item/pkNX.Structures.FlatBuffers.ZA.Item.csproj @@ -0,0 +1,2 @@ + + diff --git a/FlatBuffers/ZA/Misc/Schemas/DressUpDataArray.fbs b/FlatBuffers/ZA/Misc/Schemas/DressUpDataArray.fbs new file mode 100644 index 00000000..e456c42a --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/DressUpDataArray.fbs @@ -0,0 +1,25 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table DressUpData { + MagicValue:uint; + Name:string (required); + Field02:uint; + Field03:string (required); + Field04:uint; + Field05:uint; + Color1:string (required); // color + Color2:string (required); // color + Flag08:bool; + Field09:uint; + Field10:uint; + Field11:string; // not required + Flag12:bool; +} + +table DressUpDataArray (fs_serializer) { + Table:[DressUpData] (required); +} + +root_type DressUpDataArray; diff --git a/FlatBuffers/ZA/Misc/Schemas/DressUpEnsembleDataArray.fbs b/FlatBuffers/ZA/Misc/Schemas/DressUpEnsembleDataArray.fbs new file mode 100644 index 00000000..885f17d9 --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/DressUpEnsembleDataArray.fbs @@ -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 DressUpEnsemble { + MagicValue:uint; + Condition:[ActivationCondition] (required); +} + +table DressUpEnsembleData { + MagicValue:uint; + Ensemble:[DressUpEnsemble] (required); +} + +table DressUpEnsembleDataArray (fs_serializer) { + Table:[DressUpEnsembleData] (required); +} + +root_type DressUpEnsembleDataArray; \ No newline at end of file diff --git a/FlatBuffers/ZA/Misc/Schemas/DressUpGroupDataArray.fbs b/FlatBuffers/ZA/Misc/Schemas/DressUpGroupDataArray.fbs new file mode 100644 index 00000000..138c963f --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/DressUpGroupDataArray.fbs @@ -0,0 +1,15 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table DressUpGroupData { + Name:string (required); + Value:uint; + Group:string (required); +} + +table DressUpGroupDataArray (fs_serializer) { + Table:[DressUpGroupData] (required); +} + +root_type DressUpGroupDataArray; diff --git a/FlatBuffers/ZA/Misc/Schemas/EventConst.fbs b/FlatBuffers/ZA/Misc/Schemas/EventConst.fbs new file mode 100644 index 00000000..c40a86e9 --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/EventConst.fbs @@ -0,0 +1,14 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table EventConst { + Name:string (required); + Value:string (required); +} + +table EventConstArray (fs_serializer) { + Table:[EventConst] (required); +} + +root_type EventConstArray; diff --git a/FlatBuffers/ZA/Misc/Schemas/EventControl.fbs b/FlatBuffers/ZA/Misc/Schemas/EventControl.fbs new file mode 100644 index 00000000..9501435a --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/EventControl.fbs @@ -0,0 +1,36 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table EventControl { + Name:string (required); + Field01:uint; + Field02:bool; + Field03:bool; + Field04:bool; // unused? + Field05:bool; + Field06:bool; + Field07:bool; + Field08:string; + Field09:bool; // unused? + Field10:bool; // unused? + Field11:bool; + Field12:string; + Field13:bool; + Field14:bool; + Field15:bool; + Field16:bool; + Field17:bool; + Field18:string; + Field19:string; + Field20:bool; + Field21:bool; + Field22:bool; + Field23:bool; +} + +table EventControlArray (fs_serializer) { + Table:[EventControl] (required); +} + +root_type EventControlArray; diff --git a/FlatBuffers/ZA/Misc/Schemas/EventLabel.fbs b/FlatBuffers/ZA/Misc/Schemas/EventLabel.fbs new file mode 100644 index 00000000..36eb6d2b --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/EventLabel.fbs @@ -0,0 +1,13 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table EventLabel { + Name:string (required); +} + +table EventLabelArray (fs_serializer) { + Table:[EventLabel] (required); +} + +root_type EventLabelArray; diff --git a/FlatBuffers/ZA/Misc/Schemas/FieldWeatherTable.fbs b/FlatBuffers/ZA/Misc/Schemas/FieldWeatherTable.fbs new file mode 100644 index 00000000..7ede3619 --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/FieldWeatherTable.fbs @@ -0,0 +1,100 @@ +include "FieldWeatherType.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +enum FieldClimateType : int +{ + None = -1, + Normal = 0, + Cold = 1, + Hot = 2, +} + +enum StringForStruct : int +{ + NONE = -1, + weather_table_main = 0, + desert = 1, + snowy = 2, + room = 3, +} + +struct WeatherTimeZone { + From:float; + To:float; +} + +table WeatherSoundParam { + SoundStateEventName:string; + SoundRTPCValue:float; +} + +table WeatherSoundTable { + Sunny:WeatherSoundParam; + Cloudy:WeatherSoundParam; + Rain:WeatherSoundParam; + Storm:WeatherSoundParam; + Mist:WeatherSoundParam; + ClearSunny:WeatherSoundParam; + Rainbow:WeatherSoundParam; +} + +struct WeatherReplace { + OrgWeather:FieldWeatherType; + ReplaceWeather:FieldWeatherType; + ValidTimeZone:[WeatherTimeZone:3]; +} + +struct FieldWeatherDefine { + Type:FieldWeatherType; + Prob:int; +} + +struct FieldWeatherDefineSub { + MainWeather:FieldWeatherType; + SubWeather:[FieldWeatherDefine:9]; +} + +struct FieldWeatherSpecialTransition { + Type:FieldWeatherType; + TransitionFrom:FieldWeatherType; + TransitionTo:FieldWeatherType; + MinDuration:int; + MaxDuration:int; +} + +struct FieldWeatherStructSub { + Tag:StringForStruct; + Climate:FieldClimateType; + MinDuration:int; + MaxDuration:int; + OutdoorWeatherTable:StringForStruct; + Weather:[FieldWeatherDefineSub:11]; + SpecialTransition:[FieldWeatherSpecialTransition:4]; +} + +struct FieldWeatherStructSubList { + List:[FieldWeatherStructSub:8]; +} + +struct FieldWeatherStructMain { + Tag:StringForStruct; + Climate:FieldClimateType; + MinDuration:int; + MaxDuration:int; + Weather:[FieldWeatherDefine:9]; + SpecialTransition:[FieldWeatherSpecialTransition:4]; + Replace:[WeatherReplace:4]; +} + +table FieldWeatherTable (fs_serializer) { + TransitionSpan:float; + TransitionSpanForFix:float; + Main:FieldWeatherStructMain; + Sub:FieldWeatherStructSubList; + Sound:WeatherSoundTable; +} + +root_type FieldWeatherTable; diff --git a/FlatBuffers/ZA/Misc/Schemas/FieldWeatherType.fbs b/FlatBuffers/ZA/Misc/Schemas/FieldWeatherType.fbs new file mode 100644 index 00000000..d7dfc01b --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/FieldWeatherType.fbs @@ -0,0 +1,19 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum FieldWeatherType : int +{ + None = -1, + Sunny = 0, + Cloudy = 1, + Rain = 2, + Storm = 3, + Snow = 4, + SnowStorm = 5, + DiamondDust = 6, + SandStorm = 7, + Mist = 8, + ClearSunny = 9, + Rainbow = 10, + Count = 11, + RainToSunny = 12, +} diff --git a/FlatBuffers/ZA/Misc/Schemas/HairMakeDataArray.fbs b/FlatBuffers/ZA/Misc/Schemas/HairMakeDataArray.fbs new file mode 100644 index 00000000..9e3346e4 --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/HairMakeDataArray.fbs @@ -0,0 +1,21 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table HairMakeData { + Value:uint; + Resource:string (required); + Type:uint; + Bool03:bool; + Color:string; + Name:string; + SortOrder:uint; + Pattern1:int; + Pattern2:int; +} + +table HairMakeDataArray (fs_serializer) { + Table:[HairMakeData] (required); +} + +root_type HairMakeDataArray; diff --git a/FlatBuffers/ZA/Misc/Schemas/TitleArray.fbs b/FlatBuffers/ZA/Misc/Schemas/TitleArray.fbs new file mode 100644 index 00000000..2add3897 --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/TitleArray.fbs @@ -0,0 +1,29 @@ +include "Shared/ActivationConditionElement.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table Medal { + Name:string; + Requirement:[ActivationConditionElement]; +} + +table Title { + Index:uint; + Name:string (required); + Text:string (required); + Count:string; + Complete:string; + Type:uint; + Requirement:[ActivationConditionElement] (required); + Bronze:Medal; + Silver:Medal; + Gold:Medal; +} + +table TitleArray (fs_serializer) { + Table:[Title] (required); +} + +root_type TitleArray; diff --git a/FlatBuffers/ZA/Misc/Schemas/TitleCountArray.fbs b/FlatBuffers/ZA/Misc/Schemas/TitleCountArray.fbs new file mode 100644 index 00000000..9bdedc88 --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/TitleCountArray.fbs @@ -0,0 +1,17 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table TitleCount { + Index:string (required); + Type1:uint; + Type2:int; + Type3:uint; + Flag4:bool; +} + +table TitleCountArray (fs_serializer) { + Table:[TitleCount] (required); +} + +root_type TitleCountArray; diff --git a/FlatBuffers/ZA/Misc/Schemas/WeatherHappeningParamArray.fbs b/FlatBuffers/ZA/Misc/Schemas/WeatherHappeningParamArray.fbs new file mode 100644 index 00000000..46f82395 --- /dev/null +++ b/FlatBuffers/ZA/Misc/Schemas/WeatherHappeningParamArray.fbs @@ -0,0 +1,38 @@ +include "FieldWeatherType.fbs"; +include "Math/PackedVec3f.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +struct TimeZone { + From:int; + To:int; +} + +table WeatherHappeningParam { + Name:string; + TemplatePath:string; + SceneName:string; + PrevWeather0:FieldWeatherType; + PrevWeather1:FieldWeatherType; + PrevWeather2:FieldWeatherType; + CurWeather0:FieldWeatherType; + CurWeather1:FieldWeatherType; + CurWeather2:FieldWeatherType; + TimeZone0:TimeZone; + TimeZone1:TimeZone; + TimeZone2:TimeZone; + Prob:int; + MinDuration:int; + MaxDuration:int; + FollowCamera:bool; + Offset:PackedVec3f; + FollowSun:bool; +} + +table WeatherHappeningParamArray (fs_serializer) { + Table:[WeatherHappeningParam] (required); +} + +root_type WeatherHappeningParamArray; diff --git a/FlatBuffers/ZA/Misc/pkNX.Structures.FlatBuffers.ZA.Misc.csproj b/FlatBuffers/ZA/Misc/pkNX.Structures.FlatBuffers.ZA.Misc.csproj new file mode 100644 index 00000000..46d17945 --- /dev/null +++ b/FlatBuffers/ZA/Misc/pkNX.Structures.FlatBuffers.ZA.Misc.csproj @@ -0,0 +1,5 @@ + + + + + diff --git a/FlatBuffers/ZA/Personal/Dumpers/PersonalDumper9a.cs b/FlatBuffers/ZA/Personal/Dumpers/PersonalDumper9a.cs new file mode 100644 index 00000000..dca092aa --- /dev/null +++ b/FlatBuffers/ZA/Personal/Dumpers/PersonalDumper9a.cs @@ -0,0 +1,379 @@ +using pkNX.Containers; + +namespace pkNX.Structures.FlatBuffers.ZA; + +public class PersonalDumper9a +{ + public const bool HasAbilities = true; + + public required IReadOnlyList Abilities { private get; init; } + public required IReadOnlyList Types { private get; init; } + public required IReadOnlyList Items { private get; init; } + public required IReadOnlyList Colors { private get; init; } + public required IReadOnlyList EggGroups { private get; init; } + public required IReadOnlyList ExpGroups { private get; init; } + public required IReadOnlyList Moves { protected get; init; } + public required IReadOnlyList Species { private get; init; } + public required IReadOnlyList ZukanA { private get; init; } + public required IReadOnlyList ZukanB { private get; init; } + public required AHTB ZukanAHTB { private get; init; } + + public static ReadOnlySpan TMIndexes => PersonalInfo9ZA.TMIndexes; + + private static readonly string[] AbilitySuffix = [" (1)", " (2)", " (H)"]; + + public IReadOnlyList> MoveSpeciesLearn { get; private set; } = []; + + public readonly PersonalDumperSettings Settings = new(); + + public List Dump(PersonalTable9ZA table) + { + var lines = new List(); + var ml = new List[Moves.Count]; + for (int i = 0; i < ml.Length; i++) + ml[i] = []; + MoveSpeciesLearn = ml; + + for (ushort species = 0; species <= table.MaxSpeciesID; species++) + { + var pi = table[species]; + var specInternal = SpeciesConverterZA.GetInternal9(species); + for (byte form = 0; form < pi.FormCount; form++) + AddDump(lines, table, specInternal, species, form); + } + return lines; + } + + private string GetSpeciesName(ushort internalIndex) => Species[internalIndex]; + + public void AddDump(List lines, PersonalTable9ZA table, ushort speciesInternal, ushort species, byte form) + { + var index = table.GetFormIndex(species, form); + var entry = table[index]; + string name = GetSpeciesName(speciesInternal); + if (form != 0) + name += $"-{form}"; + name += $" #{entry.DexIndex:000}"; + AddDump(lines, entry, index, name, speciesInternal, form); + } + + private void AddDump(List lines, PersonalInfo9ZA pi, int entry, string name, ushort speciesInternal, byte form) + { + if (pi is { IsPresentInGame: false }) + return; + + var specName = GetSpeciesName(speciesInternal); + var specCode = pi.FormCount > 1 ? $"{specName}-{form}" : $"{specName}"; + + if (Settings.Stats) + AddPersonalLines(lines, pi, entry, name, specCode); + + if (pi.SpeciesClassMajor is not 0 || pi.SpeciesClassMinor is not 0) + { + var classification = pi.SpeciesClassMajor is not 0 && pi.SpeciesClassMinor is 0 ? $"Classifications: {GetClassificationDisplayNameMajor(pi.SpeciesClassMajor)}" + : pi.SpeciesClassMinor is not 0 && pi.SpeciesClassMajor is 0 ? $"Classifications: {GetClassificationDisplayNameMinor(pi.SpeciesClassMinor, speciesInternal)}" + : $"Classifications: {GetClassificationDisplayNameMajor(pi.SpeciesClassMajor)} / {GetClassificationDisplayNameMinor(pi.SpeciesClassMinor, speciesInternal)}"; + + lines.Add(classification); + } + + lines.Add($"Alpha Move: {Moves[pi.AlphaMove]}"); + if (!pi.FB.TechnicalMachine.Contains(pi.AlphaMove)) + lines.Add("ALPHA MOVE NOT IN TM LIST"); + if (Settings.Learn) + AddLearnsets(pi.FB, lines, specCode); + if (Settings.Evo) + AddEvolutions(pi.FB, lines); + if (Settings.Dex) + AddZukan(lines, ZukanA, speciesInternal, form); + + lines.Add(""); + } + + private void AddZukan(List lines, IReadOnlyList zukanA, ushort speciesInternal, byte form) + { + if (speciesInternal >= Species.Count) + return; + var hash = FnvHash.HashFnv1a_64($"ZKN_COMMENT_A_{speciesInternal:000}_{form:000}"); // no need to check for B, only one version + var line = ZukanAHTB.GetString(hash, zukanA); + lines.Add(line.Replace("\\n", " ")); + } + + private void AddLearnsets(PersonalInfo fb, List lines, string specCode) + { + var learn = fb.Learnset; + lines.Add("Level Up Moves:"); + foreach (var x in learn) + { + var move = x.Move; + var level = x.Level switch + { + -3 => "EVO", + -2 => "RELEARN", + _ => $"{x.Level:00}", + }; + lines.Add($"- [{level}] {Moves[move]} {{{x.LevelPlus}}}"); + MoveSpeciesLearn[move].Add(specCode); + } + + if (TMIndexes.Length != 0) + { + var tmMoveIDs = fb.TechnicalMachine; + if (tmMoveIDs.Count != 0) + { + lines.Add("TM Learn:"); + foreach (var move in tmMoveIDs.OrderBy(z => TMIndexes.IndexOf(z))) + { + var tmID = TMIndexes.IndexOf(move); + if (tmID < 0) + continue; + lines.Add($"- [TM{tmID+1:000}] {Moves[move]}"); + MoveSpeciesLearn[move].Add(specCode); + } + } + } + + { + var egg = fb.EggMoves; + if (egg.Count != 0) + { + lines.Add("Egg Moves:"); + foreach (var move in egg) + { + lines.Add($"- {Moves[move]}"); + MoveSpeciesLearn[move].Add(specCode); + } + } + } + { + var tmMoveIDs = fb.ReminderMoves; + if (tmMoveIDs.Count != 0) + { + lines.Add("Reminder:"); + foreach (var move in tmMoveIDs) + { + lines.Add($"- {Moves[move]}"); + MoveSpeciesLearn[move].Add(specCode); + } + } + } + } + + private void AddEvolutions(PersonalInfo fb, List lines) + { + var evo = fb.Evolutions; + if (evo.Count == 0) + return; + + foreach (var z in evo) + { + if (z.Reserved3 != 0 || z.Reserved4 != 0 || z.Reserved5 != 0) + throw new Exception("Reserved fields not 0"); + + var method = (EvolutionType)z.Method; + string arg = GetArgTypeDisplayValue(method, z.Argument); + var line = $"Evolves into {GetSpeciesName(z.SpeciesInternal)}-{z.Form} @ lv{z.Level} ({method}) [{arg}]"; + lines.Add(line); + } + } + + private string GetArgTypeDisplayValue(EvolutionType type, ushort value) + { + if (type.IsPlibUseItemType()) + { + var item = Plib9.PlibToItem[value]; + return Items[item]; + } + var argType = type.GetArgType(); + return GetArgTypeDisplayValue(argType, value); + } + + private string GetArgTypeDisplayValue(EvolutionTypeArgumentType argType, ushort value) => argType switch + { + EvolutionTypeArgumentType.Level => value.ToString(), + EvolutionTypeArgumentType.NoArg => value.ToString(), + EvolutionTypeArgumentType.Items => Items[value], + EvolutionTypeArgumentType.Moves => Moves[value], + EvolutionTypeArgumentType.Species => GetSpeciesName(value), + EvolutionTypeArgumentType.Type => Types[value], + EvolutionTypeArgumentType.Stat => value.ToString(), + EvolutionTypeArgumentType.Version => value.ToString(), + _ => throw new ArgumentOutOfRangeException(nameof(argType), argType, null), + }; + + private string GetClassificationDisplayNameMajor(byte classification) => classification switch + { + (byte)SpeciesClassificationMajor.Legend => "Legendary", + (byte)SpeciesClassificationMajor.SubLegend => "Sub-Legendary", + (byte)SpeciesClassificationMajor.Mythical => "Mythical", + _ => throw new ArgumentOutOfRangeException(nameof(classification), classification, null), + }; + + private string GetClassificationDisplayNameMinor(uint classification, ushort species) => classification switch + { + (ushort)SpeciesClassificationMinor.UltraBeast => "Ultra Beast", + (ushort)SpeciesClassificationMinor.ParadoxPast => "Paradox (Past)", + (ushort)SpeciesClassificationMinor.ParadoxFuture => "Paradox (Future)", + (ushort)SpeciesClassificationMinor.SpecialBattleForm when species is 0382 or 0383 => "Primal Reversion", + (ushort)SpeciesClassificationMinor.SpecialBattleForm => "Mega Evolution", + _ => throw new ArgumentOutOfRangeException(nameof(classification), classification, null), + }; + + private void AddPersonalLines(List lines, IPersonalInfo pi, int entry, string name, string specCode) + { + lines.Add("======"); + lines.Add($"{entry:000} - {name} (Stage: {pi.EvoStage})"); + lines.Add("======"); + if (pi is IPersonalMisc_SWSH { IsPresentInGame: false }) + lines.Add("Present: No"); + lines.Add($"Base Stats: {pi.HP}.{pi.ATK}.{pi.DEF}.{pi.SPA}.{pi.SPD}.{pi.SPE} (BST: {pi.GetBaseStatTotal()})"); + lines.Add($"EV Yield: {pi.EV_HP}.{pi.EV_ATK}.{pi.EV_DEF}.{pi.EV_SPA}.{pi.EV_SPD}.{pi.EV_SPE}"); + lines.Add($"Gender Ratio: {pi.Gender}"); + lines.Add($"Catch Rate: {pi.CatchRate}"); + + if (HasAbilities) + { + var abils = new int[pi.GetNumAbilities()]; + pi.GetAbilities(abils); + var msg = string.Join(" | ", abils.Select((z, j) => Abilities[z] + AbilitySuffix[j])); + lines.Add($"Abilities: {msg}"); + } + + lines.Add(string.Format(pi.Type1 != pi.Type2 + ? "Type: {0} / {1}" + : "Type: {0}", Types[(int)pi.Type1], Types[(int)pi.Type2])); + + lines.Add($"EXP Group: {ExpGroups[pi.EXPGrowth]}"); + lines.Add(string.Format(pi.EggGroup1 != pi.EggGroup2 + ? "Egg Group: {0} / {1}" + : "Egg Group: {0}", EggGroups[pi.EggGroup1], EggGroups[pi.EggGroup2])); + lines.Add($"Height: {(decimal)pi.Height / 100:00.00}m, Weight: {(decimal)pi.Weight / 10:000.0}kg, Color: {Colors[pi.Color]}"); + } +} + +public static class Plib9 +{ + public static bool IsPlibUseItemType(this EvolutionType method) => method switch + { + EvolutionType.UseItem => true, + EvolutionType.UseItemMale => true, + EvolutionType.UseItemFemale => true, + EvolutionType.LevelUpHeldItemDay => true, + EvolutionType.LevelUpHeldItemNight => true, + //EvolutionType.UseItemWormhole => true, + //EvolutionType.UseItemFullMoon => true, + _ => false, + }; + + // plib_item_conversion_array + // inverted {a,b} => {b,a} so we can get the item ID from plib evo arg. + + public static readonly Dictionary PlibToItem = new() + { + { 0001, 0080 }, // Sun Stone + { 0002, 0081 }, // Moon Stone + { 0003, 0082 }, // Fire Stone + { 0004, 0083 }, // Thunder Stone + { 0005, 0084 }, // Water Stone + { 0006, 0085 }, // Leaf Stone + { 0007, 0107 }, // Shiny Stone + { 0008, 0108 }, // Dusk Stone + { 0009, 0110 }, // Oval Stone + { 0010, 1779 }, // Griseous Core + { 0011, 0000 }, + { 0012, 0000 }, + { 0013, 0000 }, + { 0014, 0000 }, + { 0015, 0229 }, // Everstone + { 0016, 0236 }, // Light Ball + { 0017, 0000 }, + { 0018, 0000 }, + { 0019, 0280 }, // Destiny Knot + { 0020, 0289 }, // Power Bracer + { 0021, 0290 }, // Power Belt + { 0022, 0291 }, // Power Lens + { 0023, 0292 }, // Power Band + { 0024, 0293 }, // Power Anklet + { 0025, 0294 }, // Power Weight + { 0026, 0298 }, // Flame Plate + { 0027, 0299 }, // Splash Plate + { 0028, 0300 }, // Zap Plate + { 0029, 0301 }, // Meadow Plate + { 0030, 0302 }, // Icicle Plate + { 0031, 0303 }, // Fist Plate + { 0032, 0304 }, // Toxic Plate + { 0033, 0305 }, // Earth Plate + { 0034, 0306 }, // Sky Plate + { 0035, 0307 }, // Mind Plate + { 0036, 0308 }, // Insect Plate + { 0037, 0309 }, // Stone Plate + { 0038, 0310 }, // Spooky Plate + { 0039, 0311 }, // Draco Plate + { 0040, 0312 }, // Dread Plate + { 0041, 0313 }, // Iron Plate + { 0042, 0000 }, + { 0043, 0000 }, + { 0044, 0000 }, + { 0045, 0000 }, + { 0046, 0000 }, + { 0047, 0000 }, + { 0048, 0000 }, + { 0049, 0326 }, // Razor Claw + { 0050, 0327 }, // Razor Fang + { 0051, 0644 }, // Pixie Plate + { 0052, 0849 }, // Ice Stone + { 0053, 0000 }, + { 0054, 0000 }, + { 0055, 0000 }, + { 0056, 0000 }, + { 0057, 0000 }, + { 0058, 0000 }, + { 0059, 0000 }, + { 0060, 0000 }, + { 0061, 0000 }, + { 0062, 0000 }, + { 0063, 0000 }, + { 0064, 0000 }, + { 0065, 0000 }, + { 0066, 0000 }, + { 0067, 0000 }, + { 0068, 0000 }, + { 0069, 0000 }, + { 0070, 1103 }, // Rusted Sword + { 0071, 1104 }, // Rusted Shield + { 0072, 1109 }, // Strawberry Sweet + { 0073, 1110 }, // Love Sweet + { 0074, 1111 }, // Berry Sweet + { 0075, 1112 }, // Clover Sweet + { 0076, 1113 }, // Flower Sweet + { 0077, 1114 }, // Star Sweet + { 0078, 1115 }, // Ribbon Sweet + { 0079, 1116 }, // Sweet Apple + { 0080, 1117 }, // Tart Apple + { 0081, 1253 }, // Cracked Pot + { 0082, 1254 }, // Chipped Pot + { 0083, 1582 }, // Galarica Cuff + { 0084, 1592 }, // Galarica Wreath + { 0085, 2344 }, // Auspicious Armor + { 0086, 1861 }, // Malicious Armor + { 0087, 2345 }, // Leader’s Crest + { 0088, 1857 }, // Scroll of Darkness + { 0089, 1858 }, // Scroll of Waters + { 0090, 0000 }, + { 0091, 0000 }, + { 0092, 0218 }, // Soothe Bell + { 0093, 0109 }, // Dawn Stone + { 0094, 2403 }, // Unremarkable Teacup + { 0095, 2404 }, // Masterpiece Teacup + { 0096, 2402 }, // Syrupy Apple + { 0111, 0537 }, // Prism Scale + { 0112, 0325 }, // Reaper Cloth + { 0113, 0252 }, // Upgrade + { 0114, 0324 }, // Dubious Disc + { 0115, 0322 }, // Electirizer + { 0116, 0323 }, // Magmarizer + { 0117, 0321 }, // Protector + { 0118, 0235 }, // Dragon Scale + { 0119, 2482 }, // Metal Alloy + }; +} diff --git a/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoDex.cs b/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoDex.cs new file mode 100644 index 00000000..96fb17e0 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoDex.cs @@ -0,0 +1,3 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +public partial class PersonalInfoDex; diff --git a/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoEvolution.cs b/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoEvolution.cs new file mode 100644 index 00000000..bb1eb174 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoEvolution.cs @@ -0,0 +1,3 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +public partial class PersonalInfoEvolution; diff --git a/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoGender.cs b/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoGender.cs new file mode 100644 index 00000000..d0a74baf --- /dev/null +++ b/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoGender.cs @@ -0,0 +1,24 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +public partial class PersonalInfoGender +{ + public const int RatioMagicMale = 0; + public const int RatioMagicFemale = 254; + public const int RatioMagicGenderless = 255; + public byte RatioMagicEquivalent() => Group switch + { + 0 => Ratio switch + { + 12 => 0x1F, // 12.5% + 25 => 0x3F, // 25% + 50 => 0x7F, // 50% + 75 => 0xBF, // 75% + 89 => 0xE1, // 87.5% + _ => throw new ArgumentOutOfRangeException(nameof(Ratio)), + }, + SexGroup.MALE => RatioMagicMale, + SexGroup.FEMALE => RatioMagicFemale, + SexGroup.UNKNOWN => RatioMagicGenderless, + _ => throw new ArgumentOutOfRangeException(nameof(Group)), + }; +} diff --git a/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoStats.cs b/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoStats.cs new file mode 100644 index 00000000..41cfe709 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Personal/Types/PersonalInfoStats.cs @@ -0,0 +1,6 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +public partial class PersonalInfoStats +{ + public ushort U16() => (ushort)((HP & 0b11) | ((ATK & 0b11) << 2) | ((DEF & 0b11) << 4) | ((SPE & 0b11) << 6) | ((SPA & 0b11) << 8) | ((SPD & 0b11) << 10)); +} diff --git a/FlatBuffers/ZA/Personal/Personal/Wrapper/PersonalInfo9ZA.cs b/FlatBuffers/ZA/Personal/Personal/Wrapper/PersonalInfo9ZA.cs new file mode 100644 index 00000000..687eeb03 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Personal/Wrapper/PersonalInfo9ZA.cs @@ -0,0 +1,148 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +/// +/// Personal Info class with values from the games. +/// +public sealed class PersonalInfo9ZA(PersonalInfo fb) : IPersonalInfo +{ + public PersonalInfo FB { get; } = fb; + + public int HP { get => FB.Base.HP; set => FB.Base.HP = (byte)value; } + public int ATK { get => FB.Base.ATK; set => FB.Base.ATK = (byte)value; } + public int DEF { get => FB.Base.DEF; set => FB.Base.DEF = (byte)value; } + public int SPE { get => FB.Base.SPE; set => FB.Base.SPE = (byte)value; } + public int SPA { get => FB.Base.SPA; set => FB.Base.SPA = (byte)value; } + public int SPD { get => FB.Base.SPD; set => FB.Base.SPD = (byte)value; } + public Types Type1 { get => (Types)FB.Type1; set => FB.Type1 = (byte)value; } + public Types Type2 { get => (Types)FB.Type2; set => FB.Type2 = (byte)value; } + public int Ability1 { get => FB.Ability1; set => FB.Ability1 = (ushort)value; } + public int Ability2 { get => FB.Ability2; set => FB.Ability2 = (ushort)value; } + public int AbilityH { get => FB.AbilityH; set => FB.AbilityH = (ushort)value; } + public int CatchRate { get => FB.CatchRate; set => FB.CatchRate = (byte)value; } + public int EvoStage { get => FB.EvoStage; set => FB.EvoStage = (byte)value; } + public int EV_HP { get => FB.EVYield.HP; set => FB.EVYield.HP = (byte)value; } + public int EV_ATK { get => FB.EVYield.ATK; set => FB.EVYield.ATK = (byte)value; } + public int EV_DEF { get => FB.EVYield.DEF; set => FB.EVYield.DEF = (byte)value; } + public int EV_SPE { get => FB.EVYield.SPE; set => FB.EVYield.SPE = (byte)value; } + public int EV_SPA { get => FB.EVYield.SPA; set => FB.EVYield.SPA = (byte)value; } + public int EV_SPD { get => FB.EVYield.SPD; set => FB.EVYield.SPD = (byte)value; } + public byte GenderGroup { get => (byte)FB.Gender.Group; set => FB.Gender.Group = (SexGroup)value; } + public byte GenderRatio { get => FB.Gender.Ratio; set => FB.Gender.Ratio = value; } + public int Gender + { + get => FB.Gender.RatioMagicEquivalent(); + set { } + } + + public int BaseFriendship { get => FB.BaseFriendship; set => FB.BaseFriendship = (byte)value; } + public int EXPGrowth { get => FB.EXPGrowth; set => FB.EXPGrowth = (byte)value; } + public int EggGroup1 { get => FB.EggGroup1; set => FB.EggGroup1 = (byte)value; } + public int EggGroup2 { get => FB.EggGroup2; set => FB.EggGroup2 = (byte)value; } + public int Color { get => FB.Info.Color; set => FB.Info.Color = (byte)value; } + public bool IsPresentInGame { get => FB.IsPresentInGame; set => FB.IsPresentInGame = value; } + public int Height { get => FB.Info.Height; set => FB.Info.Height = (ushort)value; } + public int Weight { get => FB.Info.Weight; set => FB.Info.Weight = (ushort)value; } + public byte DebutVersion { get => FB.Info.DebutVersion; set => FB.Info.DebutVersion = value; } + public byte SpeciesClassMajor { get => FB.Info.SpeciesClassMajor; set => FB.Info.SpeciesClassMajor = value; } + public uint SpeciesClassMinor { get => FB.Info.SpeciesClassMinor; set => FB.Info.SpeciesClassMinor = value; } + + public ushort HatchedSpecies { get => SpeciesConverterZA.GetNational9(FB.Hatch.SpeciesInternal); set => FB.Hatch.SpeciesInternal = SpeciesConverterZA.GetInternal9(value); } + public ushort LocalFormIndex { get => FB.Hatch.Form; set => FB.Hatch.Form = value; } + public bool RegionalFlags { get => FB.Hatch.RegionalFlags == 1; set => FB.Hatch.RegionalFlags = value ? (ushort)1 : (ushort)0; } + public ushort EverstoneForm { get => FB.Hatch.EverstoneForm; set => FB.Hatch.EverstoneForm = value; } + + public ushort Form { get => FB.Info.Form; set => FB.Info.Form = value; } + + public ushort DexIndex + { + get => FB.Dex; + set => FB.Dex = value; + } + + public int Item1 { get => 0; set { } } + public int Item2 { get => 0; set { } } + public int Item3 { get => 0; set { } } + public int BaseEXP { get => 0; set { } } + public int EscapeRate { get => 0; set { } } + public int FormSprite { get => 0; set { } } + public int FormStatsIndex { get; set; } + public byte FormCount { get; set; } = 1; + + public int BST => FB.Base.HP + FB.Base.ATK + FB.Base.DEF + FB.Base.SPE + FB.Base.SPA + FB.Base.SPD; + public ushort AlphaMove { get; set; } + + public void Write(BinaryWriter bw) + { + bw.Write(FB.Base.HP); + bw.Write(FB.Base.ATK); + bw.Write(FB.Base.DEF); + bw.Write(FB.Base.SPE); + bw.Write(FB.Base.SPA); + bw.Write(FB.Base.SPD); + bw.Write(FB.Type1); + bw.Write(FB.Type2); + bw.Write(FB.CatchRate); + bw.Write(FB.EvoStage); + bw.Write(FB.EVYield.U16()); + bw.Write(FB.Gender.RatioMagicEquivalent()); + bw.Write(FB.HatchCycles); + bw.Write(FB.BaseFriendship); + bw.Write(FB.EXPGrowth); + bw.Write(FB.EggGroup1); + bw.Write(FB.EggGroup2); + bw.Write(FB.Ability1); + bw.Write(FB.Ability2); + bw.Write(FB.AbilityH); + bw.Write((ushort)FormStatsIndex); + bw.Write(FormCount); + bw.Write(FB.Info.Color); + bw.Write(FB.IsPresentInGame); + + bw.Write((byte)0); + bw.Write((ushort)DexIndex); + bw.Write(FB.Info.Height); + bw.Write(FB.Info.Weight); + bw.Write(SpeciesConverterZA.GetNational9(FB.Hatch.SpeciesInternal)); + bw.Write(FB.Hatch.Form); + bw.Write(FB.Hatch.RegionalFlags); + bw.Write(FB.Hatch.EverstoneForm); + // 0x2C + + // TMs + byte[] tmFlags = new byte[0x1E]; + if (IsPresentInGame) + { + foreach (ushort tm in FB.TechnicalMachine) + { + // Get the index within TMIndexes, then set the bitflag within tmFlags + var bitIndex = TMIndexes.IndexOf(tm); + if (bitIndex < 0) + continue; + tmFlags[bitIndex / 8] |= (byte)(1 << (bitIndex % 8)); + } + } + bw.Write(tmFlags); + bw.Write((ushort)0); // align 0x50 + bw.Write(GetEXP(BST, FB.EvoStage, FB.BaseEXPAddend)); + bw.Write(AlphaMove); // align + } + + private static ushort GetEXP(int bst, byte evoStage, short add) + => (ushort)(Math.Ceiling(bst * (1 + (3 * evoStage)) / 20d) + add); + + public static ReadOnlySpan TMIndexes => + [ + // Bit Index order + 029, 337, 473, 249, 046, 347, 092, 086, 812, 280, + 339, 157, 058, 424, 423, 113, 182, 612, 408, 583, + 422, 332, 009, 008, 242, 412, 129, 091, 007, 014, + 115, 104, 034, 400, 203, 317, 446, 126, 435, 331, + 352, 202, 019, 063, 282, 341, 097, 120, 196, 315, + 219, 414, 188, 434, 416, 038, 261, 442, 428, 248, + 421, 053, 094, 076, 444, 521, 085, 257, 089, 250, + 304, 083, 057, 247, 406, 710, 398, 523, 542, 334, + 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, + ]; +} diff --git a/FlatBuffers/ZA/Personal/Personal/Wrapper/PersonalTable9ZA.cs b/FlatBuffers/ZA/Personal/Personal/Wrapper/PersonalTable9ZA.cs new file mode 100644 index 00000000..ab49abf9 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Personal/Wrapper/PersonalTable9ZA.cs @@ -0,0 +1,123 @@ +using System.Collections; +using pkNX.Containers; +using FlatSharp; + +namespace pkNX.Structures.FlatBuffers.ZA; + +/// +/// Personal Table storing used in . +/// +public sealed class PersonalTable9ZA : IPersonalTable, IPersonalTable +{ + public PersonalInfo9ZA[] Table { get; } + private const ushort MaxSpecies = Legal.MaxSpeciesID_9a; + public int MaxSpeciesID => MaxSpecies; + + private readonly IFileContainer File; + public PersonalTable Root { get; } + + public PersonalTable9ZA(IFileContainer file) + { + File = file; + Root = PersonalTable.Serializer.Parse(file[0], FlatBufferDeserializationOption.GreedyMutable); + + var baseForms = new PersonalInfo9ZA[MaxSpecies + 1]; + var formTable = new List(); + + var formGrouped = Root.Table + .GroupBy(x => x.Info.SpeciesNational) + .OrderBy(x => x.Key).ToArray(); + + for (int i = 0; i <= MaxSpecies; i++) + { + var item = formGrouped[i]; + var forms = item.ToArray(); + + baseForms[i] = GetObj(forms[0], forms, MaxSpecies, formTable); + for (int f = 1; f < forms.Length; f++) + formTable.Add(GetObj(forms[f], forms, MaxSpecies, formTable, f)); + } + + Table = [.. baseForms, .. formTable]; + } + + private static PersonalInfo9ZA GetObj(PersonalInfo e, ICollection forms, ushort max, ICollection formTable, int f = 0) + { + return new PersonalInfo9ZA(e) + { + FormCount = (byte)forms.Count, + FormStatsIndex = (f != 0 ? 0 : forms.Count == 1 ? 0 : max + formTable.Count + 1), + }; + } + + public void Save() + { + var pool = System.Buffers.ArrayPool.Shared; + var serializer = PersonalTable.Serializer; + var size = serializer.GetMaxSize(Root); + var arr = pool.Rent(size); + var len = serializer.Write(arr, Root); + var data = arr.AsSpan(0, len).ToArray(); + pool.Return(arr); + File[0] = data; + } + + public PersonalInfo9ZA this[int index] => Table[(uint)index < Table.Length ? index : 0]; + public PersonalInfo9ZA this[ushort species, byte form] => Table[GetFormIndex(species, form)]; + public PersonalInfo9ZA GetFormEntry(ushort species, byte form) => Table[GetFormIndex(species, form)]; + + public int GetFormIndex(ushort species, byte form) + { + if ((uint)species <= MaxSpecies) + return Table[species].FormIndex(species, form); + return 0; + } + + public bool IsSpeciesInGame(ushort species) + { + if ((uint)species > MaxSpecies) + return false; + + var form0 = Table[species]; + if (form0.IsPresentInGame) + return true; + + var fc = form0.FormCount; + for (byte i = 1; i < fc; i++) + { + var entry = GetFormEntry(species, i); + if (entry.IsPresentInGame) + return true; + } + return false; + } + + public bool IsPresentInGame(ushort species, byte form) + { + if ((uint)species > MaxSpecies) + return false; + + var form0 = Table[species]; + if (form == 0) + return form0.IsPresentInGame; + if (!form0.HasForm(form)) + return false; + + var entry = GetFormEntry(species, form); + return entry.IsPresentInGame; + } + + IPersonalInfo[] IPersonalTable.Table => Table; + IPersonalInfo IPersonalTable.this[int index] => this[index]; + IPersonalInfo IPersonalTable.this[ushort species, byte form] => this[species, form]; + IPersonalInfo IPersonalTable.GetFormEntry(ushort species, byte form) => GetFormEntry(species, form); + + public byte[] Write() + { + using var ms = new MemoryStream(); + using var bw = new BinaryWriter(ms); + foreach (var entry in Table) + entry.Write(bw); + return ms.ToArray(); + } +} diff --git a/FlatBuffers/ZA/Personal/Schemas/PersonalInfoDetail.fbs b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoDetail.fbs new file mode 100644 index 00000000..0a2daf13 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoDetail.fbs @@ -0,0 +1,30 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_valueStruct"; + +enum SpeciesClassificationMajor : ubyte { + None = 0, + Legend = 1, + SubLegend = 2, + Mythical = 3, +} + +enum SpeciesClassificationMinor : uint { + None = 0, + UltraBeast = 1, + ParadoxPast = 2, + ParadoxFuture = 4, + SpecialBattleForm = 8, +} + +struct PersonalInfoDetail { // give me a class, not struct. + SpeciesInternal : ushort; + Form : ushort; + SpeciesNational : ushort; + Color : ubyte ; + BodyType : ubyte ; + Height : ushort; + Weight : ushort; + DebutVersion : ubyte ; + SpeciesClassMajor : ubyte ; + SpeciesClassMinor : uint ; +} diff --git a/FlatBuffers/ZA/Personal/Schemas/PersonalInfoEvolution.fbs b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoEvolution.fbs new file mode 100644 index 00000000..f0969322 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoEvolution.fbs @@ -0,0 +1,13 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_valueStruct"; + +struct PersonalInfoEvolution { // give me a class, not struct. + Level:ushort; + Method:ushort; + Argument:ushort; + Reserved3:ushort; + Reserved4:ushort; + Reserved5:ushort; + SpeciesInternal:ushort; + Form:ushort; +} diff --git a/FlatBuffers/ZA/Personal/Schemas/PersonalInfoGender.fbs b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoGender.fbs new file mode 100644 index 00000000..2368f1d6 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoGender.fbs @@ -0,0 +1,14 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_valueStruct"; + +enum SexGroup : ubyte { + BOTH = 0, + MALE = 1, + FEMALE = 2, + UNKNOWN = 3, +} + +struct PersonalInfoGender { // give me a class, not struct. + Group:SexGroup = BOTH; + Ratio:ubyte; // {rand(100) < value} => gender. +} diff --git a/FlatBuffers/ZA/Personal/Schemas/PersonalInfoHatch.fbs b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoHatch.fbs new file mode 100644 index 00000000..60bb71c4 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoHatch.fbs @@ -0,0 +1,9 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_valueStruct"; + +struct PersonalInfoHatch { // give me a class, not struct. + SpeciesInternal:ushort; + Form:ushort; + RegionalFlags:ushort; + EverstoneForm:ushort; +} diff --git a/FlatBuffers/ZA/Personal/Schemas/PersonalInfoMove.fbs b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoMove.fbs new file mode 100644 index 00000000..378c7e7b --- /dev/null +++ b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoMove.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_valueStruct"; + +struct PersonalInfoMove { // give me a class, not struct. + Move:ushort; + Level:byte; + LevelPlus:byte; +} diff --git a/FlatBuffers/ZA/Personal/Schemas/PersonalInfoStats.fbs b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoStats.fbs new file mode 100644 index 00000000..9d048492 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Schemas/PersonalInfoStats.fbs @@ -0,0 +1,11 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_valueStruct"; + +struct PersonalInfoStats { // give me a class, not struct. + HP :ubyte; + ATK:ubyte; + DEF:ubyte; + SPA:ubyte; + SPD:ubyte; + SPE:ubyte; +} diff --git a/FlatBuffers/ZA/Personal/Schemas/PersonalTable.fbs b/FlatBuffers/ZA/Personal/Schemas/PersonalTable.fbs new file mode 100644 index 00000000..48d43bb9 --- /dev/null +++ b/FlatBuffers/ZA/Personal/Schemas/PersonalTable.fbs @@ -0,0 +1,47 @@ +include "PersonalInfoDetail.fbs"; +include "PersonalInfoEvolution.fbs"; +include "PersonalInfoGender.fbs"; +include "PersonalInfoHatch.fbs"; +include "PersonalInfoMove.fbs"; +include "PersonalInfoStats.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +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 + Type1:ubyte; + Type2:ubyte; + Ability1:ushort; + Ability2:ushort; + AbilityH:ushort; + EXPGrowth:ubyte; + CatchRate:ubyte; + Gender:PersonalInfoGender (required); + EggGroup1:ubyte; + EggGroup2:ubyte; + Hatch:PersonalInfoHatch (required); + HatchCycles:ubyte; + BaseFriendship:ubyte; + BaseEXPAddend:short; + EvoStage:ubyte; + IsTypeChangeDisallowed:bool; // Silvally, Arceus (and Sylveon in 1.0.0, fixed) + EVYield:PersonalInfoStats (required); + Base:PersonalInfoStats (required); + Evolutions:[PersonalInfoEvolution] (required); + TechnicalMachine:[ushort] (required); + EggMoves:[ushort] (required); + ReminderMoves:[ushort] (required); + Learnset:[PersonalInfoMove] (required); +} + +table PersonalTable (fs_serializer) { + Table:[PersonalInfo] (required); +} + +root_type PersonalTable; diff --git a/FlatBuffers/ZA/Personal/pkNX.Structures.FlatBuffers.ZA.Personal.csproj b/FlatBuffers/ZA/Personal/pkNX.Structures.FlatBuffers.ZA.Personal.csproj new file mode 100644 index 00000000..35e3d842 --- /dev/null +++ b/FlatBuffers/ZA/Personal/pkNX.Structures.FlatBuffers.ZA.Personal.csproj @@ -0,0 +1,2 @@ + + diff --git a/FlatBuffers/ZA/Shared/Gen9/PokeData/ParamSet.cs b/FlatBuffers/ZA/Shared/Gen9/PokeData/ParamSet.cs new file mode 100644 index 00000000..638a70f3 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Gen9/PokeData/ParamSet.cs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +public partial class ParamSet +{ + public string SlashSeparated() => $"{HP}/{ATK}/{DEF}/{SPA}/{SPD}/{SPE}"; + + public int[] ToArray() => [HP, ATK, DEF, SPA, SPD, SPE]; +} diff --git a/FlatBuffers/ZA/Shared/Gen9/PokeData/PokeDataBattle.cs b/FlatBuffers/ZA/Shared/Gen9/PokeData/PokeDataBattle.cs new file mode 100644 index 00000000..666c6b73 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Gen9/PokeData/PokeDataBattle.cs @@ -0,0 +1,26 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +public partial class PokeDataBattle +{ + public void SerializePKHeX(BinaryWriter bw, sbyte captureLv) + { + // flag BallId if not none + if (BallId != BallID.BALL_NULL) + throw new ArgumentOutOfRangeException(nameof(BallId), BallId, $"No {nameof(BallId)} allowed!"); + + ushort species = SpeciesConverterZA.GetNational9((ushort)DevId); + byte form = species switch + { + //(ushort)Species.Vivillon or (ushort)Species.Spewpa or (ushort)Species.Scatterbug => 30, + (ushort)Species.Minior when FormId < 7 => (byte)(FormId + 7), + _ => (byte)FormId, + }; + + bw.Write(species); + bw.Write(form); + bw.Write((byte)Sex); + bw.Write((byte)Tokusei); + bw.Write((byte)RareType); + bw.Write((byte)captureLv); + } +} diff --git a/FlatBuffers/ZA/Shared/Gen9/SpeciesConverterZA.cs b/FlatBuffers/ZA/Shared/Gen9/SpeciesConverterZA.cs new file mode 100644 index 00000000..277760a8 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Gen9/SpeciesConverterZA.cs @@ -0,0 +1,88 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +/// +/// does not match National Dex ID. +/// +public static class SpeciesConverterZA +{ + public static T[] GetRearrangedAsNational(T[] specNames) + { + var result = new T[specNames.Length]; + for (ushort indexInternal = 0; indexInternal < specNames.Length; indexInternal++) + { + var indexNational = GetNational9(indexInternal); + if (indexNational >= specNames.Length) continue; + result[indexNational] = specNames[indexInternal]; + } + return result; + } + + /// + /// Converts a National Dex ID to Generation 9 internal species ID. + /// + /// National Dex ID + /// Generation 9 species ID. + public static ushort GetInternal9(ushort species) + { + var shift = species - FirstUnalignedNational9; + var table = Table9NationalToInternal; + if ((uint)shift >= table.Length) + return species; + return (ushort)(species + table[shift]); + } + + /// + /// Converts a Generation 9 internal species ID to National Dex ID. + /// + /// Generation 9 species ID. + /// National Dex ID. + public static ushort GetNational9(ushort raw) + { + var table = Table9InternalToNational; + var shift = raw - FirstUnalignedInternal9; + if ((uint)shift >= table.Length) + return raw; + return (ushort)(raw + table[shift]); + } + + private const int FirstUnalignedNational9 = 917; + private const int FirstUnalignedInternal9 = FirstUnalignedNational9; + + /// + /// Difference of National Dex IDs (index) and the associated Gen9 Species IDs (value) + /// + private static ReadOnlySpan Table9NationalToInternal => + [ + 001, 001, 001, + 001, 033, 033, 033, 021, 021, 044, 044, 007, 007, + 007, 029, 031, 031, 031, 068, 068, 068, 002, 002, + 017, 017, 030, 030, 024, 024, 028, 028, 058, 058, + 012, -13, -13, -31, -31, -29, -29, 043, 043, 043, + -31, -31, -03, -30, -30, -23, -23, -14, -24, -03, + -03, -47, -47, -12, -27, -27, -44, -46, -26, 031, + 029, -53, -65, 025, -06, -03, -07, -04, -04, -08, + -04, 001, -03, -03, -06, -04, -47, -47, -47, -23, + -23, -05, -07, -09, -07, -20, -13, -09, -09, -29, + -23, 001, 012, 012, 000, 000, 000, -06, 005, -06, + -03, -03, -02, -04, -03, -03, + ]; + + /// + /// Difference of Gen9 Species IDs (index) and the associated National Dex IDs (value) + /// + private static ReadOnlySpan Table9InternalToNational => + [ + 065, -01, -01, + -01, -01, 031, 031, 047, 047, 029, 029, 053, 031, + 031, 046, 044, 030, 030, -07, -07, -07, 013, 013, + -02, -02, 023, 023, 024, -21, -21, 027, 027, 047, + 047, 047, 026, 014, -33, -33, -33, -17, -17, 003, + -29, 012, -12, -31, -31, -31, 003, 003, -24, -24, + -44, -44, -30, -30, -28, -28, 023, 023, 006, 007, + 029, 008, 003, 004, 004, 020, 004, 023, 006, 003, + 003, 004, -01, 013, 009, 007, 005, 007, 009, 009, + -43, -43, -43, -68, -68, -68, -58, -58, -25, -29, + -31, 006, -01, 006, 000, 000, 000, 003, 003, 004, + 002, 003, 003, -05, -12, -12, + ]; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Entity/CollisionShape.fbs b/FlatBuffers/ZA/Shared/Schemas/Entity/CollisionShape.fbs new file mode 100644 index 00000000..5d6d9a9a --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Entity/CollisionShape.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum CollisionShape : int { + NONE = 0, + SPHERE = 1, + BOX = 2, + CAPSULE = 3, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Entity/ComparisonOperatorType.fbs b/FlatBuffers/ZA/Shared/Schemas/Entity/ComparisonOperatorType.fbs new file mode 100644 index 00000000..ba4ed7ca --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Entity/ComparisonOperatorType.fbs @@ -0,0 +1,10 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum ComparisonOperatorType : int { + EQUAL = 0, + NOT_EQUAL = 1, + GREATER_THAN = 2, + GREATER_THAN_EQUAL = 3, + LESS_THAN = 4, + LESS_THAN_EQUAL = 5, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Entity/ConditionSimpleAutoBattleHecklerAreaArray.fbs b/FlatBuffers/ZA/Shared/Schemas/Entity/ConditionSimpleAutoBattleHecklerAreaArray.fbs new file mode 100644 index 00000000..0156ffa5 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Entity/ConditionSimpleAutoBattleHecklerAreaArray.fbs @@ -0,0 +1,14 @@ +include "PokemonTriggerID.fbs"; +include "ComparisonOperatorType.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table ConditionSimpleAutoBattleHecklerAreaArray (fs_serializer) { + Table:[ConditionSimpleAutoBattleHecklerArea] (required); +} + +table ConditionSimpleAutoBattleHecklerArea { + TriggerID:PokemonTriggerID; + ComparisonOperatorType:ComparisonOperatorType; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Entity/OwnerInfo.fbs b/FlatBuffers/ZA/Shared/Schemas/Entity/OwnerInfo.fbs new file mode 100644 index 00000000..7bf5c7da --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Entity/OwnerInfo.fbs @@ -0,0 +1,12 @@ +include "../Shared/SexType.fbs"; +include "../Shared/LangType.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table OwnerInfo { + TrainerId:int; + Sex:SexType; + LangId:LangType; + Name:string (required); +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Entity/ParamSet.fbs b/FlatBuffers/ZA/Shared/Schemas/Entity/ParamSet.fbs new file mode 100644 index 00000000..2af04ff1 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Entity/ParamSet.fbs @@ -0,0 +1,11 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table ParamSet { + HP:int; + ATK:int; + DEF:int; + SPA:int; + SPD:int; + SPE:int; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Entity/PokeObjArray.fbs b/FlatBuffers/ZA/Shared/Schemas/Entity/PokeObjArray.fbs new file mode 100644 index 00000000..a2de4f0d --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Entity/PokeObjArray.fbs @@ -0,0 +1,61 @@ +include "../Shared/DevID.fbs"; +include "Math/Vec3f.fbs"; +include "CollisionShape.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table GrassCollision { + OffsetY:float; + Radius:float; +} + +table CGemParam { + Pos:Vec3f (required); + Rot:Vec3f (required); + Scale:Vec3f (required); +} + +table PokeParameter { + ReachDistance:float; + AcceleStartDistance:float; + DeceleStartDistance:float; + MoveAccele:float; + RotationSpeed:float; + MinWaterDepthThreshold:float; + MaxWaterDepthThreshold:float; + MinAltitudeThreshold:float; + MaxAltitudeThreshold:float; +} + +table NamedFlatBuffer { + FileName:string (required); +} + +table CharaCollision { + Shape:CollisionShape = NONE; + Pos:Vec3f (required); + Radius:float; +} + +table BodyCollision { + Shape:CollisionShape = NONE; + Pos:Vec3f (required); + Radius:float; +} + +table PokeObj { + DevId:DevID = DEV_NULL; + Body:BodyCollision; + Chara:CharaCollision; + Grass:GrassCollision; + FlatBuffer:NamedFlatBuffer; + GemParam:CGemParam; + Poke:PokeParameter; +} + +table PokeObjArray (fs_serializer) { + Table:[PokeObj] (required); +} + +root_type PokeObjArray; diff --git a/FlatBuffers/ZA/Shared/Schemas/Entity/PokemonTriggerID.fbs b/FlatBuffers/ZA/Shared/Schemas/Entity/PokemonTriggerID.fbs new file mode 100644 index 00000000..89e8baaf --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Entity/PokemonTriggerID.fbs @@ -0,0 +1,1005 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum PokemonTriggerID : int { + NONE = 0, + JUDGE_THROUGH = 1, + DUMMY_2 = 2, + DUMMY_3 = 3, + DUMMY_4 = 4, + DUMMY_5 = 5, + DUMMY_6 = 6, + DUMMY_7 = 7, + DUMMY_8 = 8, + DUMMY_9 = 9, + PATCH_0_EQUAL_EATING_EMOTION = 10, + PATCH_0_NOT_EATING_EMOTION = 11, + PATCH_0_EQUAL_RESTING_EMOTION = 12, + PATCH_0_NOT_RESTING_EMOTION = 13, + PATCH_0_EQUAL_SLEEPING_EMOTION = 14, + PATCH_0_NOT_SLEEPING_EMOTION = 15, + PATCH_0_EQUAL_EATING2_EMOTION = 16, + PATCH_0_NOT_EATING2_EMOTION = 17, + DUMMY_18 = 18, + DUMMY_19 = 19, + DUMMY_20 = 20, + DUMMY_21 = 21, + DUMMY_22 = 22, + DUMMY_23 = 23, + DUMMY_24 = 24, + DUMMY_25 = 25, + DUMMY_26 = 26, + DUMMY_27 = 27, + DUMMY_28 = 28, + DUMMY_29 = 29, + DUMMY_30 = 30, + DUMMY_31 = 31, + DUMMY_32 = 32, + DUMMY_33 = 33, + DUMMY_34 = 34, + DUMMY_35 = 35, + DUMMY_36 = 36, + DUMMY_37 = 37, + DUMMY_38 = 38, + DUMMY_39 = 39, + DUMMY_40 = 40, + DUMMY_41 = 41, + DUMMY_42 = 42, + DUMMY_43 = 43, + DUMMY_44 = 44, + DUMMY_45 = 45, + DUMMY_46 = 46, + DUMMY_47 = 47, + DUMMY_48 = 48, + DUMMY_49 = 49, + EQUAL_BOSS = 50, + NOT_BOSS = 51, + DUMMY_52 = 52, + EQUAL_SUBORDINATE = 53, + NOT_SUBORDINATE = 54, + DUMMY_55 = 55, + EQUAL_SUN = 56, + NOT_SUN = 57, + DUMMY_58 = 58, + EQUAL_MOON = 59, + NOT_MOON = 60, + DUMMY_61 = 61, + EQUAL_RARE = 62, + NOT_RARE = 63, + DUMMY_64 = 64, + EQUAL_OUTSIDE_TERRITORY = 65, + NOT_OUTSIDE_TERRITORY = 66, + DUMMY_67 = 67, + EQUAL_MOVE_THREE_POINT_3 = 68, + EQUAL_MOVE_THREE_POINT_2 = 69, + EQUAL_MOVE_THREE_POINT_1 = 70, + EQUAL_MOVE_THREE_POINT_0 = 71, + EQUAL_INSIDE_HOMERANGE = 72, + NOT_INSIDE_HOMERANGE = 73, + DUMMY_74 = 74, + EQUAL_MOVE_TERRITORY = 75, + NOT_MOVE_TERRITORY = 76, + DUMMY_77 = 77, + EQUAL_BATTLE_HECKLER_AREA = 78, + NOT_BATTLE_HECKLER_AREA = 79, + DUMMY_80 = 80, + EQUAL_SIMPLE_AUTO_BATTLE_HECKLER_AREA = 81, + NOT_SIMPLE_AUTO_BATTLE_HECKLER_AREA = 82, + DUMMY_83 = 83, + EQUAL_BATTLE_HECKLER_AREA_NEAR_RANGE = 84, + NOT_BATTLE_HECKLER_AREA_NEAR_RANGE = 85, + DUMMY_86 = 86, + DUMMY_87 = 87, + DUMMY_88 = 88, + DUMMY_89 = 89, + DUMMY_90 = 90, + DUMMY_91 = 91, + DUMMY_92 = 92, + DUMMY_93 = 93, + DUMMY_94 = 94, + DUMMY_95 = 95, + DUMMY_96 = 96, + DUMMY_97 = 97, + DUMMY_98 = 98, + DUMMY_99 = 99, + EQUAL_ACTIONPOINT_TREE_BRANCH = 100, + EQUAL_ACTIONPOINT_TREE_TRUNK = 101, + EQUAL_ACTIONPOINT_TREE_ROOT = 102, + EQUAL_ACTIONPOINT_CLIMBING_PATH_PACHIRISU = 103, + EQUAL_ACTIONPOINT_TREE_HANGING = 104, + EQUAL_ACTIONPOINT_ROOF = 105, + EQUAL_ACTIONPOINT_BUSHES = 106, + EQUAL_ACTIONPOINT_TORCH = 107, + EQUAL_ACTIONPOINT_TREE_BRANCH_LARGE = 108, + EQUAL_ACTIONPOINT_ROCK_CLIFF = 109, + EQUAL_ACTIONPOINT_TREE_CLIMBING_END_PACHIRISU = 110, + EQUAL_ACTIONPOINT_TREE_CLIMBING_END_AYEAYE2 = 111, + EQUAL_ACTIONPOINT_CLIMBING_PATH_AYEAYE2 = 112, + EQUAL_ACTIONPOINT_HANGING_APPLIN = 113, + EQUAL_ACTIONPOINT_TREE_CLIMBING_START_PACHIRISU = 114, + EQUAL_ACTIONPOINT_TREE_CLIMBING_START_AYEAYE2 = 115, + DUMMY_116 = 116, + DUMMY_117 = 117, + DUMMY_118 = 118, + DUMMY_119 = 119, + EQUAL_ATTRIBUTE_GRASSATTR = 120, + EQUAL_ATTRIBUTE_WATERATTR = 121, + EQUAL_ATTRIBUTE_LAND = 122, + EQUAL_ATTRIBUTE_UNDERWATER = 123, + EQUAL_ATTRIBUTE_SUNNY = 124, + EQUAL_ATTRIBUTE_SHADE = 125, + EQUAL_ATTRIBUTE_WATERSIDE = 126, + EQUAL_ATTRIBUTE_WATERSURFACE = 127, + EQUAL_ATTRIBUTE_SANDYBEACH = 128, + EQUAL_ATTRIBUTE_TREE = 129, + EQUAL_ATTRIBUTE_UNDERTREE = 130, + EQUAL_ATTRIBUTE_FLOWER = 131, + EQUAL_ATTRIBUTE_INLAND = 132, + EQUAL_ATTRIBUTE_FRESHWATERSIDE = 133, + EQUAL_ATTRIBUTE_SOIL = 134, + EQUAL_ATTRIBUTE_LANDSIDE = 135, + EQUAL_ATTRIBUTE_GRASSLAND = 136, + EQUAL_ATTRIBUTE_FRESHWATER = 137, + EQUAL_ATTRIBUTE_PERFECTLYSHADEAREA = 138, + EQUAL_ATTRIBUTE_ALMOSTSHADEAREA = 139, + EQUAL_ATTRIBUTE_WATERINGPLACE = 140, + EQUAL_ATTRIBUTE_GREENGRASS = 141, + EQUAL_ATTRIBUTE_DEADLEAF = 142, + EQUAL_ATTRIBUTE_SNOW = 143, + EQUAL_ATTRIBUTE_DESERT = 144, + EQUAL_ATTRIBUTE_SAND = 145, + EQUAL_ATTRIBUTE_MUD = 146, + EQUAL_ATTRIBUTE_BOTTOM = 147, + EQUAL_ATTRIBUTE_FORD = 148, + EQUAL_ATTRIBUTE_DIG = 149, + EQUAL_ATTRIBUTE_SNOW2 = 150, + EQUAL_ATTRIBUTE_AIR = 151, + DUMMY_152 = 152, + DUMMY_153 = 153, + DUMMY_154 = 154, + DUMMY_155 = 155, + DUMMY_156 = 156, + DUMMY_157 = 157, + DUMMY_158 = 158, + DUMMY_159 = 159, + EQUAL_STATE_ON_THE_GROUND = 160, + EQUAL_STATE_IN_THE_WATER = 161, + EQUAL_STATE_IN_THE_AIR = 162, + EQUAL_STATE_ON_THE_TREE = 163, + NOT_STATE_GROUND = 164, + NOT_STATE_IN_THE_WATER = 165, + NOT_STATE_IN_THE_AIR = 166, + NOT_STATE_ON_THE_TREE = 167, + DUMMY_168 = 168, + DUMMY_169 = 169, + EQUAL_STATE_KEGANI_NUSHI = 170, + NOT_STATE_KEGANI_NUSHI = 171, + EQUAL_STATE_MIMIZU_NUSHI = 172, + NOT_STATE_MIMIZU_NUSHI = 173, + EQUAL_STATE_BOOL2_NUSHI = 174, + NOT_STATE_BOOL2_NUSHI = 175, + EQUAL_STATE_MIMIZU_NUSHI_GROUND_WAIT = 176, + NOT_STATE_MIMIZU_NUSHI_GROUND_WAIT = 177, + EQUAL_STATE_MIMIZU_NUSHI_GROUND_FACE_WAIT = 178, + NOT_STATE_MIMIZU_NUSHI_GROUND_FACE_WAIT = 179, + EQUAL_TIMEZONE_MORNING = 180, + EQUAL_TIMEZONE_NOON = 181, + EQUAL_TIMEZONE_EVENING = 182, + EQUAL_TIMEZONE_NIGHT = 183, + EQUAL_TIMEZONE_MID_NIGHT = 184, + EQUAL_TIMEZONE_MORNING_NOON = 185, + EQUAL_TIMEZONE_MORNING_EVENING = 186, + EQUAL_TIMEZONE_NIGHT_MID_NIGHT = 187, + NOT_TIMEZONE_MORNING = 188, + NOT_TIMEZONE_NOON = 189, + NOT_TIMEZONE_EVENING = 190, + NOT_TIMEZONE_NIGHT = 191, + NOT_TIMEZONE_MID_NIGHT = 192, + NOT_TIMEZONE_MORNING_NOON = 193, + NOT_TIMEZONE_MORNING_EVENING = 194, + NOT_TIMEZONE_NIGHT_MID_NIGHT = 195, + DUMMY_196 = 196, + DUMMY_197 = 197, + DUMMY_198 = 198, + DUMMY_199 = 199, + EQUAL_WEATHER_SUNNY = 200, + EQUAL_WEATHER_CLOUDY = 201, + EQUAL_WEATHER_RAIN = 202, + EQUAL_WEATHER_STORM = 203, + EQUAL_WEATHER_SNOW = 204, + EQUAL_WEATHER_SNOW_STORM = 205, + EQUAL_WEATHER_DIAMOND_DUST = 206, + EQUAL_WEATHER_SAND_STORM = 207, + EQUAL_WEATHER_MIST = 208, + EQUAL_WEATHER_RAIN_STORM = 209, + EQUAL_WEATHER_SNOW_SNOW_STORM = 210, + EQUAL_WEATHER_STORM_SNOW_STORM_SAND_STORM = 211, + NOT_WEATHER_SUNNY = 212, + NOT_WEATHER_CLOUDY = 213, + NOT_WEATHER_RAIN = 214, + NOT_WEATHER_STORM = 215, + NOT_WEATHER_SNOW = 216, + NOT_WEATHER_SNOW_STORM = 217, + NOT_WEATHER_DIAMOND_DUST = 218, + NOT_WEATHER_SAND_STORM = 219, + NOT_WEATHER_MIST = 220, + NOT_WEATHER_RAIN_STORM = 221, + NOT_WEATHER_SNOW_SNOW_STORM = 222, + NOT_WEATHER_STORM_SNOW_STORM_SAND_STORM = 223, + DUMMY_224 = 224, + DUMMY_225 = 225, + DUMMY_226 = 226, + DUMMY_227 = 227, + DUMMY_228 = 228, + DUMMY_229 = 229, + EQUAL_TARGET_PLAYER = 230, + EQUAL_TARGET_POKEMON = 231, + NOT_TARGET_PLAYER = 232, + NOT_TARGET_POKEMON = 233, + DUMMY_234 = 234, + DUMMY_235 = 235, + DUMMY_236 = 236, + DUMMY_237 = 237, + DUMMY_238 = 238, + DUMMY_239 = 239, + EQUAL_HUNGER_0 = 240, + EQUAL_HUNGER_100 = 241, + EQUAL_FATIGUE_0 = 242, + EQUAL_FATIGUE_100 = 243, + EQUAL_SLEEPINESS_0 = 244, + EQUAL_SLEEPINESS_100 = 245, + NOT_HUNGER_0 = 246, + NOT_HUNGER_100 = 247, + NOT_FATIGUE_0 = 248, + NOT_FATIGUE_100 = 249, + NOT_SLEEPINESS_0 = 250, + NOT_SLEEPINESS_100 = 251, + DUMMY_252 = 252, + DUMMY_253 = 253, + DUMMY_254 = 254, + DUMMY_255 = 255, + DUMMY_256 = 256, + DUMMY_257 = 257, + DUMMY_258 = 258, + DUMMY_259 = 259, + DUMMY_260 = 260, + DUMMY_261 = 261, + DUMMY_262 = 262, + DUMMY_263 = 263, + DUMMY_264 = 264, + DUMMY_265 = 265, + DUMMY_266 = 266, + DUMMY_267 = 267, + DUMMY_268 = 268, + DUMMY_269 = 269, + EQUAL_STAMINA_0 = 270, + EQUAL_STAMINA_100 = 271, + NOT_STAMINA_0 = 272, + NOT_STAMINA_100 = 273, + DUMMY_274 = 274, + DUMMY_275 = 275, + DUMMY_276 = 276, + DUMMY_277 = 277, + DUMMY_278 = 278, + DUMMY_279 = 279, + EQUAL_TIMER_SHORT = 280, + EQUAL_TIMER_MEDIUM = 281, + EQUAL_TIMER_LONG = 282, + GREATER_THAN_EQUAL_TIMER_SHORT = 283, + GREATER_THAN_EQUAL_TIMER_MEDIUM = 284, + GREATER_THAN_EQUAL_TIMER_LONG = 285, + GREATER_TIMER_SHORT = 286, + GREATER_TIMER_MEDIUM = 287, + GREATER_TIMER_LONG = 288, + LESS_THAN_EQUAL_TIMER_SHORT = 289, + LESS_THAN_EQUAL_TIMER_MEDIUM = 290, + LESS_THAN_EQUAL_TIMER_LONG = 291, + LESS_TIMER_SHORT = 292, + LESS_TIMER_MEDIUM = 293, + LESS_TIMER_LONG = 294, + DUMMY_295 = 295, + DUMMY_296 = 296, + DUMMY_297 = 297, + DUMMY_298 = 298, + DUMMY_299 = 299, + DUMMY_300 = 300, + DUMMY_301 = 301, + DUMMY_302 = 302, + DUMMY_303 = 303, + GREATER_THAN_TIMER_20f = 304, + GREATER_THAN_TIMER_38f = 305, + GREATER_THAN_TIMER_50f = 306, + GREATER_THAN_TIMER_56f = 307, + GREATER_THAN_TIMER_80f = 308, + GREATER_THAN_TIMER_100f = 309, + GREATER_TIMER_100 = 310, + GREATER_TIMER_10 = 311, + GREATER_TIMER_20 = 312, + GREATER_TIMER_30 = 313, + LESS_TIMER_100 = 314, + LESS_TIMER_10 = 315, + LESS_TIMER_20 = 316, + LESS_TIMER_30 = 317, + GREATER_THAN_TIMER_5 = 318, + GREATER_THAN_TIMER_10 = 319, + EQUAL_PREBIOUS_ACTION_ID205 = 320, + EQUAL_PREBIOUS_ACTION_ID3272 = 321, + EQUAL_PREBIOUS_ACTION_ID3273 = 322, + EQUAL_PREBIOUS_ACTION_ID3281 = 323, + EQUAL_PREBIOUS_ACTION_ID3282 = 324, + EQUAL_PREBIOUS_ACTION_ID1933 = 325, + EQUAL_PREBIOUS_ACTION_ID2441 = 326, + EQUAL_PREBIOUS_ACTION_ID1965 = 327, + EQUAL_PREBIOUS_ACTION_ID1967 = 328, + EQUAL_PREBIOUS_ACTION_ID3287 = 329, + EQUAL_PREBIOUS_ACTION_ID3288 = 330, + EQUAL_PREBIOUS_ACTION_ID204 = 331, + EQUAL_PREBIOUS_ACTION_ID2752 = 332, + EQUAL_PREBIOUS_ACTION_ID206 = 333, + EQUAL_PREBIOUS_ACTION_ID910 = 334, + EQUAL_PREBIOUS_ACTION_ID911 = 335, + EQUAL_PREBIOUS_ACTION_ID2364 = 336, + EQUAL_PREBIOUS_ACTION_ID2370 = 337, + EQUAL_PREBIOUS_ACTION_ID3271 = 338, + DUMMY_339 = 339, + DUMMY_340 = 340, + DUMMY_341 = 341, + DUMMY_342 = 342, + DUMMY_343 = 343, + DUMMY_344 = 344, + DUMMY_345 = 345, + DUMMY_346 = 346, + DUMMY_347 = 347, + DUMMY_348 = 348, + DUMMY_349 = 349, + EQUAL_LOOP_0 = 350, + EQUAL_LOOP_1 = 351, + EQUAL_LOOP_2 = 352, + EQUAL_LOOP_3 = 353, + DUMMY_354 = 354, + DUMMY_355 = 355, + DUMMY_356 = 356, + DUMMY_357 = 357, + DUMMY_358 = 358, + DUMMY_359 = 359, + DUMMY_360 = 360, + DUMMY_361 = 361, + DUMMY_362 = 362, + DUMMY_363 = 363, + DUMMY_364 = 364, + DUMMY_365 = 365, + DUMMY_366 = 366, + DUMMY_367 = 367, + DUMMY_368 = 368, + DUMMY_369 = 369, + EQUAL_DISTANCE_NEAREST = 370, + EQUAL_DISTANCE_NEARRANGE = 371, + EQUAL_DISTANCE_MIDDLERANGE = 372, + EQUAL_DISTANCE_FARRANGE = 373, + EQUAL_DISTANCE_GENERALRANGE = 374, + EQUAL_DISTANCE_PERCEPT = 375, + GREATER_THAN_EQUAL_DISTANCE_NEAREST = 376, + GREATER_THAN_EQUAL_DISTANCE_NEARRANGE = 377, + GREATER_THAN_EQUAL_DISTANCE_MIDDLERANGE = 378, + GREATER_THAN_EQUAL_DISTANCE_FARRANGE = 379, + GREATER_THAN_EQUAL_DISTANCE_GENERALRANGE = 380, + GREATER_THAN_EQUAL_DISTANCE_PERCEPT = 381, + GREATER_DISTANCE_NEAREST = 382, + GREATER_DISTANCE_NEARRANGE = 383, + GREATER_DISTANCE_MIDDLERANGE = 384, + GREATER_DISTANCE_FARRANGE = 385, + GREATER_DISTANCE_GENERALRANGE = 386, + GREATER_DISTANCE_PERCEPT = 387, + LESS_THAN_EQUAL_DISTANCE_NEAREST = 388, + LESS_THAN_EQUAL_DISTANCE_NEARRANGE = 389, + LESS_THAN_EQUAL_DISTANCE_MIDDLERANGE = 390, + LESS_THAN_EQUAL_DISTANCE_FARRANGE = 391, + LESS_THAN_EQUAL_DISTANCE_GENERALRANGE = 392, + LESS_THAN_EQUAL_DISTANCE_PERCEPT = 393, + LESS_DISTANCE_NEAREST = 394, + LESS_DISTANCE_NEARRANGE = 395, + LESS_DISTANCE_MIDDLERANGE = 396, + LESS_DISTANCE_FARRANGE = 397, + LESS_DISTANCE_GENERALRANGE = 398, + LESS_DISTANCE_PERCEPT = 399, + DUMMY_400 = 400, + DUMMY_401 = 401, + DUMMY_402 = 402, + DUMMY_403 = 403, + DUMMY_404 = 404, + DUMMY_405 = 405, + DUMMY_406 = 406, + DUMMY_407 = 407, + DUMMY_408 = 408, + DUMMY_409 = 409, + EQUAL_DISTANCE_5 = 410, + GREATER_DISTANCE_5 = 411, + DUMMY_412 = 412, + DUMMY_413 = 413, + DUMMY_414 = 414, + DUMMY_415 = 415, + DUMMY_416 = 416, + DUMMY_417 = 417, + DUMMY_418 = 418, + DUMMY_419 = 419, + CONDITION_PLAYER_STATE_STAND_BY = 420, + PATCH_0_CONDITION_PLAYER_SQUAT = 421, + DUMMY_422 = 422, + DUMMY_423 = 423, + DUMMY_424 = 424, + DUMMY_425 = 425, + DUMMY_426 = 426, + DUMMY_427 = 427, + DUMMY_428 = 428, + DUMMY_429 = 429, + CONDITION_PLAYER_STATE_STAND_BY_5sec = 430, + CONDITION_PLAYER_STATE_STAND_BY_GREATER_THAN_EQUAL_5sec = 431, + CONDITION_PLAYER_STATE_STAND_BY_10sec = 432, + CONDITION_PLAYER_STATE_STAND_BY_GREATER_THAN_EQUAL_10sec = 433, + DUMMY_434 = 434, + DUMMY_435 = 435, + DUMMY_436 = 436, + DUMMY_437 = 437, + DUMMY_438 = 438, + DUMMY_439 = 439, + DUMMY_440 = 440, + DUMMY_441 = 441, + DUMMY_442 = 442, + DUMMY_443 = 443, + DUMMY_444 = 444, + DUMMY_445 = 445, + DUMMY_446 = 446, + DUMMY_447 = 447, + DUMMY_448 = 448, + DUMMY_449 = 449, + DUMMY_450 = 450, + DUMMY_451 = 451, + DUMMY_452 = 452, + DUMMY_453 = 453, + DUMMY_454 = 454, + DUMMY_455 = 455, + DUMMY_456 = 456, + DUMMY_457 = 457, + DUMMY_458 = 458, + DUMMY_459 = 459, + DUMMY_460 = 460, + DUMMY_461 = 461, + DUMMY_462 = 462, + DUMMY_463 = 463, + DUMMY_464 = 464, + DUMMY_465 = 465, + DUMMY_466 = 466, + DUMMY_467 = 467, + DUMMY_468 = 468, + DUMMY_469 = 469, + DUMMY_470 = 470, + DUMMY_471 = 471, + DUMMY_472 = 472, + DUMMY_473 = 473, + DUMMY_474 = 474, + DUMMY_475 = 475, + DUMMY_476 = 476, + DUMMY_477 = 477, + DUMMY_478 = 478, + DUMMY_479 = 479, + DUMMY_480 = 480, + DUMMY_481 = 481, + DUMMY_482 = 482, + DUMMY_483 = 483, + DUMMY_484 = 484, + DUMMY_485 = 485, + DUMMY_486 = 486, + DUMMY_487 = 487, + DUMMY_488 = 488, + DUMMY_489 = 489, + DUMMY_490 = 490, + DUMMY_491 = 491, + DUMMY_492 = 492, + DUMMY_493 = 493, + DUMMY_494 = 494, + DUMMY_495 = 495, + DUMMY_496 = 496, + DUMMY_497 = 497, + DUMMY_498 = 498, + DUMMY_499 = 499, + FOUND_ACTIONPOINT_TREE_BRANCH = 500, + FOUND_ACTIONPOINT_TREE_TRUNK = 501, + FOUND_ACTIONPOINT_TREE_ROOT = 502, + FOUND_ACTIONPOINT_CLIMBING_PATH_PACHIRISU = 503, + FOUND_ACTIONPOINT_TREE_HANGING = 504, + FOUND_ACTIONPOINT_ROOF = 505, + FOUND_ACTIONPOINT_BUSHES = 506, + FOUND_ACTIONPOINT_TORCH = 507, + FOUND_ACTIONPOINT_TREE_BRANCH_LARGE = 508, + FOUND_ACTIONPOINT_ROCK_CLIFF = 509, + FOUND_ACTIONPOINT_TREE_CLIMBING_END_PACHIRISU = 510, + FOUND_ACTIONPOINT_TREE_CLIMBING_END_AYEAYE2 = 511, + FOUND_ACTIONPOINT_CLIMBING_PATH_AYEAYE2 = 512, + FOUND_ACTIONPOINT_HANGING_APPLIN = 513, + FOUND_ACTIONPOINT_CLIMBING_PATH_START_PACHIRISU = 514, + FOUND_ACTIONPOINT_CLIMBING_PATH_START_AYEAYE2 = 515, + DUMMY_516 = 516, + DUMMY_517 = 517, + DUMMY_518 = 518, + DUMMY_519 = 519, + FOUND_ATTRIBUTE_GRASSATTR = 520, + FOUND_ATTRIBUTE_WATERATTR = 521, + FOUND_ATTRIBUTE_LAND = 522, + FOUND_ATTRIBUTE_UNDERWATER = 523, + FOUND_ATTRIBUTE_SUNNY = 524, + FOUND_ATTRIBUTE_SHADE = 525, + FOUND_ATTRIBUTE_WATERSIDE = 526, + FOUND_ATTRIBUTE_WATERSURFACE = 527, + FOUND_ATTRIBUTE_SANDYBEACH = 528, + FOUND_ATTRIBUTE_TREE = 529, + FOUND_ATTRIBUTE_UNDERTREE = 530, + FOUND_ATTRIBUTE_FLOWER = 531, + FOUND_ATTRIBUTE_INLAND = 532, + FOUND_ATTRIBUTE_FRESHWATERSIDE = 533, + FOUND_ATTRIBUTE_SOIL = 534, + FOUND_ATTRIBUTE_LANDSIDE = 535, + FOUND_ATTRIBUTE_GRASSLAND = 536, + FOUND_ATTRIBUTE_FRESHWATER = 537, + FOUND_ATTRIBUTE_PERFECTLYSHADEAREA = 538, + FOUND_ATTRIBUTE_ALMOSTSHADEAREA = 539, + FOUND_ATTRIBUTE_WATERINGPLACE = 540, + FOUND_ATTRIBUTE_GREENGRASS = 541, + FOUND_ATTRIBUTE_DEADLEAF = 542, + FOUND_ATTRIBUTE_SNOW = 543, + FOUND_ATTRIBUTE_DESERT = 544, + FOUND_ATTRIBUTE_SAND = 545, + FOUND_ATTRIBUTE_MUD = 546, + FOUND_ATTRIBUTE_BOTTOM = 547, + FOUND_ATTRIBUTE_FORD = 548, + FOUND_ATTRIBUTE_DIG = 549, + FOUND_ATTRIBUTE_SNOW2 = 550, + FOUND_ATTRIBUTE_AIR = 551, + FOUND_ATTRIBUTE_WATER_DEPTH_05 = 552, + FOUND_ATTRIBUTE_WATER_DEPTH_10 = 553, + FOUND_ATTRIBUTE_WATER_DEPTH_15 = 554, + FOUND_ATTRIBUTE_WATER_DEPTH_20 = 555, + FOUND_ATTRIBUTE_WATER_DEPTH_25 = 556, + DUMMY_557 = 557, + DUMMY_558 = 558, + DUMMY_559 = 559, + FOUND_POINT_NEAREST_BOTTOM_SWIM = 560, + FOUND_POINT_NEAREST_OFFSET_SWIM = 561, + FOUND_POINT_KEEP_BOTTOM_SWIM = 562, + FOUND_POINT_NEAREST_LAND_INLAND = 563, + FOUND_POINT_NEAREST_OFFSET_LEVITATION = 564, + FOUND_POINT_NEAREST_OFFSET_OFFING = 565, + FOUND_POINT_NEAREST_OFFSET_WATER_DEPTH_05 = 566, + FOUND_POINT_NEAREST_OFFSET_WATER_DEPTH_10 = 567, + FOUND_POINT_NEAREST_OFFSET_WATER_DEPTH_15 = 568, + FOUND_POINT_NEAREST_OFFSET_WATER_DEPTH_20 = 569, + FOUND_POINT_NEAREST_OFFSET_WATER_DEPTH_25 = 570, + FOUND_POINT_NEAREST_MIDDLE_ALTITUDE_WATER_SURFACE = 571, + FOUND_GPDISTANSE_LAND_LAND = 572, + FOUND_POINT_FAR_RANGE_MIDDLE_ALTITUDE_WATER_SURFACE = 573, + DUMMY_574 = 574, + DUMMY_575 = 575, + DUMMY_576 = 576, + DUMMY_577 = 577, + DUMMY_578 = 578, + DUMMY_579 = 579, + DUMMY_580 = 580, + DUMMY_581 = 581, + DUMMY_582 = 582, + DUMMY_583 = 583, + DUMMY_584 = 584, + DUMMY_585 = 585, + DUMMY_586 = 586, + DUMMY_587 = 587, + DUMMY_588 = 588, + DUMMY_589 = 589, + DUMMY_590 = 590, + DUMMY_591 = 591, + DUMMY_592 = 592, + DUMMY_593 = 593, + DUMMY_594 = 594, + DUMMY_595 = 595, + DUMMY_596 = 596, + DUMMY_597 = 597, + DUMMY_598 = 598, + DUMMY_599 = 599, + DUMMY_600 = 600, + DUMMY_601 = 601, + DUMMY_602 = 602, + DUMMY_603 = 603, + DUMMY_604 = 604, + DUMMY_605 = 605, + DUMMY_606 = 606, + DUMMY_607 = 607, + DUMMY_608 = 608, + DUMMY_609 = 609, + DUMMY_610 = 610, + DUMMY_611 = 611, + DUMMY_612 = 612, + DUMMY_613 = 613, + DUMMY_614 = 614, + DUMMY_615 = 615, + DUMMY_616 = 616, + DUMMY_617 = 617, + DUMMY_618 = 618, + DUMMY_619 = 619, + DUMMY_620 = 620, + DUMMY_621 = 621, + DUMMY_622 = 622, + DUMMY_623 = 623, + DUMMY_624 = 624, + DUMMY_625 = 625, + DUMMY_626 = 626, + DUMMY_627 = 627, + DUMMY_628 = 628, + DUMMY_629 = 629, + DUMMY_630 = 630, + DUMMY_631 = 631, + DUMMY_632 = 632, + DUMMY_633 = 633, + DUMMY_634 = 634, + DUMMY_635 = 635, + DUMMY_636 = 636, + DUMMY_637 = 637, + DUMMY_638 = 638, + DUMMY_639 = 639, + DUMMY_640 = 640, + DUMMY_641 = 641, + DUMMY_642 = 642, + DUMMY_643 = 643, + DUMMY_644 = 644, + DUMMY_645 = 645, + DUMMY_646 = 646, + DUMMY_647 = 647, + DUMMY_648 = 648, + DUMMY_649 = 649, + DUMMY_650 = 650, + DUMMY_651 = 651, + DUMMY_652 = 652, + DUMMY_653 = 653, + DUMMY_654 = 654, + DUMMY_655 = 655, + DUMMY_656 = 656, + DUMMY_657 = 657, + DUMMY_658 = 658, + DUMMY_659 = 659, + DUMMY_660 = 660, + DUMMY_661 = 661, + DUMMY_662 = 662, + DUMMY_663 = 663, + DUMMY_664 = 664, + DUMMY_665 = 665, + DUMMY_666 = 666, + DUMMY_667 = 667, + DUMMY_668 = 668, + DUMMY_669 = 669, + DUMMY_670 = 670, + DUMMY_671 = 671, + DUMMY_672 = 672, + DUMMY_673 = 673, + DUMMY_674 = 674, + DUMMY_675 = 675, + DUMMY_676 = 676, + DUMMY_677 = 677, + DUMMY_678 = 678, + DUMMY_679 = 679, + DUMMY_680 = 680, + DUMMY_681 = 681, + DUMMY_682 = 682, + DUMMY_683 = 683, + DUMMY_684 = 684, + DUMMY_685 = 685, + DUMMY_686 = 686, + DUMMY_687 = 687, + DUMMY_688 = 688, + DUMMY_689 = 689, + DUMMY_690 = 690, + DUMMY_691 = 691, + DUMMY_692 = 692, + DUMMY_693 = 693, + DUMMY_694 = 694, + DUMMY_695 = 695, + DUMMY_696 = 696, + DUMMY_697 = 697, + DUMMY_698 = 698, + DUMMY_699 = 699, + DUMMY_700 = 700, + DUMMY_701 = 701, + DUMMY_702 = 702, + DUMMY_703 = 703, + DUMMY_704 = 704, + DUMMY_705 = 705, + DUMMY_706 = 706, + DUMMY_707 = 707, + DUMMY_708 = 708, + DUMMY_709 = 709, + DUMMY_710 = 710, + DUMMY_711 = 711, + DUMMY_712 = 712, + DUMMY_713 = 713, + DUMMY_714 = 714, + DUMMY_715 = 715, + DUMMY_716 = 716, + DUMMY_717 = 717, + DUMMY_718 = 718, + DUMMY_719 = 719, + DUMMY_720 = 720, + DUMMY_721 = 721, + DUMMY_722 = 722, + DUMMY_723 = 723, + DUMMY_724 = 724, + DUMMY_725 = 725, + DUMMY_726 = 726, + DUMMY_727 = 727, + DUMMY_728 = 728, + DUMMY_729 = 729, + DUMMY_730 = 730, + DUMMY_731 = 731, + DUMMY_732 = 732, + DUMMY_733 = 733, + DUMMY_734 = 734, + DUMMY_735 = 735, + DUMMY_736 = 736, + DUMMY_737 = 737, + DUMMY_738 = 738, + DUMMY_739 = 739, + DUMMY_740 = 740, + DUMMY_741 = 741, + DUMMY_742 = 742, + DUMMY_743 = 743, + DUMMY_744 = 744, + DUMMY_745 = 745, + DUMMY_746 = 746, + DUMMY_747 = 747, + DUMMY_748 = 748, + DUMMY_749 = 749, + DUMMY_750 = 750, + DUMMY_751 = 751, + DUMMY_752 = 752, + DUMMY_753 = 753, + DUMMY_754 = 754, + DUMMY_755 = 755, + DUMMY_756 = 756, + DUMMY_757 = 757, + DUMMY_758 = 758, + DUMMY_759 = 759, + DUMMY_760 = 760, + DUMMY_761 = 761, + DUMMY_762 = 762, + DUMMY_763 = 763, + DUMMY_764 = 764, + DUMMY_765 = 765, + DUMMY_766 = 766, + DUMMY_767 = 767, + DUMMY_768 = 768, + DUMMY_769 = 769, + DUMMY_770 = 770, + DUMMY_771 = 771, + DUMMY_772 = 772, + DUMMY_773 = 773, + DUMMY_774 = 774, + DUMMY_775 = 775, + DUMMY_776 = 776, + DUMMY_777 = 777, + DUMMY_778 = 778, + DUMMY_779 = 779, + DUMMY_780 = 780, + DUMMY_781 = 781, + DUMMY_782 = 782, + DUMMY_783 = 783, + DUMMY_784 = 784, + DUMMY_785 = 785, + DUMMY_786 = 786, + DUMMY_787 = 787, + DUMMY_788 = 788, + DUMMY_789 = 789, + DUMMY_790 = 790, + DUMMY_791 = 791, + DUMMY_792 = 792, + DUMMY_793 = 793, + DUMMY_794 = 794, + DUMMY_795 = 795, + DUMMY_796 = 796, + DUMMY_797 = 797, + DUMMY_798 = 798, + DUMMY_799 = 799, + DUMMY_800 = 800, + DUMMY_801 = 801, + DUMMY_802 = 802, + DUMMY_803 = 803, + DUMMY_804 = 804, + DUMMY_805 = 805, + DUMMY_806 = 806, + DUMMY_807 = 807, + DUMMY_808 = 808, + DUMMY_809 = 809, + DUMMY_810 = 810, + DUMMY_811 = 811, + DUMMY_812 = 812, + DUMMY_813 = 813, + DUMMY_814 = 814, + DUMMY_815 = 815, + DUMMY_816 = 816, + DUMMY_817 = 817, + DUMMY_818 = 818, + DUMMY_819 = 819, + DUMMY_820 = 820, + DUMMY_821 = 821, + DUMMY_822 = 822, + DUMMY_823 = 823, + DUMMY_824 = 824, + DUMMY_825 = 825, + DUMMY_826 = 826, + DUMMY_827 = 827, + DUMMY_828 = 828, + DUMMY_829 = 829, + DUMMY_830 = 830, + DUMMY_831 = 831, + DUMMY_832 = 832, + DUMMY_833 = 833, + DUMMY_834 = 834, + DUMMY_835 = 835, + DUMMY_836 = 836, + DUMMY_837 = 837, + DUMMY_838 = 838, + DUMMY_839 = 839, + DUMMY_840 = 840, + DUMMY_841 = 841, + DUMMY_842 = 842, + DUMMY_843 = 843, + DUMMY_844 = 844, + DUMMY_845 = 845, + DUMMY_846 = 846, + DUMMY_847 = 847, + DUMMY_848 = 848, + DUMMY_849 = 849, + DUMMY_850 = 850, + DUMMY_851 = 851, + DUMMY_852 = 852, + DUMMY_853 = 853, + DUMMY_854 = 854, + DUMMY_855 = 855, + DUMMY_856 = 856, + DUMMY_857 = 857, + DUMMY_858 = 858, + DUMMY_859 = 859, + DUMMY_860 = 860, + DUMMY_861 = 861, + DUMMY_862 = 862, + DUMMY_863 = 863, + DUMMY_864 = 864, + DUMMY_865 = 865, + DUMMY_866 = 866, + DUMMY_867 = 867, + DUMMY_868 = 868, + DUMMY_869 = 869, + DUMMY_870 = 870, + DUMMY_871 = 871, + DUMMY_872 = 872, + DUMMY_873 = 873, + DUMMY_874 = 874, + DUMMY_875 = 875, + DUMMY_876 = 876, + DUMMY_877 = 877, + DUMMY_878 = 878, + DUMMY_879 = 879, + DUMMY_880 = 880, + DUMMY_881 = 881, + DUMMY_882 = 882, + DUMMY_883 = 883, + DUMMY_884 = 884, + DUMMY_885 = 885, + DUMMY_886 = 886, + DUMMY_887 = 887, + DUMMY_888 = 888, + DUMMY_889 = 889, + DUMMY_890 = 890, + DUMMY_891 = 891, + DUMMY_892 = 892, + DUMMY_893 = 893, + DUMMY_894 = 894, + DUMMY_895 = 895, + DUMMY_896 = 896, + DUMMY_897 = 897, + DUMMY_898 = 898, + DUMMY_899 = 899, + DUMMY_900 = 900, + DUMMY_901 = 901, + DUMMY_902 = 902, + DUMMY_903 = 903, + DUMMY_904 = 904, + DUMMY_905 = 905, + DUMMY_906 = 906, + DUMMY_907 = 907, + DUMMY_908 = 908, + DUMMY_909 = 909, + DUMMY_910 = 910, + DUMMY_911 = 911, + DUMMY_912 = 912, + DUMMY_913 = 913, + DUMMY_914 = 914, + DUMMY_915 = 915, + DUMMY_916 = 916, + DUMMY_917 = 917, + DUMMY_918 = 918, + DUMMY_919 = 919, + DUMMY_920 = 920, + DUMMY_921 = 921, + DUMMY_922 = 922, + DUMMY_923 = 923, + DUMMY_924 = 924, + DUMMY_925 = 925, + DUMMY_926 = 926, + DUMMY_927 = 927, + DUMMY_928 = 928, + DUMMY_929 = 929, + DUMMY_930 = 930, + DUMMY_931 = 931, + DUMMY_932 = 932, + DUMMY_933 = 933, + DUMMY_934 = 934, + DUMMY_935 = 935, + DUMMY_936 = 936, + DUMMY_937 = 937, + DUMMY_938 = 938, + DUMMY_939 = 939, + DUMMY_940 = 940, + DUMMY_941 = 941, + DUMMY_942 = 942, + DUMMY_943 = 943, + DUMMY_944 = 944, + DUMMY_945 = 945, + DUMMY_946 = 946, + DUMMY_947 = 947, + DUMMY_948 = 948, + DUMMY_949 = 949, + DUMMY_950 = 950, + DUMMY_951 = 951, + DUMMY_952 = 952, + DUMMY_953 = 953, + DUMMY_954 = 954, + DUMMY_955 = 955, + DUMMY_956 = 956, + DUMMY_957 = 957, + DUMMY_958 = 958, + DUMMY_959 = 959, + DUMMY_960 = 960, + DUMMY_961 = 961, + DUMMY_962 = 962, + DUMMY_963 = 963, + DUMMY_964 = 964, + DUMMY_965 = 965, + DUMMY_966 = 966, + DUMMY_967 = 967, + DUMMY_968 = 968, + DUMMY_969 = 969, + DUMMY_970 = 970, + DUMMY_971 = 971, + DUMMY_972 = 972, + DUMMY_973 = 973, + DUMMY_974 = 974, + DUMMY_975 = 975, + DUMMY_976 = 976, + DUMMY_977 = 977, + DUMMY_978 = 978, + DUMMY_979 = 979, + DUMMY_980 = 980, + DUMMY_981 = 981, + DUMMY_982 = 982, + DUMMY_983 = 983, + DUMMY_984 = 984, + DUMMY_985 = 985, + DUMMY_986 = 986, + DUMMY_987 = 987, + DUMMY_988 = 988, + DUMMY_989 = 989, + DUMMY_990 = 990, + DUMMY_991 = 991, + DUMMY_992 = 992, + DUMMY_993 = 993, + DUMMY_994 = 994, + DUMMY_995 = 995, + DUMMY_996 = 996, + DUMMY_997 = 997, + DUMMY_998 = 998, + DUMMY_999 = 999, + DUMMY_1000 = 1000, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Entity/PokemonUniquePathData.fbs b/FlatBuffers/ZA/Shared/Schemas/Entity/PokemonUniquePathData.fbs new file mode 100644 index 00000000..d5943be9 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Entity/PokemonUniquePathData.fbs @@ -0,0 +1,1105 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table PokemonUniquePathData (fs_serializer) { + Path000:string (required); + Path001:string (required); + Path002:string (required); + Path003:string (required); + Path004:string (required); + Path005:string (required); + Path006:string (required); + Path007:string (required); + Path008:string (required); + Path009:string (required); + Path010:string (required); + Path011:string (required); + Path012:string (required); + Path013:string (required); + Path014:string (required); + Path015:string (required); + Path016:string (required); + Path017:string (required); + Path018:string (required); + Path019:string (required); + Path020:string (required); + Path021:string (required); + Path022:string (required); + Path023:string (required); + Path024:string (required); + Path025:string (required); + Path026:string (required); + Path027:string (required); + Path028:string (required); + Path029:string (required); + Path030:string (required); + Path031:string (required); + Path032:string (required); + Path033:string (required); + Path034:string (required); + Path035:string (required); + Path036:string (required); + Path037:string (required); + Path038:string (required); + Path039:string (required); + Path040:string (required); + Path041:string (required); + Path042:string (required); + Path043:string (required); + Path044:string (required); + Path045:string (required); + Path046:string (required); + Path047:string (required); + Path048:string (required); + Path049:string (required); + Path050:string (required); + Path051:string (required); + Path052:string (required); + Path053:string (required); + Path054:string (required); + Path055:string (required); + Path056:string (required); + Path057:string (required); + Path058:string (required); + Path059:string (required); + Path060:string (required); + Path061:string (required); + Path062:string (required); + Path063:string (required); + Path064:string (required); + Path065:string (required); + Path066:string (required); + Path067:string (required); + Path068:string (required); + Path069:string (required); + Path070:string (required); + Path071:string (required); + Path072:string (required); + Path073:string (required); + Path074:string (required); + Path075:string (required); + Path076:string (required); + Path077:string (required); + Path078:string (required); + Path079:string (required); + Path080:string (required); + Path081:string (required); + Path082:string (required); + Path083:string (required); + Path084:string (required); + Path085:string (required); + Path086:string (required); + Path087:string (required); + Path088:string (required); + Path089:string (required); + Path090:string (required); + Path091:string (required); + Path092:string (required); + Path093:string (required); + Path094:string (required); + Path095:string (required); + Path096:string (required); + Path097:string (required); + Path098:string (required); + Path099:string (required); + Path100:string (required); + Path101:string (required); + Path102:string (required); + Path103:string (required); + Path104:string (required); + Path105:string (required); + Path106:string (required); + Path107:string (required); + Path108:string (required); + Path109:string (required); + Path110:string (required); + Path111:string (required); + Path112:string (required); + Path113:string (required); + Path114:string (required); + Path115:string (required); + Path116:string (required); + Path117:string (required); + Path118:string (required); + Path119:string (required); + Path120:string (required); + Path121:string (required); + Path122:string (required); + Path123:string (required); + Path124:string (required); + Path125:string (required); + Path126:string (required); + Path127:string (required); + Path128:string (required); + Path129:string (required); + Path130:string (required); + Path131:string (required); + Path132:string (required); + Path133:string (required); + Path134:string (required); + Path135:string (required); + Path136:string (required); + Path137:string (required); + Path138:string (required); + Path139:string (required); + Path140:string (required); + Path141:string (required); + Path142:string (required); + Path143:string (required); + Path144:string (required); + Path145:string (required); + Path146:string (required); + Path147:string (required); + Path148:string (required); + Path149:string (required); + Path150:string (required); + Path151:string (required); + Path152:string (required); + Path153:string (required); + Path154:string (required); + Path155:string (required); + Path156:string (required); + Path157:string (required); + Path158:string (required); + Path159:string (required); + Path160:string (required); + Path161:string (required); + Path162:string (required); + Path163:string (required); + Path164:string (required); + Path165:string (required); + Path166:string (required); + Path167:string (required); + Path168:string (required); + Path169:string (required); + Path170:string (required); + Path171:string (required); + Path172:string (required); + Path173:string (required); + Path174:string (required); + Path175:string (required); + Path176:string (required); + Path177:string (required); + Path178:string (required); + Path179:string (required); + Path180:string (required); + Path181:string (required); + Path182:string (required); + Path183:string (required); + Path184:string (required); + Path185:string (required); + Path186:string (required); + Path187:string (required); + Path188:string (required); + Path189:string (required); + Path190:string (required); + Path191:string (required); + Path192:string (required); + Path193:string (required); + Path194:string (required); + Path195:string (required); + Path196:string (required); + Path197:string (required); + Path198:string (required); + Path199:string (required); + Path200:string (required); + Path201:string (required); + Path202:string (required); + Path203:string (required); + Path204:string (required); + Path205:string (required); + Path206:string (required); + Path207:string (required); + Path208:string (required); + Path209:string (required); + Path210:string (required); + Path211:string (required); + Path212:string (required); + Path213:string (required); + Path214:string (required); + Path215:string (required); + Path216:string (required); + Path217:string (required); + Path218:string (required); + Path219:string (required); + Path220:string (required); + Path221:string (required); + Path222:string (required); + Path223:string (required); + Path224:string (required); + Path225:string (required); + Path226:string (required); + Path227:string (required); + Path228:string (required); + Path229:string (required); + Path230:string (required); + Path231:string (required); + Path232:string (required); + Path233:string (required); + Path234:string (required); + Path235:string (required); + Path236:string (required); + Path237:string (required); + Path238:string (required); + Path239:string (required); + Path240:string (required); + Path241:string (required); + Path242:string (required); + Path243:string (required); + Path244:string (required); + Path245:string (required); + Path246:string (required); + Path247:string (required); + Path248:string (required); + Path249:string (required); + Path250:string (required); + Path251:string (required); + Path252:string (required); + Path253:string (required); + Path254:string (required); + Path255:string (required); + Path256:string (required); + Path257:string (required); + Path258:string (required); + Path259:string (required); + Path260:string (required); + Path261:string (required); + Path262:string (required); + Path263:string (required); + Path264:string (required); + Path265:string (required); + Path266:string (required); + Path267:string (required); + Path268:string (required); + Path269:string (required); + Path270:string (required); + Path271:string (required); + Path272:string (required); + Path273:string (required); + Path274:string (required); + Path275:string (required); + Path276:string (required); + Path277:string (required); + Path278:string (required); + Path279:string (required); + Path280:string (required); + Path281:string (required); + Path282:string (required); + Path283:string (required); + Path284:string (required); + Path285:string (required); + Path286:string (required); + Path287:string (required); + Path288:string (required); + Path289:string (required); + Path290:string (required); + Path291:string (required); + Path292:string (required); + Path293:string (required); + Path294:string (required); + Path295:string (required); + Path296:string (required); + Path297:string (required); + Path298:string (required); + Path299:string (required); + Path300:string (required); + Path301:string (required); + Path302:string (required); + Path303:string (required); + Path304:string (required); + Path305:string (required); + Path306:string (required); + Path307:string (required); + Path308:string (required); + Path309:string (required); + Path310:string (required); + Path311:string (required); + Path312:string (required); + Path313:string (required); + Path314:string (required); + Path315:string (required); + Path316:string (required); + Path317:string (required); + Path318:string (required); + Path319:string (required); + Path320:string (required); + Path321:string (required); + Path322:string (required); + Path323:string (required); + Path324:string (required); + Path325:string (required); + Path326:string (required); + Path327:string (required); + Path328:string (required); + Path329:string (required); + Path330:string (required); + Path331:string (required); + Path332:string (required); + Path333:string (required); + Path334:string (required); + Path335:string (required); + Path336:string (required); + Path337:string (required); + Path338:string (required); + Path339:string (required); + Path340:string (required); + Path341:string (required); + Path342:string (required); + Path343:string (required); + Path344:string (required); + Path345:string (required); + Path346:string (required); + Path347:string (required); + Path348:string (required); + Path349:string (required); + Path350:string (required); + Path351:string (required); + Path352:string (required); + Path353:string (required); + Path354:string (required); + Path355:string (required); + Path356:string (required); + Path357:string (required); + Path358:string (required); + Path359:string (required); + Path360:string (required); + Path361:string (required); + Path362:string (required); + Path363:string (required); + Path364:string (required); + Path365:string (required); + Path366:string (required); + Path367:string (required); + Path368:string (required); + Path369:string (required); + Path370:string (required); + Path371:string (required); + Path372:string (required); + Path373:string (required); + Path374:string (required); + Path375:string (required); + Path376:string (required); + Path377:string (required); + Path378:string (required); + Path379:string (required); + Path380:string (required); + Path381:string (required); + Path382:string (required); + Path383:string (required); + Path384:string (required); + Path385:string (required); + Path386:string (required); + Path387:string (required); + Path388:string (required); + Path389:string (required); + Path390:string (required); + Path391:string (required); + Path392:string (required); + Path393:string (required); + Path394:string (required); + Path395:string (required); + Path396:string (required); + Path397:string (required); + Path398:string (required); + Path399:string (required); + Path400:string (required); + Path401:string (required); + Path402:string (required); + Path403:string (required); + Path404:string (required); + Path405:string (required); + Path406:string (required); + Path407:string (required); + Path408:string (required); + Path409:string (required); + Path410:string (required); + Path411:string (required); + Path412:string (required); + Path413:string (required); + Path414:string (required); + Path415:string (required); + Path416:string (required); + Path417:string (required); + Path418:string (required); + Path419:string (required); + Path420:string (required); + Path421:string (required); + Path422:string (required); + Path423:string (required); + Path424:string (required); + Path425:string (required); + Path426:string (required); + Path427:string (required); + Path428:string (required); + Path429:string (required); + Path430:string (required); + Path431:string (required); + Path432:string (required); + Path433:string (required); + Path434:string (required); + Path435:string (required); + Path436:string (required); + Path437:string (required); + Path438:string (required); + Path439:string (required); + Path440:string (required); + Path441:string (required); + Path442:string (required); + Path443:string (required); + Path444:string (required); + Path445:string (required); + Path446:string (required); + Path447:string (required); + Path448:string (required); + Path449:string (required); + Path450:string (required); + Path451:string (required); + Path452:string (required); + Path453:string (required); + Path454:string (required); + Path455:string (required); + Path456:string (required); + Path457:string (required); + Path458:string (required); + Path459:string (required); + Path460:string (required); + Path461:string (required); + Path462:string (required); + Path463:string (required); + Path464:string (required); + Path465:string (required); + Path466:string (required); + Path467:string (required); + Path468:string (required); + Path469:string (required); + Path470:string (required); + Path471:string (required); + Path472:string (required); + Path473:string (required); + Path474:string (required); + Path475:string (required); + Path476:string (required); + Path477:string (required); + Path478:string (required); + Path479:string (required); + Path480:string (required); + Path481:string (required); + Path482:string (required); + Path483:string (required); + Path484:string (required); + Path485:string (required); + Path486:string (required); + Path487:string (required); + Path488:string (required); + Path489:string (required); + Path490:string (required); + Path491:string (required); + Path492:string (required); + Path493:string (required); + Path494:string (required); + Path495:string (required); + Path496:string (required); + Path497:string (required); + Path498:string (required); + Path499:string (required); + Path500:string (required); + Path501:string (required); + Path502:string (required); + Path503:string (required); + Path504:string (required); + Path505:string (required); + Path506:string (required); + Path507:string (required); + Path508:string (required); + Path509:string (required); + Path510:string (required); + Path511:string (required); + Path512:string (required); + Path513:string (required); + Path514:string (required); + Path515:string (required); + Path516:string (required); + Path517:string (required); + Path518:string (required); + Path519:string (required); + Path520:string (required); + Path521:string (required); + Path522:string (required); + Path523:string (required); + Path524:string (required); + Path525:string (required); + Path526:string (required); + Path527:string (required); + Path528:string (required); + Path529:string (required); + Path530:string (required); + Path531:string (required); + Path532:string (required); + Path533:string (required); + Path534:string (required); + Path535:string (required); + Path536:string (required); + Path537:string (required); + Path538:string (required); + Path539:string (required); + Path540:string (required); + Path541:string (required); + Path542:string (required); + Path543:string (required); + Path544:string (required); + Path545:string (required); + Path546:string (required); + Path547:string (required); + Path548:string (required); + Path549:string (required); + Path550:string (required); + Path551:string (required); + Path552:string (required); + Path553:string (required); + Path554:string (required); + Path555:string (required); + Path556:string (required); + Path557:string (required); + Path558:string (required); + Path559:string (required); + Path560:string (required); + Path561:string (required); + Path562:string (required); + Path563:string (required); + Path564:string (required); + Path565:string (required); + Path566:string (required); + Path567:string (required); + Path568:string (required); + Path569:string (required); + Path570:string (required); + Path571:string (required); + Path572:string (required); + Path573:string (required); + Path574:string (required); + Path575:string (required); + Path576:string (required); + Path577:string (required); + Path578:string (required); + Path579:string (required); + Path580:string (required); + Path581:string (required); + Path582:string (required); + Path583:string (required); + Path584:string (required); + Path585:string (required); + Path586:string (required); + Path587:string (required); + Path588:string (required); + Path589:string (required); + Path590:string (required); + Path591:string (required); + Path592:string (required); + Path593:string (required); + Path594:string (required); + Path595:string (required); + Path596:string (required); + Path597:string (required); + Path598:string (required); + Path599:string (required); + Path600:string (required); + Path601:string (required); + Path602:string (required); + Path603:string (required); + Path604:string (required); + Path605:string (required); + Path606:string (required); + Path607:string (required); + Path608:string (required); + Path609:string (required); + Path610:string (required); + Path611:string (required); + Path612:string (required); + Path613:string (required); + Path614:string (required); + Path615:string (required); + Path616:string (required); + Path617:string (required); + Path618:string (required); + Path619:string (required); + Path620:string (required); + Path621:string (required); + Path622:string (required); + Path623:string (required); + Path624:string (required); + Path625:string (required); + Path626:string (required); + Path627:string (required); + Path628:string (required); + Path629:string (required); + Path630:string (required); + Path631:string (required); + Path632:string (required); + Path633:string (required); + Path634:string (required); + Path635:string (required); + Path636:string (required); + Path637:string (required); + Path638:string (required); + Path639:string (required); + Path640:string (required); + Path641:string (required); + Path642:string (required); + Path643:string (required); + Path644:string (required); + Path645:string (required); + Path646:string (required); + Path647:string (required); + Path648:string (required); + Path649:string (required); + Path650:string (required); + Path651:string (required); + Path652:string (required); + Path653:string (required); + Path654:string (required); + Path655:string (required); + Path656:string (required); + Path657:string (required); + Path658:string (required); + Path659:string (required); + Path660:string (required); + Path661:string (required); + Path662:string (required); + Path663:string (required); + Path664:string (required); + Path665:string (required); + Path666:string (required); + Path667:string (required); + Path668:string (required); + Path669:string (required); + Path670:string (required); + Path671:string (required); + Path672:string (required); + Path673:string (required); + Path674:string (required); + Path675:string (required); + Path676:string (required); + Path677:string (required); + Path678:string (required); + Path679:string (required); + Path680:string (required); + Path681:string (required); + Path682:string (required); + Path683:string (required); + Path684:string (required); + Path685:string (required); + Path686:string (required); + Path687:string (required); + Path688:string (required); + Path689:string (required); + Path690:string (required); + Path691:string (required); + Path692:string (required); + Path693:string (required); + Path694:string (required); + Path695:string (required); + Path696:string (required); + Path697:string (required); + Path698:string (required); + Path699:string (required); + Path700:string (required); + Path701:string (required); + Path702:string (required); + Path703:string (required); + Path704:string (required); + Path705:string (required); + Path706:string (required); + Path707:string (required); + Path708:string (required); + Path709:string (required); + Path710:string (required); + Path711:string (required); + Path712:string (required); + Path713:string (required); + Path714:string (required); + Path715:string (required); + Path716:string (required); + Path717:string (required); + Path718:string (required); + Path719:string (required); + Path720:string (required); + Path721:string (required); + Path722:string (required); + Path723:string (required); + Path724:string (required); + Path725:string (required); + Path726:string (required); + Path727:string (required); + Path728:string (required); + Path729:string (required); + Path730:string (required); + Path731:string (required); + Path732:string (required); + Path733:string (required); + Path734:string (required); + Path735:string (required); + Path736:string (required); + Path737:string (required); + Path738:string (required); + Path739:string (required); + Path740:string (required); + Path741:string (required); + Path742:string (required); + Path743:string (required); + Path744:string (required); + Path745:string (required); + Path746:string (required); + Path747:string (required); + Path748:string (required); + Path749:string (required); + Path750:string (required); + Path751:string (required); + Path752:string (required); + Path753:string (required); + Path754:string (required); + Path755:string (required); + Path756:string (required); + Path757:string (required); + Path758:string (required); + Path759:string (required); + Path760:string (required); + Path761:string (required); + Path762:string (required); + Path763:string (required); + Path764:string (required); + Path765:string (required); + Path766:string (required); + Path767:string (required); + Path768:string (required); + Path769:string (required); + Path770:string (required); + Path771:string (required); + Path772:string (required); + Path773:string (required); + Path774:string (required); + Path775:string (required); + Path776:string (required); + Path777:string (required); + Path778:string (required); + Path779:string (required); + Path780:string (required); + Path781:string (required); + Path782:string (required); + Path783:string (required); + Path784:string (required); + Path785:string (required); + Path786:string (required); + Path787:string (required); + Path788:string (required); + Path789:string (required); + Path790:string (required); + Path791:string (required); + Path792:string (required); + Path793:string (required); + Path794:string (required); + Path795:string (required); + Path796:string (required); + Path797:string (required); + Path798:string (required); + Path799:string (required); + Path800:string (required); + Path801:string (required); + Path802:string (required); + Path803:string (required); + Path804:string (required); + Path805:string (required); + Path806:string (required); + Path807:string (required); + Path808:string (required); + Path809:string (required); + Path810:string (required); + Path811:string (required); + Path812:string (required); + Path813:string (required); + Path814:string (required); + Path815:string (required); + Path816:string (required); + Path817:string (required); + Path818:string (required); + Path819:string (required); + Path820:string (required); + Path821:string (required); + Path822:string (required); + Path823:string (required); + Path824:string (required); + Path825:string (required); + Path826:string (required); + Path827:string (required); + Path828:string (required); + Path829:string (required); + Path830:string (required); + Path831:string (required); + Path832:string (required); + Path833:string (required); + Path834:string (required); + Path835:string (required); + Path836:string (required); + Path837:string (required); + Path838:string (required); + Path839:string (required); + Path840:string (required); + Path841:string (required); + Path842:string (required); + Path843:string (required); + Path844:string (required); + Path845:string (required); + Path846:string (required); + Path847:string (required); + Path848:string (required); + Path849:string (required); + Path850:string (required); + Path851:string (required); + Path852:string (required); + Path853:string (required); + Path854:string (required); + Path855:string (required); + Path856:string (required); + Path857:string (required); + Path858:string (required); + Path859:string (required); + Path860:string (required); + Path861:string (required); + Path862:string (required); + Path863:string (required); + Path864:string (required); + Path865:string (required); + Path866:string (required); + Path867:string (required); + Path868:string (required); + Path869:string (required); + Path870:string (required); + Path871:string (required); + Path872:string (required); + Path873:string (required); + Path874:string (required); + Path875:string (required); + Path876:string (required); + Path877:string (required); + Path878:string (required); + Path879:string (required); + Path880:string (required); + Path881:string (required); + Path882:string (required); + Path883:string (required); + Path884:string (required); + Path885:string (required); + Path886:string (required); + Path887:string (required); + Path888:string (required); + Path889:string (required); + Path890:string (required); + Path891:string (required); + Path892:string (required); + Path893:string (required); + Path894:string (required); + Path895:string (required); + Path896:string (required); + Path897:string (required); + Path898:string (required); + Path899:string (required); + Path900:string (required); + Path901:string (required); + Path902:string (required); + Path903:string (required); + Path904:string (required); + Path905:string (required); + Path906:string (required); + Path907:string (required); + Path908:string (required); + Path909:string (required); + Path910:string (required); + Path911:string (required); + Path912:string (required); + Path913:string (required); + Path914:string (required); + Path915:string (required); + Path916:string (required); + Path917:string (required); + Path918:string (required); + Path919:string (required); + Path920:string (required); + Path921:string (required); + Path922:string (required); + Path923:string (required); + Path924:string (required); + Path925:string (required); + Path926:string (required); + Path927:string (required); + Path928:string (required); + Path929:string (required); + Path930:string (required); + Path931:string (required); + Path932:string (required); + Path933:string (required); + Path934:string (required); + Path935:string (required); + Path936:string (required); + Path937:string (required); + Path938:string (required); + Path939:string (required); + Path940:string (required); + Path941:string (required); + Path942:string (required); + Path943:string (required); + Path944:string (required); + Path945:string (required); + Path946:string (required); + Path947:string (required); + Path948:string (required); + Path949:string (required); + Path950:string (required); + Path951:string (required); + Path952:string (required); + Path953:string (required); + Path954:string (required); + Path955:string (required); + Path956:string (required); + Path957:string (required); + Path958:string (required); + Path959:string (required); + Path960:string (required); + Path961:string (required); + Path962:string (required); + Path963:string (required); + Path964:string (required); + Path965:string (required); + Path966:string (required); + Path967:string (required); + Path968:string (required); + Path969:string (required); + Path970:string (required); + Path971:string (required); + Path972:string (required); + Path973:string (required); + Path974:string (required); + Path975:string (required); + Path976:string (required); + Path977:string (required); + Path978:string (required); + Path979:string (required); + Path980:string (required); + Path981:string (required); + Path982:string (required); + Path983:string (required); + Path984:string (required); + Path985:string (required); + Path986:string (required); + Path987:string (required); + Path988:string (required); + Path989:string (required); + Path990:string (required); + Path991:string (required); + Path992:string (required); + Path993:string (required); + Path994:string (required); + Path995:string (required); + Path996:string (required); + Path997:string (required); + Path998:string (required); + Path999:string (required); + Path1000:string; + Path1001:string; + Path1002:string; + Path1003:string; + Path1004:string; + Path1005:string; + Path1006:string; + Path1007:string; + Path1008:string; + Path1009:string; + Path1010:string; + Path1011:string; + Path1012:string; + Path1013:string; + Path1014:string; + Path1015:string; + Path1016:string; + Path1017:string; + Path1018:string; + Path1019:string; + Path1020:string; + Path1021:string; + Path1022:string; + Path1023:string; + Path1024:string; + Path1025:string; + Path1026:string; + Path1027:string; + Path1028:string; + Path1029:string; + Path1030:string; + Path1031:string; + Path1032:string; + Path1033:string; + Path1034:string; + Path1035:string; + Path1036:string; + Path1037:string; + Path1038:string; + Path1039:string; + Path1040:string; + Path1041:string; + Path1042:string; + Path1043:string; + Path1044:string; + Path1045:string; + Path1046:string; + Path1047:string; + Path1048:string; + Path1049:string; + Path1050:string; + Path1051:string; + Path1052:string; + Path1053:string; + Path1054:string; + Path1055:string; + Path1056:string; + Path1057:string; + Path1058:string; + Path1059:string; + Path1060:string; + Path1061:string; + Path1062:string; + Path1063:string; + Path1064:string; + Path1065:string; + Path1066:string; + Path1067:string; + Path1068:string; + Path1069:string; + Path1070:string; + Path1071:string; + Path1072:string; + Path1073:string; + Path1074:string; + Path1075:string; + Path1076:string; + Path1077:string; + Path1078:string; + Path1079:string; + Path1080:string; + Path1081:string; + Path1082:string; + Path1083:string; + Path1084:string; + Path1085:string; + Path1086:string; + Path1087:string; + Path1088:string; + Path1089:string; + Path1090:string; + Path1091:string; + Path1092:string; + Path1093:string; + Path1094:string; + Path1095:string; + Path1096:string; + Path1097:string; + Path1098:string; + Path1099:string; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Misc/CaptureBallData.fbs b/FlatBuffers/ZA/Shared/Schemas/Misc/CaptureBallData.fbs new file mode 100644 index 00000000..7664b635 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Misc/CaptureBallData.fbs @@ -0,0 +1,35 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +struct TimerBallData { + Count:uint; + Ratio:float; +} + +table CaptureBallData (fs_serializer) { + Poke:float; + Great:float; + Ultra:float; + Net:float; + Repeat:float; + Timer:[TimerBallData]; + Nest:float; + Luxury:float; + Heal:float; + Dive:float; + Quick:float; + Dusk:float; + Premier:float; + Beast:float; + Dream:float; + Fast:float; + Friend:float; + Heavy:[float]; + Moon:float; + Love:float; + Lure:float; + Level:[float]; +} + +root_type CaptureBallData; diff --git a/FlatBuffers/ZA/Shared/Schemas/Misc/CaptureData.fbs b/FlatBuffers/ZA/Shared/Schemas/Misc/CaptureData.fbs new file mode 100644 index 00000000..3efa747b --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Misc/CaptureData.fbs @@ -0,0 +1,40 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table CaptureSick { + Koori:float; + Nemuri:float; + Doku:float; + Yakedo:float; + Mahi:float; +} + +table CaptureBackStrike { + Cowardice:float; + NotCowardice:float; +} + +table CaptureAiState { + Normal:float; + NotAware:float; + Eating:float; + Sleeping:float; + Resting:float; +} + +table CaptureData (fs_serializer) { + Sick:CaptureSick; + Rare:float; + BackStrike:CaptureBackStrike; + Cowardice:CaptureAiState; + NotCowardice:CaptureAiState; + Chance:float; + Oyabun:float; + OyabunChance:float; + Coef:float; + backStrikeAngle:int; + backStrikeHeight:int; +} + +root_type CaptureData; diff --git a/FlatBuffers/ZA/Shared/Schemas/Misc/CaptureZARankData.fbs b/FlatBuffers/ZA/Shared/Schemas/Misc/CaptureZARankData.fbs new file mode 100644 index 00000000..24f094a0 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Misc/CaptureZARankData.fbs @@ -0,0 +1,32 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; +attribute "fs_valueStruct"; +attribute "fs_nonVirtual"; + +table CaptureZARankData (fs_serializer) { + LevelThreshold:ZARankLevelThreshold (required); + ZRank:ZARankArray (required); + YRank:ZARankArray (required); + XRank:ZARankArray (required); + WRank:ZARankArray (required); + VRank:ZARankArray (required); + GRank:ZARankArray (required); + FRank:ZARankArray (required); + ERank:ZARankArray (required); + DRank:ZARankArray (required); + CRank:ZARankArray (required); + BRank:ZARankArray (required); + ARank:ZARankArray (required); + InfRank:ZARankArray (required); +} + +struct ZARankLevelThreshold { + Level:[int:10] (fs_nonVirtual); +} + +struct ZARankArray { + Ratio:[float:10] (fs_nonVirtual); +} + +root_type CaptureZARankData; diff --git a/FlatBuffers/ZA/Shared/Schemas/Misc/MegaEvoArray.fbs b/FlatBuffers/ZA/Shared/Schemas/Misc/MegaEvoArray.fbs new file mode 100644 index 00000000..131a5086 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Misc/MegaEvoArray.fbs @@ -0,0 +1,21 @@ +include "../Shared/DevID.fbs"; +include "../Shared/ItemID.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table MegaEvo { + Species:DevID; + Item:ItemID; + FromForm:uint; + ToForm:uint; + Type:string (required); + Short:string (required); +} + +table MegaEvoArray (fs_serializer) { + Table:[MegaEvo] (required); +} + +root_type MegaEvoArray; diff --git a/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataBattle.fbs b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataBattle.fbs new file mode 100644 index 00000000..03c22de0 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataBattle.fbs @@ -0,0 +1,34 @@ +include "../Shared/DevID.fbs"; +include "../Shared/SexType.fbs"; +include "../Shared/ItemID.fbs"; +include "../Shared/SeikakuType.fbs"; +include "../Shared/TokuseiType.fbs"; +include "../Shared/TalentType.fbs"; +include "../Shared/RareType.fbs"; +include "../Shared/SizeType.fbs"; +include "../Shared/BallID.fbs"; + +include "../PokeData/WazaSetBattle.fbs"; +include "../Entity/ParamSet.fbs"; +include "../Shared/WazaType.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table PokeDataBattle { + DevId:DevID; + FormId:short; + Sex:SexType; + Item:ItemID; + Level:int; + BallId:BallID; + Waza1:WazaSetBattle (required); + Waza2:WazaSetBattle (required); + Waza3:WazaSetBattle (required); + Waza4:WazaSetBattle (required); + Seikaku:SeikakuType; + Tokusei:TokuseiType; + TalentValue:ParamSet (required); + EffortValue:ParamSet (required); + RareType:RareType; + ScaleValue:short; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataDLCGift.fbs b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataDLCGift.fbs new file mode 100644 index 00000000..e4a2662e --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataDLCGift.fbs @@ -0,0 +1,43 @@ +include "../Shared/DevID.fbs"; +include "../Shared/SexType.fbs"; +include "../Shared/ItemID.fbs"; +include "../Shared/SeikakuType.fbs"; +include "../Shared/TokuseiType.fbs"; +include "../Shared/TalentType.fbs"; +include "../Shared/RareType.fbs"; +include "../Shared/SizeType.fbs"; +include "../Shared/BallID.fbs"; +include "../Shared/RibbonType.fbs"; + +include "../Entity/ParamSet.fbs"; +include "../PokeData/WazaSet.fbs"; +include "../Shared/WazaType.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table PokeDataDLCGift { + DevId:DevID = DEV_NULL; + FormId:short; + Level:int; + Sex:SexType; + Tokusei:TokuseiType; + RareType:RareType; + ScaleType:SizeType; + ScaleValue:short; + TalentType:TalentType; + TalentVnum:byte; + TalentValue:ParamSet; + EffortValue:ParamSet; + Item:ItemID = ITEMID_NONE; + Seikaku:SeikakuType; + SeikakuHosei:SeikakuType; + WazaType:WazaType; + Waza1:WazaSet; + Waza2:WazaSet; + Waza3:WazaSet; + Waza4:WazaSet; + BallId:BallID; + UseNickName:bool; + NicknameLabel:ulong; + ParentSex:SexType; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataEventBattle.fbs b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataEventBattle.fbs new file mode 100644 index 00000000..ddb388ea --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataEventBattle.fbs @@ -0,0 +1,41 @@ +include "../Shared/DevID.fbs"; +include "../Shared/SexType.fbs"; +include "../Shared/ItemID.fbs"; +include "../Shared/SeikakuType.fbs"; +include "../Shared/TokuseiType.fbs"; +include "../Shared/TalentType.fbs"; +include "../Shared/RareType.fbs"; +include "../Shared/SizeType.fbs"; +include "../Shared/RibbonType.fbs"; + +include "../PokeData/WazaSet.fbs"; +include "../Entity/ParamSet.fbs"; +include "../Shared/WazaType.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table PokeDataEventBattle { + DevId:DevID = DEV_NULL; + FormId:short; + Sex:SexType; + Level:int; + RareType:RareType; + TalentType:TalentType; + TalentVnum:byte; + TalentValue:ParamSet (required); + EffortValue:ParamSet (required); + Item:ItemID = ITEMID_NONE; + DropItem:ItemID = ITEMID_NONE; + DropItemNum:byte; + Seikaku:SeikakuType; + SeikakuHosei:SeikakuType; + Tokusei:TokuseiType; + WazaType:WazaType; + Waza1:WazaSet (required); + Waza2:WazaSet (required); + Waza3:WazaSet (required); + Waza4:WazaSet (required); + ScaleType:SizeType; + ScaleValue:short; + SetRibbon:RibbonType; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataFull.fbs b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataFull.fbs new file mode 100644 index 00000000..c4b58d0d --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataFull.fbs @@ -0,0 +1,64 @@ +include "../Shared/DevID.fbs"; +include "../Shared/SexType.fbs"; +include "../Shared/ItemID.fbs"; +include "../Shared/SeikakuType.fbs"; +include "../Shared/TokuseiType.fbs"; +include "../Shared/TalentType.fbs"; +include "../Shared/RareType.fbs"; +include "../Shared/SizeType.fbs"; + +include "../Entity/ParamSet.fbs"; +include "../Shared/LangType.fbs"; +include "../Shared/BallID.fbs"; +include "../Shared/RibbonType.fbs"; +include "../Shared/PokeMemoType.fbs"; +include "../Shared/WazaType.fbs"; +include "../PokeData/WazaSet.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table PokeDataFull { + DevId:DevID = DEV_NULL; + FormId:short; + Item:ItemID = ITEMID_NONE; + Level:int; + Sex:SexType; + Seikaku:SeikakuType; + SeikakuHosei:SeikakuType; + Tokusei:TokuseiType; + RareType:RareType; + RareTryCount:int; + TalentType:TalentType; + TalentValue:ParamSet; + TalentVnum:byte; + EffortValue:ParamSet; + Friendship:int; + ScaleType:SizeType; + ScaleValue:short; + SetPersonalRand:bool; + PersonalRand:ulong; + SetRandSeed:bool; + RandSeed:ulong; + WazaType:WazaType; + Waza1:WazaSet; + Waza2:WazaSet; + Waza3:WazaSet; + Waza4:WazaSet; + UseNickName:bool; + NicknameLabel:ulong; + ParentNameLabel:ulong; + ParentSex:SexType; + ParentLangId:LangType; + ParentMemoryCode:int; + ParentMemoryData:int; + ParentMemoryFeel:int; + ParentMemoryLevel:int; + LangId:LangType; + BallId:BallID; + SetRibbon:RibbonType; + EventFlg:bool; + WazaConfirmLevel:byte; + PokeMemo:PokeMemoType; + PokeMemoPlace:int; + TrainerId:long; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataSymbol.fbs b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataSymbol.fbs new file mode 100644 index 00000000..10ad70e2 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataSymbol.fbs @@ -0,0 +1,31 @@ +include "../Shared/DevID.fbs"; +include "../Shared/SexType.fbs"; +include "../Shared/RareType.fbs"; +include "../Shared/TalentType.fbs"; +include "../Shared/TokuseiType.fbs"; +include "../Shared/SizeType.fbs"; + +include "../PokeData/WazaSet.fbs"; +include "../Entity/ParamSet.fbs"; +include "../Shared/WazaType.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table PokeDataSymbol { + DevId:DevID = DEV_NULL; + FormId:short; + Level:int; + Sex:SexType; + RareType:RareType; + TalentType:TalentType; + TalentValue:ParamSet (required); + TalentVNum:byte; + WazaType:WazaType; + Waza1:WazaSet (required); + Waza2:WazaSet (required); + Waza3:WazaSet (required); + Waza4:WazaSet (required); + TokuseiIndex:TokuseiType; + ScaleType:SizeType; + ScaleValue:short; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataTrade.fbs b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataTrade.fbs new file mode 100644 index 00000000..c39edc66 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/PokeData/PokeDataTrade.fbs @@ -0,0 +1,45 @@ +include "../Shared/DevID.fbs"; +include "../Shared/SexType.fbs"; +include "../Shared/ItemID.fbs"; +include "../Shared/SeikakuType.fbs"; +include "../Shared/TokuseiType.fbs"; +include "../Shared/TalentType.fbs"; +include "../Shared/RareType.fbs"; +include "../Shared/SizeType.fbs"; +include "../Shared/BallID.fbs"; +include "../Shared/RibbonType.fbs"; + +include "../Entity/ParamSet.fbs"; +include "../PokeData/WazaSet.fbs"; +include "../Shared/WazaType.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table PokeDataTrade { + DevId:DevID = DEV_NULL; + FormId:short; + Level:int; + Sex:SexType; + Tokusei:TokuseiType; + RareType:RareType; + ScaleType:SizeType; + ScaleValue:short; + TalentType:TalentType; + TalentVnum:byte; + TalentValue:ParamSet; + EffortValue:ParamSet; + Item:ItemID = ITEMID_NONE; + Seikaku:SeikakuType; + SeikakuHosei:SeikakuType; + WazaType:WazaType; + Waza1:WazaSet; + Waza2:WazaSet; + Waza3:WazaSet; + Waza4:WazaSet; + BallId:BallID; + UseNickName:bool; + NicknameLabel:ulong; + ParentNameLabel:ulong; + TrainerId:long; + ParentSex:SexType; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/PokeData/WazaSet.fbs b/FlatBuffers/ZA/Shared/Schemas/PokeData/WazaSet.fbs new file mode 100644 index 00000000..ff4cb92a --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/PokeData/WazaSet.fbs @@ -0,0 +1,9 @@ +include "../Shared/WazaID.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table WazaSet { + WazaId:WazaID; + PointUp:byte; + IsPlusWaza:bool; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/PokeData/WazaSetBattle.fbs b/FlatBuffers/ZA/Shared/Schemas/PokeData/WazaSetBattle.fbs new file mode 100644 index 00000000..e70b592d --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/PokeData/WazaSetBattle.fbs @@ -0,0 +1,8 @@ +include "../Shared/WazaID.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table WazaSetBattle { + WazaId:WazaID; + IsPlusWaza:bool; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/ActivationCondition.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/ActivationCondition.fbs new file mode 100644 index 00000000..e155c84e --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/ActivationCondition.fbs @@ -0,0 +1,9 @@ +include "../Shared/ActivationConditionElement.fbs"; +include "../Shared/TriggerCommand.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table ActivationCondition { + Element:[ActivationConditionElement]; + Triggers:[TriggerCommand]; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/ActivationConditionElement.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/ActivationConditionElement.fbs new file mode 100644 index 00000000..da7245e5 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/ActivationConditionElement.fbs @@ -0,0 +1,7 @@ +include "../Shared/ActivationConditionParam.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table ActivationConditionElement { + Param:[ActivationConditionParam]; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/ActivationConditionParam.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/ActivationConditionParam.fbs new file mode 100644 index 00000000..f51f082c --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/ActivationConditionParam.fbs @@ -0,0 +1,7 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +table ActivationConditionParam { + Condition:string (required); + Op:int; + Param:[string]; // not required; null instead of count:0 +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/AppearanceInfo.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/AppearanceInfo.fbs new file mode 100644 index 00000000..b70b8df6 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/AppearanceInfo.fbs @@ -0,0 +1,6 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +table AppearanceInfo { + MinCount:int; + MaxCount:int; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/BallID.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/BallID.fbs new file mode 100644 index 00000000..c08c4245 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/BallID.fbs @@ -0,0 +1,43 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum BallID : ubyte +{ + BALL_NULL = 0, + MASUTAABOORU = 1, + HAIPAABOORU = 2, + SUUPAABOORU = 3, + MONSUTAABOORU = 4, + SAFARIBOORU = 5, + NETTOBOORU = 6, + DAIBUBOORU = 7, + NESUTOBOORU = 8, + RIPIITOBOORU = 9, + TAIMAABOORU = 10, + GOOZYASUBOORU = 11, + PUREMIABOORU = 12, + DAAKUBOORU = 13, + HIIRUBOORU = 14, + KUIKKUBOORU = 15, + PURESYASUBOORU = 16, + SUPIIDOBOORU = 17, + REBERUBOORU = 18, + RUAABOORU = 19, + HEBIIBOORU = 20, + RABURABUBOORU = 21, + HURENDOBOORU = 22, + MUUNBOORU = 23, + KONPEBOORU = 24, + DORIIMUBOORU = 25, + URUTORABOORU = 26, + SUTORENZIBOORU = 27, + MONSUTAABOORU_HA = 28, + SUUPAABOORU_HA = 29, + HAIPAABOORU_HA = 30, + HUHEZAABOORU = 31, + UINGUBOORU = 32, + ZIHETOBOORU = 33, + HEBIIBOORU_HA = 34, + MEGATONBOORU = 35, + GIGANTOBOORU = 36, + ORIZINBOORU = 37, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/BattleType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/BattleType.fbs new file mode 100644 index 00000000..0ea2d8ec --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/BattleType.fbs @@ -0,0 +1,7 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum BattleType : int { + SINGLE = 0, + DOUBLE = 1, + MULTI = 2, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/ClerkType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/ClerkType.fbs new file mode 100644 index 00000000..073f77a8 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/ClerkType.fbs @@ -0,0 +1,6 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum ClerkType : int { + CLERK = 0, + NO_CLERK = 1, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/CondEnum.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/CondEnum.fbs new file mode 100644 index 00000000..0555e1e5 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/CondEnum.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum CondEnum : int { + NONE = 0, + SYSTEM_FLAG = 1, + SCENARIO = 2, + GYMBADGENUM = 3, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/CoolTimeInfo.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/CoolTimeInfo.fbs new file mode 100644 index 00000000..b9ce07a7 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/CoolTimeInfo.fbs @@ -0,0 +1,5 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +table CoolTimeInfo { + Time:float; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/DataType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/DataType.fbs new file mode 100644 index 00000000..ab00dddf --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/DataType.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum DataType : int { + NORMAL = 0, + ITEM = 1, + WAZA = 2, + MULTI = 3, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/DevID.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/DevID.fbs new file mode 100644 index 00000000..0cdb5d70 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/DevID.fbs @@ -0,0 +1,1031 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +/// Internal Species ID (not National Dex ID) +enum DevID : ushort { + DEV_NULL = 0, + DEV_HUSIGIDANE = 1, + DEV_HUSIGISOU = 2, + DEV_HUSIGIBANA = 3, + DEV_HITOKAGE = 4, + DEV_RIZAADO = 5, + DEV_RIZAADON = 6, + DEV_ZENIGAME = 7, + DEV_KAMEERU = 8, + DEV_KAMEKKUSU = 9, + DEV_KYATAPII = 10, + DEV_TORANSERU = 11, + DEV_BATAHURII = 12, + DEV_BIIDORU = 13, + DEV_KOKUUN = 14, + DEV_SUPIAA = 15, + DEV_POPPO = 16, + DEV_PIZYON = 17, + DEV_PIZYOTTO = 18, + DEV_KORATTA = 19, + DEV_RATTA = 20, + DEV_ONISUZUME = 21, + DEV_ONIDORIRU = 22, + DEV_AABO = 23, + DEV_AABOKKU = 24, + DEV_PIKATYUU = 25, + DEV_RAITYUU = 26, + DEV_SANDO = 27, + DEV_SANDOPAN = 28, + DEV_NIDORAN_F = 29, + DEV_NIDORIINA = 30, + DEV_NIDOKUIN = 31, + DEV_NIDORAN_M = 32, + DEV_NIDORIINO = 33, + DEV_NIDOKINGU = 34, + DEV_PIPPI = 35, + DEV_PIKUSII = 36, + DEV_ROKON = 37, + DEV_KYUUKON = 38, + DEV_PURIN = 39, + DEV_PUKURIN = 40, + DEV_ZUBATTO = 41, + DEV_GORUBATTO = 42, + DEV_NAZONOKUSA = 43, + DEV_KUSAIHANA = 44, + DEV_RAHURESIA = 45, + DEV_PARASU = 46, + DEV_PARASEKUTO = 47, + DEV_KONPAN = 48, + DEV_MORUFON = 49, + DEV_DHIGUDA = 50, + DEV_DAGUTORIO = 51, + DEV_NYAASU = 52, + DEV_PERUSIAN = 53, + DEV_KODAKKU = 54, + DEV_GORUDAKKU = 55, + DEV_MANKII = 56, + DEV_OKORIZARU = 57, + DEV_GAADHI = 58, + DEV_UINDHI = 59, + DEV_NYOROMO = 60, + DEV_NYOROZO = 61, + DEV_NYOROBON = 62, + DEV_KEESHI = 63, + DEV_YUNGERAA = 64, + DEV_HUUDHIN = 65, + DEV_WANRIKII = 66, + DEV_GOORIKII = 67, + DEV_KAIRIKII = 68, + DEV_MADATUBOMI = 69, + DEV_UTUDON = 70, + DEV_UTUBOTTO = 71, + DEV_MENOKURAGE = 72, + DEV_DOKUKURAGE = 73, + DEV_ISITUBUTE = 74, + DEV_GOROON = 75, + DEV_GOROONYA = 76, + DEV_PONIITA = 77, + DEV_GYAROPPU = 78, + DEV_YADON = 79, + DEV_YADORAN = 80, + DEV_KOIRU = 81, + DEV_REAKOIRU = 82, + DEV_KAMONEGI = 83, + DEV_DOODOO = 84, + DEV_DOODORIO = 85, + DEV_PAUWAU = 86, + DEV_ZYUGON = 87, + DEV_BETOBETAA = 88, + DEV_BETOBETON = 89, + DEV_SHERUDAA = 90, + DEV_PARUSHEN = 91, + DEV_GOOSU = 92, + DEV_GOOSUTO = 93, + DEV_GENGAA = 94, + DEV_IWAAKU = 95, + DEV_SURIIPU = 96, + DEV_SURIIPAA = 97, + DEV_KURABU = 98, + DEV_KINGURAA = 99, + DEV_BIRIRIDAMA = 100, + DEV_MARUMAIN = 101, + DEV_TAMATAMA = 102, + DEV_NASSII = 103, + DEV_KARAKARA = 104, + DEV_GARAGARA = 105, + DEV_SAWAMURAA = 106, + DEV_EBIWARAA = 107, + DEV_BERORINGA = 108, + DEV_DOGAASU = 109, + DEV_MATADOGASU = 110, + DEV_SAIHOON = 111, + DEV_SAIDON = 112, + DEV_RAKKII = 113, + DEV_MONZYARA = 114, + DEV_GARUURA = 115, + DEV_TATTUU = 116, + DEV_SIIDORA = 117, + DEV_TOSAKINTO = 118, + DEV_AZUMAOU = 119, + DEV_HITODEMAN = 120, + DEV_SUTAAMII = 121, + DEV_BARIYAADO = 122, + DEV_SUTORAIKU = 123, + DEV_RUUZYURA = 124, + DEV_EREBUU = 125, + DEV_BUUBAA = 126, + DEV_KAIROSU = 127, + DEV_KENTAROSU = 128, + DEV_KOIKINGU = 129, + DEV_GYARADOSU = 130, + DEV_RAPURASU = 131, + DEV_METAMON = 132, + DEV_IIBUI = 133, + DEV_SYAWAAZU = 134, + DEV_SANDAASU = 135, + DEV_BUUSUTAA = 136, + DEV_PORIGON = 137, + DEV_OMUNAITO = 138, + DEV_OMUSUTAA = 139, + DEV_KABUTO = 140, + DEV_KABUTOPUSU = 141, + DEV_PUTERA = 142, + DEV_KABIGON = 143, + DEV_HURIIZAA = 144, + DEV_SANDAA = 145, + DEV_FAIYAA = 146, + DEV_MINIRYUU = 147, + DEV_HAKURYUU = 148, + DEV_KAIRYUU = 149, + DEV_MYUUTUU = 150, + DEV_MYUU = 151, + DEV_TIKORIITA = 152, + DEV_BEIRIIHU = 153, + DEV_MEGANIUMU = 154, + DEV_HINOARASI = 155, + DEV_MAGUMARASI = 156, + DEV_BAKUHUUN = 157, + DEV_WANINOKO = 158, + DEV_ARIGEITU = 159, + DEV_OODAIRU = 160, + DEV_OTATI = 161, + DEV_OOTATI = 162, + DEV_HOOHOO = 163, + DEV_YORUNOZUKU = 164, + DEV_REDHIBA = 165, + DEV_REDHIAN = 166, + DEV_ITOMARU = 167, + DEV_ARIADOSU = 168, + DEV_KUROBATTO = 169, + DEV_TYONTII = 170, + DEV_RANTAAN = 171, + DEV_PITYUU = 172, + DEV_PHI = 173, + DEV_PUPURIN = 174, + DEV_TOGEPII = 175, + DEV_TOGETIKKU = 176, + DEV_NEITHI = 177, + DEV_NEITHIO = 178, + DEV_MERIIPU = 179, + DEV_MOKOKO = 180, + DEV_DENRYUU = 181, + DEV_KIREIHANA = 182, + DEV_MARIRU = 183, + DEV_MARIRURI = 184, + DEV_USOKKII = 185, + DEV_NYOROTONO = 186, + DEV_HANEKKO = 187, + DEV_POPOKKO = 188, + DEV_WATAKKO = 189, + DEV_EIPAMU = 190, + DEV_HIMANATTU = 191, + DEV_KIMAWARI = 192, + DEV_YANYANMA = 193, + DEV_UPAA = 194, + DEV_NUOO = 195, + DEV_EEFI = 196, + DEV_BURAKKII = 197, + DEV_YAMIKARASU = 198, + DEV_YADOKINGU = 199, + DEV_MUUMA = 200, + DEV_ANNOON = 201, + DEV_SOONANSU = 202, + DEV_KIRINRIKI = 203, + DEV_KUNUGIDAMA = 204, + DEV_FORETOSU = 205, + DEV_NOKOTTI = 206, + DEV_GURAIGAA = 207, + DEV_HAGANEERU = 208, + DEV_BURUU = 209, + DEV_GURANBURU = 210, + DEV_HARIISEN = 211, + DEV_HASSAMU = 212, + DEV_TUBOTUBO = 213, + DEV_HERAKUROSU = 214, + DEV_NYUURA = 215, + DEV_HIMEGUMA = 216, + DEV_RINGUMA = 217, + DEV_MAGUMAGGU = 218, + DEV_MAGUKARUGO = 219, + DEV_URIMUU = 220, + DEV_INOMUU = 221, + DEV_SANIIGO = 222, + DEV_TEPPOUO = 223, + DEV_OKUTAN = 224, + DEV_DERIBAADO = 225, + DEV_MANTAIN = 226, + DEV_EAAMUDO = 227, + DEV_DERUBIRU = 228, + DEV_HERUGAA = 229, + DEV_KINGUDORA = 230, + DEV_GOMAZOU = 231, + DEV_DONFAN = 232, + DEV_PORIGON2 = 233, + DEV_ODOSISI = 234, + DEV_DOOBURU = 235, + DEV_BARUKII = 236, + DEV_KAPOERAA = 237, + DEV_MUTYUURU = 238, + DEV_EREKIDDO = 239, + DEV_BUBHI = 240, + DEV_MIRUTANKU = 241, + DEV_HAPINASU = 242, + DEV_RAIKOU = 243, + DEV_ENTEI = 244, + DEV_SUIKUN = 245, + DEV_YOOGIRASU = 246, + DEV_SANAGIRASU = 247, + DEV_BANGIRASU = 248, + DEV_RUGIA = 249, + DEV_HOUOU = 250, + DEV_SEREBHI = 251, + DEV_KIMORI = 252, + DEV_ZYUPUTORU = 253, + DEV_ZYUKAIN = 254, + DEV_ATYAMO = 255, + DEV_WAKASYAMO = 256, + DEV_BASYAAMO = 257, + DEV_MIZUGOROU = 258, + DEV_NUMAKUROO = 259, + DEV_RAGURAAZI = 260, + DEV_POTIENA = 261, + DEV_GURAENA = 262, + DEV_ZIGUZAGUMA = 263, + DEV_MASSUGUMA = 264, + DEV_KEMUSSO = 265, + DEV_KARASARISU = 266, + DEV_AGEHANTO = 267, + DEV_MAYURUDO = 268, + DEV_DOKUKEIRU = 269, + DEV_HASUBOO = 270, + DEV_HASUBURERO = 271, + DEV_RUNPAPPA = 272, + DEV_TANEBOO = 273, + DEV_KONOHANA = 274, + DEV_DAATENGU = 275, + DEV_SUBAME = 276, + DEV_OOSUBAME = 277, + DEV_KYAMOME = 278, + DEV_PERIPPAA = 279, + DEV_RARUTOSU = 280, + DEV_KIRURIA = 281, + DEV_SAANAITO = 282, + DEV_AMETAMA = 283, + DEV_AMEMOOSU = 284, + DEV_KINOKOKO = 285, + DEV_KINOGASSA = 286, + DEV_NAMAKERO = 287, + DEV_YARUKIMONO = 288, + DEV_KEKKINGU = 289, + DEV_TUTININ = 290, + DEV_TEKKANIN = 291, + DEV_NUKENIN = 292, + DEV_GONYONYO = 293, + DEV_DOGOOMU = 294, + DEV_BAKUONGU = 295, + DEV_MAKUNOSITA = 296, + DEV_HARITEYAMA = 297, + DEV_RURIRI = 298, + DEV_NOZUPASU = 299, + DEV_ENEKO = 300, + DEV_ENEKORORO = 301, + DEV_YAMIRAMI = 302, + DEV_KUTIITO = 303, + DEV_KOKODORA = 304, + DEV_KODORA = 305, + DEV_BOSUGODORA = 306, + DEV_ASANAN = 307, + DEV_TYAAREMU = 308, + DEV_RAKURAI = 309, + DEV_RAIBORUTO = 310, + DEV_PURASURU = 311, + DEV_MAINAN = 312, + DEV_BARUBIITO = 313, + DEV_IRUMIIZE = 314, + DEV_ROZERIA = 315, + DEV_GOKURIN = 316, + DEV_MARUNOOMU = 317, + DEV_KIBANIA = 318, + DEV_SAMEHADAA = 319, + DEV_HOERUKO = 320, + DEV_HOERUOO = 321, + DEV_DONMERU = 322, + DEV_BAKUUDA = 323, + DEV_KOOTASU = 324, + DEV_BANEBUU = 325, + DEV_BUUPIGGU = 326, + DEV_PATTIIRU = 327, + DEV_NAKKURAA = 328, + DEV_BIBURAABA = 329, + DEV_HURAIGON = 330, + DEV_SABONEA = 331, + DEV_NOKUTASU = 332, + DEV_TIRUTTO = 333, + DEV_TIRUTARISU = 334, + DEV_ZANGUUSU = 335, + DEV_HABUNEEKU = 336, + DEV_RUNATOON = 337, + DEV_SORUROKKU = 338, + DEV_DOZYOTTI = 339, + DEV_NAMAZUN = 340, + DEV_HEIGANI = 341, + DEV_SIZARIGAA = 342, + DEV_YAZIRON = 343, + DEV_NENDOORU = 344, + DEV_RIRIIRA = 345, + DEV_YUREIDORU = 346, + DEV_ANOPUSU = 347, + DEV_AAMARUDO = 348, + DEV_HINBASU = 349, + DEV_MIROKAROSU = 350, + DEV_POWARUN = 351, + DEV_KAKUREON = 352, + DEV_KAGEBOUZU = 353, + DEV_ZYUPETTA = 354, + DEV_YOMAWARU = 355, + DEV_SAMAYOORU = 356, + DEV_TOROPIUSU = 357, + DEV_TIRIIN = 358, + DEV_ABUSORU = 359, + DEV_SOONANO = 360, + DEV_YUKIWARASI = 361, + DEV_ONIGOORI = 362, + DEV_TAMAZARASI = 363, + DEV_TODOGURAA = 364, + DEV_TODOZERUGA = 365, + DEV_PAARURU = 366, + DEV_HANTEERU = 367, + DEV_SAKURABISU = 368, + DEV_ZIIRANSU = 369, + DEV_RABUKASU = 370, + DEV_TATUBEI = 371, + DEV_KOMORUU = 372, + DEV_BOOMANDA = 373, + DEV_DANBARU = 374, + DEV_METANGU = 375, + DEV_METAGUROSU = 376, + DEV_REZIROKKU = 377, + DEV_REZIAISU = 378, + DEV_REZISUTIRU = 379, + DEV_RATHIASU = 380, + DEV_RATHIOSU = 381, + DEV_KAIOOGA = 382, + DEV_GURAADON = 383, + DEV_REKKUUZA = 384, + DEV_ZIRAATI = 385, + DEV_DEOKISISU = 386, + DEV_NAETORU = 387, + DEV_HAYASIGAME = 388, + DEV_DODAITOSU = 389, + DEV_HIKOZARU = 390, + DEV_MOUKAZARU = 391, + DEV_GOUKAZARU = 392, + DEV_POTTYAMA = 393, + DEV_POTTAISI = 394, + DEV_ENPERUTO = 395, + DEV_MUKKURU = 396, + DEV_MUKUBAADO = 397, + DEV_MUKUHOOKU = 398, + DEV_BIPPA = 399, + DEV_BIIDARU = 400, + DEV_KOROBOOSI = 401, + DEV_KOROTOKKU = 402, + DEV_KORINKU = 403, + DEV_RUKUSIO = 404, + DEV_RENTORAA = 405, + DEV_SUBOMII = 406, + DEV_ROZUREIDO = 407, + DEV_ZUGAIDOSU = 408, + DEV_RAMUPARUDO = 409, + DEV_TATETOPUSU = 410, + DEV_TORIDEPUSU = 411, + DEV_MINOMUTTI = 412, + DEV_MINOMADAMU = 413, + DEV_GAAMEIRU = 414, + DEV_MITUHANII = 415, + DEV_BIIKUIN = 416, + DEV_PATIRISU = 417, + DEV_BUIZERU = 418, + DEV_HUROOZERU = 419, + DEV_THERINBO = 420, + DEV_THERIMU = 421, + DEV_KARANAKUSI = 422, + DEV_TORITODON = 423, + DEV_ETEBOOSU = 424, + DEV_HUWANTE = 425, + DEV_HUWARAIDO = 426, + DEV_MIMIRORU = 427, + DEV_MIMIROPPU = 428, + DEV_MUUMAAZI = 429, + DEV_DONKARASU = 430, + DEV_NYARUMAA = 431, + DEV_BUNYATTO = 432, + DEV_RIISYAN = 433, + DEV_SUKANPUU = 434, + DEV_SUKATANKU = 435, + DEV_DOOMIRAA = 436, + DEV_DOOTAKUN = 437, + DEV_USOHATI = 438, + DEV_MANENE = 439, + DEV_PINPUKU = 440, + DEV_PERAPPU = 441, + DEV_MIKARUGE = 442, + DEV_HUKAMARU = 443, + DEV_GABAITO = 444, + DEV_GABURIASU = 445, + DEV_GONBE = 446, + DEV_RIORU = 447, + DEV_RUKARIO = 448, + DEV_HIPOPOTASU = 449, + DEV_KABARUDON = 450, + DEV_SUKORUPI = 451, + DEV_DORAPION = 452, + DEV_GUREGGURU = 453, + DEV_DOKUROGGU = 454, + DEV_MASUKIPPA = 455, + DEV_KEIKOUO = 456, + DEV_NEORANTO = 457, + DEV_TAMANTA = 458, + DEV_YUKIKABURI = 459, + DEV_YUKINOOO = 460, + DEV_MANYUURA = 461, + DEV_ZIBAKOIRU = 462, + DEV_BEROBERUTO = 463, + DEV_DOSAIDON = 464, + DEV_MOZYANBO = 465, + DEV_EREKIBURU = 466, + DEV_BUUBAAN = 467, + DEV_TOGEKISSU = 468, + DEV_MEGAYANMA = 469, + DEV_RIIFIA = 470, + DEV_GUREISIA = 471, + DEV_GURAION = 472, + DEV_MANMUU = 473, + DEV_PORIGONz = 474, + DEV_ERUREIDO = 475, + DEV_DAINOOZU = 476, + DEV_YONOWAARU = 477, + DEV_YUKIMENOKO = 478, + DEV_ROTOMU = 479, + DEV_YUKUSII = 480, + DEV_EMURITTO = 481, + DEV_AGUNOMU = 482, + DEV_DHIARUGA = 483, + DEV_PARUKIA = 484, + DEV_HIIDORAN = 485, + DEV_REZIGIGASU = 486, + DEV_GIRATHINA = 487, + DEV_KURESERIA = 488, + DEV_FIONE = 489, + DEV_MANAFI = 490, + DEV_DAAKURAI = 491, + DEV_SHEIMI = 492, + DEV_ARUSEUSU = 493, + DEV_BIKUTHINI = 494, + DEV_TUTAAZYA = 495, + DEV_ZYANOBII = 496, + DEV_ZYAROODA = 497, + DEV_POKABU = 498, + DEV_TYAOBUU = 499, + DEV_ENBUOO = 500, + DEV_MIZYUMARU = 501, + DEV_HUTATIMARU = 502, + DEV_DAIKENKI = 503, + DEV_MINEZUMI = 504, + DEV_MIRUHOGGU = 505, + DEV_YOOTERII = 506, + DEV_HAADERIA = 507, + DEV_MUURANDO = 508, + DEV_TYORONEKO = 509, + DEV_REPARUDASU = 510, + DEV_YANAPPU = 511, + DEV_YANAKKII = 512, + DEV_BAOPPU = 513, + DEV_BAOKKII = 514, + DEV_HIYAPPU = 515, + DEV_HIYAKKII = 516, + DEV_MUNNA = 517, + DEV_MUSYAANA = 518, + DEV_MAMEPATO = 519, + DEV_HATOOBOO = 520, + DEV_KENHOROU = 521, + DEV_SIMAMA = 522, + DEV_ZEBURAIKA = 523, + DEV_DANGORO = 524, + DEV_GANTORU = 525, + DEV_GIGAIASU = 526, + DEV_KOROMORI = 527, + DEV_KOKOROMORI = 528, + DEV_MOGURYUU = 529, + DEV_DORYUUZU = 530, + DEV_TABUNNE = 531, + DEV_DOKKORAA = 532, + DEV_DOTEKKOTU = 533, + DEV_ROOBUSIN = 534, + DEV_OTAMARO = 535, + DEV_GAMAGARU = 536, + DEV_GAMAGEROGE = 537, + DEV_NAGEKI = 538, + DEV_DAGEKI = 539, + DEV_KURUMIRU = 540, + DEV_KURUMAYU = 541, + DEV_HAHAKOMORI = 542, + DEV_HUSIDE = 543, + DEV_HOIIGA = 544, + DEV_PENDORAA = 545, + DEV_MONMEN = 546, + DEV_ERUHUUN = 547, + DEV_TYURINE = 548, + DEV_DOREDHIA = 549, + DEV_BASURAO = 550, + DEV_MEGUROKO = 551, + DEV_WARUBIRU = 552, + DEV_WARUBIARU = 553, + DEV_DARUMAKKA = 554, + DEV_HIHIDARUMA = 555, + DEV_MARAKATTI = 556, + DEV_ISIZUMAI = 557, + DEV_IWAPARESU = 558, + DEV_ZURUGGU = 559, + DEV_ZURUZUKIN = 560, + DEV_SINBORAA = 561, + DEV_DESUMASU = 562, + DEV_DESUKAAN = 563, + DEV_PUROTOOGA = 564, + DEV_ABAGOORA = 565, + DEV_AAKEN = 566, + DEV_AAKEOSU = 567, + DEV_YABUKURON = 568, + DEV_DASUTODASU = 569, + DEV_ZOROA = 570, + DEV_ZOROAAKU = 571, + DEV_TIRAAMHI = 572, + DEV_TIRATIINO = 573, + DEV_GOTIMU = 574, + DEV_GOTIMIRU = 575, + DEV_GOTIRUZERU = 576, + DEV_YUNIRAN = 577, + DEV_DABURAN = 578, + DEV_RANKURUSU = 579, + DEV_KOARUHII = 580, + DEV_SUWANNA = 581, + DEV_BANIPUTTI = 582, + DEV_BANIRITTI = 583, + DEV_BAIBANIRA = 584, + DEV_SIKIZIKA = 585, + DEV_MEBUKIZIKA = 586, + DEV_EMONGA = 587, + DEV_KABURUMO = 588, + DEV_SYUBARUGO = 589, + DEV_TAMAGETAKE = 590, + DEV_MOROBARERU = 591, + DEV_PURURIRU = 592, + DEV_BURUNGERU = 593, + DEV_MAMANBOU = 594, + DEV_BATYURU = 595, + DEV_DENTYURA = 596, + DEV_TESSIIDO = 597, + DEV_NATTOREI = 598, + DEV_GIARU = 599, + DEV_GIGIARU = 600, + DEV_GIGIGIARU = 601, + DEV_SIBISIRASU = 602, + DEV_SIBIBIIRU = 603, + DEV_SIBIRUDON = 604, + DEV_RIGUREE = 605, + DEV_OOBEMU = 606, + DEV_HITOMOSI = 607, + DEV_RANPURAA = 608, + DEV_SYANDERA = 609, + DEV_KIBAGO = 610, + DEV_ONONDO = 611, + DEV_ONONOKUSU = 612, + DEV_KUMASYUN = 613, + DEV_TUNBEAA = 614, + DEV_HURIIZIO = 615, + DEV_TYOBOMAKI = 616, + DEV_AGIRUDAA = 617, + DEV_MAGGYO = 618, + DEV_KOZYOHUU = 619, + DEV_KOZYONDO = 620, + DEV_KURIMUGAN = 621, + DEV_GOBITTO = 622, + DEV_GORUUGU = 623, + DEV_KOMATANA = 624, + DEV_KIRIKIZAN = 625, + DEV_BAHHURON = 626, + DEV_WASIBON = 627, + DEV_WHOOGURU = 628, + DEV_BARUTYAI = 629, + DEV_BARUZIINA = 630, + DEV_KUITARAN = 631, + DEV_AIANTO = 632, + DEV_MONOZU = 633, + DEV_ZIHEDDO = 634, + DEV_SAZANDORA = 635, + DEV_MERARUBA = 636, + DEV_URUGAMOSU = 637, + DEV_KOBARUON = 638, + DEV_TERAKION = 639, + DEV_BIRIZION = 640, + DEV_TORUNEROSU = 641, + DEV_BORUTOROSU = 642, + DEV_RESIRAMU = 643, + DEV_ZEKUROMU = 644, + DEV_RANDOROSU = 645, + DEV_KYUREMU = 646, + DEV_KERUDHIO = 647, + DEV_MEROETTA = 648, + DEV_GENOSEKUTO = 649, + DEV_HARIMARON = 650, + DEV_HARIBOOGU = 651, + DEV_BURIGARON = 652, + DEV_FOKKO = 653, + DEV_TEERUNAA = 654, + DEV_MAFOKUSII = 655, + DEV_KEROMATU = 656, + DEV_GEKOGASIRA = 657, + DEV_GEKKOUGA = 658, + DEV_HORUBII = 659, + DEV_HORUUDO = 660, + DEV_YAYAKOMA = 661, + DEV_HINOYAKOMA = 662, + DEV_FAIAROO = 663, + DEV_KOHUKIMUSI = 664, + DEV_KOHUURAI = 665, + DEV_BIBIYON = 666, + DEV_SISIKO = 667, + DEV_KAENZISI = 668, + DEV_HURABEBE = 669, + DEV_HURAETTE = 670, + DEV_HURAAJESU = 671, + DEV_MHEEKURU = 672, + DEV_GOOGOOTO = 673, + DEV_YANTYAMU = 674, + DEV_GORONDA = 675, + DEV_TORIMIAN = 676, + DEV_NYASUPAA = 677, + DEV_NYAONIKUSU = 678, + DEV_HITOTUKI = 679, + DEV_NIDANGIRU = 680, + DEV_GIRUGARUDO = 681, + DEV_SYUSYUPU = 682, + DEV_HUREHUWAN = 683, + DEV_PEROPPAHU = 684, + DEV_PERORIIMU = 685, + DEV_MAAIIKA = 686, + DEV_KARAMANERO = 687, + DEV_KAMETETE = 688, + DEV_GAMENODESU = 689, + DEV_KUZUMOO = 690, + DEV_DORAMIDORO = 691, + DEV_UDEPPOU = 692, + DEV_BUROSUTAA = 693, + DEV_ERIKITERU = 694, + DEV_EREZAADO = 695, + DEV_TIGORASU = 696, + DEV_GATIGORASU = 697, + DEV_AMARUSU = 698, + DEV_AMARURUGA = 699, + DEV_NINFIA = 700, + DEV_RUTYABURU = 701, + DEV_DEDENNE = 702, + DEV_MERESII = 703, + DEV_NUMERA = 704, + DEV_NUMEIRU = 705, + DEV_NUMERUGON = 706, + DEV_KUREHFI = 707, + DEV_BOKUREE = 708, + DEV_OOROTTO = 709, + DEV_BAKETTYA = 710, + DEV_PANPUZIN = 711, + DEV_KATIKOORU = 712, + DEV_KUREBEESU = 713, + DEV_ONBATTO = 714, + DEV_ONBAAN = 715, + DEV_ZERUNEASU = 716, + DEV_IBERUTARU = 717, + DEV_ZIGARUDE = 718, + DEV_DHIANSII = 719, + DEV_HUUPA = 720, + DEV_BORUKENION = 721, + DEV_MOKUROO = 722, + DEV_HUKUSUROO = 723, + DEV_ZYUNAIPAA = 724, + DEV_NYABII = 725, + DEV_NYAHIITO = 726, + DEV_GAOGAEN = 727, + DEV_ASIMARI = 728, + DEV_OSYAMARI = 729, + DEV_ASIREENU = 730, + DEV_TUTUKERA = 731, + DEV_KERARAPPA = 732, + DEV_DODEKABASI = 733, + DEV_YANGUUSU = 734, + DEV_DEKAGUUSU = 735, + DEV_AGOZIMUSI = 736, + DEV_DENDIMUSI = 737, + DEV_KUWAGANON = 738, + DEV_MAKENKANI = 739, + DEV_KEKENKANI = 740, + DEV_ODORIDORI = 741, + DEV_ABURII = 742, + DEV_ABURIBON = 743, + DEV_IWANKO = 744, + DEV_RUGARUGAN = 745, + DEV_YOWASI = 746, + DEV_HIDOIDE = 747, + DEV_DOHIDOIDE = 748, + DEV_DOROBANKO = 749, + DEV_BANBADORO = 750, + DEV_SIZUKUMO = 751, + DEV_ONISIZUKUMO = 752, + DEV_KARIKIRI = 753, + DEV_RARANTESU = 754, + DEV_NEMASYU = 755, + DEV_MASHEEDO = 756, + DEV_YATOUMORI = 757, + DEV_ENNYUUTO = 758, + DEV_NUIKOGUMA = 759, + DEV_KITERUGUMA = 760, + DEV_AMAKAZI = 761, + DEV_AMAMAIKO = 762, + DEV_AMAAZYO = 763, + DEV_KYUWAWAA = 764, + DEV_YAREYUUTAN = 765, + DEV_NAGETUKESARU = 766, + DEV_KOSOKUMUSI = 767, + DEV_GUSOKUMUSYA = 768, + DEV_SUNABHA = 769, + DEV_SIRODESUNA = 770, + DEV_NAMAKOBUSI = 771, + DEV_TAIPUNURU = 772, + DEV_SIRUVHADHI = 773, + DEV_METENO = 774, + DEV_NEKKOARA = 775, + DEV_BAKUGAMESU = 776, + DEV_TOGEDEMARU = 777, + DEV_MIMIKKYU = 778, + DEV_HAGIGISIRI = 779, + DEV_ZIZIIRON = 780, + DEV_DADARIN = 781, + DEV_ZYARAKO = 782, + DEV_ZYARANGO = 783, + DEV_ZYARARANGA = 784, + DEV_KAPUKOKEKO = 785, + DEV_KAPUTETEHU = 786, + DEV_KAPUBURURU = 787, + DEV_KAPUREHIRE = 788, + DEV_KOSUMOGGU = 789, + DEV_KOSUMOUMU = 790, + DEV_SORUGAREO = 791, + DEV_RUNAAARA = 792, + DEV_UTUROIDO = 793, + DEV_MASSIBUUN = 794, + DEV_FEROOTHE = 795, + DEV_DENZYUMOKU = 796, + DEV_TEKKAGUYA = 797, + DEV_KAMITURUGI = 798, + DEV_AKUZIKINGU = 799, + DEV_NEKUROZUMA = 800, + DEV_MAGIANA = 801, + DEV_MAASYADOO = 802, + DEV_BEBENOMU = 803, + DEV_AAGOYON = 804, + DEV_TUNDETUNDE = 805, + DEV_ZUGADOON = 806, + DEV_ZERAORA = 807, + DEV_MERUTAN = 808, + DEV_MERUMETARU = 809, + DEV_SARUNORI = 810, + DEV_BATINKII = 811, + DEV_GORIRANDAA = 812, + DEV_HIBANII = 813, + DEV_RABIHUTTO = 814, + DEV_EESUBAAN = 815, + DEV_MESSON = 816, + DEV_ZIMEREON = 817, + DEV_INTEREON = 818, + DEV_HOSIGARISU = 819, + DEV_YOKUBARISU = 820, + DEV_KOKOGARA = 821, + DEV_AOGARASU = 822, + DEV_AAMAAGAA = 823, + DEV_SATTIMUSI = 824, + DEV_REDOOMUSI = 825, + DEV_IORUBU = 826, + DEV_KUSUNE = 827, + DEV_FOKUSURAI = 828, + DEV_HIMENKA = 829, + DEV_WATASIRAGA = 830, + DEV_UURUU = 831, + DEV_BAIUURUU = 832, + DEV_KAMUKAME = 833, + DEV_KAZIRIGAME = 834, + DEV_WANPATI = 835, + DEV_PARUSUWAN = 836, + DEV_TANDON = 837, + DEV_TOROGGON = 838, + DEV_SEKITANZAN = 839, + DEV_KAZITTYU = 840, + DEV_APPURYUU = 841, + DEV_TARUPPURU = 842, + DEV_SUNAHEBI = 843, + DEV_SADAIZYA = 844, + DEV_UUU = 845, + DEV_SASIKAMASU = 846, + DEV_KAMASUZYOO = 847, + DEV_EREZUN = 848, + DEV_SUTORINDAA = 849, + DEV_YAKUDE = 850, + DEV_MARUYAKUDE = 851, + DEV_TATAKKO = 852, + DEV_OTOSUPASU = 853, + DEV_YABATYA = 854, + DEV_POTTODESU = 855, + DEV_MIBURIMU = 856, + DEV_TEBURIMU = 857, + DEV_BURIMUON = 858, + DEV_BEROBAA = 859, + DEV_GIMOO = 860, + DEV_OORONGE = 861, + DEV_TATIHUSAGUMA = 862, + DEV_NYAIKINGU = 863, + DEV_SANIGOON = 864, + DEV_NEGIGANAITO = 865, + DEV_BARIKOORU = 866, + DEV_DESUBAAN = 867, + DEV_MAHOMIRU = 868, + DEV_MAHOIPPU = 869, + DEV_TAIREETU = 870, + DEV_BATINUNI = 871, + DEV_YUKIHAMI = 872, + DEV_MOSUNOU = 873, + DEV_ISIHENZIN = 874, + DEV_KOORIPPO = 875, + DEV_IESSAN = 876, + DEV_MORUPEKO = 877, + DEV_ZOUDOU = 878, + DEV_DAIOUDOU = 879, + DEV_PATTIRAGON = 880, + DEV_PATTIRUDON = 881, + DEV_UONORAGON = 882, + DEV_UOTIRUDON = 883, + DEV_ZYURARUDON = 884, + DEV_DORAMESIYA = 885, + DEV_DORONTI = 886, + DEV_DORAPARUTO = 887, + DEV_ZASIAN = 888, + DEV_ZAMAZENTA = 889, + DEV_MUGENDAINA = 890, + DEV_AAMAA1 = 891, + DEV_AAMAA2 = 892, + DEV_m23 = 893, + DEV_REDEN = 894, + DEV_REDORA = 895, + DEV_HAKUBA = 896, + DEV_KOKUBA = 897, + DEV_KURAUN = 898, + DEV_ODOSISI2 = 899, + DEV_SUTORAIKU2 = 900, + DEV_HIMEGUMA3 = 901, + DEV_rBASURAO2 = 902, + DEV_rNYUURA2 = 903, + DEV_rHARISEN2 = 904, + DEV_FEATOROSU = 905, + DEV_NEKO1 = 906, + DEV_NEKO2 = 907, + DEV_NEKO3 = 908, + DEV_WANI1 = 909, + DEV_WANI2 = 910, + DEV_WANI3 = 911, + DEV_KAMO1 = 912, + DEV_KAMO2 = 913, + DEV_KAMO3 = 914, + DEV_BUTA1 = 915, + DEV_BUTA2 = 916, + DEV_NOKOTTI2 = 917, + DEV_KUMO1 = 918, + DEV_KUMO2 = 919, + DEV_BATTA1 = 920, + DEV_BATTA2 = 921, + DEV_SUKARABE1 = 922, + DEV_SUKARABE2 = 923, + DEV_OBAKEINU1 = 924, + DEV_OBAKEINU2 = 925, + DEV_DATYOU1 = 926, + DEV_DATYOU2 = 927, + DEV_KIRINRIKI2 = 928, + DEV_UMIDHIGUDA = 929, + DEV_UMITORIO = 930, + DEV_OYAKATA = 931, + DEV_MERURUUSA = 932, + DEV_IRUKA1 = 933, + DEV_IRUKA2 = 934, + DEV_ORIIBU1 = 935, + DEV_ORIIBU2 = 936, + DEV_ORIIBU3 = 937, + DEV_HABANERO1 = 938, + DEV_HABANERO2 = 939, + DEV_KAERU1 = 940, + DEV_KAERU2 = 941, + DEV_ENZIN1 = 942, + DEV_ENZIN2 = 943, + DEV_MIMIZU = 944, + DEV_NEZUMI1 = 945, + DEV_NEZUMI2 = 946, + DEV_OKAKUZIRA1 = 947, + DEV_OKAKUZIRA2 = 948, + DEV_KOORIDORA1 = 949, + DEV_KOORIDORA2 = 950, + DEV_KOORIDORA3 = 951, + DEV_SUSIDORA = 952, + DEV_BAIKU = 953, + DEV_MAAMOTTO1 = 954, + DEV_MAAMOTTO2 = 955, + DEV_MAAMOTTO3 = 956, + DEV_MIZUDORI1 = 957, + DEV_MIZUDORI2 = 958, + DEV_KOUNOTORI = 959, + DEV_INKO = 960, + DEV_HURAMINGO = 961, + DEV_KEGANI = 962, + DEV_GANEN1 = 963, + DEV_GANEN2 = 964, + DEV_GANEN3 = 965, + DEV_KARUKAN1 = 966, + DEV_KARUKAN2 = 967, + DEV_AIAI1 = 968, + DEV_AIAI2 = 969, + DEV_PANINU1 = 970, + DEV_PANINU2 = 971, + DEV_MASUTHIHU1 = 972, + DEV_MASUTHIHU2 = 973, + DEV_TANBURU1 = 974, + DEV_TANBURU2 = 975, + DEV_KOIN1 = 976, + DEV_KOIN2 = 977, + DEV_ADONFAN = 978, + DEV_AMOROBARERU = 979, + DEV_AKETUBAN = 980, + DEV_AREAKOIRU = 981, + DEV_APURIN = 982, + DEV_AMUUMA = 983, + DEV_AURUGAMOSU = 984, + DEV_AAAAA = 985, + DEV_BDONFAN = 986, + DEV_BKETUBAN = 987, + DEV_BURUGAMOSU = 988, + DEV_BHARITEYAMA = 989, + DEV_BSAZANDORA = 990, + DEV_BBANGIRASU = 991, + DEV_BKOORI = 992, + DEV_BBBBB = 993, + DEV_ZYUNDEN1 = 994, + DEV_ZYUNDEN2 = 995, + DEV_ZYUNDEN3 = 996, + DEV_ZYUNDEN4 = 997, + DEV_AIGUANA = 998, + DEV_BIGUANA = 999, + DEV_FEARII1 = 1000, + DEV_FEARII2 = 1001, + DEV_FEARII3 = 1002, + DEV_HINOKO1 = 1003, + DEV_HINOKO2A = 1004, + DEV_HINOKO2B = 1005, + DEV_OKAKINGU = 1006, + DEV_OKAGYARADOSU = 1007, + DEV_KOMATANA3 = 1008, + DEV_rUPAA2 = 1009, + DEV_MANKII3 = 1010, + DEV_KAMENONI = 1011, + DEV_KAZITTYU2 = 1012, + DEV_KAZITTYU3 = 1013, + DEV_DOKUINU = 1014, + DEV_DOKUZARU = 1015, + DEV_DOKUKIZI = 1016, + DEV_AENTEI = 1017, + DEV_ARAIKOU = 1018, + DEV_BKOBARUON = 1019, + DEV_BTERAKION = 1020, + DEV_KODAIGAME = 1021, + DEV_DOKUTAROU = 1022, + DEV_ZYURARUDO2 = 1023, + DEV_MATCHA1 = 1024, + DEV_MATCHA2 = 1025, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/HoldItem.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/HoldItem.fbs new file mode 100644 index 00000000..034416d9 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/HoldItem.fbs @@ -0,0 +1,5 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +table HoldItem { + ItemId:int; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/ItemID.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/ItemID.fbs new file mode 100644 index 00000000..7a1affed --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/ItemID.fbs @@ -0,0 +1,571 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum ItemID : int +{ + ITEMID_NONE = 0, + ITEMID_MASUTAABOORU = 1, + ITEMID_HAIPAABOORU = 2, + ITEMID_SUUPAABOORU = 3, + ITEMID_MONSUTAABOORU = 4, + ITEMID_SAFARIBOORU = 5, + ITEMID_NETTOBOORU = 6, + ITEMID_DAIBUBOORU = 7, + ITEMID_NESUTOBOORU = 8, + ITEMID_RIPIITOBOORU = 9, + ITEMID_TAIMAABOORU = 10, + ITEMID_GOOZYASUBOORU = 11, + ITEMID_PUREMIABOORU = 12, + ITEMID_DAAKUBOORU = 13, + ITEMID_HIIRUBOORU = 14, + ITEMID_KUIKKUBOORU = 15, + ITEMID_PURESYASUBOORU = 16, + ITEMID_KIZUGUSURI = 17, + ITEMID_DOKUKESI = 18, + ITEMID_YAKEDONAOSI = 19, + ITEMID_KOORINAOSI = 20, + ITEMID_NEMUKEZAMASI = 21, + ITEMID_MAHINAOSI = 22, + ITEMID_KAIHUKUNOKUSURI = 23, + ITEMID_MANTANNOKUSURI = 24, + ITEMID_SUGOIKIZUGUSURI = 25, + ITEMID_IIKIZUGUSURI = 26, + ITEMID_NANDEMONAOSI = 27, + ITEMID_GENKINOKAKERA = 28, + ITEMID_GENKINOKATAMARI = 29, + ITEMID_OISIIMIZU = 30, + ITEMID_SAIKOSOODA = 31, + ITEMID_MIKKUSUORE = 32, + ITEMID_MOOMOOMIRUKU = 33, + ITEMID_MAKKUSUAPPU = 45, + ITEMID_TAURIN = 46, + ITEMID_BUROMUHEKISIN = 47, + ITEMID_INDOMETASIN = 48, + ITEMID_RIZOTIUMU = 49, + ITEMID_HUSIGINAAME = 50, + ITEMID_KITOSAN = 52, + ITEMID_EFEKUTOGAADO = 55, + ITEMID_KURITHIKATTO = 56, + ITEMID_PURASUPAWAA = 57, + ITEMID_DHIFENDAA = 58, + ITEMID_SUPIIDAA = 59, + ITEMID_YOKUATAARU = 60, + ITEMID_SUPESYARUAPPU = 61, + ITEMID_SUPESYARUGAADO = 62, + ITEMID_SIRUBAASUPUREE = 76, + ITEMID_GOORUDOSUPUREE = 77, + ITEMID_MUSIYOKESUPUREE = 79, + ITEMID_TAIYOUNOISI = 80, + ITEMID_TUKINOISI = 81, + ITEMID_HONOONOISI = 82, + ITEMID_KAMINARINOISI = 83, + ITEMID_MIZUNOISI = 84, + ITEMID_RIIHUNOISI = 85, + ITEMID_TIISANAKINOKO = 86, + ITEMID_SINZYU = 88, + ITEMID_OOKINASINZYU = 89, + ITEMID_KINNOTAMA = 92, + ITEMID_HIMITUNOKOHAKU = 103, + ITEMID_HIKARINOISI = 107, + ITEMID_YAMINOISI = 108, + ITEMID_MEZAMEISI = 109, + ITEMID_KURABONOMI = 149, + ITEMID_KAGONOMI = 150, + ITEMID_MOMONNOMI = 151, + ITEMID_TIIGONOMI = 152, + ITEMID_NANASINOMI = 153, + ITEMID_ORENNOMI = 155, + ITEMID_KIINOMI = 156, + ITEMID_RAMUNOMI = 157, + ITEMID_OBONNOMI = 158, + ITEMID_FIRANOMI = 159, + ITEMID_UINOMI = 160, + ITEMID_MAGONOMI = 161, + ITEMID_BANZINOMI = 162, + ITEMID_IANOMI = 163, + ITEMID_ZAROKUNOMI = 169, + ITEMID_NEKOBUNOMI = 170, + ITEMID_TAPORUNOMI = 171, + ITEMID_ROMENOMI = 172, + ITEMID_UBUNOMI = 173, + ITEMID_MATOMANOMI = 174, + ITEMID_OKKANOMI = 184, + ITEMID_ITOKENOMI = 185, + ITEMID_SOKUNONOMI = 186, + ITEMID_RINDONOMI = 187, + ITEMID_YATHENOMI = 188, + ITEMID_YOPUNOMI = 189, + ITEMID_BIAANOMI = 190, + ITEMID_SYUKANOMI = 191, + ITEMID_BAKOUNOMI = 192, + ITEMID_UTANNOMI = 193, + ITEMID_TANGANOMI = 194, + ITEMID_YOROGINOMI = 195, + ITEMID_KASIBUNOMI = 196, + ITEMID_HABANNOMI = 197, + ITEMID_NAMONOMI = 198, + ITEMID_RIRIBANOMI = 199, + ITEMID_HOZUNOMI = 200, + ITEMID_TIIRANOMI = 201, + ITEMID_RYUGANOMI = 202, + ITEMID_KAMURANOMI = 203, + ITEMID_YATAPINOMI = 204, + ITEMID_ZUANOMI = 205, + ITEMID_SANNOMI = 206, + ITEMID_SUTAANOMI = 207, + ITEMID_MIKURUNOMI = 209, + ITEMID_IBANNOMI = 210, + ITEMID_HIKARINOKONA = 213, + ITEMID_SIROIHAABU = 214, + ITEMID_SENSEINOTUME = 217, + ITEMID_YASURAGINOSUZU = 218, + ITEMID_MENTARUHAABU = 219, + ITEMID_KODAWARIHATIMAKI = 220, + ITEMID_OUZYANOSIRUSI = 221, + ITEMID_GINNOKONA = 222, + ITEMID_OMAMORIKOBAN = 223, + ITEMID_KOKORONOSIZUKU = 225, + ITEMID_KIAINOHATIMAKI = 230, + ITEMID_SIAWASETAMAGO = 231, + ITEMID_PINTORENZU = 232, + ITEMID_METARUKOOTO = 233, + ITEMID_TABENOKOSI = 234, + ITEMID_DENKIDAMA = 236, + ITEMID_YAWARAKAISUNA = 237, + ITEMID_KATAIISI = 238, + ITEMID_KISEKINOTANE = 239, + ITEMID_KUROIMEGANE = 240, + ITEMID_KUROOBI = 241, + ITEMID_ZISYAKU = 242, + ITEMID_SINPINOSIZUKU = 243, + ITEMID_SURUDOIKUTIBASI = 244, + ITEMID_DOKUBARI = 245, + ITEMID_TOKENAIKOORI = 246, + ITEMID_NOROINOOHUDA = 247, + ITEMID_MAGATTASUPUUN = 248, + ITEMID_MOKUTAN = 249, + ITEMID_RYUUNOKIBA = 250, + ITEMID_SIRUKUNOSUKAAHU = 251, + ITEMID_KAIGARANOSUZU = 253, + ITEMID_KOUKAKURENZU = 265, + ITEMID_TIKARANOHATIMAKI = 266, + ITEMID_MONOSIRIMEGANE = 267, + ITEMID_TATUZINNOOBI = 268, + ITEMID_INOTINOTAMA = 270, + ITEMID_PAWAHURUHAABU = 271, + ITEMID_KIAINOTASUKI = 275, + ITEMID_METORONOOMU = 277, + ITEMID_KUROITEKKYUU = 278, + ITEMID_KOUKOUNOSIPPO = 279, + ITEMID_AKAIITO = 280, + ITEMID_KUROIHEDORO = 281, + ITEMID_TUMETAIIWA = 282, + ITEMID_SARASARAIWA = 283, + ITEMID_ATUIIWA = 284, + ITEMID_SIMETTAIWA = 285, + ITEMID_NEBARINOKAGIDUME = 286, + ITEMID_KODAWARISUKAAHU = 287, + ITEMID_KUTTUKIBARI = 288, + ITEMID_PAWAARISUTO = 289, + ITEMID_PAWAABERUTO = 290, + ITEMID_PAWAARENZU = 291, + ITEMID_PAWAABANDO = 292, + ITEMID_PAWAAANKURU = 293, + ITEMID_PAWAAUEITO = 294, + ITEMID_KIREINANUKEGARA = 295, + ITEMID_OOKINANEKKO = 296, + ITEMID_KODAWARIMEGANE = 297, + ITEMID_WAZAMASIN01 = 328, + ITEMID_WAZAMASIN02 = 329, + ITEMID_WAZAMASIN03 = 330, + ITEMID_WAZAMASIN04 = 331, + ITEMID_WAZAMASIN05 = 332, + ITEMID_WAZAMASIN06 = 333, + ITEMID_WAZAMASIN07 = 334, + ITEMID_WAZAMASIN08 = 335, + ITEMID_WAZAMASIN09 = 336, + ITEMID_WAZAMASIN10 = 337, + ITEMID_WAZAMASIN11 = 338, + ITEMID_WAZAMASIN12 = 339, + ITEMID_WAZAMASIN13 = 340, + ITEMID_WAZAMASIN14 = 341, + ITEMID_WAZAMASIN15 = 342, + ITEMID_WAZAMASIN16 = 343, + ITEMID_WAZAMASIN17 = 344, + ITEMID_WAZAMASIN18 = 345, + ITEMID_WAZAMASIN19 = 346, + ITEMID_WAZAMASIN20 = 347, + ITEMID_WAZAMASIN21 = 348, + ITEMID_WAZAMASIN22 = 349, + ITEMID_WAZAMASIN23 = 350, + ITEMID_WAZAMASIN24 = 351, + ITEMID_WAZAMASIN25 = 352, + ITEMID_WAZAMASIN26 = 353, + ITEMID_WAZAMASIN27 = 354, + ITEMID_WAZAMASIN28 = 355, + ITEMID_WAZAMASIN29 = 356, + ITEMID_WAZAMASIN30 = 357, + ITEMID_WAZAMASIN31 = 358, + ITEMID_WAZAMASIN32 = 359, + ITEMID_WAZAMASIN33 = 360, + ITEMID_WAZAMASIN34 = 361, + ITEMID_WAZAMASIN35 = 362, + ITEMID_WAZAMASIN36 = 363, + ITEMID_WAZAMASIN37 = 364, + ITEMID_WAZAMASIN38 = 365, + ITEMID_WAZAMASIN39 = 366, + ITEMID_WAZAMASIN40 = 367, + ITEMID_WAZAMASIN41 = 368, + ITEMID_WAZAMASIN42 = 369, + ITEMID_WAZAMASIN43 = 370, + ITEMID_WAZAMASIN44 = 371, + ITEMID_WAZAMASIN45 = 372, + ITEMID_WAZAMASIN46 = 373, + ITEMID_WAZAMASIN47 = 374, + ITEMID_WAZAMASIN48 = 375, + ITEMID_WAZAMASIN49 = 376, + ITEMID_WAZAMASIN50 = 377, + ITEMID_WAZAMASIN51 = 378, + ITEMID_WAZAMASIN52 = 379, + ITEMID_WAZAMASIN53 = 380, + ITEMID_WAZAMASIN54 = 381, + ITEMID_WAZAMASIN55 = 382, + ITEMID_WAZAMASIN56 = 383, + ITEMID_WAZAMASIN57 = 384, + ITEMID_WAZAMASIN58 = 385, + ITEMID_WAZAMASIN59 = 386, + ITEMID_WAZAMASIN60 = 387, + ITEMID_WAZAMASIN61 = 388, + ITEMID_WAZAMASIN62 = 389, + ITEMID_WAZAMASIN63 = 390, + ITEMID_WAZAMASIN64 = 391, + ITEMID_WAZAMASIN65 = 392, + ITEMID_WAZAMASIN66 = 393, + ITEMID_WAZAMASIN67 = 394, + ITEMID_WAZAMASIN68 = 395, + ITEMID_WAZAMASIN69 = 396, + ITEMID_WAZAMASIN70 = 397, + ITEMID_WAZAMASIN71 = 398, + ITEMID_WAZAMASIN72 = 399, + ITEMID_WAZAMASIN73 = 400, + ITEMID_WAZAMASIN74 = 401, + ITEMID_WAZAMASIN75 = 402, + ITEMID_WAZAMASIN76 = 403, + ITEMID_WAZAMASIN77 = 404, + ITEMID_WAZAMASIN78 = 405, + ITEMID_WAZAMASIN79 = 406, + ITEMID_WAZAMASIN80 = 407, + ITEMID_WAZAMASIN81 = 408, + ITEMID_WAZAMASIN82 = 409, + ITEMID_WAZAMASIN83 = 410, + ITEMID_WAZAMASIN84 = 411, + ITEMID_WAZAMASIN85 = 412, + ITEMID_WAZAMASIN86 = 413, + ITEMID_WAZAMASIN87 = 414, + ITEMID_WAZAMASIN88 = 415, + ITEMID_WAZAMASIN89 = 416, + ITEMID_WAZAMASIN90 = 417, + ITEMID_WAZAMASIN91 = 418, + ITEMID_WAZAMASIN92 = 419, + ITEMID_SUPIIDOBOORU = 492, + ITEMID_REBERUBOORU = 493, + ITEMID_RUAABOORU = 494, + ITEMID_HEBIIBOORU = 495, + ITEMID_RABURABUBOORU = 496, + ITEMID_HURENDOBOORU = 497, + ITEMID_MUUNBOORU = 498, + ITEMID_KONPEBOORU = 499, + ITEMID_SINKANOKISEKI = 538, + ITEMID_KARUISI = 539, + ITEMID_GOTUGOTUMETTO = 540, + ITEMID_HUUSEN = 541, + ITEMID_REDDOKAADO = 542, + ITEMID_NERAINOMATO = 543, + ITEMID_SIMETUKEBANDO = 544, + ITEMID_KYUUKON = 545, + ITEMID_ZYUUDENTI = 546, + ITEMID_DASSYUTUBOTAN = 547, + ITEMID_NOOMARUZYUERU = 564, + ITEMID_TAIRYOKUNOHANE = 565, + ITEMID_KINRYOKUNOHANE = 566, + ITEMID_TEIKOUNOHANE = 567, + ITEMID_TIRYOKUNOHANE = 568, + ITEMID_SEISINNOHANE = 569, + ITEMID_SYUNPATUNOHANE = 570, + ITEMID_KIREINAHANE = 571, + ITEMID_DORIIMUBOORU = 576, + ITEMID_DEKAIKINNOTAMA = 581, + ITEMID_ODANGOSINZYU = 582, + ITEMID_WAZAMASIN93 = 618, + ITEMID_WAZAMASIN94 = 619, + ITEMID_WAZAMASIN95 = 620, + ITEMID_HIKARUOMAMORI = 632, + ITEMID_ZYAKUTENHOKEN = 639, + ITEMID_TOTUGEKITYOKKI = 640, + ITEMID_TOKUSEIKAPUSERU = 645, + ITEMID_HOIPPUPOPPU = 646, + ITEMID_NIOIBUKURO = 647, + ITEMID_HIKARIGOKE = 648, + ITEMID_YUKIDAMA = 649, + ITEMID_BOUZINGOOGURU = 650, + ITEMID_GENGANAITO = 656, + ITEMID_SAANAITONAITO = 657, + ITEMID_DENRYUUNAITO = 658, + ITEMID_HUSIGIBANAITO = 659, + ITEMID_RIZAADONAITOx = 660, + ITEMID_KAMEKKUSUNAITO = 661, + ITEMID_MYUUTUNAITOx = 662, + ITEMID_MYUUTUNAITOy = 663, + ITEMID_BASYAAMONAITO = 664, + ITEMID_TYAAREMUNAITO = 665, + ITEMID_HERUGANAITO = 666, + ITEMID_BOSUGODORANAITO = 667, + ITEMID_ZYUPETTANAITO = 668, + ITEMID_BANGIRASUNAITO = 669, + ITEMID_HASSAMUNAITO = 670, + ITEMID_KAIROSUNAITO = 671, + ITEMID_PUTERANAITO = 672, + ITEMID_RUKARIONAITO = 673, + ITEMID_YUKINOONAITO = 674, + ITEMID_GARUURANAITO = 675, + ITEMID_GYARADOSUNAITO = 676, + ITEMID_ABUSORUNAITO = 677, + ITEMID_RIZAADONAITOy = 678, + ITEMID_HUUDHINAITO = 679, + ITEMID_HERAKUROSUNAITO = 680, + ITEMID_KUTIITONAITO = 681, + ITEMID_RAIBORUTONAITO = 682, + ITEMID_GABURIASUNAITO = 683, + ITEMID_RATHIASUNAITO = 684, + ITEMID_RATHIOSUNAITO = 685, + ITEMID_ROZERUNOMI = 686, + ITEMID_WAZAMASIN96 = 690, + ITEMID_WAZAMASIN97 = 691, + ITEMID_WAZAMASIN98 = 692, + ITEMID_WAZAMASIN99 = 693, + ITEMID_EREBEETANOKII = 700, + ITEMID_MIAREGARETTO = 708, + ITEMID_AGONOKASEKI = 710, + ITEMID_HIRENOKASEKI = 711, + ITEMID_RAGURAAZINAITO = 752, + ITEMID_ZYUKAINNAITO = 753, + ITEMID_YAMIRAMINAITO = 754, + ITEMID_TIRUTARISUNAITO = 755, + ITEMID_ERUREIDONAITO = 756, + ITEMID_TABUNNENAITO = 757, + ITEMID_METAGUROSUNAITO = 758, + ITEMID_SAMEHADANAITO = 759, + ITEMID_YADORANNAITO = 760, + ITEMID_HAGANEERUNAITO = 761, + ITEMID_PIZYOTTONAITO = 762, + ITEMID_ONIGOORINAITO = 763, + ITEMID_DHIANSINAITO = 764, + ITEMID_IMASIMENOTUBO = 765, + ITEMID_BAKUUDANAITO = 767, + ITEMID_MIMIROPPUNAITO = 768, + ITEMID_BOOMANDANAITO = 769, + ITEMID_SUPIANAITO = 770, + ITEMID_GINNOOUKAN = 795, + ITEMID_KINNOOUKAN = 796, + ITEMID_BIBIRIDAMA = 846, + ITEMID_ZIGARUDEKYUUBU = 847, + ITEMID_KOORINOISI = 849, + ITEMID_URUTORABOORU = 851, + ITEMID_GURANDOKOOTO = 879, + ITEMID_BOUGOPATTO = 880, + ITEMID_EREKISIIDO = 881, + ITEMID_SAIKOSIIDO = 882, + ITEMID_MISUTOSIIDO = 883, + ITEMID_GURASUSIIDO = 884, + ITEMID_NODOAME = 1118, + ITEMID_DASSYUTUPAKKU = 1119, + ITEMID_ATUZOKOBUUTU = 1120, + ITEMID_KARABURIHOKEN = 1121, + ITEMID_RUUMUSAABISU = 1122, + ITEMID_BANNOUGASA = 1123, + ITEMID_KEIKENTIAME_1 = 1124, + ITEMID_KEIKENTIAME_2 = 1125, + ITEMID_KEIKENTIAME_3 = 1126, + ITEMID_KEIKENTIAME_4 = 1127, + ITEMID_KEIKENTIAME_5 = 1128, + ITEMID_SAMISIGARIMINTO = 1231, + ITEMID_IZIPPARIMINTO = 1232, + ITEMID_YANTYAMINTO = 1233, + ITEMID_YUKANMINTO = 1234, + ITEMID_ZUBUTOIMINTO = 1235, + ITEMID_WANPAKUMINTO = 1236, + ITEMID_NOUTENKIMINTO = 1237, + ITEMID_NONKIMINTO = 1238, + ITEMID_HIKAEMEMINTO = 1239, + ITEMID_OTTORIMINTO = 1240, + ITEMID_UKKARIMINTO = 1241, + ITEMID_REISEIMINTO = 1242, + ITEMID_ODAYAKAMINTO = 1243, + ITEMID_OTONASIIMINTO = 1244, + ITEMID_SINTYOUMINTO = 1245, + ITEMID_NAMAIKIMINTO = 1246, + ITEMID_OKUBYOUMINTO = 1247, + ITEMID_SEKKTIMINTO = 1248, + ITEMID_YOUKIMINTO = 1249, + ITEMID_MUJYAKIMINTO = 1250, + ITEMID_MAZIMEMINTO = 1251, + ITEMID_GARANATUBURESU = 1582, + ITEMID_AKASINOOMAMORI = 1589, + ITEMID_GARANATURIISU = 1592, + ITEMID_TOKUSEIPATTI = 1606, + ITEMID_SENTOUBAFFA1 = 1881, + ITEMID_SENTOUBAFFA2 = 1882, + ITEMID_SENTOUBAFFA3 = 1883, + ITEMID_SENTOUBAFFA4 = 1884, + ITEMID_SENTOUBAFFA5 = 1885, + ITEMID_SENTOUBAFFA6 = 1886, + ITEMID_WAZAMASIN100 = 2160, + ITEMID_WAZAMASIN101 = 2161, + ITEMID_WAZAMASIN102 = 2162, + ITEMID_WAZAMASIN103 = 2163, + ITEMID_WAZAMASIN104 = 2164, + ITEMID_WAZAMASIN105 = 2165, + ITEMID_WAZAMASIN106 = 2166, + ITEMID_WAZAMASIN107 = 2167, + ITEMID_WAZAMASIN108 = 2168, + ITEMID_WAZAMASIN109 = 2169, + ITEMID_WAZAMASIN110 = 2170, + ITEMID_WAZAMASIN111 = 2171, + ITEMID_WAZAMASIN112 = 2172, + ITEMID_WAZAMASIN113 = 2173, + ITEMID_WAZAMASIN114 = 2174, + ITEMID_WAZAMASIN115 = 2175, + ITEMID_WAZAMASIN116 = 2176, + ITEMID_WAZAMASIN117 = 2177, + ITEMID_WAZAMASIN118 = 2178, + ITEMID_WAZAMASIN119 = 2179, + ITEMID_WAZAMASIN120 = 2180, + ITEMID_WAZAMASIN121 = 2181, + ITEMID_WAZAMASIN122 = 2182, + ITEMID_WAZAMASIN123 = 2183, + ITEMID_WAZAMASIN124 = 2184, + ITEMID_WAZAMASIN125 = 2185, + ITEMID_WAZAMASIN126 = 2186, + ITEMID_WAZAMASIN127 = 2187, + ITEMID_WAZAMASIN128 = 2188, + ITEMID_WAZAMASIN129 = 2189, + ITEMID_WAZAMASIN130 = 2190, + ITEMID_WAZAMASIN131 = 2191, + ITEMID_WAZAMASIN132 = 2192, + ITEMID_WAZAMASIN133 = 2193, + ITEMID_WAZAMASIN134 = 2194, + ITEMID_WAZAMASIN135 = 2195, + ITEMID_WAZAMASIN136 = 2196, + ITEMID_WAZAMASIN137 = 2197, + ITEMID_WAZAMASIN138 = 2198, + ITEMID_WAZAMASIN139 = 2199, + ITEMID_WAZAMASIN140 = 2200, + ITEMID_WAZAMASIN141 = 2201, + ITEMID_WAZAMASIN142 = 2202, + ITEMID_WAZAMASIN143 = 2203, + ITEMID_WAZAMASIN144 = 2204, + ITEMID_WAZAMASIN145 = 2205, + ITEMID_WAZAMASIN146 = 2206, + ITEMID_WAZAMASIN147 = 2207, + ITEMID_WAZAMASIN148 = 2208, + ITEMID_WAZAMASIN149 = 2209, + ITEMID_WAZAMASIN150 = 2210, + ITEMID_WAZAMASIN151 = 2211, + ITEMID_WAZAMASIN152 = 2212, + ITEMID_WAZAMASIN153 = 2213, + ITEMID_WAZAMASIN154 = 2214, + ITEMID_WAZAMASIN155 = 2215, + ITEMID_WAZAMASIN156 = 2216, + ITEMID_WAZAMASIN157 = 2217, + ITEMID_WAZAMASIN158 = 2218, + ITEMID_WAZAMASIN159 = 2219, + ITEMID_WAZAMASIN160 = 2220, + ITEMID_WAZAMASIN161 = 2221, + ITEMID_WAZAMASIN162 = 2222, + ITEMID_WAZAMASIN163 = 2223, + ITEMID_WAZAMASIN164 = 2224, + ITEMID_WAZAMASIN165 = 2225, + ITEMID_WAZAMASIN166 = 2226, + ITEMID_WAZAMASIN167 = 2227, + ITEMID_WAZAMASIN168 = 2228, + ITEMID_WAZAMASIN169 = 2229, + ITEMID_WAZAMASIN170 = 2230, + ITEMID_WAZAMASIN171 = 2231, + ITEMID_YOUSEINOHANE = 2401, + ITEMID_KAIDENNOTANE = 2558, + ITEMID_PIKUSINAITO = 2559, + ITEMID_UTUBOTTONAITO = 2560, + ITEMID_STAAMIINAITO = 2561, + ITEMID_KAIRYUNAITO = 2562, + ITEMID_MEGANIUMUNAITO = 2563, + ITEMID_OODAIRUNAITO = 2564, + ITEMID_EAAMUDONAITO = 2565, + ITEMID_YUKIMENOKONAITO = 2566, + ITEMID_HIIDORANAITO = 2567, + ITEMID_DAAKURANAITO = 2568, + ITEMID_ENBUONAITO = 2569, + ITEMID_DORYUUZUNAITO = 2570, + ITEMID_PENDORANAITO = 2571, + ITEMID_ZURUZUKINAITO = 2572, + ITEMID_SIBIRUDONAITO = 2573, + ITEMID_SYANDERANAITO = 2574, + ITEMID_BURIGARONAITO = 2575, + ITEMID_MAFOKUSINAITO = 2576, + ITEMID_GEKKOUGANAITO = 2577, + ITEMID_KAENZISINAITO = 2578, + ITEMID_HURAETTENAITO = 2579, + ITEMID_KARAMANERONAITO = 2580, + ITEMID_GAMENODESUNAITO = 2581, + ITEMID_DORAMIDORONAITO = 2582, + ITEMID_RUTYABURUNAITO = 2583, + ITEMID_ZIGARUDENAITO = 2584, + ITEMID_ZIZIIRONAITO = 2585, + ITEMID_ZERAORANAITO = 2586, + ITEMID_TAIREETUNAITO = 2587, + ITEMID_202GOUSITUNOKAGI = 2588, + ITEMID_SUGOIMIAREGARETTO = 2589, + ITEMID_RABONOKAADOKIIA = 2590, + ITEMID_RABONOKAADOKIIB = 2591, + ITEMID_RABONOKAADOKIIC = 2592, + ITEMID_RABONOKAADOKIIM = 2593, + ITEMID_RABONOKAADOKIIX = 2594, + ITEMID_ISHIKORO = 2595, + ITEMID_OMOIDENOYUBIWA = 2596, + ITEMID_SAINIRINONUI = 2597, + 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_DAIZINAMONO27 = 2614, + ITEMID_DAIZINAMONO28 = 2615, + ITEMID_DAIZINAMONO29 = 2616, + ITEMID_DAIZINAMONO30 = 2617, + ITEMID_MEGAKAKERA = 2618, + ITEMID_OMAMORISOZAI = 2619, + ITEMID_AKANOKANARYINUI1 = 2620, + ITEMID_AKANOKANARYINUI2 = 2621, + ITEMID_AKANOKANARYINUI3 = 2622, + ITEMID_KINNOKANARYINUI1 = 2623, + ITEMID_KINNOKANARYINUI2 = 2624, + ITEMID_KINNOKANARYINUI3 = 2625, + ITEMID_PINKUNOKANARYINUI1 = 2626, + ITEMID_PINKUNOKANARYINUI2 = 2627, + ITEMID_PINKUNOKANARYINUI3 = 2628, + ITEMID_MIDORINOKANARYINUI1 = 2629, + ITEMID_MIDORINOKANARYINUI2 = 2630, + ITEMID_MIDORINOKANARYINUI3 = 2631, + ITEMID_AONOKANARYINUI1 = 2632, + ITEMID_AONOKANARYINUI2 = 2633, + ITEMID_AONOKANARYINUI3 = 2634, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/LangType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/LangType.fbs new file mode 100644 index 00000000..e5096279 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/LangType.fbs @@ -0,0 +1,14 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum LangType : int { + ROM_LANG = 0, + JAPAN = 1, + ENGLISH = 2, + FRANCE = 3, + ITALY = 4, + GERMANY = 5, + SPAIN = 6, + KOREA = 7, + SIMPLIFIED_CHINESE = 8, + TRADITIONAL_CHINESE = 9, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/MahoippuViewID.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/MahoippuViewID.fbs new file mode 100644 index 00000000..85fd7ed6 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/MahoippuViewID.fbs @@ -0,0 +1,11 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum MahoippuViewID : int { + STRAWBERRY = 0, + BERRY = 1, + HEART = 2, + STAR = 3, + CLOVER = 4, + FLOWER = 5, + RIBBON = 6, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/MoveType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/MoveType.fbs new file mode 100644 index 00000000..d03c4f53 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/MoveType.fbs @@ -0,0 +1,23 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum MoveType : byte { + Normal = 0, + Kakutou = 1, + Hikou = 2, + Doku = 3, + Jimen = 4, + Iwa = 5, + Mushi = 6, + Ghost = 7, + Hagane = 8, + Honoo = 9, + Mizu = 10, + Kusa = 11, + Denki = 12, + Esper = 13, + Koori = 14, + Dragon = 15, + Aku = 16, + Fairy = 17, + Null = 18, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/PayType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/PayType.fbs new file mode 100644 index 00000000..b16cb9a9 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/PayType.fbs @@ -0,0 +1,7 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum PayType : int { + OKOZUKAI = 0, + LP = 1, + BP = 2, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/PokeMemoType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/PokeMemoType.fbs new file mode 100644 index 00000000..23083a9b --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/PokeMemoType.fbs @@ -0,0 +1,14 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum PokeMemoType : byte { NONE = 0, + Capture = 1, + EventGet = 2, + EventCapture = 3, + InnerTrade = 4, + NetTrade = 5, + EggHatch = 6, + Bank = 7, + MysteryGift = 8, + EggTakenFirst = 9, + EggTakenTrade = 10, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/RareType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/RareType.fbs new file mode 100644 index 00000000..9a41fc7d --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/RareType.fbs @@ -0,0 +1,6 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum RareType : int { DEFAULT = 0, + NO_RARE = 1, + RARE = 2, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/RibbonType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/RibbonType.fbs new file mode 100644 index 00000000..60b5e9dc --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/RibbonType.fbs @@ -0,0 +1,116 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum RibbonType : int +{ NONE = 0, + CAROS_CHAMP = 1, + HOUEN_CHAMP = 2, + SINOU_CHAMP = 3, + KAWAIGARI = 4, + TRAINING = 5, + SUPER_BATTLE = 6, + MASTER_BATTLE = 7, + GANBA = 8, + SYAKKIRI = 9, + DOKKIRI = 10, + SYONBORI = 11, + UKKARI = 12, + SUKKIRI = 13, + GUSSURI = 14, + NIKKORI = 15, + GORGEOUS = 16, + ROYAL = 17, + GORGEOUS_ROYAL = 18, + BROMIDE = 19, + ASHIATO = 20, + RECORD = 21, + LEGEND = 22, + COUNTRY = 23, + NATIONAL = 24, + EARTH = 25, + WORLD = 26, + CLASSIC = 27, + PREMIERE = 28, + EVENT = 29, + BIRTHDAY = 30, + SPECIAL = 31, + MEMORIAL = 32, + WISH = 33, + BATTLE_CHAMP = 34, + AREA_CHAMP = 35, + NATIONAL_CHAMP = 36, + WORLD_CHAMP = 37, + LUMPING_CONTEST = 38, + LUMPING_TOWER = 39, + SANGO_CHAMP = 40, + CONTEST_STAR = 41, + STYLE_MASTER = 42, + BEAUTIFUL_MASTER = 43, + CUTE_MASTER = 44, + CLEVER_MASTER = 45, + STRONG_MASTER = 46, + NIJI_CROWN = 47, + NIJI_ROYAL = 48, + NIJI_BTLTOWER = 49, + NIJI_MASTER = 50, + ORION_GARAL = 51, + ORION_MASTER_TOWER = 52, + ORION_MASTER_RANK = 53, + ORION_NOON = 54, + ORION_MIDNIGHT = 55, + ORION_TWILIGHT = 56, + ORION_DAYBREAK = 57, + ORION_CLOUDY_WEATHER = 58, + ORION_RAIN = 59, + ORION_THUNDER = 60, + ORION_SNOWFALL = 61, + ORION_HEAVY_SONWFALL = 62, + ORION_DRYING = 63, + ORION_SAND_DUST = 64, + ORION_DENSE_FOG = 65, + ORION_FATE = 66, + ORION_FISH = 67, + ORION_CURRY = 68, + ORION_SOMETIMES = 69, + ORION_NOTLOOKING = 70, + ORION_NAUGHTINESS = 71, + ORION_CAREFREE = 72, + ORION_TENSION = 73, + ORION_EXPECTATION = 74, + ORION_CHARISMA = 75, + ORION_CALM = 76, + ORION_PASSION = 77, + ORION_CARELESSNESS = 78, + ORION_EUPHORIA = 79, + ORION_FURY = 80, + ORION_SMILE = 81, + ORION_SAD = 82, + ORION_GOOD_CONDITION = 83, + ORION_EMERGENCY = 84, + ORION_REASON = 85, + ORION_INSTINCT = 86, + ORION_CUNNING = 87, + ORION_STRENGTH = 88, + ORION_WEAK = 89, + ORION_UPSET = 90, + ORION_ELEVATION = 91, + ORION_FATIGUE = 92, + ORION_CONFIDENCE = 93, + ORION_DISTRUST = 94, + ORION_ARTLESSNESS = 95, + ORION_IMPURITY = 96, + ORION_VIM = 97, + ORION_SLUMP = 98, + PIONEER = 99, + TWINKLE_STAR = 100, + TITAN_PALDEA_CHAMP = 101, + TITAN_HUGE = 102, + TITAN_TINY = 103, + TITAN_PICKING_UP_THINGS = 104, + TITAN_PARTNER = 105, + TITAN_GOURM = 106, + TITAN_ONE_CHANCE_IN_A_MILLION = 107, + TITAN_OYABUN = 108, + TITAN_STRONGEST = 109, + TITAN_NUSHI = 110, + SUDACHI_PARTNER = 111, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/SeikakuType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/SeikakuType.fbs new file mode 100644 index 00000000..7f8e3cfa --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/SeikakuType.fbs @@ -0,0 +1,30 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum SeikakuType : int +{ DEFAULT = 0, + GANBARIYA = 1, + SAMISIGARIYA = 2, + YUUKAN = 3, + IJIPPARI = 4, + YANTYA = 5, + ZUBUTOI = 6, + SUNAO = 7, + NONKI = 8, + WANPAKU = 9, + NOUTENKI = 10, + OKUBYOU = 11, + SEKKATI = 12, + MAJIME = 13, + YOUKI = 14, + MUJYAKI = 15, + HIKAEME = 16, + OTTORI = 17, + REISEI = 18, + TEREYA = 19, + UKKARIYA = 20, + ODAYAKA = 21, + OTONASII = 22, + NAMAIKI = 23, + SINNTYOU = 24, + KIMAGURE = 25, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/SellType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/SellType.fbs new file mode 100644 index 00000000..6d0665de --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/SellType.fbs @@ -0,0 +1,6 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum SellType : int { + SELL_BUY = 0, + BUY_ONLY = 1, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/Sex.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/Sex.fbs new file mode 100644 index 00000000..47e23d44 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/Sex.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +/// Actual Gender +enum Sex : int { + MALE = 0, + FEMALE = 1, + UNKNOWN = 2, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/SexType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/SexType.fbs new file mode 100644 index 00000000..f5da13d6 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/SexType.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +/// Gender Spec +enum SexType : int { + DEFAULT = 0, + MALE = 1, + FEMALE = 2, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/ShopKind.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/ShopKind.fbs new file mode 100644 index 00000000..f9853397 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/ShopKind.fbs @@ -0,0 +1,22 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum ShopKind : int { + NONE = 0, + FRIENDLYSHOP = 1, + RESTAURANT = 2, + HAIRMAKE = 3, + WAZAMACHINEMACHINE = 4, + DRESSUP = 5, + LUXURYRESTAURANT = 6, + DELIBIRD = 7, + DELICATESSEN = 8, + DRUG_STORE = 9, + KANZUME = 10, + BAKERY = 11, + SUPERMARKET = 12, + KOUBAI = 13, + PICNIC = 14, + SYOUTEN = 15, + BBKOUBAI = 16, + BBZIHANKI = 17, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/SizeType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/SizeType.fbs new file mode 100644 index 00000000..b7e25f58 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/SizeType.fbs @@ -0,0 +1,11 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum SizeType : int { + RANDOM = 0, + XS = 1, + S = 2, + M = 3, + L = 4, + XL = 5, + VALUE = 6, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/TalentType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/TalentType.fbs new file mode 100644 index 00000000..8dc8a005 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/TalentType.fbs @@ -0,0 +1,7 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum TalentType : int { + RANDOM = 0, + V_NUM = 1, + VALUE = 2, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/TokuseiID.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/TokuseiID.fbs new file mode 100644 index 00000000..f63bfa2b --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/TokuseiID.fbs @@ -0,0 +1,311 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum TokuseiID : ushort { + TOKUSEI_NULL = 0, + TOKUSEI_AKUSYUU = 1, + TOKUSEI_AMEHURASI = 2, + TOKUSEI_KASOKU = 3, + TOKUSEI_KABUTOAAMAA = 4, + TOKUSEI_GANZYOU = 5, + TOKUSEI_SIMERIKE = 6, + TOKUSEI_ZYUUNAN = 7, + TOKUSEI_SUNAGAKURE = 8, + TOKUSEI_SEIDENKI = 9, + TOKUSEI_TIKUDEN = 10, + TOKUSEI_TYOSUI = 11, + TOKUSEI_DONKAN = 12, + TOKUSEI_NOOTENKI = 13, + TOKUSEI_HUKUGAN = 14, + TOKUSEI_HUMIN = 15, + TOKUSEI_HENSYOKU = 16, + TOKUSEI_MENEKI = 17, + TOKUSEI_MORAIBI = 18, + TOKUSEI_RINPUN = 19, + TOKUSEI_MAIPEESU = 20, + TOKUSEI_KYUUBAN = 21, + TOKUSEI_IKAKU = 22, + TOKUSEI_KAGEHUMI = 23, + TOKUSEI_SAMEHADA = 24, + TOKUSEI_HUSIGINAMAMORI = 25, + TOKUSEI_HUYUU = 26, + TOKUSEI_HOUSI = 27, + TOKUSEI_SINKURO = 28, + TOKUSEI_KURIABODHI = 29, + TOKUSEI_SIZENKAIHUKU = 30, + TOKUSEI_HIRAISIN = 31, + TOKUSEI_TENNOMEGUMI = 32, + TOKUSEI_SUISUI = 33, + TOKUSEI_YOURYOKUSO = 34, + TOKUSEI_HAKKOU = 35, + TOKUSEI_TOREESU = 36, + TOKUSEI_TIKARAMOTI = 37, + TOKUSEI_DOKUNOTOGE = 38, + TOKUSEI_SEISINRYOKU = 39, + TOKUSEI_MAGUMANOYOROI = 40, + TOKUSEI_MIZUNOBEERU = 41, + TOKUSEI_ZIRYOKU = 42, + TOKUSEI_BOUON = 43, + TOKUSEI_AMEUKEZARA = 44, + TOKUSEI_SUNAOKOSI = 45, + TOKUSEI_PURESSYAA = 46, + TOKUSEI_ATUISIBOU = 47, + TOKUSEI_HAYAOKI = 48, + TOKUSEI_HONOONOKARADA = 49, + TOKUSEI_NIGEASI = 50, + TOKUSEI_SURUDOIME = 51, + TOKUSEI_KAIRIKIBASAMI = 52, + TOKUSEI_MONOHIROI = 53, + TOKUSEI_NAMAKE = 54, + TOKUSEI_HARIKIRI = 55, + TOKUSEI_MEROMEROBODHI = 56, + TOKUSEI_PURASU = 57, + TOKUSEI_MAINASU = 58, + TOKUSEI_TENKIYA = 59, + TOKUSEI_NENTYAKU = 60, + TOKUSEI_DAPPI = 61, + TOKUSEI_KONZYOU = 62, + TOKUSEI_HUSIGINAUROKO = 63, + TOKUSEI_HEDOROEKI = 64, + TOKUSEI_SINRYOKU = 65, + TOKUSEI_MOUKA = 66, + TOKUSEI_GEKIRYUU = 67, + TOKUSEI_MUSINOSIRASE = 68, + TOKUSEI_ISIATAMA = 69, + TOKUSEI_HIDERI = 70, + TOKUSEI_ARIZIGOKU = 71, + TOKUSEI_YARUKI = 72, + TOKUSEI_SIROIKEMURI = 73, + TOKUSEI_YOGAPAWAA = 74, + TOKUSEI_SHERUAAMAA = 75, + TOKUSEI_EAROKKU = 76, + TOKUSEI_TIDORIASI = 77, + TOKUSEI_DENKIENZIN = 78, + TOKUSEI_TOUSOUSIN = 79, + TOKUSEI_HUKUTUNOKOKORO = 80, + TOKUSEI_YUKIGAKURE = 81, + TOKUSEI_KUISINBOU = 82, + TOKUSEI_IKARINOTUBO = 83, + TOKUSEI_KARUWAZA = 84, + TOKUSEI_TAINETU = 85, + TOKUSEI_TANZYUN = 86, + TOKUSEI_KANSOUHADA = 87, + TOKUSEI_DAUNROODO = 88, + TOKUSEI_TETUNOKOBUSI = 89, + TOKUSEI_POIZUNHIIRU = 90, + TOKUSEI_TEKIOURYOKU = 91, + TOKUSEI_SUKIRURINKU = 92, + TOKUSEI_URUOIBODHI = 93, + TOKUSEI_SANPAWAA = 94, + TOKUSEI_HAYAASI = 95, + TOKUSEI_NOOMARUSUKIN = 96, + TOKUSEI_SUNAIPAA = 97, + TOKUSEI_MAZIKKUGAADO = 98, + TOKUSEI_NOOGAADO = 99, + TOKUSEI_ATODASI = 100, + TOKUSEI_TEKUNISYAN = 101, + TOKUSEI_RIIHUGAADO = 102, + TOKUSEI_BUKIYOU = 103, + TOKUSEI_KATAYABURI = 104, + TOKUSEI_KYOUUN = 105, + TOKUSEI_YUUBAKU = 106, + TOKUSEI_KIKENYOTI = 107, + TOKUSEI_YOTIMU = 108, + TOKUSEI_TENNEN = 109, + TOKUSEI_IROMEGANE = 110, + TOKUSEI_FIRUTAA = 111, + TOKUSEI_SUROOSUTAATO = 112, + TOKUSEI_KIMOTTAMA = 113, + TOKUSEI_YOBIMIZU = 114, + TOKUSEI_AISUBODHI = 115, + TOKUSEI_HAADOROKKU = 116, + TOKUSEI_YUKIHURASI = 117, + TOKUSEI_MITUATUME = 118, + TOKUSEI_OMITOOSI = 119, + TOKUSEI_SUTEMI = 120, + TOKUSEI_MARUTITAIPU = 121, + TOKUSEI_HURAWAAGIHUTO = 122, + TOKUSEI_NAITOMEA = 123, + TOKUSEI_WARUITEGUSE = 124, + TOKUSEI_TIKARAZUKU = 125, + TOKUSEI_AMANOZYAKU = 126, + TOKUSEI_KINTYOUKAN = 127, + TOKUSEI_MAKENKI = 128, + TOKUSEI_YOWAKI = 129, + TOKUSEI_NOROWAREBODHI = 130, + TOKUSEI_IYASINOKOKORO = 131, + TOKUSEI_HURENDOGAADO = 132, + TOKUSEI_KUDAKERUYOROI = 133, + TOKUSEI_HEVHIMETARU = 134, + TOKUSEI_RAITOMETARU = 135, + TOKUSEI_MARUTISUKEIRU = 136, + TOKUSEI_DOKUBOUSOU = 137, + TOKUSEI_NETUBOUSOU = 138, + TOKUSEI_SYUUKAKU = 139, + TOKUSEI_TEREPASII = 140, + TOKUSEI_MURAKKE = 141, + TOKUSEI_BOUZIN = 142, + TOKUSEI_DOKUSYU = 143, + TOKUSEI_SAISEIRYOKU = 144, + TOKUSEI_HATOMUNE = 145, + TOKUSEI_SUNAKAKI = 146, + TOKUSEI_MIRAKURUSUKIN = 147, + TOKUSEI_ANARAIZU = 148, + TOKUSEI_IRYUUZYON = 149, + TOKUSEI_KAWARIMONO = 150, + TOKUSEI_SURINUKE = 151, + TOKUSEI_MIIRA = 152, + TOKUSEI_ZISINKAZYOU = 153, + TOKUSEI_SEIGINOKOKORO = 154, + TOKUSEI_BIBIRI = 155, + TOKUSEI_MAZIKKUMIRAA = 156, + TOKUSEI_SOUSYOKU = 157, + TOKUSEI_ITAZURAGOKORO = 158, + TOKUSEI_SUNANOTIKARA = 159, + TOKUSEI_TETUNOTOGE = 160, + TOKUSEI_DARUMAMOODO = 161, + TOKUSEI_SYOURINOHOSI = 162, + TOKUSEI_TAABOBUREIZU = 163, + TOKUSEI_TERABORUTEEZI = 164, + TOKUSEI_AROMABEERU = 165, + TOKUSEI_HURAWAABEERU = 166, + TOKUSEI_HOOBUKURO = 167, + TOKUSEI_HENGENZIZAI = 168, + TOKUSEI_FAAKOOTO = 169, + TOKUSEI_MAZISYAN = 170, + TOKUSEI_BOUDAN = 171, + TOKUSEI_KATIKI = 172, + TOKUSEI_GANZYOUAGO = 173, + TOKUSEI_HURIIZUSUKIN = 174, + TOKUSEI_SUIITOBEERU = 175, + TOKUSEI_BATORUSUITTI = 176, + TOKUSEI_HAYATENOTUBASA = 177, + TOKUSEI_MEGARANTYAA = 178, + TOKUSEI_KUSANOKEGAWA = 179, + TOKUSEI_KYOUSEI = 180, + TOKUSEI_KATAITUME = 181, + TOKUSEI_FEARIISUKIN = 182, + TOKUSEI_NUMENUME = 183, + TOKUSEI_SUKAISUKIN = 184, + TOKUSEI_OYAKOAI = 185, + TOKUSEI_DAAKUOORA = 186, + TOKUSEI_FEARIIOORA = 187, + TOKUSEI_OORABUREIKU = 188, + TOKUSEI_HAZIMARINOUMI = 189, + TOKUSEI_OWARINODAITI = 190, + TOKUSEI_DERUTASUTORIIMU = 191, + TOKUSEI_ZIKYUURYOKU = 192, + TOKUSEI_NIGEGOSI = 193, + TOKUSEI_KIKIKAIHI = 194, + TOKUSEI_MIZUGATAME = 195, + TOKUSEI_HITODENASI = 196, + TOKUSEI_RIMITTOSIIRUDO = 197, + TOKUSEI_HARIKOMI = 198, + TOKUSEI_SUIHOU = 199, + TOKUSEI_HAGANETUKAI = 200, + TOKUSEI_GYAKUZYOU = 201, + TOKUSEI_YUKIKAKI = 202, + TOKUSEI_ENKAKU = 203, + TOKUSEI_URUOIBOISU = 204, + TOKUSEI_HIIRINGUSIHUTO = 205, + TOKUSEI_EREKISUKIN = 206, + TOKUSEI_SAAHUTEERU = 207, + TOKUSEI_GYOGUN = 208, + TOKUSEI_BAKENOKAWA = 209, + TOKUSEI_KIZUNAHENGE = 210, + TOKUSEI_SUWAAMUTHENZI = 211, + TOKUSEI_HUSYOKU = 212, + TOKUSEI_ZETTAINEMURI = 213, + TOKUSEI_ZYOOUNOIGEN = 214, + TOKUSEI_TOBIDASUNAKAMI = 215, + TOKUSEI_ODORIKO = 216, + TOKUSEI_BATTERII = 217, + TOKUSEI_MOHUMOHU = 218, + TOKUSEI_BIBIDDOBODHI = 219, + TOKUSEI_SOURUHAATO = 220, + TOKUSEI_KAARIIHEAA = 221, + TOKUSEI_RESIIBAA = 222, + TOKUSEI_KAGAKUNOTIKARA = 223, + TOKUSEI_BIISUTOBUUSUTO = 224, + TOKUSEI_arSISUTEMU = 225, + TOKUSEI_EREKIMEIKAA = 226, + TOKUSEI_SAIKOMEIKAA = 227, + TOKUSEI_MISUTOMEIKAA = 228, + TOKUSEI_GURASUMEIKAA = 229, + TOKUSEI_METARUPUROTEKUTO = 230, + TOKUSEI_FANTOMUGAADO = 231, + TOKUSEI_PURIZUMUAAMAA = 232, + TOKUSEI_BUREINFOOSU = 233, + TOKUSEI_HUTOUNOTURUGI = 234, + TOKUSEI_HUKUTUNOTATE = 235, + TOKUSEI_RIBERO = 236, + TOKUSEI_TAMAHIROI = 237, + TOKUSEI_WATAGE = 238, + TOKUSEI_SUKURYUUOBIRE = 239, + TOKUSEI_MIRAAAAMAA = 240, + TOKUSEI_UNOMISAIRU = 241, + TOKUSEI_SUZIGANEIRI = 242, + TOKUSEI_ZYOUKIKIKAN = 243, + TOKUSEI_PANKUROKKU = 244, + TOKUSEI_SUNAHAKI = 245, + TOKUSEI_KOORINORINPUN = 246, + TOKUSEI_ZYUKUSEI = 247, + TOKUSEI_AISUFEISU = 248, + TOKUSEI_PAWAASUPOTTO = 249, + TOKUSEI_GITAI = 250, + TOKUSEI_BARIAHURII = 251, + TOKUSEI_HAGANENOSEISIN = 252, + TOKUSEI_HOROBINOBODHI = 253, + TOKUSEI_SAMAYOUTAMASII = 254, + TOKUSEI_GORIMUTYUU = 255, + TOKUSEI_KAGAKUHENKAGASU = 256, + TOKUSEI_PASUTERUBEERU = 257, + TOKUSEI_HARAPEKOSUITTI = 258, + TOKUSEI_KUIKKUDOROU = 259, + TOKUSEI_HUKASINOKOBUSI = 260, + TOKUSEI_KIMYOUNAKUSURI = 261, + TOKUSEI_TORANZISUTA = 262, + TOKUSEI_RYUUNOAGITO = 263, + TOKUSEI_SIRONOINANAKI = 264, + TOKUSEI_KURONOINANAKI = 265, + TOKUSEI_ZINBAITTAISIRO = 266, + TOKUSEI_ZINBAITTAIKURO = 267, + TOKUSEI_TORENAINIOI = 268, + TOKUSEI_KOBOREDANE = 269, + TOKUSEI_NETUKOUKAN = 270, + TOKUSEI_IKARINOKOURA = 271, + TOKUSEI_KIYOMENOSIO = 272, + TOKUSEI_KONGARIBODHI = 273, + TOKUSEI_KAZENORI = 274, + TOKUSEI_BANKEN = 275, + TOKUSEI_IWAHAKOBI = 276, + TOKUSEI_HUURYOKUDENKI = 277, + TOKUSEI_MAITHITHENZI = 278, + TOKUSEI_SIREITOU = 279, + TOKUSEI_DENKINIKAERU = 280, + TOKUSEI_KODAIKASSEI = 281, + TOKUSEI_KWOOKUTYAAZI = 282, + TOKUSEI_OUGONNOKARADA = 283, + TOKUSEI_WAZAWAINOUTUWA = 284, + TOKUSEI_WAZAWAINOTURUGI = 285, + TOKUSEI_WAZAWAINOOHUDA = 286, + TOKUSEI_WAZAWAINOTAMA = 287, + TOKUSEI_HIHIIRONOKODOU = 288, + TOKUSEI_HADORONENZIN = 289, + TOKUSEI_BINZYOU = 290, + TOKUSEI_HANSUU = 291, + TOKUSEI_KIREAZI = 292, + TOKUSEI_SOUDAISYOU = 293, + TOKUSEI_KYOUEN = 294, + TOKUSEI_DOKUGESYOU = 295, + TOKUSEI_TEIRUAAMAA = 296, + TOKUSEI_DOSYOKU = 297, + TOKUSEI_KINSINOTIKARA = 298, + TOKUSEI_MOTENASHINOKOKORO = 299, + TOKUSEI_HISUINOHITOMI = 300, + TOKUSEI_KAMENNOSHINKAMIDORI = 301, + TOKUSEI_KAMENNOSHINKAKAMADO = 302, + TOKUSEI_KAMENNOSHINKAIDO = 303, + TOKUSEI_KAMENNOOSHINKAISHIZUE = 304, + TOKUSEI_KUSARIEN = 305, + TOKUSEI_KANRONAMITUAME = 306, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/TokuseiType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/TokuseiType.fbs new file mode 100644 index 00000000..8db7cf45 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/TokuseiType.fbs @@ -0,0 +1,9 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum TokuseiType : int { + RANDOM_12 = 0, + RANDOM_123 = 1, + SET_1 = 2, + SET_2 = 3, + SET_3 = 4, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/TriggerCommand.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/TriggerCommand.fbs new file mode 100644 index 00000000..61a5f8fb --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/TriggerCommand.fbs @@ -0,0 +1,10 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +table TriggerCommandElement { + Command:int; + Param:[string]; +} + +table TriggerCommand { + Element:[TriggerCommandElement]; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/TriggerTable.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/TriggerTable.fbs new file mode 100644 index 00000000..81c72041 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/TriggerTable.fbs @@ -0,0 +1,21 @@ +include "../Shared/ActivationCondition.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table TriggerCondition { + Condition:uint; + Param:[string]; + Activators:[ActivationCondition]; +} + +table Trigger { + Start:TriggerCondition; +} + +table TriggerTable (fs_serializer) { + Table:[Trigger]; +} + +root_type TriggerTable; diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/WazaID.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/WazaID.fbs new file mode 100644 index 00000000..e47b672a --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/WazaID.fbs @@ -0,0 +1,925 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum WazaID : ushort { + WAZA_NULL = 0, + WAZA_HATAKU = 1, + WAZA_KARATETYOPPU = 2, + WAZA_OUHUKUBINTA = 3, + WAZA_RENZOKUPANTI = 4, + WAZA_MEGATONPANTI = 5, + WAZA_NEKONIKOBAN = 6, + WAZA_HONOONOPANTI = 7, + WAZA_REITOUPANTI = 8, + WAZA_KAMINARIPANTI = 9, + WAZA_HIKKAKU = 10, + WAZA_HASAMU = 11, + WAZA_HASAMIGIROTIN = 12, + WAZA_KAMAITATI = 13, + WAZA_TURUGINOMAI = 14, + WAZA_IAIGIRI = 15, + WAZA_KAZEOKOSI = 16, + WAZA_TUBASADEUTU = 17, + WAZA_HUKITOBASI = 18, + WAZA_SORAWOTOBU = 19, + WAZA_SIMETUKERU = 20, + WAZA_TATAKITUKERU = 21, + WAZA_TURUNOMUTI = 22, + WAZA_HUMITUKE = 23, + WAZA_NIDOGERI = 24, + WAZA_MEGATONKIKKU = 25, + WAZA_TOBIGERI = 26, + WAZA_MAWASIGERI = 27, + WAZA_SUNAKAKE = 28, + WAZA_ZUTUKI = 29, + WAZA_TUNODETUKU = 30, + WAZA_MIDAREDUKI = 31, + WAZA_TUNODORIRU = 32, + WAZA_TAIATARI = 33, + WAZA_NOSIKAKARI = 34, + WAZA_MAKITUKU = 35, + WAZA_TOSSIN = 36, + WAZA_ABARERU = 37, + WAZA_SUTEMITAKKURU = 38, + WAZA_SIPPOWOHURU = 39, + WAZA_DOKUBARI = 40, + WAZA_DABURUNIIDORU = 41, + WAZA_MISAIRUBARI = 42, + WAZA_NIRAMITUKERU = 43, + WAZA_KAMITUKU = 44, + WAZA_NAKIGOE = 45, + WAZA_HOERU = 46, + WAZA_UTAU = 47, + WAZA_TYOUONPA = 48, + WAZA_SONIKKUBUUMU = 49, + WAZA_KANASIBARI = 50, + WAZA_YOUKAIEKI = 51, + WAZA_HINOKO = 52, + WAZA_KAENHOUSYA = 53, + WAZA_SIROIKIRI = 54, + WAZA_MIZUDEPPOU = 55, + WAZA_HAIDOROPONPU = 56, + WAZA_NAMINORI = 57, + WAZA_REITOUBIIMU = 58, + WAZA_HUBUKI = 59, + WAZA_SAIKEKOUSEN = 60, + WAZA_BABURUKOUSEN = 61, + WAZA_OORORABIIMU = 62, + WAZA_HAKAIKOUSEN = 63, + WAZA_TUTUKU = 64, + WAZA_DORIRUKUTIBASI = 65, + WAZA_ZIGOKUGURUMA = 66, + WAZA_KETAGURI = 67, + WAZA_KAUNTAA = 68, + WAZA_TIKYUUNAGE = 69, + WAZA_KAIRIKI = 70, + WAZA_SUITORU = 71, + WAZA_MEGADOREIN = 72, + WAZA_YADORIGINOTANE = 73, + WAZA_SEITYOU = 74, + WAZA_HAPPAKATTAA = 75, + WAZA_SOORAABIIMU = 76, + WAZA_DOKUNOKONA = 77, + WAZA_SIBIREGONA = 78, + WAZA_NEMURIGONA = 79, + WAZA_HANABIRANOMAI = 80, + WAZA_ITOWOHAKU = 81, + WAZA_RYUUNOIKARI = 82, + WAZA_HONOONOUZU = 83, + WAZA_DENKISYOKKU = 84, + WAZA_10MANBORUTO = 85, + WAZA_DENZIHA = 86, + WAZA_KAMINARI = 87, + WAZA_IWAOTOSI = 88, + WAZA_ZISIN = 89, + WAZA_ZIWARE = 90, + WAZA_ANAWOHORU = 91, + WAZA_DOKUDOKU = 92, + WAZA_NENRIKI = 93, + WAZA_SAIKOKINESISU = 94, + WAZA_SAIMINZYUTU = 95, + WAZA_YOGANOPOOZU = 96, + WAZA_KOUSOKUIDOU = 97, + WAZA_DENKOUSEKKA = 98, + WAZA_IKARI = 99, + WAZA_TEREPOOTO = 100, + WAZA_NAITOHEDDO = 101, + WAZA_MONOMANE = 102, + WAZA_IYANAOTO = 103, + WAZA_KAGEBUNSIN = 104, + WAZA_ZIKOSAISEI = 105, + WAZA_KATAKUNARU = 106, + WAZA_TIISAKUNARU = 107, + WAZA_ENMAKU = 108, + WAZA_AYASIIHIKARI = 109, + WAZA_KARANIKOMORU = 110, + WAZA_MARUKUNARU = 111, + WAZA_BARIAA = 112, + WAZA_HIKARINOKABE = 113, + WAZA_KUROIKIRI = 114, + WAZA_RIHUREKUTAA = 115, + WAZA_KIAIDAME = 116, + WAZA_GAMAN = 117, + WAZA_YUBIWOHURU = 118, + WAZA_OUMUGAESI = 119, + WAZA_ZIBAKU = 120, + WAZA_TAMAGOBAKUDAN = 121, + WAZA_SITADENAMERU = 122, + WAZA_SUMOGGU = 123, + WAZA_HEDOROKOUGEKI = 124, + WAZA_HONEKONBOU = 125, + WAZA_DAIMONZI = 126, + WAZA_TAKINOBORI = 127, + WAZA_KARADEHASAMU = 128, + WAZA_SUPIIDOSUTAA = 129, + WAZA_ROKETTOZUTUKI = 130, + WAZA_TOGEKYANON = 131, + WAZA_KARAMITUKU = 132, + WAZA_DOWASURE = 133, + WAZA_SUPUUNMAGE = 134, + WAZA_TAMAGOUMI = 135, + WAZA_TOBIHIZAGERI = 136, + WAZA_HEBINIRAMI = 137, + WAZA_YUMEKUI = 138, + WAZA_DOKUGASU = 139, + WAZA_TAMANAGE = 140, + WAZA_KYUUKETU = 141, + WAZA_AKUMANOKISSU = 142, + WAZA_GODDOBAADO = 143, + WAZA_HENSIN = 144, + WAZA_AWA = 145, + WAZA_PIYOPIYOPANTI = 146, + WAZA_KINOKONOHOUSI = 147, + WAZA_HURASSYU = 148, + WAZA_SAIKOWHEEBU = 149, + WAZA_HANERU = 150, + WAZA_TOKERU = 151, + WAZA_KURABUHANMAA = 152, + WAZA_DAIBAKUHATU = 153, + WAZA_MIDAREHIKKAKI = 154, + WAZA_HONEBUUMERAN = 155, + WAZA_NEMURU = 156, + WAZA_IWANADARE = 157, + WAZA_HISSATUMAEBA = 158, + WAZA_KAKUBARU = 159, + WAZA_TEKUSUTYAA = 160, + WAZA_TORAIATAKKU = 161, + WAZA_IKARINOMAEBA = 162, + WAZA_KIRISAKU = 163, + WAZA_MIGAWARI = 164, + WAZA_WARUAGAKI = 165, + WAZA_SUKETTI = 166, + WAZA_TORIPURUKIKKU = 167, + WAZA_DOROBOU = 168, + WAZA_KUMONOSU = 169, + WAZA_KOKORONOME = 170, + WAZA_AKUMU = 171, + WAZA_KAENGURUMA = 172, + WAZA_IBIKI = 173, + WAZA_NOROI = 174, + WAZA_ZITABATA = 175, + WAZA_TEKUSUTYAA2 = 176, + WAZA_EAROBURASUTO = 177, + WAZA_WATAHOUSI = 178, + WAZA_KISIKAISEI = 179, + WAZA_URAMI = 180, + WAZA_KONAYUKI = 181, + WAZA_MAMORU = 182, + WAZA_MAHHAPANTI = 183, + WAZA_KOWAIKAO = 184, + WAZA_DAMASIUTI = 185, + WAZA_TENSINOKISSU = 186, + WAZA_HARADAIKO = 187, + WAZA_HEDOROBAKUDAN = 188, + WAZA_DOROKAKE = 189, + WAZA_OKUTANHOU = 190, + WAZA_MAKIBISI = 191, + WAZA_DENZIHOU = 192, + WAZA_MIYABURU = 193, + WAZA_MITIDURE = 194, + WAZA_HOROBINOUTA = 195, + WAZA_KOGOERUKAZE = 196, + WAZA_MIKIRI = 197, + WAZA_BOONRASSYU = 198, + WAZA_ROKKUON = 199, + WAZA_GEKIRIN = 200, + WAZA_SUNAARASI = 201, + WAZA_GIGADOREIN = 202, + WAZA_KORAERU = 203, + WAZA_AMAERU = 204, + WAZA_KOROGARU = 205, + WAZA_MINEUTI = 206, + WAZA_IBARU = 207, + WAZA_MIRUKUNOMI = 208, + WAZA_SUPAAKU = 209, + WAZA_RENZOKUGIRI = 210, + WAZA_HAGANENOTUBASA = 211, + WAZA_KUROIMANAZASI = 212, + WAZA_MEROMERO = 213, + WAZA_NEGOTO = 214, + WAZA_IYASINOSUZU = 215, + WAZA_ONGAESI = 216, + WAZA_PUREZENTO = 217, + WAZA_YATUATARI = 218, + WAZA_SINPINOMAMORI = 219, + WAZA_ITAMIWAKE = 220, + WAZA_SEINARUHONOO = 221, + WAZA_MAGUNITYUUDO = 222, + WAZA_BAKURETUPANTI = 223, + WAZA_MEGAHOON = 224, + WAZA_RYUUNOIBUKI = 225, + WAZA_BATONTATTI = 226, + WAZA_ANKOORU = 227, + WAZA_OIUTI = 228, + WAZA_KOUSOKUSUPIN = 229, + WAZA_AMAIKAORI = 230, + WAZA_AIANTEERU = 231, + WAZA_METARUKUROO = 232, + WAZA_ATEMINAGE = 233, + WAZA_ASANOHIZASI = 234, + WAZA_KOUGOUSEI = 235, + WAZA_TUKINOHIKARI = 236, + WAZA_MEZAMERUPAWAA = 237, + WAZA_KUROSUTYOPPU = 238, + WAZA_TATUMAKI = 239, + WAZA_AMAGOI = 240, + WAZA_NIHONBARE = 241, + WAZA_KAMIKUDAKU = 242, + WAZA_MIRAAKOOTO = 243, + WAZA_ZIKOANZI = 244, + WAZA_SINSOKU = 245, + WAZA_GENSINOTIKARA = 246, + WAZA_SYADOOBOORU = 247, + WAZA_MIRAIYOTI = 248, + WAZA_IWAKUDAKI = 249, + WAZA_UZUSIO = 250, + WAZA_HUKURODATAKI = 251, + WAZA_NEKODAMASI = 252, + WAZA_SAWAGU = 253, + WAZA_TAKUWAERU = 254, + WAZA_HAKIDASU = 255, + WAZA_NOMIKOMU = 256, + WAZA_NEPPUU = 257, + WAZA_ARARE = 258, + WAZA_ITYAMON = 259, + WAZA_ODATERU = 260, + WAZA_ONIBI = 261, + WAZA_OKIMIYAGE = 262, + WAZA_KARAGENKI = 263, + WAZA_KIAIPANTI = 264, + WAZA_KITUKE = 265, + WAZA_KONOYUBITOMARE = 266, + WAZA_SIZENNOTIKARA = 267, + WAZA_ZYUUDEN = 268, + WAZA_TYOUHATU = 269, + WAZA_TEDASUKE = 270, + WAZA_TORIKKU = 271, + WAZA_NARIKIRI = 272, + WAZA_NEGAIGOTO = 273, + WAZA_NEKONOTE = 274, + WAZA_NEWOHARU = 275, + WAZA_BAKADIKARA = 276, + WAZA_MAZIKKUKOOTO = 277, + WAZA_RISAIKURU = 278, + WAZA_RIBENZI = 279, + WAZA_KAWARAWARI = 280, + WAZA_AKUBI = 281, + WAZA_HATAKIOTOSU = 282, + WAZA_GAMUSYARA = 283, + WAZA_HUNKA = 284, + WAZA_SUKIRUSUWAPPU = 285, + WAZA_HUUIN = 286, + WAZA_RIHURESSYU = 287, + WAZA_ONNEN = 288, + WAZA_YOKODORI = 289, + WAZA_HIMITUNOTIKARA = 290, + WAZA_DAIBINGU = 291, + WAZA_TUPPARI = 292, + WAZA_HOGOSYOKU = 293, + WAZA_HOTARUBI = 294, + WAZA_RASUTAAPAAZI = 295, + WAZA_MISUTOBOORU = 296, + WAZA_FEZAADANSU = 297, + WAZA_HURAHURADANSU = 298, + WAZA_BUREIZUKIKKU = 299, + WAZA_DOROASOBI = 300, + WAZA_AISUBOORU = 301, + WAZA_NIIDORUAAMU = 302, + WAZA_NAMAKERU = 303, + WAZA_HAIPAABOISU = 304, + WAZA_DOKUDOKUNOKIBA = 305, + WAZA_BUREIKUKUROO = 306, + WAZA_BURASUTOBAAN = 307, + WAZA_HAIDOROKANON = 308, + WAZA_KOMETTOPANTI = 309, + WAZA_ODOROKASU = 310, + WAZA_WHEZAABOORU = 311, + WAZA_AROMASERAPII = 312, + WAZA_USONAKI = 313, + WAZA_EAKATTAA = 314, + WAZA_OOBAAHIITO = 315, + WAZA_KAGIWAKERU = 316, + WAZA_GANSEKIHUUZI = 317, + WAZA_GINIRONOKAZE = 318, + WAZA_KINZOKUON = 319, + WAZA_KUSABUE = 320, + WAZA_KUSUGURU = 321, + WAZA_KOSUMOPAWAA = 322, + WAZA_SIOHUKI = 323, + WAZA_SIGUNARUBIIMU = 324, + WAZA_SYADOOPANTI = 325, + WAZA_ZINTUURIKI = 326, + WAZA_SUKAIAPPAA = 327, + WAZA_SUNAZIGOKU = 328, + WAZA_ZETTAIREIDO = 329, + WAZA_DAKURYUU = 330, + WAZA_TANEMASINGAN = 331, + WAZA_TUBAMEGAESI = 332, + WAZA_TURARABARI = 333, + WAZA_TEPPEKI = 334, + WAZA_TOOSENBOU = 335, + WAZA_TOOBOE = 336, + WAZA_DORAGONKUROO = 337, + WAZA_HAADOPURANTO = 338, + WAZA_BIRUDOAPPU = 339, + WAZA_TOBIHANERU = 340, + WAZA_MADDOSYOTTO = 341, + WAZA_POIZUNTEERU = 342, + WAZA_HOSIGARU = 343, + WAZA_BORUTEKKAA = 344, + WAZA_MAZIKARURIIHU = 345, + WAZA_MIZUASOBI = 346, + WAZA_MEISOU = 347, + WAZA_RIIHUBUREEDO = 348, + WAZA_RYUUNOMAI = 349, + WAZA_ROKKUBURASUTO = 350, + WAZA_DENGEKIHA = 351, + WAZA_MIZUNOHADOU = 352, + WAZA_HAMETUNONEGAI = 353, + WAZA_SAIKOBUUSUTO = 354, + WAZA_HANEYASUME = 355, + WAZA_ZYUURYOKU = 356, + WAZA_MIRAKURUAI = 357, + WAZA_MEZAMASIBINTA = 358, + WAZA_AAMUHANMAA = 359, + WAZA_ZYAIROBOORU = 360, + WAZA_IYASINONEGAI = 361, + WAZA_SIOMIZU = 362, + WAZA_SIZENNOMEGUMI = 363, + WAZA_FEINTO = 364, + WAZA_TUIBAMU = 365, + WAZA_OIKAZE = 366, + WAZA_TUBOWOTUKU = 367, + WAZA_METARUBAASUTO = 368, + WAZA_TONBOGAERI = 369, + WAZA_INFAITO = 370, + WAZA_SIPPEGAESI = 371, + WAZA_DAMEOSI = 372, + WAZA_SASIOSAE = 373, + WAZA_NAGETUKERU = 374, + WAZA_SAIKOSIHUTO = 375, + WAZA_KIRIHUDA = 376, + WAZA_KAIHUKUHUUZI = 377, + WAZA_SIBORITORU = 378, + WAZA_PAWAATORIKKU = 379, + WAZA_IEKI = 380, + WAZA_OMAZINAI = 381, + WAZA_SAKIDORI = 382, + WAZA_MANEKKO = 383, + WAZA_PAWAASUWAPPU = 384, + WAZA_GAADOSUWAPPU = 385, + WAZA_OSIOKI = 386, + WAZA_TOTTEOKI = 387, + WAZA_NAYAMINOTANE = 388, + WAZA_HUIUTI = 389, + WAZA_DOKUBISI = 390, + WAZA_HAATOSUWAPPU = 391, + WAZA_AKUARINGU = 392, + WAZA_DENZIHUYUU = 393, + WAZA_HUREADORAIBU = 394, + WAZA_HAKKEI = 395, + WAZA_HADOUDAN = 396, + WAZA_ROKKUKATTO = 397, + WAZA_DOKUDUKI = 398, + WAZA_AKUNOHADOU = 399, + WAZA_TUZIGIRI = 400, + WAZA_AKUATEERU = 401, + WAZA_TANEBAKUDAN = 402, + WAZA_EASURASSYU = 403, + WAZA_SIZAAKUROSU = 404, + WAZA_MUSINOSAZAMEKI = 405, + WAZA_RYUUNOHADOU = 406, + WAZA_DORAGONDAIBU = 407, + WAZA_PAWAAJEMU = 408, + WAZA_DOREINPANTI = 409, + WAZA_SINKUUHA = 410, + WAZA_KIAIDAMA = 411, + WAZA_ENAZIIBOORU = 412, + WAZA_BUREIBUBAADO = 413, + WAZA_DAITINOTIKARA = 414, + WAZA_SURIKAE = 415, + WAZA_GIGAINPAKUTO = 416, + WAZA_WARUDAKUMI = 417, + WAZA_BARETTOPANTI = 418, + WAZA_YUKINADARE = 419, + WAZA_KOORINOTUBUTE = 420, + WAZA_SYADOOKUROO = 421, + WAZA_KAMINARINOKIBA = 422, + WAZA_KOORINOKIBA = 423, + WAZA_HONOONOKIBA = 424, + WAZA_KAGEUTI = 425, + WAZA_DOROBAKUDAN = 426, + WAZA_SAIKOKATTAA = 427, + WAZA_SINENNOZUTUKI = 428, + WAZA_MIRAASYOTTO = 429, + WAZA_RASUTAAKANON = 430, + WAZA_ROKKUKURAIMU = 431, + WAZA_KIRIBARAI = 432, + WAZA_TORIKKURUUMU = 433, + WAZA_RYUUSEIGUN = 434, + WAZA_HOUDEN = 435, + WAZA_HUNEN = 436, + WAZA_RIIHUSUTOOMU = 437, + WAZA_PAWAAWHIPPU = 438, + WAZA_GANSEKIHOU = 439, + WAZA_KUROSUPOIZUN = 440, + WAZA_DASUTOSYUUTO = 441, + WAZA_AIANHEDDO = 442, + WAZA_MAGUNETTOBOMU = 443, + WAZA_SUTOONEZZI = 444, + WAZA_YUUWAKU = 445, + WAZA_SUTERUSUROKKU = 446, + WAZA_KUSAMUSUBI = 447, + WAZA_OSYABERI = 448, + WAZA_SABAKINOTUBUTE = 449, + WAZA_MUSIKUI = 450, + WAZA_TYAAZIBIIMU = 451, + WAZA_UDDOHANMAA = 452, + WAZA_AKUAJETTO = 453, + WAZA_KOUGEKISIREI = 454, + WAZA_BOUGYOSIREI = 455, + WAZA_KAIHUKUSIREI = 456, + WAZA_MOROHANOZUTUKI = 457, + WAZA_DABURUATAKKU = 458, + WAZA_TOKINOHOUKOU = 459, + WAZA_AKUUSETUDAN = 460, + WAZA_MIKADUKINOMAI = 461, + WAZA_NIGIRITUBUSU = 462, + WAZA_MAGUMASUTOOMU = 463, + WAZA_DAAKUHOORU = 464, + WAZA_SIIDOHUREA = 465, + WAZA_AYASIIKAZE = 466, + WAZA_SYADOODAIBU = 467, + WAZA_TUMETOGI = 468, + WAZA_WAIDOGAADO = 469, + WAZA_GAADOSHEA = 470, + WAZA_PAWAASHEA = 471, + WAZA_WANDAARUUMU = 472, + WAZA_SAIKOSYOKKU = 473, + WAZA_BENOMUSYOKKU = 474, + WAZA_BODHIPAAZI = 475, + WAZA_IKARINOKONA = 476, + WAZA_TEREKINESISU = 477, + WAZA_MAZIKKURUUMU = 478, + WAZA_UTIOTOSU = 479, + WAZA_YAMAARASI = 480, + WAZA_HAZIKERUHONOO = 481, + WAZA_HEDOROWHEEBU = 482, + WAZA_TYOUNOMAI = 483, + WAZA_HEBIIBONBAA = 484, + WAZA_SINKURONOIZU = 485, + WAZA_EREKIBOORU = 486, + WAZA_MIZUBITASI = 487, + WAZA_NITOROTYAAZI = 488, + WAZA_TOGUROWOMAKU = 489, + WAZA_ROOKIKKU = 490, + WAZA_ASIDDOBOMU = 491, + WAZA_IKASAMA = 492, + WAZA_SINPURUBIIMU = 493, + WAZA_NAKAMADUKURI = 494, + WAZA_OSAKINIDOUZO = 495, + WAZA_RINSYOU = 496, + WAZA_EKOOBOISU = 497, + WAZA_NASIKUZUSI = 498, + WAZA_KURIASUMOGGU = 499, + WAZA_ASISUTOPAWAA = 500, + WAZA_FASUTOGAADO = 501, + WAZA_SAIDOTHENZI = 502, + WAZA_NETTOU = 503, + WAZA_KARAWOYABURU = 504, + WAZA_IYASINOHADOU = 505, + WAZA_TATARIME = 506, + WAZA_HURIIFOORU = 507, + WAZA_GIATHENZI = 508, + WAZA_TOMOENAGE = 509, + WAZA_YAKITUKUSU = 510, + WAZA_SAKIOKURI = 511, + WAZA_AKUROBATTO = 512, + WAZA_MIRAATAIPU = 513, + WAZA_KATAKIUTI = 514, + WAZA_INOTIGAKE = 515, + WAZA_GIHUTOPASU = 516, + WAZA_RENGOKU = 517, + WAZA_MIZUNOTIKAI = 518, + WAZA_HONOONOTIKAI = 519, + WAZA_KUSANOTIKAI = 520, + WAZA_BORUTOTHENZI = 521, + WAZA_MUSINOTEIKOU = 522, + WAZA_ZINARASI = 523, + WAZA_KOORINOIBUKI = 524, + WAZA_DORAGONTEERU = 525, + WAZA_HURUITATERU = 526, + WAZA_EREKINETTO = 527, + WAZA_WAIRUDOBORUTO = 528, + WAZA_DORIRURAINAA = 529, + WAZA_DABURUTYOPPU = 530, + WAZA_HAATOSUTANPU = 531, + WAZA_UDDOHOON = 532, + WAZA_SEINARUTURUGI = 533, + WAZA_SHERUBUREEDO = 534, + WAZA_HIITOSUTANPU = 535, + WAZA_GURASUMIKISAA = 536, + WAZA_HAADOROORAA = 537, + WAZA_KOTTONGAADO = 538, + WAZA_NAITOBAASUTO = 539, + WAZA_SAIKOBUREIKU = 540, + WAZA_SUIIPUBINTA = 541, + WAZA_BOUHUU = 542, + WAZA_AHUROBUREIKU = 543, + WAZA_GIASOOSAA = 544, + WAZA_KAENDAN = 545, + WAZA_TEKUNOBASUTAA = 546, + WAZA_INISIENOUTA = 547, + WAZA_SINPINOTURUGI = 548, + WAZA_KOGOERUSEKAI = 549, + WAZA_RAIGEKI = 550, + WAZA_AOIHONOO = 551, + WAZA_HONOONOMAI = 552, + WAZA_HURIIZUBORUTO = 553, + WAZA_KOORUDOHUREA = 554, + WAZA_BAAKUAUTO = 555, + WAZA_TURARAOTOSI = 556, + WAZA_vJENEREETO = 557, + WAZA_KUROSUHUREIMU = 558, + WAZA_KUROSUSANDAA = 559, + WAZA_HURAINGUPURESU = 560, + WAZA_TATAMIGAESI = 561, + WAZA_GEPPU = 562, + WAZA_TAGAYASU = 563, + WAZA_NEBANEBANETTO = 564, + WAZA_TODOMEBARI = 565, + WAZA_GOOSUTODAIBU = 566, + WAZA_HAROWHIN = 567, + WAZA_OTAKEBI = 568, + WAZA_PURAZUMASYAWAA = 569, + WAZA_PARABORATYAAZI = 570, + WAZA_MORINONOROI = 571, + WAZA_HANAHUBUKI = 572, + WAZA_HURIIZUDORAI = 573, + WAZA_TYAAMUBOISU = 574, + WAZA_SUTEZERIHU = 575, + WAZA_HIKKURIKAESU = 576, + WAZA_DOREINKISSU = 577, + WAZA_TORIKKUGAADO = 578, + WAZA_HURAWAAGAADO = 579, + WAZA_GURASUFIIRUDO = 580, + WAZA_MISUTOFIIRUDO = 581, + WAZA_SOUDEN = 582, + WAZA_ZYARETUKU = 583, + WAZA_YOUSEINOKAZE = 584, + WAZA_MUUNFOOSU = 585, + WAZA_BAKUONPA = 586, + WAZA_FEARIIROKKU = 587, + WAZA_KINGUSIIRUDO = 588, + WAZA_NAKAYOKUSURU = 589, + WAZA_NAISYOBANASI = 590, + WAZA_DAIYASUTOOMU = 591, + WAZA_SUTIIMUBAASUTO = 592, + WAZA_IZIGENHOORU = 593, + WAZA_MIZUSYURIKEN = 594, + WAZA_MAZIKARUHUREIMU = 595, + WAZA_NIIDORUGAADO = 596, + WAZA_AROMAMISUTO = 597, + WAZA_KAIDENPA = 598, + WAZA_BENOMUTORAPPU = 599, + WAZA_HUNZIN = 600, + WAZA_ZIOKONTOROORU = 601, + WAZA_ZIBASOUSA = 602, + WAZA_HAPPIITAIMU = 603, + WAZA_EREKIFIIRUDO = 604, + WAZA_MAZIKARUSYAIN = 605, + WAZA_OIWAI = 606, + WAZA_TEWOTUNAGU = 607, + WAZA_TUBURANAHITOMI = 608, + WAZA_HOPPESURISURI = 609, + WAZA_TEKAGEN = 610, + WAZA_MATOWARITUKU = 611, + WAZA_GUROUPANTI = 612, + WAZA_DESUUINGU = 613, + WAZA_SAUZANAROO = 614, + WAZA_SAUZANWHEEBU = 615, + WAZA_GURANDOFOOSU = 616, + WAZA_HAMETUNOHIKARI = 617, + WAZA_KONGENNOHADOU = 618, + WAZA_DANGAINOTURUGI = 619, + WAZA_GARYOUTENSEI = 620, + WAZA_IZIGENRASSYU = 621, + WAZA_URUTORADASSYUATAKKU = 622, + WAZA_NOOMARUZENRYOKU = 623, + WAZA_ZENRYOKUMUSOUGEKIRETUKEN = 624, + WAZA_KAKUTOUZENRYOKU = 625, + WAZA_FAINARUDAIBUKURASSYU = 626, + WAZA_HIKOUZENRYOKU = 627, + WAZA_ASIDDOPOIZUNDERIITO = 628, + WAZA_DOKUZENRYOKU = 629, + WAZA_RAIZINGURANDOOOBAA = 630, + WAZA_ZIMENZENRYOKU = 631, + WAZA_WAARUZUENDOFOORU = 632, + WAZA_IWAZENRYOKU = 633, + WAZA_ZETTAIHOSYOKUKAITENZAN = 634, + WAZA_MUSIZENRYOKU = 635, + WAZA_MUGENANYAHENOIZANAI = 636, + WAZA_GOOSUTOZENRYOKU = 637, + WAZA_TYOUZETURASENRENGEKI = 638, + WAZA_HAGANEZENRYOKU = 639, + WAZA_DAINAMIKKUHURUHUREIMU = 640, + WAZA_HONOOZENRYOKU = 641, + WAZA_SUUPAAAKUATORUNEEDO = 642, + WAZA_MIZUZENRYOKU = 643, + WAZA_BURUUMUSYAINEKUSUTORA = 644, + WAZA_KUSAZENRYOKU = 645, + WAZA_SUPAAKINGUGIGABORUTO = 646, + WAZA_DENKIZENRYOKU = 647, + WAZA_MAKISIMAMUSAIBUREIKAA = 648, + WAZA_ESUPAAZENRYOKU = 649, + WAZA_REIZINGUZIOHURIIZU = 650, + WAZA_KOORIZENRYOKU = 651, + WAZA_ARUTHIMETTODORAGONBAAN = 652, + WAZA_DORAGONZENRYOKU = 653, + WAZA_BURAKKUHOORUIKURIPUSU = 654, + WAZA_AKUZENRYOKU = 655, + WAZA_RABURIISUTAAINPAKUTO = 656, + WAZA_FEARIIZENRYOKU = 657, + WAZA_HISSATUNOPIKATYUUTO = 658, + WAZA_SUNAATUME = 659, + WAZA_DEAIGASIRA = 660, + WAZA_TOOTIKA = 661, + WAZA_KAGENUI = 662, + WAZA_ddRARIATTO = 663, + WAZA_UTAKATANOARIA = 664, + WAZA_AISUHANMAA = 665, + WAZA_HURAWAAHIIRU = 666, + WAZA_10MANBARIKI = 667, + WAZA_TIKARAWOSUITORU = 668, + WAZA_SOORAABUREEDO = 669, + WAZA_KONOHA = 670, + WAZA_SUPOTTORAITO = 671, + WAZA_DOKUNOITO = 672, + WAZA_TOGISUMASU = 673, + WAZA_ASISUTOGIA = 674, + WAZA_ZIGOKUDUKI = 675, + WAZA_KAHUNDANGO = 676, + WAZA_ANKAASYOTTO = 677, + WAZA_SAIKOFIIRUDO = 678, + WAZA_TOBIKAKARU = 679, + WAZA_HONOONOMUTI = 680, + WAZA_TUKEAGARU = 681, + WAZA_MOETUKIRU = 682, + WAZA_SUPIIDOSUWAPPU = 683, + WAZA_SUMAATOHOON = 684, + WAZA_ZYOUKA = 685, + WAZA_MEZAMERUDANSU = 686, + WAZA_KOAPANISSYAA = 687, + WAZA_TOROPIKARUKIKKU = 688, + WAZA_SAIHAI = 689, + WAZA_KUTIBASIKYANON = 690, + WAZA_SUKEIRUNOIZU = 691, + WAZA_DORAGONHANMAA = 692, + WAZA_BUNMAWASU = 693, + WAZA_OORORABEERU = 694, + WAZA_SYADOOAROOZUSUTORAIKU = 695, + WAZA_HAIPAADAAKUKURASSYAA = 696, + WAZA_WADATUMINOSINFONIA = 697, + WAZA_GAADHIANDEAROORA = 698, + WAZA_SITISEIDAKKONTAI = 699, + WAZA_RAITONINGUSAAHURAIDO = 700, + WAZA_HONKIWODASUKOUGEKI = 701, + WAZA_NAINEBORUBUUSUTO = 702, + WAZA_ORIZINZUSUUPAANOVHA = 703, + WAZA_TORAPPUSHERU = 704, + WAZA_HURUURUKANON = 705, + WAZA_SAIKOFANGU = 706, + WAZA_ZIDANDA = 707, + WAZA_SYADOOBOON = 708, + WAZA_AKUSERUROKKU = 709, + WAZA_AKUABUREIKU = 710, + WAZA_PURIZUMUREEZAA = 711, + WAZA_SYADOOSUTIIRU = 712, + WAZA_METEODORAIBU = 713, + WAZA_SYADOOREI = 714, + WAZA_NAMIDAME = 715, + WAZA_BIRIBIRITIKUTIKU = 716, + WAZA_SIZENNOIKARI = 717, + WAZA_MARUTIATAKKU = 718, + WAZA_1000MANBORUTO = 719, + WAZA_BIKKURIHEDDO = 720, + WAZA_PURAZUMAFISUTO = 721, + WAZA_FOTONGEIZAA = 722, + WAZA_TENKOGASUMETUBOUNOHIKARI = 723, + WAZA_SANSYAINSUMASSYAA = 724, + WAZA_MUUNRAITOBURASUTAA = 725, + WAZA_POKABOKAHURENDOTAIMU = 726, + WAZA_RAZIARUEZZISUTOOMU = 727, + WAZA_BUREIZINGUSOURUBIITO = 728, + WAZA_BATIBATIAKUSERU = 729, + WAZA_ZABUZABUSAAHU = 730, + WAZA_HUWAHUWAFOORU = 731, + WAZA_PIKAPIKASANDAA = 732, + WAZA_IKIIKIBABURU = 733, + WAZA_BIRIBIRIEREKI = 734, + WAZA_MERAMERABAAN = 735, + WAZA_DOBADOBAOORA = 736, + WAZA_WARUWARUZOON = 737, + WAZA_SUKUSUKUBONBAA = 738, + WAZA_KOTIKOTIHUROSUTO = 739, + WAZA_KIRAKIRASUTOOMU = 740, + WAZA_BUIBUIBUREIKU = 741, + WAZA_DABURUPANTHAA = 742, + WAZA_DAIWHOORU = 743, + WAZA_DAIMAKKUSUHOU = 744, + WAZA_NERAIUTI = 745, + WAZA_KURAITUKU = 746, + WAZA_HOOBARU = 747, + WAZA_HAISUINOZIN = 748, + WAZA_TAARUSYOTTO = 749, + WAZA_MAHOUNOKONA = 750, + WAZA_DORAGONAROO = 751, + WAZA_OTYAKAI = 752, + WAZA_TAKOGATAME = 753, + WAZA_DENGEKIKUTIBASI = 754, + WAZA_ERAGAMI = 755, + WAZA_KOOTOTHENZI = 756, + WAZA_DAIBAAN = 757, + WAZA_DAIWAAMU = 758, + WAZA_DAISANDAA = 759, + WAZA_DAIATAKKU = 760, + WAZA_DAINAKKURU = 761, + WAZA_DAIHOROU = 762, + WAZA_DAIAISU = 763, + WAZA_DAIASIDDO = 764, + WAZA_DAISUTORIIMU = 765, + WAZA_DAIJETTO = 766, + WAZA_DAIFEARII = 767, + WAZA_DAIDORAGUUN = 768, + WAZA_DAISAIKO = 769, + WAZA_DAIROKKU = 770, + WAZA_DAIAASU = 771, + WAZA_DAIAAKU = 772, + WAZA_DAISOUGEN = 773, + WAZA_DAISUTIRU = 774, + WAZA_SOURUBIITO = 775, + WAZA_BODHIPURESU = 776, + WAZA_DEKOREESYON = 777, + WAZA_DORAMUATAKKU = 778, + WAZA_TORABASAMI = 779, + WAZA_KAENBOORU = 780, + WAZA_KYOZYUUZAN = 781, + WAZA_KYOZYUUDAN = 782, + WAZA_OORAGURUMA = 783, + WAZA_WAIDOBUREIKAA = 784, + WAZA_EDADUKI = 785, + WAZA_OOBAADORAIBU = 786, + WAZA_RINGOSAN = 787, + WAZA_NYUUTON = 788, + WAZA_SOURUKURASSYU = 789, + WAZA_WANDAASUTIIMU = 790, + WAZA_INOTINOSIZUKU = 791, + WAZA_BUROKKINGU = 792, + WAZA_DOGEZATUKI = 793, + WAZA_SUTAAASARUTO = 794, + WAZA_MUGENDAIBIIMU = 795, + WAZA_TETTEIKOUSEN = 796, + WAZA_WAIDOFOOSU = 797, + WAZA_AIANROORAA = 798, + WAZA_SUKEIRUSYOTTO = 799, + WAZA_METEOBIIMU = 800, + WAZA_SHERUAAMUZU = 801, + WAZA_MISUTOBAASUTO = 802, + WAZA_GURASUSURAIDAA = 803, + WAZA_RAIZINGUBORUTO = 804, + WAZA_DAITINOHADOU = 805, + WAZA_HAIYORUITIGEKI = 806, + WAZA_SITTONOHONOO = 807, + WAZA_UPPUNBARASI = 808, + WAZA_PORUTAAGAISUTO = 809, + WAZA_HUSYOKUGASU = 810, + WAZA_KOOTINGU = 811, + WAZA_KUIKKUTAAN = 812, + WAZA_TORIPURUAKUSERU = 813, + WAZA_DABURUUINGU = 814, + WAZA_NESSANODAITI = 815, + WAZA_ZYANGURUHIIRU = 816, + WAZA_ANKOKUKYOUDA = 817, + WAZA_SUIRYUURENDA = 818, + WAZA_SANDAAPURIZUN = 819, + WAZA_DORAGONENAZII = 820, + WAZA_ITETUKUSISEN = 821, + WAZA_MOEAGARUIKARI = 822, + WAZA_RAIMEIGERI = 823, + WAZA_BURIZAADORANSU = 824, + WAZA_ASUTORARUBITTO = 825, + WAZA_BUKIMINAZYUMON = 826, + WAZA_FEITARUKUROO = 827, + WAZA_BARIAARASSYU = 828, + WAZA_PAWAASIHUTO = 829, + WAZA_GANSEKIAKKUSU = 830, + WAZA_HARUNOARASI = 831, + WAZA_SINPINOTIKARA = 832, + WAZA_DAIHUNGEKI = 833, + WAZA_WHEEBUTAKKURU = 834, + WAZA_KUROROBURASUTO = 835, + WAZA_HYOUZANOROSI = 836, + WAZA_SYOURINOMAI = 837, + WAZA_BUTIKAMASI = 838, + WAZA_DOKUBARISENBON = 839, + WAZA_OORAUINGU = 840, + WAZA_URAMITURAMI = 841, + WAZA_TATEKOMORU = 842, + WAZA_3BONNOYA = 843, + WAZA_HYAKKIYAKOU = 844, + WAZA_HIKENTIENAMI = 845, + WAZA_KOGARASIARASI = 846, + WAZA_KAMINARIARASI = 847, + WAZA_NESSANOARASI = 848, + WAZA_MIKADUKINOINORI = 849, + WAZA_BUREIBUTYAAZI = 850, + WAZA_TERABAASUTO = 851, + WAZA_SUREDDOTORAPPU = 852, + WAZA_KAKATOOTOSI = 853, + WAZA_OHAKAMAIRI = 854, + WAZA_RUMINAKORIZYON = 855, + WAZA_ITTYOUAGARI = 856, + WAZA_JETTOPANTI = 857, + WAZA_HABANEROEKISU = 858, + WAZA_HOIIRUSUPIN = 859, + WAZA_NEZUMIZAN = 860, + WAZA_AISUSUPINAA = 861, + WAZA_KYOKENTOTUGEKI = 862, + WAZA_SAIKINOINORI = 863, + WAZA_SIODUKE = 864, + WAZA_TORIPURUDAIBU = 865, + WAZA_KARUKANSUPIN = 866, + WAZA_UTUSIE = 867, + WAZA_MIWOKEZURU = 868, + WAZA_DOGEZAN = 869, + WAZA_TORIKKUHURAWAA = 870, + WAZA_HUREASONGU = 871, + WAZA_AKUASUTEPPU = 872, + WAZA_REIZINGUBURU = 873, + WAZA_GOORUDORASSYU = 874, + WAZA_SAIKOBUREIDO = 875, + WAZA_HAIDOROSUTIIMU = 876, + WAZA_KATASUTOROFII = 877, + WAZA_AKUSERUBUREIKU = 878, + WAZA_INAZUMADORAIBU = 879, + WAZA_SIPPOKIRI = 880, + WAZA_SAMUIGYAGU = 881, + WAZA_OKATADUKE = 882, + WAZA_YUKIGESIKI = 883, + WAZA_TOBITUKU = 884, + WAZA_KUSAWAKE = 885, + WAZA_HIYAMIZU = 886, + WAZA_HAIPAADORIRU = 887, + WAZA_TUINBIIMU = 888, + WAZA_HUNDONOKOBUSI = 889, + WAZA_AAMAAKYANON = 890, + WAZA_MUNENNOTURUGI = 891, + WAZA_DENKOUSOUGEKI = 892, + WAZA_GIGAHANMAA = 893, + WAZA_HOUHUKU = 894, + WAZA_AKUAKATTAA = 895, + WAZA_MOOBIRUKOUGEKI = 896, + WAZA_MOOBIRUKOUGEKI2 = 897, + WAZA_MOOBIRUKOUGEKI3 = 898, + WAZA_MOOBIRUKOUGEKI4 = 899, + WAZA_MOOBIRUKOUGEKI5 = 900, + WAZA_BURADDOMUN = 901, + WAZA_SHAKASHAKAHO = 902, + WAZA_MITSUAMEKOTO = 903, + WAZA_ONIKANABOO = 904, + WAZA_TYOUDENGIHOU = 905, + WAZA_TERAKURASUTAA = 906, + WAZA_KIMAGUREEZAA = 907, + WAZA_KAZANNOFURIRU = 908, + WAZA_SEITENHEKIREKI = 909, + WAZA_ROKKUKUREIMOA = 910, + WAZA_METARUSXYOOTERU = 911, + WAZA_HAADOPURESU = 912, + WAZA_WOOKURAI = 913, + WAZA_TENSHINOSOPURANO = 914, + WAZA_YAKETUPATI = 915, + WAZA_INAZUMADAIBU = 916, + WAZA_SAIKONOIZU = 917, + WAZA_HAYATEGAESHI = 918, + WAZA_KUSARIENN = 919, + WAZA_MUNIKISUHIKARI = 920, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/WazaList.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/WazaList.fbs new file mode 100644 index 00000000..74ee1713 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/WazaList.fbs @@ -0,0 +1,10 @@ +include "../Shared/WazaID.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table WazaList { + Waza1:WazaID; + Waza2:WazaID; + Waza3:WazaID; + Waza4:WazaID; +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/WazaType.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/WazaType.fbs new file mode 100644 index 00000000..b3f826ea --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/WazaType.fbs @@ -0,0 +1,6 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum WazaType : int { + DEFAULT = 0, + MANUAL = 1, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/ZARank.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/ZARank.fbs new file mode 100644 index 00000000..3e6ef669 --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/ZARank.fbs @@ -0,0 +1,32 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum ZARank : byte { + NONE = 0, + Z = 1, + Y = 2, + X = 3, + W = 4, + V = 5, + U = 6, + T = 7, + S = 8, + R = 9, + Q = 10, + P = 11, + O = 12, + N = 13, + M = 14, + L = 15, + K = 16, + J = 17, + I = 18, + H = 19, + G = 20, + F = 21, + E = 22, + D = 23, + C = 24, + B = 25, + A = 26, + Infinite = 27, +} diff --git a/FlatBuffers/ZA/Shared/Schemas/Shared/ZoneInfo.fbs b/FlatBuffers/ZA/Shared/Schemas/Shared/ZoneInfo.fbs new file mode 100644 index 00000000..65cceb9d --- /dev/null +++ b/FlatBuffers/ZA/Shared/Schemas/Shared/ZoneInfo.fbs @@ -0,0 +1,6 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +table ZoneInfo { + ZoneId:string; + VariationId:string; +} diff --git a/FlatBuffers/ZA/Shared/pkNX.Structures.FlatBuffers.ZA.Shared.csproj b/FlatBuffers/ZA/Shared/pkNX.Structures.FlatBuffers.ZA.Shared.csproj new file mode 100644 index 00000000..35e3d842 --- /dev/null +++ b/FlatBuffers/ZA/Shared/pkNX.Structures.FlatBuffers.ZA.Shared.csproj @@ -0,0 +1,2 @@ + + diff --git a/FlatBuffers/ZA/Trainers/Schemas/MedalRateDefeatBonusArray.fbs b/FlatBuffers/ZA/Trainers/Schemas/MedalRateDefeatBonusArray.fbs new file mode 100644 index 00000000..0020477c --- /dev/null +++ b/FlatBuffers/ZA/Trainers/Schemas/MedalRateDefeatBonusArray.fbs @@ -0,0 +1,13 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table MedalRateDefeatBonus { + NumTrainersDefeated:uint; + Multiplier:float; +} + +table MedalRateDefeatBonusArray (fs_serializer) { + Table:[MedalRateDefeatBonus] (required); +} + +root_type MedalRateDefeatBonusArray; diff --git a/FlatBuffers/ZA/Trainers/Schemas/NpcAssetDataDBArray.fbs b/FlatBuffers/ZA/Trainers/Schemas/NpcAssetDataDBArray.fbs new file mode 100644 index 00000000..f221f3e8 --- /dev/null +++ b/FlatBuffers/ZA/Trainers/Schemas/NpcAssetDataDBArray.fbs @@ -0,0 +1,22 @@ +include "Shared/ActivationCondition.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table NpcInfo { + ObjectTemplateId:int; + Name:string; + Gender:uint; + ActivationConditionArray:[ActivationCondition]; +} + +table NpcAssetData { + AssetId:string (required); + NpcInfoList:[NpcInfo] (required); +} + +table NpcAssetDataDBArray (fs_serializer) { + Table:[NpcAssetData] (required); +} + +root_type NpcAssetDataDBArray; diff --git a/FlatBuffers/ZA/Trainers/Schemas/TrDataMainArray.fbs b/FlatBuffers/ZA/Trainers/Schemas/TrDataMainArray.fbs new file mode 100644 index 00000000..1c1e3c94 --- /dev/null +++ b/FlatBuffers/ZA/Trainers/Schemas/TrDataMainArray.fbs @@ -0,0 +1,42 @@ +include "PokeData/PokeDataBattle.fbs"; +include "Shared/BattleType.fbs"; +include "Shared/DataType.fbs"; +include "Shared/ZARank.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table TrDataMain { + TrId:string (required); + TrType:ulong; + TrType2:ulong; + ZARank:ZARank; + MoneyRate:ubyte; + MegEvolution:bool; + LastHandMega:bool; + Poke1:PokeDataBattle (required); + Poke2:PokeDataBattle (required); + Poke3:PokeDataBattle (required); + Poke4:PokeDataBattle (required); + Poke5:PokeDataBattle (required); + Poke6:PokeDataBattle (required); + AiBasic:bool; + AiHigh:bool; + AiExpert:bool; + AiDouble:bool; + AiRaid:bool; + AiWeak:bool; + AiItem:bool; + AiChange:bool; + ViewHorizontalAngle:float; + ViewVerticalAngle:float; + ViewRange:float; + HearingRange:float; +} + +table TrDataMainArray (fs_serializer) { + Table:[TrDataMain] (required); +} + +root_type TrDataMainArray; diff --git a/FlatBuffers/ZA/Trainers/Schemas/TrainerBattleDataGlobal.fbs b/FlatBuffers/ZA/Trainers/Schemas/TrainerBattleDataGlobal.fbs new file mode 100644 index 00000000..657cf3c9 --- /dev/null +++ b/FlatBuffers/ZA/Trainers/Schemas/TrainerBattleDataGlobal.fbs @@ -0,0 +1,38 @@ +include "Shared/ActivationCondition.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table TrainerBattleDetail { + Type:string (required); + ActivationConditionArray:[ActivationCondition] (required); +} + +table TrainerBattleData { + Type:string (required); + TrainerBattleID:string; + NPCAssetID:string; + Field03:string; + Field04:string; + Field05:string; + Field06:string; + Field07:string; + Field08:string; + Field09:string; + Field10:string; + Field11:string; + Field12:string; + Field13:uint; + TrainerLoseText:string; + Field15:string; + Field16:string; + Field17:string; + Field18:string; + Field19:[TrainerBattleDetail] (required); +} + +table TrainerBattleGlobalDBArray (fs_serializer) { + Table:[TrainerBattleData] (required); +} + +root_type TrainerBattleGlobalDBArray; diff --git a/FlatBuffers/ZA/Trainers/Schemas/TrainerBodySize.fbs b/FlatBuffers/ZA/Trainers/Schemas/TrainerBodySize.fbs new file mode 100644 index 00000000..e48b2009 --- /dev/null +++ b/FlatBuffers/ZA/Trainers/Schemas/TrainerBodySize.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum TrainerBodySize : int { + S = 0, + M = 1, + L = 2, + LL = 3, +} diff --git a/FlatBuffers/ZA/Trainers/Schemas/TrainerCategory.fbs b/FlatBuffers/ZA/Trainers/Schemas/TrainerCategory.fbs new file mode 100644 index 00000000..3e5b5c7f --- /dev/null +++ b/FlatBuffers/ZA/Trainers/Schemas/TrainerCategory.fbs @@ -0,0 +1,6 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum TrainerCategory : byte { + NORMAL = 0, + GYM_LEADER = 1, +} diff --git a/FlatBuffers/ZA/Trainers/Schemas/TrainerEnvArray.fbs b/FlatBuffers/ZA/Trainers/Schemas/TrainerEnvArray.fbs new file mode 100644 index 00000000..c2bcc7ad --- /dev/null +++ b/FlatBuffers/ZA/Trainers/Schemas/TrainerEnvArray.fbs @@ -0,0 +1,88 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +enum CheckCategory : int +{ + TurnCheck = 0, + PokemonCheck = 1, + FirstDamage = 2, + HpCheck = 3, + WazaCheck = 4, + TurnEndCheck = 5, + WazaAdvantageCheck = 6, + WazaNoneCheck = 7, + WazaCriticalCheck = 8, + WeatherCheck = 9, + StartCheck = 10, + SelectActionCheck = 11, + PokemonIDCheck = 12, + UseItem = 13, + ChengeGem = 14, + TurnEndAndGemStartCheck = 15, + TurnEndAndPokemonDownCheck = 16, + TurnEndAndHpCheck = 17, + TurnEndAndWazaAdvantageCheck = 18, + TurnEndAndTurnCount = 19, + WazaDisadvantageCheck = 20, + WazaAdvantageAttackCheck = 21, +} + +enum TalkRankEffect : uint +{ + None = 0, + Attack = 1, + Defence = 2, + SpAttack = 3, + SpDefence = 4, + Agility = 5, + Hit = 6, + Avoid = 7, + CriticalRaito = 8, + Multi5 = 9, + Attack_SpAttack = 11, + Defence_SpDefence = 12, + Attack2 = 13, + SpAttack2 = 14, +} + +table TalkData { + EventName:string (required); + Category:CheckCategory; + ValueA:int; + ValueB:int; + ValueC:int; + RankEffect:TalkRankEffect; +} + +table TrainerEnv { + TrEnvId:string (required); + TalkData1:TalkData (required); + TalkData2:TalkData (required); + TalkData3:TalkData (required); + TalkData4:TalkData (required); + TalkData5:TalkData (required); + TalkData6:TalkData (required); + TalkData7:TalkData (required); + TalkData8:TalkData (required); + TalkData9:TalkData (required); + TalkData10:TalkData (required); + TalkData11:TalkData; + TalkData12:TalkData; + TalkData13:TalkData; + TalkData14:TalkData; + TalkData15:TalkData; + IntroTml:string (required); + ThrowTml:string (required); + CameraObjectName:string (required); + LoseTml:string (required); + IntroObjectName:string (required); + LoseObjectName:string (required); + BgmEventName:string (required); +} + +table TrainerEnvArray (fs_serializer) { + Table:[TrainerEnv] (required); +} + +root_type TrainerEnvArray; diff --git a/FlatBuffers/ZA/Trainers/Schemas/TrainerTypeArray.fbs b/FlatBuffers/ZA/Trainers/Schemas/TrainerTypeArray.fbs new file mode 100644 index 00000000..a5c2cc4b --- /dev/null +++ b/FlatBuffers/ZA/Trainers/Schemas/TrainerTypeArray.fbs @@ -0,0 +1,28 @@ +include "Shared/Sex.fbs"; +include "TrainerCategory.fbs"; +include "TrainerBodySize.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table TrainerType { + NameLabel:string (required); + MsgLabel:string (required); + Sex:Sex; + Category:TrainerCategory; + IntroTml:string (required); + ThrowTml:string (required); + CameraObjectName:string (required); + LoseTml:string (required); + IntroObjectName:string (required); + LoseObjectName:string (required); + BGMEventName:string (required); + TrainerBodySize:TrainerBodySize; +} + +table TrainerTypeArray (fs_serializer) { + Table:[TrainerType] (required); +} + +root_type TrainerTypeArray; diff --git a/FlatBuffers/ZA/Trainers/pkNX.Structures.FlatBuffers.ZA.Trainers.csproj b/FlatBuffers/ZA/Trainers/pkNX.Structures.FlatBuffers.ZA.Trainers.csproj new file mode 100644 index 00000000..35e3d842 --- /dev/null +++ b/FlatBuffers/ZA/Trainers/pkNX.Structures.FlatBuffers.ZA.Trainers.csproj @@ -0,0 +1,2 @@ + + diff --git a/FlatBuffers/ZA/Trinity/Archive/TrinityFileDescriptors.cs b/FlatBuffers/ZA/Trinity/Archive/TrinityFileDescriptors.cs new file mode 100644 index 00000000..a7cabd87 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Archive/TrinityFileDescriptors.cs @@ -0,0 +1,38 @@ +using System.Diagnostics; + +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; + +public partial class TrinityFileDescriptors +{ + public ulong GetSubFileIndex(ulong hash) + { + var index = BinarySearch(hash); + Debug.Assert((uint)index < SubFileHashes.Count); + return SubFileInfos[index].Index; + } + + public bool GetHasSubFile(ulong hash) + { + var index = BinarySearch(hash); + return index >= 0; + } + + private int BinarySearch(ulong hash) + { + var arr = SubFileHashes; + var lo = 0; + var hi = arr.Count - 1; + while (lo <= hi) + { + var mid = lo + (hi - lo >> 1); + var midVal = arr[mid]; + if (midVal < hash) + lo = mid + 1; + else if (midVal > hash) + hi = mid - 1; + else + return mid; + } + return -1; + } +} diff --git a/FlatBuffers/ZA/Trinity/Archive/TrinityFileSystemManager.cs b/FlatBuffers/ZA/Trinity/Archive/TrinityFileSystemManager.cs new file mode 100644 index 00000000..80d10ff0 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Archive/TrinityFileSystemManager.cs @@ -0,0 +1,99 @@ +using System.Diagnostics; +using FlatSharp; +using pkNX.Containers; + +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; + +/// +/// Wrapper object that extracts raw data from a Trinity Pack Filesystem file. +/// +public sealed class TrinityFileSystemManager : IDisposable, IFileInternal +{ + private readonly BinaryReader Reader; + private readonly TrinityFileDescriptors FileData; + private readonly TrinityFileSystemMetadata Meta; + public const ulong MAGIC_ONEPACK = 0x004B4341_50454E4F; // ONEPACK\x00 + + public TrinityFileSystemManager(string pathFs, string pathFd) + { + var trpfs = File.OpenRead(pathFs); // DO NOT DISPOSE UNTIL THIS OBJECT IS DISPOSED + var br = new BinaryReader(trpfs); + var totalLength = br.BaseStream.Length; + + // Read the trpfs meta -- check the file header first. + var magic = br.ReadUInt64(); + Debug.Assert(magic == MAGIC_ONEPACK); + + // Locate the meta FlatBuffer + var ofsMetaFB = br.ReadInt64(); + br.BaseStream.Seek(ofsMetaFB, SeekOrigin.Begin); + + // Extract the meta FlatBuffer + var dataMetaFB = br.ReadBytes((int)(totalLength - ofsMetaFB)); + var meta = TrinityFileSystemMetadata.Serializer.Parse(dataMetaFB, FlatBufferDeserializationOption.GreedyMutable); + + // Read the trpfd + var dataFd = File.ReadAllBytes(pathFd); + var fd = TrinityFileDescriptors.Serializer.Parse(dataFd, FlatBufferDeserializationOption.GreedyMutable); + Debug.Assert(meta.FileHashes.Count == fd.FileInfos.Count); + + Reader = br; + FileData = fd; + Meta = meta; + } + + public void Dispose() + { + Reader.Dispose(); + } + + public int FileCount => FileData.FilePaths.Count; + public string GetPackPath(int packIndex) => FileData.FilePaths[packIndex]; + + public byte[] GetData(ulong offset, ulong length) + { + Reader.BaseStream.Seek((long)offset, SeekOrigin.Begin); + return Reader.ReadBytes((int)length); + } + + public void GetData(ulong offset, ulong length, Span data) + { + Reader.BaseStream.Seek((long)offset, SeekOrigin.Begin); + _ = Reader.Read(data[..(int)length]); + } + + public TrinityPak GetPak(int index) + { + var data = GetPakData(index); + return TrinityPak.Serializer.Parse(data, FlatBufferDeserializationOption.GreedyMutable); + } + + public ulong GetPakHash(int index) => FnvHash.HashFnv1a_64(GetPackPath(index)); + public ulong GetPakLength(int index) => FileData.FileInfos[index].FileSize; + public ulong GetPakOffset(ulong hash) => Meta.GetFileOffset(hash); + + public byte[] GetPakData(int index) + { + var size = GetPakLength(index); + var hash = GetPakHash(index); + var offset = GetPakOffset(hash); + return GetData(offset, size); + } + + public byte[] GetPackedFile(ulong hash) + { + var index = FileData.GetSubFileIndex(hash); + var pak = GetPak((int)index); + var file = pak.GetFileData(hash); + return file.Decompress(); + } + + public byte[] GetPackedFile(string path) => GetPackedFile(FnvHash.HashFnv1a_64(path)); + public bool HasFile(string path) => HasFile(FnvHash.HashFnv1a_64(path)); + public bool HasFile(ulong hash) + { + if (Meta.HasFile(hash)) + return true; + return FileData.GetHasSubFile(hash); + } +} diff --git a/FlatBuffers/ZA/Trinity/Archive/TrinityFileSystemMetadata.cs b/FlatBuffers/ZA/Trinity/Archive/TrinityFileSystemMetadata.cs new file mode 100644 index 00000000..7d17092a --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Archive/TrinityFileSystemMetadata.cs @@ -0,0 +1,33 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; + +public partial class TrinityFileSystemMetadata +{ + public ulong GetFileOffset(ulong hashFnv) + { + var index = BinarySearch(hashFnv); + if (index < 0) + throw new ArgumentException(null, nameof(hashFnv)); + return FileOffsets[index]; + } + + public bool HasFile(ulong hashFnv) => BinarySearch(hashFnv) >= 0; + + private int BinarySearch(ulong hash) + { + var arr = FileHashes; + var lo = 0; + var hi = arr.Count - 1; + while (lo <= hi) + { + var mid = lo + (hi - lo >> 1); + var midVal = arr[mid]; + if (midVal < hash) + lo = mid + 1; + else if (midVal > hash) + hi = mid - 1; + else + return mid; + } + return -1; + } +} diff --git a/FlatBuffers/ZA/Trinity/Archive/TrinityPak.cs b/FlatBuffers/ZA/Trinity/Archive/TrinityPak.cs new file mode 100644 index 00000000..571d55c5 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Archive/TrinityPak.cs @@ -0,0 +1,72 @@ +using pkNX.Containers; +using System.Diagnostics; + +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; + +public partial class TrinityPak +{ + public TrinityPakFileData GetFileData(ulong hash) + { + var index = BinarySearch(hash); + Debug.Assert((uint)index < Hashes.Count); + return Files[index]; + } + + private int BinarySearch(ulong hash) + { + var arr = Hashes; + var lo = 0; + var hi = arr.Count - 1; + while (lo <= hi) + { + var mid = lo + (hi - lo >> 1); + var midVal = arr[mid]; + if (midVal < hash) + lo = mid + 1; + else if (midVal > hash) + hi = mid - 1; + else + return mid; + } + return -1; + } +} + +public partial class TrinityPakFileData +{ + public byte[] Decompress() => CompressionType switch + { + DataCompressionType.None => Data.ToArray(), // Uncompressed + DataCompressionType.Zlib => Zlib.Decompress(Data.Span, (int)UncompressedSize), + DataCompressionType.Lz4 => LZ4.Decode(Data.Span, (int)UncompressedSize), + >= DataCompressionType.OodleKraken and <= DataCompressionType.OodleHydra => Oodle.Decompress(Data.Span, (long)UncompressedSize)!, // Oodle + _ => throw new ArgumentException($"Unknown compression type {CompressionType}"), + }; + + public void DecompressTo(Span result) + { + if (CompressionType == DataCompressionType.None) + Data.Span.CopyTo(result); // Uncompressed + else if (CompressionType == DataCompressionType.Zlib) + Zlib.Decompress(Data.Span, result); + else if (CompressionType == DataCompressionType.Lz4) + LZ4.Decode(Data.Span, result); + else if (CompressionType is >= DataCompressionType.OodleKraken and <= DataCompressionType.OodleHydra) + Oodle.TryDecompress(Data.Span, result, out _); + else + throw new ArgumentException($"Unknown compression type {CompressionType}"); + } + + public static ReadOnlySpan Compress(ReadOnlySpan data, DataCompressionType type, OodleCompressionLevel level = OodleCompressionLevel.Optimal2) => type switch + { + DataCompressionType.None => data, + DataCompressionType.Zlib => Zlib.Compress(data), + DataCompressionType.Lz4 => LZ4.Encode(data), + DataCompressionType.OodleKraken => Oodle.Compress(data, out _, OodleFormat.Kraken, level), + DataCompressionType.OodleLeviathan => Oodle.Compress(data, out _, OodleFormat.Leviathan, level), + DataCompressionType.OodleMermaid => Oodle.Compress(data, out _, OodleFormat.Mermaid, level), + DataCompressionType.OodleSelkie => Oodle.Compress(data, out _, OodleFormat.Selkie, level), + DataCompressionType.OodleHydra => Oodle.Compress(data, out _, OodleFormat.Hydra, level), + _ => throw new NotImplementedException($"Compression type {type} is not implemented."), + }; +} diff --git a/FlatBuffers/ZA/Trinity/Archive/TrinityPakExtractor.cs b/FlatBuffers/ZA/Trinity/Archive/TrinityPakExtractor.cs new file mode 100644 index 00000000..ba0fe648 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Archive/TrinityPakExtractor.cs @@ -0,0 +1,106 @@ +using System.Buffers; +using pkNX.Containers; + +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; + +public static class TrinityPakExtractor +{ + public const string DumpArchiveExtracted = "extracted"; + private const string DumpArchivePak = "paks"; + + public static void DumpArchives(string pathRomFS, string dirRootDump) + { + var pathFs = Path.Combine(pathRomFS, "arc", "data.trpfs"); + var pathFd = Path.Combine(pathRomFS, "arc", "data.trpfd"); + var reader = new TrinityFileSystemManager(pathFs, pathFd); + Extract(dirRootDump, reader); + reader.Dispose(); + } + + private static void Extract(string dirRoot, TrinityFileSystemManager manager) + { + Directory.CreateDirectory(dirRoot); + + var dirPak = Path.Combine(dirRoot, DumpArchivePak); + Directory.CreateDirectory(dirPak); + + var dirExtract = Path.Combine(dirRoot, DumpArchiveExtracted); + Directory.CreateDirectory(dirExtract); + + var count = manager.FileCount; + for (var i = 0; i < count; i++) + ExportArc(manager, i, dirPak, dirExtract); + } + + private static void ExportArc(TrinityFileSystemManager reader, int packIndex, string dirPak, string dirExtract) + { + var pool = ArrayPool.Shared; + var hash = reader.GetPakHash(packIndex); + var length = reader.GetPakLength(packIndex); + var offset = reader.GetPakOffset(hash); + var rent = pool.Rent((int)length); + var data = rent.AsMemory(0, (int)length); + try + { + reader.GetData(offset, length, data.Span); + var packFilePath = reader.GetPackPath(packIndex); + ExportPackFile(data.Span, dirPak, packFilePath); + ExportPackExtract(data, dirExtract, packFilePath); + } + finally + { + data.Span.Clear(); + pool.Return(rent); + } + } + + private static void ExportPackFile(ReadOnlySpan data, string dir, string pakFilePath) + { + var fileName = Path.Combine(dir, pakFilePath); + var dirName = Path.GetDirectoryName(fileName); + if (string.IsNullOrEmpty(dirName)) + throw new Exception($"{fileName} directory name is null"); + Directory.CreateDirectory(dirName); + + File.WriteAllBytes(fileName, data); + } + + private static void ExportPackExtract(Memory data, string dir, string pakFilePath) + { + var folder = Path.Combine(dir, pakFilePath); + Directory.CreateDirectory(folder); + var obj = FlatBufferConverter.DeserializeFrom(data); + ExtractPack(obj, folder); + } + + private static void ExtractPack(TrinityPak trpak, string dir) + { + for (var i = 0; i < trpak.Files.Count; i++) + WriteFile(trpak.Files[i], trpak.Hashes[i], dir, i); + } + + private static void WriteFile(TrinityPakFileData file, ulong hash, string dir, int fileIndex) + { + if (file.CompressionType is DataCompressionType.None) + { + WriteFile(file.Data.Span, hash, dir, fileIndex); + return; + } + + var pool = ArrayPool.Shared; + var length = (int)file.UncompressedSize; + var rent = pool.Rent(length); + var decompressed = rent.AsSpan(0, length); + file.DecompressTo(decompressed); + WriteFile(decompressed, hash, dir, fileIndex); + decompressed.Clear(); + pool.Return(rent); + } + + private static void WriteFile(ReadOnlySpan decompressed, ulong hash, string dir, int fileIndex) + { + var ext = TrinityUtil.GuessExtension(decompressed); + var filepath = Path.Combine(dir, $"{fileIndex:0000} - {hash:X16}.{ext}"); + File.WriteAllBytes(filepath, decompressed); + } +} diff --git a/FlatBuffers/ZA/Trinity/Scene/SceneDumper.cs b/FlatBuffers/ZA/Trinity/Scene/SceneDumper.cs new file mode 100644 index 00000000..07f7e45c --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Scene/SceneDumper.cs @@ -0,0 +1,526 @@ +using pkNX.Containers; + +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; + +public static class SceneDumper +{ + private const char PadChar = '\t'; + private static void Write(TextWriter tw, int depth, string str) => tw.WriteLine(new string(PadChar, depth) + str); + + public static string Bucket { get; set; } = ""; + public static string BucketError { get; set; } = ""; + public static bool ThrowOnUnknownType { get; set; } = false; + + public static TrinitySceneObjectTemplate Dump(string path) => Dump(path, Console.Out); + + public static TrinitySceneObjectTemplate Dump(string path, TextWriter tw) + { + var data = File.ReadAllBytes(path); + var scene = FlatBufferConverter.DeserializeFrom(data); + Dump(scene, tw); + return scene; + } + + private static void Dump(TrinitySceneObjectTemplate scene, TextWriter tw) + { + const int depth = 0; + Dump(scene, tw, depth); + foreach (var obj in scene.Objects) + Dump(obj, tw, depth + 1); + } + + private static void Dump(TrinitySceneObjectTemplateEntry scene, TextWriter tw, int depth) + { + Dump(scene.Data, scene.Type, tw, depth); + Dump(scene.SubObjects, tw, depth); + } + + private static void Dump(IList arr, TextWriter tw, int depth) + { + foreach (var obj in arr) + { + Dump(obj.Data, obj.Type, tw, depth + 1); + Dump(obj.SubObjects, tw, depth + 1); + } + } + + private static void Dump(TrinitySceneObjectTemplate scene, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(scene.ObjectTemplateName)}: {scene.ObjectTemplateName} ({FnvHash.HashFnv1a_64(scene.ObjectTemplateName):X16})"); + Write(tw, depth, $"{nameof(scene.Field02)}: {scene.Field02}"); + Write(tw, depth, $"{nameof(scene.Field03)}: {scene.Field03}"); + Dump(scene.Field05, tw, depth, nameof(scene.Field05)); + Write(tw, depth, $"{nameof(scene.Objects)}: {scene.Objects.Count}"); + } + + private static void AddToBucket(Span data, string type, string bucket) + { + var hash = FnvHash.HashFnv1a_64(data); + var dir = Path.Combine(bucket, type); + var path = Path.Combine(dir, hash.ToString("X16")); + Directory.CreateDirectory(dir); + File.WriteAllBytes(path, data.ToArray()); + } + + private static void Dump(Memory data, string type, TextWriter tw, int depth) + { + const string UnknownType = "Unknown Type"; + Write(tw, depth++, type); + try + { + switch (type) + { + case "SubScene": DumpSubScene(data, tw, depth); break; + case "trinity_PropertySheet": DumpPropertySheet(data, tw, depth); break; + case "trinity_SceneObject": DumpSceneObject(data, tw, depth); break; + case "trinity_ScenePoint": DumpScenePoint(data, tw, depth); break; + case "trinity_ObjectTemplate": DumpObjectTemplate(data, tw, depth); break; + case "trinity_ScriptComponent": DumpScriptComponent(data, tw, depth); break; + case "trinity_ObjectSwitcher": DumpObjectSwitcher(data, tw, depth); break; + case "trinity_ModelComponent": DumpModelComponent(data, tw, depth); break; + case "trinity_CollisionComponent": DumpCollisionComponent(data, tw, depth); break; + case "trinity_ParticleComponent": DumpParticleComponent(data, tw, depth); break; + case "trinity_GroundPlaceComponent": DumpGroundPlaceComponent(data, tw, depth); break; + case "ti_AIPerceptualComponent": DumpTIAIPerceptualComponent(data, tw, depth); break; + case "ti_ModelDitherFadeComponent": DumpTIModelDitherFadeComponent(data, tw, depth); break; + case "ti_DynamicExclusionComponent": DumpTIDynamicExclusionComponent(data, tw, depth); break; + case "trinity_CollisionEventTriggerComponent": DumpCollisionEventTriggerComponent(data, tw, depth); break; + case "trinity_EnvironmentParameter": DumpTrinityEnvironmentParameter(data, tw, depth); break; + case "trinity_OverrideSensorData": DumpTrinityOverrideSensorData(data, tw, depth); break; + case "trinity_PlacementRegistry": DumpPlacementRegistry(data, tw, depth); break; + default: + if (ThrowOnUnknownType) + throw new ArgumentOutOfRangeException(nameof(type), type, null); + Write(tw, depth, $"{UnknownType}: {type}"); + break; + } + } + catch (Exception ex) when (!ex.Message.StartsWith(UnknownType)) + { + Write(tw, depth, $"Error Parsing ({ex.GetType().Name}): {ex.Message}"); + if (BucketError.Length != 0) + AddToBucket(data.Span, type, BucketError); + } + if (Bucket.Length != 0) + AddToBucket(data.Span, type, Bucket); + } + + private static void DumpPlacementRegistry(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + var entry = props.Entry; + Write(tw, depth, $"{entry.Kind}:"); + + switch (entry.Kind) + { + case PlacementEntry.ItemKind.PlacementObjectArray: DumpPlacementObjectArray(entry.PlacementObjectArray, tw, depth); break; + case PlacementEntry.ItemKind.PlacementObjectTemplateArray: DumpPlacementObjectTemplateArray(entry.PlacementObjectTemplateArray, tw, depth); break; + case PlacementEntry.ItemKind.PlacementPositionArray: DumpPlacementPositionArray(entry.PlacementPositionArray, tw, depth); break; + case PlacementEntry.ItemKind.PlacementSpawnerArray: DumpPlacementSpawnerArray(entry.PlacementSpawnerArray, tw, depth); break; + default: throw new ArgumentException(nameof(entry)); + } + } + + private static void DumpPlacementObjectArray(PlacementObjectArray value, TextWriter tw, int depth) + { + var array = value.Table; + Write(tw, depth, $"{nameof(array.Count)}: {array.Count}"); + depth++; + foreach (var entry in array) + { + Write(tw, depth, $"{nameof(entry.Name)}: {entry.Name} ({FnvHash.HashFnv1a_64(entry.Name):X16})"); + Write(tw, depth, $"{nameof(entry.Type)}: {entry.Type}"); + Write(tw, depth, $"{nameof(entry.File)}: {entry.File}"); + } + } + + private static void DumpPlacementObjectTemplateArray(PlacementObjectTemplateArray value, TextWriter tw, int depth) + { + var array = value.Table; + Write(tw, depth, $"{nameof(array.Count)}: {array.Count}"); + depth++; + foreach (var entry in array) + { + Write(tw, depth, $"{nameof(entry.Name)}: {entry.Name} ({FnvHash.HashFnv1a_64(entry.Name):X16})"); + Write(tw, depth, $"{nameof(entry.Path)}: {entry.Path}"); + } + } + + private static void DumpPlacementPositionArray(PlacementPositionArray value, TextWriter tw, int depth) + { + var array = value.Table; + Write(tw, depth, $"{nameof(array.Count)}: {array.Count}"); + depth++; + foreach (var entry in array) + { + Write(tw, depth, $"{nameof(entry.Name)}: {entry.Name} ({FnvHash.HashFnv1a_64(entry.Name):X16})"); + Write(tw, depth, $"{nameof(entry.Position)}: {entry.Position}"); + Write(tw, depth, $"{nameof(entry.Rotation)}: {entry.Rotation}"); + if (entry.Arguments is null) + Write(tw, depth, "Arguments: null"); + else + Write(tw, depth, $"Arguments: [{string.Join(",", entry.Arguments.Select(GetFormattedArg))}]"); + } + } + + private static void DumpPlacementSpawnerArray(PlacementSpawnerArray value, TextWriter tw, int depth) + { + var array = value.Table; + Write(tw, depth, $"{nameof(array.Count)}: {array.Count}"); + depth++; + foreach (var entry in array) + { + Write(tw, depth, $"{nameof(entry.Name)}: {entry.Name} ({FnvHash.HashFnv1a_64(entry.Name):X16})"); + Write(tw, depth, $"{nameof(entry.Scene)}: {entry.Scene}"); + Write(tw, depth, $"Arguments: {entry.Arguments?.Count}"); + if (entry.Arguments is null) + continue; + for (var i = 0; i < entry.Arguments.Count; i++) + { + var arg = entry.Arguments[i]; + Write(tw, depth, $"Arg[{i}]:"); + DumpPlacementRule(tw, depth + 1, arg); + } + } + } + + private static void DumpPlacementRule(TextWriter tw, int depth, PlacementLogic logic) + { + Write(tw, depth, $"{nameof(logic.Name)}: {logic.Name}"); + if (logic.Expression is null) + return; + Write(tw, depth, $"{nameof(logic.Expression)}:"); + Write(tw, depth + 1, logic.Expression); + } + + private static void Write(TextWriter tw, int depth, LogicExpression exp) + { + if (exp.Root is { } root) + { + Write(tw, depth, $"{nameof(exp.Root)}:"); + Write(tw, depth + 1, root); + } + } + + private static void Write(TextWriter tw, int depth, ExpressionNode node) + { + Write(tw, depth, $"{node.Kind}:"); + switch (node.Kind) + { + case ExpressionNode.ItemKind.ExpressionLeaf: + var leaf = node.ExpressionLeaf; + Write(tw, depth, $"{nameof(leaf.ConditionName)}: {leaf.ConditionName}"); + Write(tw, depth, $"{nameof(leaf.Op)}: {leaf.Op}"); + if (leaf.Arguments is null) + Write(tw, depth, "Arguments: null"); + else + Write(tw, depth, $"Arguments: [{string.Join(",", leaf.Arguments.Select(GetFormattedArg))}]"); + + break; + case ExpressionNode.ItemKind.ExpressionBranch: + var branch = node.ExpressionBranch; + Write(tw, depth, $"{nameof(branch.Operand)}: {branch.Operand}"); + if (branch.Left is { } left) + { + Write(tw, depth, $"{nameof(branch.Left)}:"); + Write(tw, depth + 1, left); + } + if (branch.Right is { } right) + { + Write(tw, depth, $"{nameof(branch.Right)}:"); + Write(tw, depth + 1, right); + } + + break; + default: + throw new ArgumentException(nameof(node)); + } + } + + private static string GetFormattedArg(string? arg) + { + if (arg is null) + return string.Empty; + return $"\"{arg}\""; + } + + private static void DumpTrinityOverrideSensorData(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Field00)}: {props.Field00}"); + Write(tw, depth, $"{nameof(props.Field01)}: {props.Field01}"); + Write(tw, depth, $"{nameof(props.Field02)}: {props.Field02}"); + Write(tw, depth, $"{nameof(props.Field03)}: {props.Field03}"); + } + + private static void DumpTrinityEnvironmentParameter(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Field00)}: {props.Field00}"); + Write(tw, depth, $"{nameof(props.Field01)}: {props.Field01}"); + } + + private static void DumpCollisionEventTriggerComponent(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Field00)}: {props.Field00}"); + Write(tw, depth, $"{nameof(props.Field01)}: {props.Field01}"); + Write(tw, depth, $"{nameof(props.Field02)}: {props.Field02}"); + Write(tw, depth, $"{nameof(props.Field03)}: {props.Field03}"); + Write(tw, depth, $"{nameof(props.Field04)}: {props.Field04}"); + Write(tw, depth, $"{nameof(props.Field05)}: {props.Field05}"); + } + + private static void DumpTIDynamicExclusionComponent(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Field00)}: {props.Field00}"); + } + + private static void DumpTIModelDitherFadeComponent(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Field00)}: {props.Field00}"); + Write(tw, depth, $"{nameof(props.Field01)}: {props.Field01}"); + Write(tw, depth, $"{nameof(props.Field02)}: {props.Field02}"); + Write(tw, depth, $"{nameof(props.Field03)}: {props.Field03}"); + Write(tw, depth, $"{nameof(props.Field04)}: {props.Field04}"); + } + + private static void DumpTIAIPerceptualComponent(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Value)}: {props.Value}"); + } + + private static void DumpGroundPlaceComponent(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Index)}: {props.Index}"); + } + + private static void DumpParticleComponent(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.ParticleFile)}: {props.ParticleFile}"); + Write(tw, depth, $"{nameof(props.ParticleName)}: {props.ParticleName}"); + Write(tw, depth, $"{nameof(props.ParticleParent)}: {props.ParticleParent}"); + } + + private static void DumpCollisionComponent(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + var shape = props.Component.CollisionComponent.Shape; + Write(tw, depth, $"{nameof(props.Component.CollisionComponent.Shape)}: {shape.Kind}"); + Write(tw, depth, $"v3f: {GetV4F(props.Component.CollisionComponent.Field08)}"); + depth++; + switch (shape.Kind) + { + case CollisionUnion.ItemKind.Sphere: DumpCollision(shape.Sphere, tw, depth); break; + case CollisionUnion.ItemKind.Box: DumpCollision(shape.Box, tw, depth); break; + case CollisionUnion.ItemKind.Capsule: DumpCollision(shape.Capsule, tw, depth); break; + case CollisionUnion.ItemKind.Havok: DumpCollision(shape.Havok, tw, depth); break; + default: throw new ArgumentException(nameof(shape)); + } + } + + private static void DumpModelComponent(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Field00)}: {props.Field00}"); + Write(tw, depth, $"{nameof(props.Field01)}: {props.Field01}"); + Write(tw, depth, $"{nameof(props.Field02)}: {props.Field02}"); + Write(tw, depth, $"{nameof(props.Field03)}: {props.Field03}"); + Write(tw, depth, $"{nameof(props.Field05)}: {props.Field05}"); + Write(tw, depth, $"{nameof(props.Field06)}: {props.Field06}"); + Write(tw, depth, $"{nameof(props.Field07)}: {props.Field07}"); + Write(tw, depth, $"{nameof(props.Field19)}: {props.Field19}"); + Write(tw, depth, $"{nameof(props.Field20)}: {props.Field20}"); + Write(tw, depth, $"{nameof(props.Field21)}: {props.Field21}"); + Write(tw, depth, $"{nameof(props.Field22)}: {props.Field22}"); + } + + private static void DumpScriptComponent(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.ScriptFileName)}: {props.ScriptFileName}"); + Write(tw, depth, $"{nameof(props.ScriptFileNameHash)}: {props.ScriptFileNameHash}"); + Write(tw, depth, $"{nameof(props.ScriptFileClass)}: {props.ScriptFileClass}"); + } + + private static void DumpSubScene(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Field00)}: {props.Field00}"); + Write(tw, depth, $"{nameof(props.Field01)}: {props.Field01}"); + } + + private static void DumpObjectSwitcher(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Field00)}: {props.Field00}"); + Write(tw, depth, $"{nameof(props.Field01)}: {props.Field01}"); + } + + private static void DumpObjectTemplate(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.ObjectTemplateName)}: {props.ObjectTemplateName} ({FnvHash.HashFnv1a_64(props.ObjectTemplateName):X16})"); + Write(tw, depth, $"{nameof(props.ObjectTemplatePath)}: {props.ObjectTemplatePath}"); + Write(tw, depth, $"{nameof(props.ObjectTemplateExtra)}: {props.ObjectTemplateExtra}"); + Write(tw, depth, $"{nameof(props.Field03)}: {props.Field03}"); + Dump(props.Data, props.Type, tw, ++depth); + } + + private static void DumpScenePoint(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Name)}: {props.Name}"); + Write(tw, depth, $"{nameof(props.Position)}: {props.Position}"); + Write(tw, depth, $"{nameof(props.Field02)}: {props.Field02}"); + } + + private static void DumpSceneObject(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Name)}: {props.Name} ({FnvHash.HashFnv1a_64(props.Name):X16})"); + Write(tw, depth, $"{nameof(props.Position)}:"); + Dump(props.Position, tw, depth + 1); + Write(tw, depth, $"{nameof(props.Field02)}: {props.Field02}"); + Write(tw, depth, $"{nameof(props.ApplySRT)}: {props.ApplySRT}"); + Write(tw, depth, $"{nameof(props.Field04)}: {props.Field04}"); + Write(tw, depth, $"{nameof(props.Field05)}: {props.Field05}"); + Write(tw, depth, $"{nameof(props.Field06)}: {props.Field06}"); + Write(tw, depth, $"{nameof(props.Field07)}: {props.Field07}"); + if (props.Field08 is not null) + Dump(props.Field08, tw, depth, nameof(props.Field08)); + } + + private static void DumpCollision(Sphere shape, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(shape.Transform)}: {GetV3F(shape.Transform)}"); + Write(tw, depth, $"{nameof(shape.Radius)}: {shape.Radius}"); + } + + private static void DumpCollision(Box shape, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(shape.Size)}: {GetV3F(shape.Size)}"); + Write(tw, depth, $"{nameof(shape.Rotation)}: {GetV3F(shape.Rotation)}"); + Write(tw, depth, $"{nameof(shape.Transform)}: {GetV3F(shape.Transform)}"); + } + + private static void DumpCollision(Capsule shape, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(shape.Height)}: {shape.Height}"); + Write(tw, depth, $"{nameof(shape.Radius)}: {shape.Radius}"); + Write(tw, depth, $"{nameof(shape.Rotation)}: {GetV3F(shape.Rotation)}"); + Write(tw, depth, $"{nameof(shape.Transform)}: {GetV3F(shape.Transform)}"); + } + + private static void DumpCollision(Havok shape, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(shape.TrcolFilePath)}: {shape.TrcolFilePath}"); + Write(tw, depth, $"{nameof(shape.Scale)}: {GetV3F(shape.Scale)}"); + Write(tw, depth, $"{nameof(shape.Rotation)}: {GetV3F(shape.Rotation)}"); + Write(tw, depth, $"{nameof(shape.Transform)}: {GetV3F(shape.Transform)}"); + } + + private static string GetV3F(Vec3f props) => $"({props.X}, {props.Y}, {props.Z})"; + private static string GetV3F(PackedVec3f props) => $"({props.X}, {props.Y}, {props.Z})"; + private static string GetV4F(Vec4f props) => $"({props.X}, {props.Y}, {props.Z} @ {props.W})"; + + private static void Dump(IList arr, TextWriter tw, int depth, string name) + { + Write(tw, depth, $"{name}:"); + for (var i = 0; i < arr.Count; i++) + Write(tw, depth + 1, $"[{i}]: {arr[i]}"); + } + + private static void Dump(SRT p, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(p.Scale)}: {p.Scale}"); + Write(tw, depth, $"{nameof(p.Rotation)}: {p.Rotation}"); + Write(tw, depth, $"{nameof(p.Translation)}: {p.Translation}"); + } + + private static void DumpPropertySheet(Memory data, TextWriter tw, int depth) + { + var props = FlatBufferConverter.DeserializeFrom(data); + Write(tw, depth, $"{nameof(props.Name)}: {props.Name} ({FnvHash.HashFnv1a_64(props.Name):X16})"); + if (!string.IsNullOrWhiteSpace(props.Extra)) + Write(tw, depth, $"{nameof(props.Extra)}: {props.Extra}"); + foreach (var p in props.Properties) + { + foreach (var f in p.Fields) + Dump(f, tw, depth + 1); + } + } + + private static void Dump(TrinityPropertySheetField f, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(f.Name)}: {f.Name}"); + //Write(tw, depth, $"{nameof(f.Data.Discriminator)}: {f.Data.Discriminator}"); + Dump(f.Data, tw, depth); + } + + private static void Dump(TrinityPropertySheetValue v, TextWriter tw, int depth) + { + switch (v.Discriminator) + { + case 1: Dump(v.Item1, tw, depth); break; + case 2: Dump(v.Item2, tw, depth); break; + case 3: Dump(v.Item3, tw, depth); break; + case 4: Dump(v.Item4, tw, depth); break; + case 5: Dump(v.Item5, tw, depth); break; + case 6: Dump(v.Item6, tw, depth); break; + case 7: Dump(v.Item7, tw, depth); break; + case 8: Dump(v.Item8, tw, depth); break; + case 9: Dump(v.Item9, tw, depth); break; + default: throw new ArgumentOutOfRangeException(nameof(v.Discriminator), v.Discriminator, null); + } + } + + private static void Dump(TrinityPropertySheetField1 item, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(item.Value)}: {item.Value}"); + //Write(tw, depth, $"{nameof(item.FieldType)}: {item.FieldType}"); + } + + private static void Dump(TrinityPropertySheetField2 item, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(item.Value)}: {item.Value}"); + //Write(tw, depth, $"{nameof(item.FieldType)}: {item.FieldType}"); + } + + private static void Dump(TrinityPropertySheetFieldStringValue item, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(item.Value)}: {item.Value}"); + } + + private static void Dump(TrinityPropertySheetField4 item, TextWriter tw, int depth) => + Write(tw, depth, $"UNDOCUMENTED {nameof(TrinityPropertySheetField4)}"); + + private static void Dump(TrinityPropertySheetField5 item, TextWriter tw, int depth) => + Write(tw, depth, $"UNDOCUMENTED {nameof(TrinityPropertySheetField5)}"); + + private static void Dump(TrinityPropertySheetField6 item, TextWriter tw, int depth) => + Write(tw, depth, $"UNDOCUMENTED {nameof(TrinityPropertySheetField6)}"); + + private static void Dump(TrinityPropertySheetFieldEnumName item, TextWriter tw, int depth) + { + Write(tw, depth, $"{nameof(item.Enum)}: {item.Enum}"); + Write(tw, depth, $"{nameof(item.Value)}: {item.Value}"); + } + + private static void Dump(TrinityPropertySheetObjectArray item, TextWriter tw, int depth) + { + foreach (var obj in item.Value) + Dump(obj, tw, depth + 1); + } + + private static void Dump(TrinityPropertySheetObject item, TextWriter tw, int depth) + { + foreach (var f in item.Fields) + Dump(f, tw, depth + 1); + } +} diff --git a/FlatBuffers/ZA/Trinity/Schemas/LogicExpression.fbs b/FlatBuffers/ZA/Trinity/Schemas/LogicExpression.fbs new file mode 100644 index 00000000..3d3d91ba --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/LogicExpression.fbs @@ -0,0 +1,34 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +// same as ActivationConditionParam +table ExpressionLeaf { + ConditionName:string; + Op:int; + Arguments:[string]; +} + +enum ExpressionBranchOperand: int { + And = 0, + Or = 1 +} + +union ExpressionNode { + ExpressionLeaf, + ExpressionBranch +} + +table ExpressionBranch { + Operand:ExpressionBranchOperand; + LeftCondition:ExpressionNode; + Left:ExpressionNode; + RightCondition:ExpressionNode; + Right:ExpressionNode; +} + +table LogicExpression (fs_serializer) { + Root:ExpressionNode; +} + +root_type LogicExpression; diff --git a/FlatBuffers/ZA/Trinity/Schemas/PlacementRegistry.fbs b/FlatBuffers/ZA/Trinity/Schemas/PlacementRegistry.fbs new file mode 100644 index 00000000..781066ec --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/PlacementRegistry.fbs @@ -0,0 +1,64 @@ +include "LogicExpression.fbs"; +include "Math/PackedVec3f.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table PlacementLogic { + Name:string; + Expression:LogicExpression; +} + +table PlacementSpawner { + Name:string; + Scene:string; + Arguments:[PlacementLogic]; +} + +table PlacementPosition { + Name:string; + Position:PackedVec3f; + Rotation:PackedVec3f; + Arguments:[string]; +} + +table PlacementObjectTemplate { + Name:string; + Path:string; +} + +table PlacementObject { + Name:string; + Type:string; + File:string; +} + +table PlacementSpawnerArray { + Table:[PlacementSpawner] (required); +} + +table PlacementPositionArray { + Table:[PlacementPosition] (required); +} + +table PlacementObjectTemplateArray { + Table:[PlacementObjectTemplate] (required); +} + +table PlacementObjectArray { + Table:[PlacementObject] (required); +} + +union PlacementEntry { + PlacementObjectArray, + PlacementObjectTemplateArray, + PlacementPositionArray, + PlacementSpawnerArray +} + +table PlacementRegistry (fs_serializer) { + Entry:PlacementEntry (required); +} + +root_type PlacementRegistry; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TIAIPerceptualComponent.fbs b/FlatBuffers/ZA/Trinity/Schemas/TIAIPerceptualComponent.fbs new file mode 100644 index 00000000..4be59352 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TIAIPerceptualComponent.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TIAIPerceptualComponent (fs_serializer) { + Value:byte; // not a bool +} + +root_type TIAIPerceptualComponent; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TIDynamicExclusionComponent.fbs b/FlatBuffers/ZA/Trinity/Schemas/TIDynamicExclusionComponent.fbs new file mode 100644 index 00000000..aeca74d3 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TIDynamicExclusionComponent.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TIDynamicExclusionComponent (fs_serializer) { + Field_00:byte; +} + +root_type TIDynamicExclusionComponent; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TIModelDitherFadeComponent.fbs b/FlatBuffers/ZA/Trinity/Schemas/TIModelDitherFadeComponent.fbs new file mode 100644 index 00000000..af25aa1b --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TIModelDitherFadeComponent.fbs @@ -0,0 +1,12 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TIModelDitherFadeComponent (fs_serializer) { + Field_00:byte; //unknown + Field_01:float; + Field_02:float; + Field_03:float; + Field_04:float; +} + +root_type TIModelDitherFadeComponent; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityComponent.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityComponent.fbs new file mode 100644 index 00000000..4bdd5e5d --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityComponent.fbs @@ -0,0 +1,57 @@ +include "Math/Vec4f.fbs"; +include "Math/PackedVec3f.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table Sphere { + Transform:PackedVec3f (required); + Radius:float; +} + +table Box { + // Just a box. No TrcolFilePath. + Transform:PackedVec3f (required); + Size:PackedVec3f (required); + Rotation:PackedVec3f (required); +} + +table Capsule { + Transform:PackedVec3f (required); + Radius:float; + Height:float; + Rotation:PackedVec3f (required); +} + +table Havok { + TrcolFilePath:string (required); + Transform:PackedVec3f (required); + Rotation:PackedVec3f (required); + Scale:PackedVec3f (required); +} + +union CollisionUnion {Sphere, Box, Capsule, Havok} + +table CollisionComponent (fs_serializer) { + Shape:CollisionUnion (required); + // field 01 is the object ptr for ^ + Field_02:uint; //unknown + Field_03:bool; + Field_04:bool; //unknown + Field_05:bool; //unknown + Field_06:uint; + Field_07:bool; //unknown + Field_08:Vec4f (required); + Field_09:string (required); + Field_0A:bool; + Field_0B:bool; + Field_0C:bool; +} + +union ComponentUnion {CollisionComponent} + +table TrinityComponent (fs_serializer) { + Component:ComponentUnion (required); +} + +root_type TrinityComponent; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityEnvironmentParameter.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityEnvironmentParameter.fbs new file mode 100644 index 00000000..5d09363b --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityEnvironmentParameter.fbs @@ -0,0 +1,9 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinityEnvironmentParameter (fs_serializer) { + Field_00:string (required); + Field_01:float; +} + +root_type TrinityEnvironmentParameter; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityFileDescriptors.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityFileDescriptors.fbs new file mode 100644 index 00000000..058cdb0e --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityFileDescriptors.fbs @@ -0,0 +1,23 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinityFileDescriptorSubFileUnknown { + Field_00:uint; // TODO +} + +table TrinityFileDescriptorSubFileInfo { + Index:ulong; + SubInfo:TrinityFileDescriptorSubFileUnknown (required); +} + +table TrinityFileDescriptorInfo { + FileSize:ulong; + FileCount:ulong; +} + +table TrinityFileDescriptors (fs_serializer:"Progressive") { + SubFileHashes:[ulong] (required); + FilePaths:[string] (required); + SubFileInfos:[TrinityFileDescriptorSubFileInfo] (required); + FileInfos:[TrinityFileDescriptorInfo] (required); +} diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityFileSystemMetadata.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityFileSystemMetadata.fbs new file mode 100644 index 00000000..f6d1385e --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityFileSystemMetadata.fbs @@ -0,0 +1,9 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinityFileSystemMetadata (fs_serializer:"Progressive") { + FileHashes:[ulong] (required); + FileOffsets:[ulong] (required); +} + +root_type TrinityFileSystemMetadata; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityGroundPlaceComponent.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityGroundPlaceComponent.fbs new file mode 100644 index 00000000..00fd7860 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityGroundPlaceComponent.fbs @@ -0,0 +1,8 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinityGroundPlaceComponent (fs_serializer) { + Index:uint; +} + +root_type TrinityGroundPlaceComponent; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityModelComponent.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityModelComponent.fbs new file mode 100644 index 00000000..d0ed9927 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityModelComponent.fbs @@ -0,0 +1,30 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinityModelComponent (fs_serializer) { + Field_00:string (required); + Field_01:string (required); + Field_02:string (required); + Field_03:string (required); + Field_04:ubyte; // unknown + Field_05:float; + Field_06:float; + Field_07:float; + Field_08:ubyte; // unknown + Field_09:ubyte; // unknown + Field_10:ubyte; // unknown + Field_11:ubyte; // unknown + Field_12:ubyte; // unknown + Field_13:ubyte; // unknown + Field_14:ubyte; // unknown + Field_15:ubyte; // unknown + Field_16:ubyte; // unknown + Field_17:ubyte; // unknown + Field_18:ubyte; // unknown + Field_19:string (required); + Field_20:string (required); + Field_21:bool; + Field_22:string (required); +} + +root_type TrinityModelComponent; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityOverrideSensorData.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityOverrideSensorData.fbs new file mode 100644 index 00000000..c46c133a --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityOverrideSensorData.fbs @@ -0,0 +1,11 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinityOverrideSensorData (fs_serializer) { + Field_00:float; + Field_01:float; + Field_02:float; + Field_03:float; +} + +root_type TrinityOverrideSensorData; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityPak.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityPak.fbs new file mode 100644 index 00000000..42768588 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityPak.fbs @@ -0,0 +1,28 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +enum DataCompressionType : byte +{ + None = -1, + Invalid = 0, + Zlib = 1, + Lz4 = 2, + OodleKraken = 3, + OodleLeviathan = 4, + OodleMermaid = 5, + OodleSelkie = 6, + OodleHydra = 7, +} + +table TrinityPakFileData { + Field_00:uint; + CompressionType:DataCompressionType; + CompressionLevel:ubyte; + UncompressedSize:ulong; + Data:[ubyte] (required); +} + +table TrinityPak (fs_serializer:"Lazy") { + Hashes:[ulong] (required); + Files:[TrinityPakFileData] (required); +} diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityParticleComponent.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityParticleComponent.fbs new file mode 100644 index 00000000..9d1a6656 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityParticleComponent.fbs @@ -0,0 +1,12 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinityParticleComponent (fs_serializer) { + ParticleFile:string (required); + Field_01:string (required); + Field_02:bool; + ParticleName:string (required); + ParticleParent:string (required); +} + +root_type TrinityParticleComponent; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityPropertySheet.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityPropertySheet.fbs new file mode 100644 index 00000000..fbafa342 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityPropertySheet.fbs @@ -0,0 +1,40 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinityPropertySheetField1 { Value:ulong; FieldType:byte; } +table TrinityPropertySheetField2 { Value:uint; FieldType:byte; } +table TrinityPropertySheetFieldStringValue { Value:string (required); } +table TrinityPropertySheetField4 { } +table TrinityPropertySheetField5 { } +table TrinityPropertySheetField6 { } +table TrinityPropertySheetFieldEnumName { Enum:string (required); Value:uint; } + + /// Recursive! +table TrinityPropertySheetObject { Fields:[TrinityPropertySheetField] (required); } + +union TrinityPropertySheetValue { + TrinityPropertySheetField1, + TrinityPropertySheetField2, + TrinityPropertySheetFieldStringValue, + TrinityPropertySheetField4, + TrinityPropertySheetField5, + TrinityPropertySheetField6, + TrinityPropertySheetFieldEnumName, + TrinityPropertySheetObjectArray, + TrinityPropertySheetObject +} + +table TrinityPropertySheetObjectArray { Value:[TrinityPropertySheetValue] (required); } + +table TrinityPropertySheetField { + Name:string (required); + Data:TrinityPropertySheetValue (required); +} + +table TrinityPropertySheet (fs_serializer) { + Name:string (required); + Extra:string (required); + Properties:[TrinityPropertySheetObject] (required); +} + +root_type TrinityPropertySheet; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinitySceneObject.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinitySceneObject.fbs new file mode 100644 index 00000000..e45d4969 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinitySceneObject.fbs @@ -0,0 +1,50 @@ +include "Math/PackedVec3f.fbs"; +include "Geometry/SRT.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table SubScene (fs_serializer) { + Field_00:string (required); + Field_01:string (required); +} + +table TrinityCollisionEventTriggerComponent (fs_serializer) { + Field_00:string (required); + Field_01:string (required); + Field_02:byte; // unknown + Field_03:uint; // unknown + Field_04:string (required); + Field_05:string (required); +} + +table TrinityObjectSwitcher (fs_serializer) { + Field_00:string (required); + Field_01:string (required); +} + +table TrinityScriptComponent (fs_serializer) { + ScriptFileName:string (required); + ScriptFileNameHash:string (required); + Field_02:uint; + Field_03:uint; + Field_04:uint; + ScriptFileClass:string (required); +} + +table TrinityScene07 { +} + +table TrinitySceneObject (fs_serializer) { + Name:string (required); + Position:SRT (required); + Field_02:bool; + ApplySRT:bool; + Field_04:string (required); + Field_05:bool; + Field_06:byte; + Field_07:[TrinityScene07] (required); + Field_08:[string]; +} + +root_type TrinitySceneObject; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinitySceneObjectTemplate.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinitySceneObjectTemplate.fbs new file mode 100644 index 00000000..76555701 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinitySceneObjectTemplate.fbs @@ -0,0 +1,29 @@ +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinitySceneObjectTemplateData (fs_serializer) { + ObjectTemplateName:string (required); + ObjectTemplateExtra:string (required); + ObjectTemplatePath:string (required); + Field_03:ubyte; + Type:string (required); + Data:[ubyte] (required); +} + +table TrinitySceneObjectTemplateEntry { + Type:string (required); + Data:[ubyte] (required); + SubObjects:[TrinitySceneObjectTemplateEntry] (required); // Recursive ! +} + +table TrinitySceneObjectTemplate (fs_serializer) { + ObjectTemplateName:string (required); + ObjectTemplateExtra:string; + Field_02:uint; + Field_03:uint; + Objects:[TrinitySceneObjectTemplateEntry] (required); + Field_05:[string] (required); + Field_06:ubyte; +} + +root_type TrinitySceneObjectTemplate; diff --git a/FlatBuffers/ZA/Trinity/Schemas/TrinityScenePoint.fbs b/FlatBuffers/ZA/Trinity/Schemas/TrinityScenePoint.fbs new file mode 100644 index 00000000..0b519b04 --- /dev/null +++ b/FlatBuffers/ZA/Trinity/Schemas/TrinityScenePoint.fbs @@ -0,0 +1,12 @@ +include "Math/PackedVec3f.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA.Trinity; +attribute "fs_serializer"; + +table TrinityScenePoint (fs_serializer) { + Name:string (required); + Position:PackedVec3f (required); + Field_02:ubyte; +} + +root_type TrinityScenePoint; diff --git a/FlatBuffers/ZA/Trinity/pkNX.Structures.FlatBuffers.ZA.Trinity.csproj b/FlatBuffers/ZA/Trinity/pkNX.Structures.FlatBuffers.ZA.Trinity.csproj new file mode 100644 index 00000000..51a0cc4d --- /dev/null +++ b/FlatBuffers/ZA/Trinity/pkNX.Structures.FlatBuffers.ZA.Trinity.csproj @@ -0,0 +1,5 @@ + + + + + diff --git a/FlatBuffers/ZA/Waza/Schemas/PersonalWazaParamDBArray.fbs b/FlatBuffers/ZA/Waza/Schemas/PersonalWazaParamDBArray.fbs new file mode 100644 index 00000000..05f251b7 --- /dev/null +++ b/FlatBuffers/ZA/Waza/Schemas/PersonalWazaParamDBArray.fbs @@ -0,0 +1,55 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table PersonalWazaParam { + WazaID:uint; + ExtentionType:ubyte; + Type:ubyte; + Category:ubyte; + DamageType:ubyte; + Power:ubyte; + CriticalRank:ubyte; + HpRecoverRatio:byte; + ShrinkPer:ubyte; + SickParam_SickID:ushort; + SickParam_Per:ubyte; + SickParam_SickCont:ubyte; + SickParam_SickTurnMin:ubyte; + SickParam_SickTurnMax:ubyte; + RankEffect_0_Type:ubyte; + RankEffect_0_Value:byte; + RankEffect_0_Per:ubyte; + RankEffect_1_Type:ubyte; + RankEffect_1_Value:byte; + RankEffect_1_Per:ubyte; + RankEffect_2_Type:ubyte; + RankEffect_2_Value:byte; + RankEffect_2_Per:ubyte; + DamageRecoverRatio:byte; + DamageDrainRatio:byte; + IsGuard:bool; + IsAvoidByFloat:bool; + IsTouch:bool; + IsCut:bool; + IsWind:bool; + CanThroughMigawari:bool; + CanMeltFrozen:bool; + IsHpRecover:bool; + IsKaihukuHuuziEnable:bool; + IsYubiWoHuruPermit:bool; + IsSick:bool; + IsMamoruEnable:bool; + CantKill:bool; + ValueEffectRatio:byte; +} + +table PersonalWazaParamDB { + Table:[PersonalWazaParam] (required); +} + +table PersonalWazaParamDBArray (fs_serializer) { + Table:[PersonalWazaParamDB] (required); +} + +root_type PersonalWazaParamDBArray; diff --git a/FlatBuffers/ZA/Waza/Schemas/TokuseiArray.fbs b/FlatBuffers/ZA/Waza/Schemas/TokuseiArray.fbs new file mode 100644 index 00000000..0c677f2a --- /dev/null +++ b/FlatBuffers/ZA/Waza/Schemas/TokuseiArray.fbs @@ -0,0 +1,20 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table Tokusei { + DisabledByNeutralizingGas:bool; // Can be suppressed by Neutralizing Gas if != CantSuppress + FailRolePlay:bool; // Includes Doodle + NoReceiver:bool; // Includes Power of Alchemy + NoEntrain:bool; + NoTrace:bool; + FailSkillSwap:bool; // Includes Wandering Spirit + CantSuppress:bool; // Can't be suppressed by Gastro Acid + Breakable:bool; // Can be disabled by Mold Breaker + NoTransform:bool; // Disable if user is Transformed +} + +table TokuseiTable (fs_serializer) { + Table:[Tokusei] (required); +} + +root_type TokuseiTable; diff --git a/FlatBuffers/ZA/Waza/Schemas/Waza.fbs b/FlatBuffers/ZA/Waza/Schemas/Waza.fbs new file mode 100644 index 00000000..bd6f23bb --- /dev/null +++ b/FlatBuffers/ZA/Waza/Schemas/Waza.fbs @@ -0,0 +1,97 @@ +include "WazaInflict.fbs"; +include "WazaAffinity.fbs"; +include "WazaEntityStat.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table Waza { + MoveID:ushort; + CanUseMove:bool; + Type:ubyte; + Quality:ubyte; + Category:ubyte; + Power:ubyte; + Accuracy:ubyte; + PP:ubyte; + Priority:byte; + HitMax:ubyte; + HitMin:ubyte; + Inflict:WazaInflict (required); + CritStage:ubyte; + Flinch:ubyte; + EffectSequence:ushort; + Recoil:byte; // % of damage converted to Damage Self points (negative) + + // compared to S/V, this used to be just one property + SelfHeal:byte; // % of HP of self to change (+/-) + DamageHeal:ubyte; // % of damage converted to Heal Self points (positive) + + RawTarget:ubyte; + StatAmps:WazaEntityStat (required); + Affinity:WazaAffinity = None; + Flag_MakesContact:bool; + Flag_Charge:bool; + Flag_Recharge:bool; + Flag_Protect:bool; + Flag_Reflectable:bool; + Flag_Snatch:bool; + Flag_Mirror:bool; + Flag_Punch:bool; + Flag_Sound:bool; + Flag_Dance:bool; + Flag_Gravity:bool; + Flag_Defrost:bool; + Flag_DistanceTriple:bool; + Flag_Heal:bool; + Flag_IgnoreSubstitute:bool; + Flag_FailSkyBattle:bool; + Flag_AnimateAlly:bool; + Flag_Metronome:bool; + Flag_FailEncore:bool; + Flag_FailMeFirst:bool; + Flag_FutureAttack:bool; + Flag_Pressure:bool; + Flag_Combo:bool; + Flag_NoSleepTalk:bool; + Flag_NoAssist:bool; + Flag_FailCopycat:bool; + Flag_FailMimic:bool; + Flag_FailInstruct:bool; + Flag_Powder:bool; + Flag_Bite:bool; + Flag_Bullet:bool; + Flag_NoMultiHit:bool; + Flag_NoEffectiveness:bool; + Flag_SheerForce:bool; + Flag_Slicing:bool; + Flag_Wind:bool; + + // adjust names +1 compared to S/V due to above split property + Unknown_57:bool; + Unknown_58:bool; + Unknown_59:bool; + Unknown_60:bool; + Unknown_61:bool; + + // not used by any move + Unused_62:bool; + Unused_63:bool; + Unused_64:bool; + Unused_65:bool; + Unused_66:bool; + Unused_67:bool; + Unused_68:bool; + Unused_69:bool; + Unused_70:bool; + Unused_71:bool; + + Flag_CantUseTwice:bool; + // sketch used by S/V, not set by any as the NoSketch was added in S/V DLC 2. +} + +table WazaTable (fs_serializer) { + Table:[Waza] (required); +} + +root_type WazaTable; diff --git a/FlatBuffers/ZA/Waza/Schemas/WazaAffinity.fbs b/FlatBuffers/ZA/Waza/Schemas/WazaAffinity.fbs new file mode 100644 index 00000000..f60f7e6c --- /dev/null +++ b/FlatBuffers/ZA/Waza/Schemas/WazaAffinity.fbs @@ -0,0 +1,10 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum WazaAffinity : byte { + None = 0, + Support = 3, + Self = 4, + Attack = 5, + Strong = 6, + Shuriken = 7, +} diff --git a/FlatBuffers/ZA/Waza/Schemas/WazaEntityStat.fbs b/FlatBuffers/ZA/Waza/Schemas/WazaEntityStat.fbs new file mode 100644 index 00000000..646433f7 --- /dev/null +++ b/FlatBuffers/ZA/Waza/Schemas/WazaEntityStat.fbs @@ -0,0 +1,14 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_valueStruct"; + +struct WazaEntityStat (fs_valueStruct) { + Stat1:byte; + Stat2:byte; + Stat3:byte; + Stat1Stage:byte; + Stat2Stage:byte; + Stat3Stage:byte; + Stat1Percent:ubyte; + Stat2Percent:ubyte; + Stat3Percent:ubyte; +} diff --git a/FlatBuffers/ZA/Waza/Schemas/WazaInflict.fbs b/FlatBuffers/ZA/Waza/Schemas/WazaInflict.fbs new file mode 100644 index 00000000..f7256f03 --- /dev/null +++ b/FlatBuffers/ZA/Waza/Schemas/WazaInflict.fbs @@ -0,0 +1,10 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_valueStruct"; + +struct WazaInflict (fs_valueStruct) { + Value:ushort; + Chance:ubyte; + Turn1:ubyte; + Turn2:ubyte; + Turn3:ubyte; +} diff --git a/FlatBuffers/ZA/Waza/Schemas/WazaParamDBArray.fbs b/FlatBuffers/ZA/Waza/Schemas/WazaParamDBArray.fbs new file mode 100644 index 00000000..9866cd44 --- /dev/null +++ b/FlatBuffers/ZA/Waza/Schemas/WazaParamDBArray.fbs @@ -0,0 +1,51 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table WazaParam { + WazaId:int; + ChargeFrame:int; + AttackLoopFrame:int; + SpawnOrigin:int; + SpawnLocator:string; + SpawnOffsetX:float; + SpawnOffsetY:float; + SpawnOffsetZ:float; + ShotDirection:int; + CorrectTargetType:int; + ImpactMotionSpeed:float; + PlayWazaMoveType:int; + WazaRangeMin:float; + WazaRangeMax:float; + HeightTolerance:float; + EffectiveRange:float; + MinShootNum:int; + MaxShootNum:int; + HitPer:int; + WazaRecastTime:float; + EffectTime:float; + EffectValue:int; + AddMegaPowerValue:float; + PlayedMotionSpeed:float; + OverwriteBulletId1:int; + ReplaceBulletId1:int; + OverwriteBulletId2:int; + ReplaceBulletId2:int; + OverwriteBulletId3:int; + ReplaceBulletId3:int; + OverwriteBulletId4:int; + ReplaceBulletId4:int; + OverwriteBulletId5:int; + ReplaceBulletId5:int; + BulletCorrectScale:float; +} + +table WazaParamDB { + Table:[WazaParam] (required); +} + +table WazaParamDBArray (fs_serializer) { + Table:[WazaParamDB] (required); +} + +root_type WazaParamDBArray; diff --git a/FlatBuffers/ZA/Waza/pkNX.Structures.FlatBuffers.ZA.Waza.csproj b/FlatBuffers/ZA/Waza/pkNX.Structures.FlatBuffers.ZA.Waza.csproj new file mode 100644 index 00000000..35e3d842 --- /dev/null +++ b/FlatBuffers/ZA/Waza/pkNX.Structures.FlatBuffers.ZA.Waza.csproj @@ -0,0 +1,2 @@ + + diff --git a/FlatBuffers/ZA/World/Schemas/Area/AreaConfig.fbs b/FlatBuffers/ZA/World/Schemas/Area/AreaConfig.fbs new file mode 100644 index 00000000..c85952dc --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/AreaConfig.fbs @@ -0,0 +1,9 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table AreaConfig (fs_serializer) { + BattleZoneCheckRadius:float; +} + +root_type AreaConfig; diff --git a/FlatBuffers/ZA/World/Schemas/Area/AreaLayer.fbs b/FlatBuffers/ZA/World/Schemas/Area/AreaLayer.fbs new file mode 100644 index 00000000..522c181f --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/AreaLayer.fbs @@ -0,0 +1,12 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum AreaLayer : int { + Scene = 0, + MainArea = 1, + SubArea = 2, + Location1 = 3, + Location2 = 4, + Location3 = 5, + BattleZone = 6, + WildZone = 7, +} diff --git a/FlatBuffers/ZA/World/Schemas/Area/AreaType.fbs b/FlatBuffers/ZA/World/Schemas/Area/AreaType.fbs new file mode 100644 index 00000000..ec5d3c0c --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/AreaType.fbs @@ -0,0 +1,9 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +enum AreaType : int { + Default = 0, + Field = 1, + Town = 2, + Cave = 3, + Room = 4, +} diff --git a/FlatBuffers/ZA/World/Schemas/Area/CacheOption.fbs b/FlatBuffers/ZA/World/Schemas/Area/CacheOption.fbs new file mode 100644 index 00000000..b0e8e872 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/CacheOption.fbs @@ -0,0 +1,6 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +table CacheOption { + CacheableScene:bool; + CacheDeleteScene:bool; +} diff --git a/FlatBuffers/ZA/World/Schemas/Area/DungeonMapUIDataArray.fbs b/FlatBuffers/ZA/World/Schemas/Area/DungeonMapUIDataArray.fbs new file mode 100644 index 00000000..3cee9fb3 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/DungeonMapUIDataArray.fbs @@ -0,0 +1,16 @@ +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table DungeonMapUIData { + Field00:uint; + Field01:uint; + Field02:string (required); + Field03:float; + //Field04:[ulong]; // dunno what this is, might be object[]? +} + +table DungeonMapUIDataArray (fs_serializer) { + Table:[DungeonMapUIData] (required); +} + +root_type DungeonMapUIDataArray; diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldAreaInfo.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldAreaInfo.fbs new file mode 100644 index 00000000..b7c4db47 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldAreaInfo.fbs @@ -0,0 +1,37 @@ +include "AreaType.fbs"; +include "Math/PackedVec3f.fbs"; +include "FieldShadowInfo.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table FieldAreaInfo { + AreaName:string (required); + ScenePath:string; + AreaCategory:string (required); + IsSafety:bool; + IsInteriorCamera:bool; + IsTimerSuspend:bool; + IsImportantArea:bool; + IsRoom:bool; + CanRide:bool; + ProhibitReadyBallThrow:bool; + ProhibitPartnerPutout:bool; + IsOptimizeWaterLight:bool; + DefaultStartPosition:PackedVec3f; + DefaultStartYaw:float; + Music:string; + SoundEffect:string; + LightFile_p1:string; + LightFile_p2:string; + LightFile_p3:string; + WeatherTable:string; + AreaType:AreaType; + ShadowPresetName:string; + ShadowInfo:FieldShadowInfo; + MainAreaName:string; + SubAreaName:string; + LocationName:string; + FastTravelFlagId:string; + SubAreaReachedFlgId:string; + MapId:string; +} diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldBattleZoneArray.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldBattleZoneArray.fbs new file mode 100644 index 00000000..c3201c87 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldBattleZoneArray.fbs @@ -0,0 +1,17 @@ +include "FieldAreaInfo.fbs"; +include "AreaLayer.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table FieldBattleZoneArray (fs_serializer) { + Table:[FieldBattleZone] (required); +} + +table FieldBattleZone { + AreaInfo:FieldAreaInfo (required); + Layer:AreaLayer; + ZoneID:string (required); +} + +root_type FieldBattleZoneArray; diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldConfig.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldConfig.fbs new file mode 100644 index 00000000..33a63b83 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldConfig.fbs @@ -0,0 +1,26 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table FieldSpawnerConfig { + IsSkipSpawnByDiffYLimitMinEnable:bool; + IsSkipSpawnByDiffYLimitMaxEnable:bool; + SkipSpawnByDiffYLimitMin:float; + SkipSpawnByDiffYLimitMax:float; +} + +table FieldNightVisibleControllerConfig { + NightBeginTimeInHour:float; + NightEndTimeInHour:float; +} + +table FieldConfig (fs_serializer) { + SystemSceneLoadTimeoutSeconds:float; + MapChangeTimeoutSeconds:float; + UnLoadWaitFrame:int; + AllocatableSizeThreshold:int; + NightVisibleControllerConfig:FieldNightVisibleControllerConfig (required); + SpawnerConfig:FieldSpawnerConfig (required); +} + +root_type FieldConfig; diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldDataConfigArray.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldDataConfigArray.fbs new file mode 100644 index 00000000..d78aac58 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldDataConfigArray.fbs @@ -0,0 +1,79 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +enum FieldDataType : int +{ + Area = 0, + ShadowPreset = 1, + JumpPoint = 2, + EnvironmentTable = 3, + TimePreset = 4, + TimeZone = 5, + WeatherTable = 6, + WindTable = 7, + Config = 8, + EncountData = 9, + PokemonSpawner = 10, + WazaGimmickPrivateTable = 11, + WazaGimmickPublicTable = 12, + AreaCategory = 13, + WazaGimmickPokemonSpawner = 14, + TrafficNpcSpawner = 17, + NpcGroupData = 18, + NpcObjectTemplateData = 19, + RandomPopItemSpawner = 20, + SceneSection = 21, + MapReplace = 22, + GroundEffectConfig = 23, + GroundEffect = 24, + ZoneData = 25, + ItemTableData = 26, + ItemSpawner = 27, + BattleArea = 28, + WazaGimmickItemSpawner = 29, + EggHatchData = 30, + DistantViewEffectConfig = 31, + DistantViewEffect = 32, + WeatherHappening = 33, + WeatherScheduleTable = 34, + WazagimmickSpawner = 35, + ItemBallObjectTemplateData = 37, + WazaAttribute = 38, + Vignette = 39, + NpcAssetData = 40, + PlacementNpcSpawner = 41, + SpawnerTransformData = 42, + ItemTypeData = 43, + GetMedalCountData = 44, + OyabunSettingData = 45, + BattleZoneLotteryData = 46, + ImapBakeSceneData = 47, + ImapOverrideBakeSceneData = 48, + ImapOverrideBakeAshibaGimmickData = 49, + ZaTrainerSpawner = 50, + ZaTrainerData = 51, + NpcPokemonGroupData = 52, + ZaTrainerTableData = 53, + LightOverrideFlagWorkData = 54, + SpawnPointGroundCheck = 55, + SpawnPointNearCheck = 56, + OyabunWazaData = 57, + AreaConfig = 58, +} + +table FieldDataInfo { + Type:FieldDataType; + Category:string; + BasePath:string; +} + +table FieldDataConfig { + Info:FieldDataInfo (required); +} + +table FieldDataConfigArray (fs_serializer) { + Table:[FieldDataConfig] (required); +} + +root_type FieldDataConfigArray; diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldLocationArray.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldLocationArray.fbs new file mode 100644 index 00000000..a6d16dba --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldLocationArray.fbs @@ -0,0 +1,16 @@ +include "FieldAreaInfo.fbs"; +include "AreaLayer.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table FieldLocationArray (fs_serializer) { + Table:[FieldLocation] (required); +} + +table FieldLocation { + AreaInfo:FieldAreaInfo (required); + Layer:AreaLayer; +} + +root_type FieldLocationArray; diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldMainAreaArray.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldMainAreaArray.fbs new file mode 100644 index 00000000..d4d08085 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldMainAreaArray.fbs @@ -0,0 +1,16 @@ +include "FieldAreaInfo.fbs"; +include "AreaLayer.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table FieldMainAreaArray (fs_serializer) { + Table:[FieldMainArea] (required); +} + +table FieldMainArea { + AreaInfo:FieldAreaInfo (required); + Layer:AreaLayer; +} + +root_type FieldMainAreaArray; diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldPlayer.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldPlayer.fbs new file mode 100644 index 00000000..c4725efd --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldPlayer.fbs @@ -0,0 +1,259 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table FacialParameter { + AutoBlinkIntervalMin:float; + AutoBlinkIntervalMax:float; +} + +table AerialKinesisParameter { + Accel:float; + Friction:float; + SelfSpeedMax:float; + BackwardAngle:float; + GripAngle:float; +} + +enum Easing : int +{ + InSine = 0, + OutSine = 1, + InOutSin = 2, + InQuad = 3, + OutQuad = 4, + InOutQuad = 5, + InCubic = 6, + OutCubic = 7, + InOutCubic = 8, + InQuart = 9, + OutQuart = 10, + InOutQuart = 11, + InQuint = 12, + OutQuint = 13, + InOutQuint = 14, + InExpo = 15, + OutExpo = 16, + InOutExpo = 17, + InCirc = 18, + OutCirc = 19, + InOutCirc = 20, + InBack = 21, + OutBack = 22, + InOutBack = 23, + InElastic = 24, + OutElastic = 25, + InOutElastic = 26, + InBounce = 27, + OutBounce = 28, + InOutBounce = 29, + Linear = 30, +} +table TotterParameter { + Interval:float; + Height:float; + DistanceMax:float; + BackDistance:float; +} + +table SwimKinesisParameter { + SelfSpeedMax:float; + Accel:float; + Friction:float; + MinGripAngle:float; + MaxGripAngle:float; +} + +table SquatKinesisParameter { + SpeedFixed:float; + SlipFriction:float; + GripFactor:float; +} + +table SlidingKinesisParameter { + Friction:float; + SlipFriction:float; + InitVelocityRate:float; + BreakDecrease:float; + BreakIncrease:float; +} + +table SlideDropParameter { + ForwardDirFactor:float; + BackwardDirFactor:float; + UpwardDirFactor:float; + BackwardTime:float; + LeanFactor:float; +} + +table SlideDropKinesisParameter { + ForwardGripFactor:float; + BackwardGripFactor:float; + Accel:float; + Friction:float; + SpeedMax:float; + CurveAngle:float; + SpeedUpInputThreshold:float; + SideInputTolerance:float; + SideMaxVelocityRate:float; + SideFriction:float; + SpeedUpRate:float; + SpeedDownRate:float; + ForwardSideAccel:float; + BackwardSideAccel:float; +} + +table SelfieParameter { + MaxFactor:float; + RotAngleMax:float; +} + +table PlayerUniqueParameter { + IdlingIntervalMin:float; + IdlingIntervalMax:float; + FacialIdlingCountMin:int; + FacialIdlingCountMax:int; + RunFacialIntervalMin:float; + RunFacialIntervalMax:float; + RunMouthIntervalMin:float; + RunMouthIntervalMax:float; + SlideDropLeanAngle:float; + SlideDropFwdAngle:float; + SquatRate:float; + RideChangeCheckHeight:float; + RideChangeBottomOffset:float; + RideChangeRadiusScale:float; + HiddenMargin:float; +} + +table MoveParameter { + PitchFactor:float; + LeanAngle:float; + LeanFactor:float; + RotationFactor:float; + ReverseSpeedFactor:float; + ReverseTurnAngle:float; + ReverseFrictionFactor:float; + LightLandingHeight:float; + HeavyLandingHeight:float; + DynamicsResetCount:int; + SpinCount:int; + SpinMaxSpeed:float; + SpinMaxAnimationSpeed:float; + SpinInterpolation:float; + SlideDropToleranceTime:float; + StopToleranceTime:float; + TurnStickDiffThreashold:float; + SliderModeRate:float; + BallThrowFrictionFactor:float; + BallThrowBackFrictionFactor:float; + UnlandablePushVelocity:float; +} + +table LadderParameter { + LowerCorrectRate:float; + UpperCorrectRate:float; + UpperLaunchAngle:float; + LowerLaunchAngle:float; + UpperForwardAngle:float; + LowerForwardAngle:float; +} + +table InputParameter { + StickTolerance:float; + SpinThreshold:float; +} + +table GroundParameter { + SlideDropThreshold:float; + VerticalMargin:float; + WallHitAngle:float; + WaterDraftLine:float; + WaterSurfaceMargin:float; + WaterWithstandLine:float; + UnderWaterThreshold:float; + ShallowWaterThreshold:float; + AcceptableRadiusRate:float; +} + +table GroundKinesisParameter { + FirstSpeedMax:float; + SecondSpeedMax:float; + SlowSpeedMax:float; + FirstAccel:float; + SecondAccel:float; + SlowAccel:float; + Friction:float; + SlipFriction:float; + SlipFrictionExp:float; + MaxGripFactor:float; + MinGripFactor:float; + RunStickThreshold:float; +} + +table GravityParameter { + Accel:float; + SpeedMax:float; +} + +table GlideKinesisParameter { + SelfSpeedMax:float; + Accel:float; + Friction:float; + MinGripAngle:float; + MaxGripAngle:float; + GravityRate:float; + FlareSpeedMax:float; +} + +table FloatationParameter { + Floatage:float; + Dumping:float; + SpeedMax:float; + SurfaceDumpingRate:float; +} + +table FlightKinesisParameter { + Accel:float; + PitchMaxUpAngle:float; + PitchMaxDownAngle:float; + PitchMaxTotalAngle:float; + YawAngleSpeed:float; + PitchAngleSpeed:float; + PitchUpSpeedRate:float; + PitchDownSpeedRate:float; + PitchStableSpeedRate:float; + PitchBaseAngle:float; + RollMaxAngle:float; + RollFactor:float; + UpAccelRate:float; + DownAccelRate:float; + MaxSpeed:float; + MaxDiveSpeed:float; + PitchUpSpeedThreshold:float; + PitchRateExp:float; + ReadyScale:float; + FaintThreshold:float; + AirRegist:float; +} + +table FieldPlayer (fs_serializer) { + Gravity:GravityParameter (required); + Input:InputParameter (required); + Move:MoveParameter (required); + Totter:TotterParameter (required); + Ground:GroundParameter (required); + SlideDrop:SlideDropParameter (required); + Ladder:LadderParameter (required); + Facial:FacialParameter (required); + Unique:PlayerUniqueParameter (required); + GroundKinesis:GroundKinesisParameter (required); + AerialKinesis:AerialKinesisParameter (required); + SlideDropKinesis:SlideDropKinesisParameter (required); + SquatKinesis:SquatKinesisParameter (required); + SlidingKinesis:SlidingKinesisParameter (required); + Selfie:SelfieParameter (required); + Floatation:FloatationParameter (required); +} + +root_type FieldPlayer; diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldSceneAreaArray.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldSceneAreaArray.fbs new file mode 100644 index 00000000..85bd4799 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldSceneAreaArray.fbs @@ -0,0 +1,20 @@ +include "FieldAreaInfo.fbs"; +include "AreaLayer.fbs"; +include "CacheOption.fbs"; +include "StreamingConfig.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table FieldSceneAreaArray (fs_serializer) { + Table:[FieldSceneArea] (required); +} + +table FieldSceneArea { + AreaInfo:FieldAreaInfo (required); + Layer:AreaLayer; + AreaCacheOption:CacheOption; + AreaStreamingConfig:StreamingConfig; +} + +root_type FieldSceneAreaArray; diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldShadowInfo.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldShadowInfo.fbs new file mode 100644 index 00000000..b36e949b --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldShadowInfo.fbs @@ -0,0 +1,7 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +struct FieldShadowInfo { + ShadowClipHeightOffset:float; + ShadowClipHeightMinOffset:float; + ShadowClipFadeWidth:float; +} diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldSubArea.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldSubArea.fbs new file mode 100644 index 00000000..b9ec1d93 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldSubArea.fbs @@ -0,0 +1,16 @@ +include "FieldAreaInfo.fbs"; +include "AreaLayer.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table FieldSubAreaArray (fs_serializer) { + Table:[FieldSubArea] (required); +} + +table FieldSubArea { + AreaInfo:FieldAreaInfo (required); + Layer:AreaLayer; +} + +root_type FieldSubAreaArray; diff --git a/FlatBuffers/ZA/World/Schemas/Area/FieldWildZoneArray.fbs b/FlatBuffers/ZA/World/Schemas/Area/FieldWildZoneArray.fbs new file mode 100644 index 00000000..b1661e69 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/FieldWildZoneArray.fbs @@ -0,0 +1,17 @@ +include "FieldAreaInfo.fbs"; +include "AreaLayer.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table FieldWildZoneArray (fs_serializer) { + Table:[FieldWildZone] (required); +} + +table FieldWildZone { + AreaInfo:FieldAreaInfo (required); + Layer:AreaLayer; + ZoneID:string (required); +} + +root_type FieldWildZoneArray; diff --git a/FlatBuffers/ZA/World/Schemas/Area/OyabunSetting.fbs b/FlatBuffers/ZA/World/Schemas/Area/OyabunSetting.fbs new file mode 100644 index 00000000..975005bb --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/OyabunSetting.fbs @@ -0,0 +1,10 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table OyabunSetting (fs_serializer) { + MaxTalentValueCount:byte; + StrengthenValue:short; +} + +root_type OyabunSetting; diff --git a/FlatBuffers/ZA/World/Schemas/Area/StreamingConfig.fbs b/FlatBuffers/ZA/World/Schemas/Area/StreamingConfig.fbs new file mode 100644 index 00000000..19852c6f --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Area/StreamingConfig.fbs @@ -0,0 +1,10 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +table StreamingConfig { + GridRealizeOffset:float; + GridUnrealizeOffset:float; + OverrideSensorRealizeOffset:float; + OverrideSensorUnrealizeOffset:float; + ConditionalRealizeOffset:float; + ConditionalUnrealizeOffset:float; +} diff --git a/FlatBuffers/ZA/World/Schemas/Encount/EncountDataDBArray.fbs b/FlatBuffers/ZA/World/Schemas/Encount/EncountDataDBArray.fbs new file mode 100644 index 00000000..fb2fd1b2 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Encount/EncountDataDBArray.fbs @@ -0,0 +1,47 @@ +include "Entity/ParamSet.fbs"; +include "Shared/ActivationCondition.fbs"; +include "Shared/DevID.fbs"; +include "Shared/HoldItem.fbs"; +include "Shared/WazaList.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +table ItemDropInfo { + ItemTableId:string; + DropConditionList:[int] (required); + DropProbability:uint; + MinCount:uint; + MaxCount:uint; +} + +table EncountData { + Id:string (required); + DevNo:DevID; + MinLevel:int; + MaxLevel:int; + Sex:int; + FormNo:int; + Rare:int; + Tokusei:int; + Seikaku:int; + TalentScale:int; + TalentVNum:int; + OyabunProbability:float; + OyabunAdditionalLevel:int; + ActivationConditionArray:[ActivationCondition]; // not required + TalentValue:ParamSet (required); + StrengthenValue:ParamSet; // not required + Moves:WazaList; // not required + Item:HoldItem; // not required + ItemDropInfoList:[ItemDropInfo]; // not required +} + +table EncountDataDB { + Table:[EncountData] (required); +} + +table EncountDataDBArray (fs_serializer) { + Table:[EncountDataDB] (required); +} + +root_type EncountDataDBArray; diff --git a/FlatBuffers/ZA/World/Schemas/Encount/PokemonDataDBArray.fbs b/FlatBuffers/ZA/World/Schemas/Encount/PokemonDataDBArray.fbs new file mode 100644 index 00000000..a605a000 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Encount/PokemonDataDBArray.fbs @@ -0,0 +1,39 @@ +include "Entity/ParamSet.fbs"; +include "Shared/ActivationCondition.fbs"; +include "Shared/DevID.fbs"; +include "Shared/HoldItem.fbs"; +include "Shared/WazaList.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table PokemonData { + Id:string (required); + DevNo:DevID; + MinLevel:int; + MaxLevel:int; + Sex:int; + FormNo:int; + Rare:int; + Tokusei:int; + Seikaku:int; + TalentScale:int; + TalentVNum:int; + OyabunProbability:float; + OyabunAdditionalLevel:int; + ActivationConditionArray:[ActivationCondition]; // not required; null instead of count:0 + TalentValue:ParamSet (required); + Moves:WazaList; // not required + Item:HoldItem; // not required +} + +table PokemonDataDB { + Table:[PokemonData] (required); +} + +table PokemonDataDBArray (fs_serializer) { + Table:[PokemonDataDB] (required); +} + +root_type PokemonDataDBArray; diff --git a/FlatBuffers/ZA/World/Schemas/Encount/PokemonDropItemTableDataDBArray.fbs b/FlatBuffers/ZA/World/Schemas/Encount/PokemonDropItemTableDataDBArray.fbs new file mode 100644 index 00000000..22453209 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Encount/PokemonDropItemTableDataDBArray.fbs @@ -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 PokemonDropItemTableData { + Id:string (required); + ItemLotteryDataList:[ItemLotteryData]; +} + +table ItemLotteryData { + ItemId:string (required); + Weight:int; + MaxCount:int; + Type:int; + ActivationConditionArray:[ActivationCondition]; +} + +table PokemonDropItemTableDataDB { + Data:[PokemonDropItemTableData] (required); +} + +table PokemonDropItemTableDataDBArray (fs_serializer) { + Table:[PokemonDropItemTableDataDB] (required); +} + +root_type PokemonDropItemTableDataDBArray; diff --git a/FlatBuffers/ZA/World/Schemas/Oyabun/OyabunWazaDB.fbs b/FlatBuffers/ZA/World/Schemas/Oyabun/OyabunWazaDB.fbs new file mode 100644 index 00000000..ad234a3a --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Oyabun/OyabunWazaDB.fbs @@ -0,0 +1,19 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table FormTable { + FormNo:ushort; + WazaNo:ushort; +} + +table OyabunWaza { + DevNo:ushort; + FormTableList:[FormTable] (required); +} + +table OyabunWazaDB (fs_serializer) { + Table:[OyabunWaza] (required); +} + +root_type OyabunWazaDB; diff --git a/FlatBuffers/ZA/World/Schemas/Spawner/PokemonSpawnerDataDBArray.fbs b/FlatBuffers/ZA/World/Schemas/Spawner/PokemonSpawnerDataDBArray.fbs new file mode 100644 index 00000000..9449b043 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Spawner/PokemonSpawnerDataDBArray.fbs @@ -0,0 +1,76 @@ +include "Shared/ActivationCondition.fbs"; +include "Shared/AppearanceInfo.fbs"; +include "Shared/ZoneInfo.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table AiInfo { + ActionId:int; + PointName:string; +} + +table PokemonCoolTimeInfo { + Condition:int; + Time:float; +} + +table RepopProbability { + AfterCaptured:int; + AfterDefeated:int; +} + +table EncountDataAiInfo { + ActionId:int; + PointName:string; + ActorName:string; + CreateIgnoreFlagList:[int]; + Homerange:float; + PopActionId:int; +} + +table EncountDataInfo { + EncountDataId:string; + Weight:int; + MaxCount:int; + AdditionalLevel:int; + TagList:[string]; + ShowMapIcon:int; + AppearedTimeCondition:int; + AppearedWeatherCondition:int; + Ai:EncountDataAiInfo; + ActivationConditionList:[ActivationCondition]; + ActivationConditionForUiList:[ActivationCondition]; + Repop:RepopProbability; +} + +table PokemonAppearanceSpawnerObjectInfo { + ObjectName:string (required); + CreateScenePath:string (required); + DungeonName:string; + AdditionalFlagList:[int]; + BattleAreaId:string; + TagList:[string]; + Zone:ZoneInfo; + Ai:AiInfo; + Appearance:AppearanceInfo (required); +} + +table PokemonSpawnerData { + Id:string (required); + AppearanceSpawnerObjectInfoList:[PokemonAppearanceSpawnerObjectInfo] (required); + ActivationConditionList:[ActivationCondition] (required); + ActivationConditionForUiList:[ActivationCondition]; + CoolTime:PokemonCoolTimeInfo (required); + EncountDataInfoList:[EncountDataInfo] (required); +} + +table PokemonSpawnerDataDB { + Table:[PokemonSpawnerData] (required); +} + +table PokemonSpawnerDataDBArray (fs_serializer) { + Table:[PokemonSpawnerDataDB] (required); +} + +root_type PokemonSpawnerDataDBArray; diff --git a/FlatBuffers/ZA/World/Schemas/Spawner/SpawnerDataDBArray.fbs b/FlatBuffers/ZA/World/Schemas/Spawner/SpawnerDataDBArray.fbs new file mode 100644 index 00000000..8df74b63 --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Spawner/SpawnerDataDBArray.fbs @@ -0,0 +1,49 @@ +include "Shared/AppearanceInfo.fbs"; +include "Shared/CoolTimeInfo.fbs"; +include "Shared/ZoneInfo.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table TableInfoActivationConditionParam { + Condition:string; + Op:int; + Param:[string]; +} + +table TableInfoActivationConditionElement { + Param:[TableInfoActivationConditionParam] (required); +} + +table TableInfoActivationCondition { + Element:[TableInfoActivationConditionElement] (required); +} + +table TableInfo { + TableId:string; + ActivationCondition:[TableInfoActivationCondition] (required); +} + +table AppearanceSpawnerObjectInfo { + ObjectName:string (required); + CreateScenePath:string; + Zone:ZoneInfo; + Appearance:AppearanceInfo; +} + +table SpawnerData { + Id:string (required); + CoolTime:CoolTimeInfo; + TableInfoList:[TableInfo] (required); + AppearanceSpawnerObjectInfoList:[AppearanceSpawnerObjectInfo]; +} + +table SpawnerDataDB { + Table:[SpawnerData] (required); +} + +table SpawnerDataDBArray (fs_serializer) { + Table:[SpawnerDataDB] (required); +} + +root_type SpawnerDataDBArray; diff --git a/FlatBuffers/ZA/World/Schemas/Spawner/SpawnerTransformDataDBArray.fbs b/FlatBuffers/ZA/World/Schemas/Spawner/SpawnerTransformDataDBArray.fbs new file mode 100644 index 00000000..7074ae3f --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Spawner/SpawnerTransformDataDBArray.fbs @@ -0,0 +1,21 @@ +include "Math/PackedVec3f.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table SpawnerTransformData { + Name:string; + Position:PackedVec3f; + Rotation:PackedVec3f; + AttachTransformEnable:bool; +} + +table SpawnerTransformDataDB { + Table:[SpawnerTransformData] (required); +} + +table SpawnerTransformDataDBArray (fs_serializer) { + Table:[SpawnerTransformDataDB] (required); +} + +root_type SpawnerTransformDataDBArray; diff --git a/FlatBuffers/ZA/World/Schemas/Spawner/WazaGimmickSpawnerDataDBArray.fbs b/FlatBuffers/ZA/World/Schemas/Spawner/WazaGimmickSpawnerDataDBArray.fbs new file mode 100644 index 00000000..36bfca1d --- /dev/null +++ b/FlatBuffers/ZA/World/Schemas/Spawner/WazaGimmickSpawnerDataDBArray.fbs @@ -0,0 +1,45 @@ +include "Shared/ActivationCondition.fbs"; +include "Shared/AppearanceInfo.fbs"; +include "Shared/CoolTimeInfo.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; +attribute "fs_serializer"; + +table SpawnWazaGimmickInfo { + PrivateId:string; + Weight:int; + MaxCount:int; + ActivationConditionList:[ActivationCondition]; +} + +table WazaGimmickAiInfo { + ActionId:int; + PointName:string; +} + +table WazaGimmickAppearanceSpawnerObjectInfo { + ObjectName:string; + CreateScenePath:string; + AdditionalFlagList:[int]; + TagList:[string]; + Ai:WazaGimmickAiInfo; + Appearance:AppearanceInfo; +} + +table WazaGimmickSpawnerData { + Id:string (required); + AppearanceSpawnerObjectInfoList:[WazaGimmickAppearanceSpawnerObjectInfo]; + ActivationConditionList:[ActivationCondition]; + CoolTime:CoolTimeInfo; + SpawnWazaGimmickInfoList:[SpawnWazaGimmickInfo]; +} + +table WazaGimmickSpawnerDataDB { + Table:[WazaGimmickSpawnerData] (required); +} + +table WazaGimmickSpawnerDataDBArray (fs_serializer) { + Table:[WazaGimmickSpawnerDataDB] (required); +} + +root_type WazaGimmickSpawnerDataDBArray; diff --git a/FlatBuffers/ZA/World/World/IAreaLayer.cs b/FlatBuffers/ZA/World/World/IAreaLayer.cs new file mode 100644 index 00000000..2a0ebd82 --- /dev/null +++ b/FlatBuffers/ZA/World/World/IAreaLayer.cs @@ -0,0 +1,20 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +public interface IAreaLayer +{ + AreaLayer Layer { get; } + FieldAreaInfo AreaInfo { get; } +} + +partial class FieldLocation : IAreaLayer; +partial class FieldSubArea : IAreaLayer; +partial class FieldMainArea : IAreaLayer; +partial class FieldSceneArea : IAreaLayer; + +partial class FieldBattleZone : IAreaLayer, IZoneLayer; +partial class FieldWildZone : IAreaLayer, IZoneLayer; + +public interface IZoneLayer +{ + string? ZoneID { get; } +} diff --git a/FlatBuffers/ZA/World/pkNX.Structures.FlatBuffers.ZA.World.csproj b/FlatBuffers/ZA/World/pkNX.Structures.FlatBuffers.ZA.World.csproj new file mode 100644 index 00000000..6b512ec9 --- /dev/null +++ b/FlatBuffers/ZA/World/pkNX.Structures.FlatBuffers.ZA.World.csproj @@ -0,0 +1 @@ + diff --git a/FlatBuffers/ZA/Zukan/Schemas/PokedexBlackListMainArray.fbs b/FlatBuffers/ZA/Zukan/Schemas/PokedexBlackListMainArray.fbs new file mode 100644 index 00000000..20983adc --- /dev/null +++ b/FlatBuffers/ZA/Zukan/Schemas/PokedexBlackListMainArray.fbs @@ -0,0 +1,14 @@ +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_serializer"; + +table PokedexBlackListMain { + DevNo:short; + FormNo:short; +} + +table PokedexBlackListMainArray (fs_serializer) { + Table:[PokedexBlackListMain] (required); +} + +root_type PokedexBlackListMainArray; diff --git a/FlatBuffers/ZA/Zukan/Schemas/RankBattleRewardArray.fbs b/FlatBuffers/ZA/Zukan/Schemas/RankBattleRewardArray.fbs new file mode 100644 index 00000000..480bb490 --- /dev/null +++ b/FlatBuffers/ZA/Zukan/Schemas/RankBattleRewardArray.fbs @@ -0,0 +1,39 @@ +include "Shared/ItemID.fbs"; + +namespace pkNX.Structures.FlatBuffers.ZA; + +attribute "fs_vector"; +attribute "fs_serializer"; +attribute "fs_valueStruct"; +attribute "fs_nonVirtual"; +attribute "fs_unsafeStructVector"; + +enum RankedPlacement : byte { + Rank1st = 0, + Rank2nd = 1, + Rank3rd = 2, + Rank4th = 3, +} + +struct RankBattleRewardItem { + Item:ItemID; + Count:ushort; +} + +table RankBattleReward { + Rank:RankedPlacement; + LotteryWeight:ushort; + Money:uint; + Item1:RankBattleRewardItem (required); + Item2:RankBattleRewardItem (required); + Item3:RankBattleRewardItem (required); + Item4:RankBattleRewardItem (required); + Item5:RankBattleRewardItem (required); + Item6:RankBattleRewardItem (required); +} + +table RankBattleRewardArray (fs_serializer) { + Table:[RankBattleReward] (required); +} + +root_type RankBattleRewardArray; diff --git a/FlatBuffers/ZA/Zukan/pkNX.Structures.FlatBuffers.ZA.Zukan.csproj b/FlatBuffers/ZA/Zukan/pkNX.Structures.FlatBuffers.ZA.Zukan.csproj new file mode 100644 index 00000000..35e3d842 --- /dev/null +++ b/FlatBuffers/ZA/Zukan/pkNX.Structures.FlatBuffers.ZA.Zukan.csproj @@ -0,0 +1,2 @@ + + diff --git a/FlatBuffers/pkNX.Structures.FlatBuffers.Reflection/ReflectionDumpSchema.cs b/FlatBuffers/pkNX.Structures.FlatBuffers.Reflection/ReflectionDumpSchema.cs index af56d491..97298f63 100644 --- a/FlatBuffers/pkNX.Structures.FlatBuffers.Reflection/ReflectionDumpSchema.cs +++ b/FlatBuffers/pkNX.Structures.FlatBuffers.Reflection/ReflectionDumpSchema.cs @@ -41,7 +41,7 @@ public static void DumpSchema(Memory data, TextWriter fbs, TextWriter cs, public static void DumpSchema(Schema schema, TextWriter fbs, TextWriter cs, SchemaDumpSettings settings) { - WriteHeaderFBS(schema, fbs, settings.FileNamespace); + WriteHeaderFBS(schema, fbs, settings.FileNamespace, settings); WriteHeaderCS(schema, cs, settings.FileNamespace); DumpObjects(schema, fbs, cs, settings.StripNamespace); @@ -51,7 +51,7 @@ public static void DumpSchema(Schema schema, TextWriter fbs, TextWriter cs, Sche fbs.WriteLine($"root_type {x};"); } - private static void WriteHeaderFBS(Schema schema, TextWriter fbs, ReadOnlySpan fileNameSpace) + private static void WriteHeaderFBS(Schema schema, TextWriter fbs, ReadOnlySpan fileNameSpace, SchemaDumpSettings settings) { fbs.WriteLine($"namespace {fileNameSpace};"); fbs.WriteLine(); @@ -60,6 +60,9 @@ private static void WriteHeaderFBS(Schema schema, TextWriter fbs, ReadOnlySpan $"{{ R: {R}, G: {G}, B: {B} }}"; + public readonly override string ToString() => $"{{ R: {R}, G: {G}, B: {B} }}"; } diff --git a/FlatBuffers/pkNX.Structures.FlatBuffers/FlatBufferConverter.cs b/FlatBuffers/pkNX.Structures.FlatBuffers/FlatBufferConverter.cs index 50d6f0a2..4316db16 100644 --- a/FlatBuffers/pkNX.Structures.FlatBuffers/FlatBufferConverter.cs +++ b/FlatBuffers/pkNX.Structures.FlatBuffers/FlatBufferConverter.cs @@ -6,7 +6,7 @@ namespace pkNX.Structures.FlatBuffers; public static class FlatBufferConverter { - public static T[] DeserializeFrom(string[] files) + public static T[] DeserializeFrom(ReadOnlySpan files) where T : class, IFlatBufferSerializable { var result = new T[files.Length]; @@ -19,7 +19,6 @@ public static T[] DeserializeFrom(string[] files) } public static T DeserializeFrom(string path) where T : class, IFlatBufferSerializable => DeserializeFrom(path, GreedyMutable); - public static T DeserializeFrom(byte[] data) where T : class, IFlatBufferSerializable => DeserializeFrom(data, GreedyMutable); public static T DeserializeFrom(Memory data) where T : class, IFlatBufferSerializable => DeserializeFrom(data, GreedyMutable); public static T DeserializeFrom(string path, FlatBufferDeserializationOption opt) @@ -29,16 +28,6 @@ public static T DeserializeFrom(string path, FlatBufferDeserializationOption return DeserializeFrom(data, opt); } - public static T DeserializeFrom(byte[] data, FlatBufferDeserializationOption opt) - where T : class, IFlatBufferSerializable => opt switch - { - Lazy => T.LazySerializer.Parse(data), - Progressive => T.ProgressiveSerializer.Parse(data), - Greedy => T.GreedySerializer.Parse(data), - GreedyMutable => T.GreedyMutableSerializer.Parse(data), - _ => throw new ArgumentOutOfRangeException(nameof(opt), opt, null), - }; - public static T DeserializeFrom(Memory data, FlatBufferDeserializationOption opt) where T : class, IFlatBufferSerializable => opt switch { diff --git a/FlatBuffers/pkNX.Structures.FlatBuffers/Math/PackedVec3f.cs b/FlatBuffers/pkNX.Structures.FlatBuffers/Math/PackedVec3f.cs index 67aa4398..a5bb50c2 100644 --- a/FlatBuffers/pkNX.Structures.FlatBuffers/Math/PackedVec3f.cs +++ b/FlatBuffers/pkNX.Structures.FlatBuffers/Math/PackedVec3f.cs @@ -26,6 +26,7 @@ public PackedVec3f(float x = 0, float y = 0, float z = 0) public readonly float Dot(PackedVec3f other) => (X * other.X) + (Y * other.Y) + (Z * other.Z); public readonly PackedVec3f Cross(PackedVec3f other) => new((Y * other.Z) - (Z * other.Y), (Z * other.X) - (X * other.Z), (X * other.Y) - (Y * other.X)); public readonly float DistanceTo(PackedVec3f other) => (this - other).Magnitude(); + public readonly float DistanceTo(float x, float z) => new PackedVec3f(x, 0, z).DistanceTo(new PackedVec3f(X, 0, Z)); public readonly float DistanceToSqr(PackedVec3f other) => (this - other).MagnitudeSqr(); public readonly PackedVec3f Lerp(PackedVec3f other, float t) => this + ((other - this) * t); @@ -38,6 +39,7 @@ public PackedVec3f(float x = 0, float y = 0, float z = 0) public readonly override string ToString() => $"V3f({X}, {Y}, {Z})"; public readonly string ToTriple() => $"({X}, {Y}, {Z})"; + public readonly string ToShortString() => $"({X:F2}, {Y:F2}, {Z:F2})"; public readonly bool Equals(PackedVec3f other) { diff --git a/FlatBuffers/pkNX.Structures.FlatBuffers/Schemas/Geometry/SRT.fbs b/FlatBuffers/pkNX.Structures.FlatBuffers/Schemas/Geometry/SRT.fbs new file mode 100644 index 00000000..55d79361 --- /dev/null +++ b/FlatBuffers/pkNX.Structures.FlatBuffers/Schemas/Geometry/SRT.fbs @@ -0,0 +1,9 @@ +include "../Math/math.fbs"; + +namespace pkNX.Structures.FlatBuffers; + +table SRT { + Scale:PackedVec3f (required); + Rotation:PackedVec3f (required); + Translation:PackedVec3f (required); +} diff --git a/FlatBuffers/pkNX.Structures.FlatBuffers/Util/FlatDumper.cs b/FlatBuffers/pkNX.Structures.FlatBuffers/Util/FlatDumper.cs index c8435aff..7a414359 100644 --- a/FlatBuffers/pkNX.Structures.FlatBuffers/Util/FlatDumper.cs +++ b/FlatBuffers/pkNX.Structures.FlatBuffers/Util/FlatDumper.cs @@ -10,7 +10,7 @@ public static class FlatDumper return GetTable(data, sel); } - public static string GetTable(byte[] data, Func> sel) where T1 : class, IFlatBufferSerializable where T2 : notnull + public static string GetTable(Memory data, Func> sel) where T1 : class, IFlatBufferSerializable where T2 : notnull { var obj = FlatBufferConverter.DeserializeFrom(data); var table = sel(obj); diff --git a/pkNX.Containers/FileMitm.cs b/pkNX.Containers/FileMitm.cs index 4c27c888..7e455a06 100644 --- a/pkNX.Containers/FileMitm.cs +++ b/pkNX.Containers/FileMitm.cs @@ -22,7 +22,7 @@ public static byte[] ReadAllBytes(string path) return File.ReadAllBytes(path); } - public static void WriteAllBytes(string path, byte[] data) + public static void WriteAllBytes(string path, ReadOnlySpan data) { if (string.IsNullOrWhiteSpace(path)) throw new FileNotFoundException("Invalid filename."); diff --git a/pkNX.Containers/FolderContainer.cs b/pkNX.Containers/FolderContainer.cs index 91848ee8..a623f632 100644 --- a/pkNX.Containers/FolderContainer.cs +++ b/pkNX.Containers/FolderContainer.cs @@ -51,14 +51,22 @@ public void AddFiles(IEnumerable files) AddFile(f); } - public byte[]? GetFileData(string file) + public bool TryGetFileData(string file, out ReadOnlySpan data) { + data = []; var index = GetFileIndex(file); if (index < 0) - return null; + return false; string path = Paths[index]; - var data = Data[index] ??= FileMitm.ReadAllBytes(path); - return (byte[])data.Clone(); + data = Data[index] ??= FileMitm.ReadAllBytes(path); + return true; + } + + public ReadOnlySpan GetFileData(string file) + { + if (TryGetFileData(file, out var data)) + return data; + throw new ArgumentException($"File not found: {file}", nameof(file)); } public byte[] GetFileData(int index) diff --git a/pkNX.Containers/Mini/MiniUtil.cs b/pkNX.Containers/Mini/MiniUtil.cs index 83bc40b3..a84119b3 100644 --- a/pkNX.Containers/Mini/MiniUtil.cs +++ b/pkNX.Containers/Mini/MiniUtil.cs @@ -153,3 +153,114 @@ public static string GetIsMini(byte[] data) catch { return string.Empty; } } } + +/// +/// Utility class for writing BinLinker files. +/// +public static class BinLinkerWriter +{ + public static byte[] Compress(T[] arr, ReadOnlySpan ident, Func sel, int padTo = 0) + { + // Convert th + var result = new byte[arr.Length][]; + for (int i = 0; i < arr.Length; i++) + result[i] = sel(arr[i]); + return Write16(result, ident, padTo); + } + + /// + /// Writes to a new file with the given identifier. + /// + /// Data to write + /// Identifier for the file + /// Padding size for each file + /// Writeable byte array + public static byte[] Write32(byte[][] data, ReadOnlySpan identifier, int padTo = 4) + { + using var ms = new MemoryStream(4096); + using var bw = new BinaryWriter(ms); + + bw.Write(identifier[..2]); + bw.Write((ushort)data.Length); + const int start = 0; + + // Preallocate the offset map + int count = data.Length; + int dataOffset = 4 + ((count + 1) * sizeof(uint)); + for (int i = 0; i < count; i++) + bw.Write((uint)0); + bw.Write((uint)0); + + // Write each file, then update the offset map + for (int i = 0; i < count; i++) + { + // Write File Offset + var fileOffset = bw.BaseStream.Length - start; + bw.Seek(start + 4 + (i * sizeof(uint)), SeekOrigin.Begin); + bw.Write((uint)fileOffset); + // Write File to Stream + bw.Seek(0, SeekOrigin.End); + bw.Write(data[i]); + if (padTo != 0) + { + while ((ms.Position - start) % padTo != 0) + bw.Write((byte)0); + } + } + + // Cap the File + { + var fileOffset = bw.BaseStream.Length - start; + bw.Seek(start + 4 + (count * sizeof(uint)), SeekOrigin.Begin); + bw.Write((uint)fileOffset); + } + + // Return the byte array + return ms.ToArray(); + } + + /// + public static byte[] Write16(byte[][] data, ReadOnlySpan identifier, int padTo = 2) + { + using var ms = new MemoryStream(4096); + using var bw = new BinaryWriter(ms); + const int start = 0; + + bw.Write(identifier[..2]); + bw.Write((ushort)data.Length); + + // Preallocate the offset map + int count = data.Length; + int dataOffset = 4 + ((count + 1) * sizeof(ushort)); + for (int i = 0; i < count; i++) + bw.Write((ushort)0); + bw.Write((ushort)0); + + // Write each file, then update the offset map + for (int i = 0; i < count; i++) + { + // Write File Offset + var fileOffset = bw.BaseStream.Length - start; + bw.Seek(start + 4 + (i * sizeof(ushort)), SeekOrigin.Begin); + bw.Write((ushort)fileOffset); + // Write File to Stream + bw.Seek(0, SeekOrigin.End); + bw.Write(data[i]); + if (padTo != 0) + { + while ((ms.Position - start) % padTo != 0) + bw.Write((byte)0); + } + } + + // Cap the File + { + var fileOffset = bw.BaseStream.Length - start; + bw.Seek(start + 4 + (count * sizeof(ushort)), SeekOrigin.Begin); + bw.Write((ushort)fileOffset); + } + + // Return the byte array + return ms.ToArray(); + } +} diff --git a/pkNX.Containers/Misc/AHTB.cs b/pkNX.Containers/Misc/AHTB.cs index ce495cc5..035bd23f 100644 --- a/pkNX.Containers/Misc/AHTB.cs +++ b/pkNX.Containers/Misc/AHTB.cs @@ -1,9 +1,10 @@ -using pkNX.Containers.VFS; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using pkNX.Containers.VFS; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Containers; @@ -14,18 +15,37 @@ namespace pkNX.Containers; [Serializable] public class AHTB : IBinarySerializable { - public AHTBEntry[] Entries { get; private set; } = null!; + /// + /// Indexed list of entries in this AHTB. + /// + public List Entries { get; } = []; + public const uint Magic = 0x42544841; // AHTB - public int Count => Entries.Length; + public int Count => Entries.Count; - public static bool IsAHTB(byte[] data) => BitConverter.ToUInt32(data, 0) == Magic; + /// + /// Determines whether the specified data begins with the predefined magic number. + /// + /// A read-only span of bytes to check. + /// if the first four bytes of match the magic number; otherwise, . + public static bool IsAHTB(ReadOnlySpan data) => ReadUInt32LittleEndian(data) == Magic; - public AHTB(byte[] table) + public AHTB(ReadOnlySpan table) { - using var ms = new MemoryStream(table); - using var br = new BinaryReader(ms); - Read(br); + var magic = ReadUInt32LittleEndian(table); + Debug.Assert(magic == Magic); + + var count = ReadInt32LittleEndian(table.Slice(4, 4)); + Entries.EnsureCapacity(count); + + int offset = 8; + for (int i = 0; i < count; i++) + { + var span = table[offset..]; + Entries.Add(AHTBEntry.Read(span, out var used)); + offset += used; + } } public AHTB(Stream table) @@ -36,43 +56,41 @@ public AHTB(Stream table) public AHTB(Dictionary source) { - Entries = new AHTBEntry[source.Count]; - int i = 0; + Entries.EnsureCapacity(source.Count); foreach (var entry in source) - { - Entries[i] = new AHTBEntry(entry.Key, (ushort)entry.Value.Length, entry.Value); - ++i; - } + Entries.Add(new AHTBEntry(entry.Key, entry.Value)); } public void Read(BinaryReader br) { var magic = br.ReadUInt32(); Debug.Assert(magic == Magic); - var count = br.ReadUInt32(); - Entries = new AHTBEntry[count]; + var count = br.ReadInt32(); + Entries.EnsureCapacity(count); + for (int i = 0; i < count; i++) - { - var e = new AHTBEntry(br); - Entries[i] = e; - } + Entries.Add(new AHTBEntry(br)); + } + + public byte[] Write() + { + using var ms = new MemoryStream(); + using var bw = new BinaryWriter(ms); + Write(bw); + return ms.ToArray(); } public void Write(BinaryWriter bw) { - bw.Write((uint)Magic); - bw.Write((uint)Entries.Length); + bw.Write(Magic); + bw.Write(Entries.Count); foreach (var entry in Entries) entry.Write(bw); } - public int GetIndex(ulong hash) - { - return Array.FindIndex(Entries, z => z.Hash == hash); - } - + public int GetIndex(ulong hash) => Entries.FindIndex(z => z.Hash == hash); public int GetIndex(string value) => GetIndex(FnvHash.HashFnv1a_64(value)); public IEnumerable Summary => Entries.Select((z, i) => $"{i:0000}|{z}"); @@ -85,4 +103,48 @@ public int GetIndex(ulong hash) map[entry.Hash] = entry.Name; return map; } + + public Dictionary ToDictionary(ReadOnlySpan resource) + { + var count = Math.Min(resource.Length, Entries.Count); + var map = new Dictionary(count); + for (int i = 0; i < count; i++) + { + var value = resource[i]; + var hash = Entries[i].Hash; + map[hash] = value; + } + return map; + } + + public Dictionary ToIndexedDictionary(ReadOnlySpan value) + { + var map = new Dictionary(); + for (var i = 0; i < value.Length; i++) + map[Entries[i].Name] = (value[i], i); + return map; + } + + public string[] MergeFlat(ReadOnlySpan lines) + { + var detailed = new string[Count]; + for (int i = 0; i < lines.Length; i++) + { + var entry = Entries[i]; + var hash = entry.Hash; + var name = entry.Name; + var line = lines[i]; + detailed[i] = $"{i:000}\t{hash:X16}\t{name}\t{line}"; + } + return detailed; + } + + public string GetString(ulong hash, IReadOnlyList text, string fallback = "NO TEXT FOUND") + { + var entries = Entries; + var index = entries.FindIndex(z => z.Hash == hash); + if (index == -1) + return fallback; + return text[index]; + } } diff --git a/pkNX.Containers/Misc/AHTBEntry.cs b/pkNX.Containers/Misc/AHTBEntry.cs index cf7d6e12..2d83a2ca 100644 --- a/pkNX.Containers/Misc/AHTBEntry.cs +++ b/pkNX.Containers/Misc/AHTBEntry.cs @@ -1,26 +1,56 @@ +using System; using System.IO; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Containers; -public class AHTBEntry(ulong hash, ushort namelen, string name) +/// +/// An entry in an AHTB. +/// +public sealed record AHTBEntry { - public ulong Hash = hash; - public ushort NameLength = namelen; - public string Name = name; + public ulong Hash { get; set; } // fnv1a_64 hash of Name + public string Name { get; set; } // u16 length + utf8 bytes + \0 - public AHTBEntry(BinaryReader br) : this(br.ReadUInt64(), br.ReadUInt16(), br.ReadStringBytesUntil(0)) + public static AHTBEntry Read(ReadOnlySpan data, out int used) { + var Hash = ReadUInt64LittleEndian(data[..8]); + var length = ReadUInt16LittleEndian(data.Slice(8, 2)); + var Name = System.Text.Encoding.UTF8.GetString(data.Slice(10, length - 1)); + used = 10 + length; + return new AHTBEntry(Hash, Name); + } + + public AHTBEntry(BinaryReader br) + { + Hash = br.ReadUInt64(); + var length = br.ReadUInt16(); + Span nameBytes = stackalloc byte[length]; + _ = br.Read(nameBytes); + Name = System.Text.Encoding.UTF8.GetString(nameBytes[..^1]); //Debug.Assert(FnvHash.HashFnv1a_64(Name) == Hash); //Debug.Assert(Name.Length + 1 == NameLength); // Always null terminated } + public AHTBEntry(ulong hash, string name) + { + Hash = hash; + Name = name; + //Debug.Assert(FnvHash.HashFnv1a_64(Name) == Hash); + } + public void Write(BinaryWriter bw) { bw.Write((ulong)Hash); - bw.Write((ushort)(Name.Length + 1)); - bw.Write(Name); + var data = System.Text.Encoding.UTF8.GetBytes(Name); + bw.Write((ushort)(data.Length + 1)); // +1 for null terminator + bw.Write(data); bw.Write((byte)0); // \0 terminator } + public static ulong GetHash(ReadOnlySpan name) => FnvHash.HashFnv1a_64(name); + public ulong Update(string name) => Hash = GetHash(Name = name); + public ulong Update() => Hash = GetHash(Name); + public override string ToString() => $"0x{Hash:X16}|{Name}"; } diff --git a/pkNX.Containers/Misc/BinaryRWExtensions.cs b/pkNX.Containers/Misc/BinaryRWExtensions.cs deleted file mode 100644 index 5d8dd215..00000000 --- a/pkNX.Containers/Misc/BinaryRWExtensions.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Diagnostics; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; - -namespace pkNX.Containers; - -public static class BinaryRWExtensions -{ - public static T ReadStruct(this BinaryReader br) where T : struct - { - var bytes = br.ReadBytes(Marshal.SizeOf()); - return bytes.ToStructure(); - } - - public static T[] ReadStructArray(this BinaryReader br, uint count) where T : struct - { - Debug.Assert(count < 1000); // pls no - var arr = new T[count]; - for (int i = 0; i < arr.Length; i++) - arr[i] = br.ReadStruct(); - return arr; - } - - public static string ReadNXString(this BinaryReader br) - { - var length = br.ReadUInt16(); - var bytes = br.ReadBytes(length); - var str = Encoding.ASCII.GetString(bytes); - br.ReadByte(); // \0 - if (br.BaseStream.Position % 2 != 0) - br.ReadByte(); // fix align - return str; - } - - public static string ReadStringBytesUntil(this BinaryReader br, byte end = 0) - { - StringBuilder str = new(); - byte b; - while ((b = br.ReadByte()) != end) - str.Append((char)b); - return str.ToString(); - } -} diff --git a/pkNX.Containers/Misc/GFPack.cs b/pkNX.Containers/Misc/GFPack.cs index 605d2985..ab7a172d 100644 --- a/pkNX.Containers/Misc/GFPack.cs +++ b/pkNX.Containers/Misc/GFPack.cs @@ -39,6 +39,13 @@ public GFPack(byte[] data) ReadPack(br); } + public GFPack(ReadOnlySpan data) + { + using var ms = new MemoryStream(data.ToArray()); + using var br = new BinaryReader(ms); + ReadPack(br); + } + public GFPack(BinaryReader br) => ReadPack(br); #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. @@ -221,37 +228,31 @@ public byte[] Write() return ms.ToArray(); } - private static byte[] Decompress(byte[] encryptedData, int decryptedLength, CompressionType type) + private static byte[] Decompress(byte[] encryptedData, int decryptedLength, CompressionType type) => type switch { - return type switch - { - CompressionType.None => encryptedData, - CompressionType.Zlib => throw new NotSupportedException(nameof(CompressionType.Zlib)), // not implemented - CompressionType.Lz4 => LZ4.Decode(encryptedData, decryptedLength), - CompressionType.OodleKraken => Oodle.Decompress(encryptedData, decryptedLength)!, - CompressionType.OodleLeviathan => Oodle.Decompress(encryptedData, decryptedLength)!, - CompressionType.OodleMermaid => Oodle.Decompress(encryptedData, decryptedLength)!, - CompressionType.OodleSelkie => Oodle.Decompress(encryptedData, decryptedLength)!, - CompressionType.OodleHydra => Oodle.Decompress(encryptedData, decryptedLength)!, - _ => throw new ArgumentOutOfRangeException(nameof(type)), - }; - } + CompressionType.None => encryptedData, + CompressionType.Zlib => Zlib.Decompress(encryptedData, decryptedLength), + CompressionType.Lz4 => LZ4.Decode(encryptedData, decryptedLength), + CompressionType.OodleKraken => Oodle.Decompress(encryptedData, decryptedLength)!, + CompressionType.OodleLeviathan => Oodle.Decompress(encryptedData, decryptedLength)!, + CompressionType.OodleMermaid => Oodle.Decompress(encryptedData, decryptedLength)!, + CompressionType.OodleSelkie => Oodle.Decompress(encryptedData, decryptedLength)!, + CompressionType.OodleHydra => Oodle.Decompress(encryptedData, decryptedLength)!, + _ => throw new ArgumentOutOfRangeException(nameof(type)), + }; - private static byte[] Compress(byte[] decryptedData, CompressionType type) + private static byte[] Compress(byte[] decryptedData, CompressionType type) => type switch { - return type switch - { - CompressionType.None => decryptedData, - CompressionType.Zlib => throw new NotSupportedException(nameof(CompressionType.Zlib)), // not implemented - CompressionType.Lz4 => LZ4.Encode(decryptedData), - CompressionType.OodleKraken => Oodle.Compress(decryptedData, out _, OodleFormat.Kraken).ToArray(), - CompressionType.OodleLeviathan => Oodle.Compress(decryptedData, out _, OodleFormat.Leviathan).ToArray(), - CompressionType.OodleMermaid => Oodle.Compress(decryptedData, out _, OodleFormat.Mermaid).ToArray(), - CompressionType.OodleSelkie => Oodle.Compress(decryptedData, out _, OodleFormat.Selkie).ToArray(), - CompressionType.OodleHydra => Oodle.Compress(decryptedData, out _, OodleFormat.Hydra).ToArray(), - _ => throw new ArgumentOutOfRangeException(nameof(type)), - }; - } + CompressionType.None => decryptedData, + CompressionType.Zlib => Zlib.Compress(decryptedData), + CompressionType.Lz4 => LZ4.Encode(decryptedData), + CompressionType.OodleKraken => Oodle.Compress(decryptedData, out _, OodleFormat.Kraken).ToArray(), + CompressionType.OodleLeviathan => Oodle.Compress(decryptedData, out _, OodleFormat.Leviathan).ToArray(), + CompressionType.OodleMermaid => Oodle.Compress(decryptedData, out _, OodleFormat.Mermaid).ToArray(), + CompressionType.OodleSelkie => Oodle.Compress(decryptedData, out _, OodleFormat.Selkie).ToArray(), + CompressionType.OodleHydra => Oodle.Compress(decryptedData, out _, OodleFormat.Hydra).ToArray(), + _ => throw new ArgumentOutOfRangeException(nameof(type)), + }; public void CancelEdits() { @@ -425,21 +426,21 @@ public class FileHashIndex public bool IsMatch(string fileName) => FnvHash.HashFnv1a_64(fileName) == HashFnv1aPathFileName; } -[StructLayout(LayoutKind.Sequential)] +[StructLayout(LayoutKind.Explicit)] public class FileData { public const int SIZE = 0x18; - public ushort Level = 9; // quality? - public CompressionType Type; - public int SizeDecompressed; - public int SizeCompressed; - public int Padding = 0xCC; - public int OffsetPacked; - public uint unused; + [FieldOffset(0x00)] public ushort Level = 9; // quality? + [FieldOffset(0x02)] public CompressionType Type; + [FieldOffset(0x04)] public int SizeDecompressed; + [FieldOffset(0x08)] public int SizeCompressed; + [FieldOffset(0x0C)] public int Padding = 0xCC; + [FieldOffset(0x10)] public int OffsetPacked; + [FieldOffset(0x14)] public uint unused; } -public enum CompressionType : ushort +public enum CompressionType : byte { None = 0, Zlib = 1, diff --git a/pkNX.Containers/Misc/Oodle.cs b/pkNX.Containers/Misc/Oodle.cs index f8a29ab9..c9ec36af 100644 --- a/pkNX.Containers/Misc/Oodle.cs +++ b/pkNX.Containers/Misc/Oodle.cs @@ -30,33 +30,66 @@ public static class Oodle /// /// Oodle64 Compression Method /// - [DllImport(OodleLibraryPath)] + [DllImport(OodleLibraryPath, CallingConvention = CallingConvention.Cdecl)] private static extern long OodleLZ_Compress(OodleFormat format, ref byte buffer, long bufferSize, ref byte result, OodleCompressionLevel level, long opts = 0, long context = 0, long unused = 0, long scratch = 0, long scratch_size = 0); /// - /// Decompresses a span of Oodle Compressed bytes (Requires Oodle DLL) + /// Decompresses compressed data into a newly allocated array. Returns null on failure. /// /// Input Compressed Data /// Decompressed Size /// Resulting Array if success, otherwise null. public static byte[]? Decompress(ReadOnlySpan input, long decompressedLength) { - var result = new byte[decompressedLength]; - return Decompress(input, result); - } + if (decompressedLength is < 0 or > int.MaxValue) + throw new ArgumentOutOfRangeException(nameof(decompressedLength)); + if (decompressedLength == 0) + return []; - private static byte[]? Decompress(ReadOnlySpan input, byte[] result) - { - var dest = result.AsSpan(); - long decodedSize = OodleLZ_Decompress(ref MemoryMarshal.GetReference(input), input.Length, ref MemoryMarshal.GetReference(dest), result.Length); - if (decodedSize == 0) - return null; // failed - return result; + var result = new byte[(int)decompressedLength]; + return DecompressInternal(input, result) ? result : null; } /// - /// Compresses a span of bytes to Oodle Compressed bytes (Requires Oodle DLL) + /// Try to decompress into a caller-provided destination buffer. + /// + /// Compressed data. + /// Destination buffer (must be large enough). + /// Actual decompressed size on success. + public static bool TryDecompress(ReadOnlySpan input, Span destination, out int bytesWritten) + { + bytesWritten = 0; + + if (destination.Length == 0) + return input.Length == 0; + + if (input.Length == 0) + return false; + + ref byte src = ref MemoryMarshal.GetReference(input); + ref byte dst = ref MemoryMarshal.GetReference(destination); + + long decoded = OodleLZ_Decompress( + ref src, + input.Length, + ref dst, + destination.Length, + OodleFuzzSafe.Yes, + OodleCheckCrc.No, + OodleVerbosity.None, + 0, 0, 0, 0, 0, 0, + OodleThreadPhase.Unthreaded); + + if (decoded <= 0 || decoded > destination.Length) + return false; + + bytesWritten = (int)decoded; + return true; + } + + /// + /// Compresses data and returns a Span over the allocated buffer (aligned length). /// /// Input Decompressed Data /// Actual Compressed Data size @@ -66,31 +99,123 @@ public static class Oodle public static Span Compress(ReadOnlySpan input, out int compressedSize, OodleFormat format = OodleFormat.Kraken, OodleCompressionLevel level = OodleCompressionLevel.Optimal2) { - var maxSize = GetCompressedBufferSizeNeeded(input.Length); - var result = new byte[maxSize].AsSpan(); - return Compress(input, result, out compressedSize, format, level); + if (input.Length == 0) + { + compressedSize = 0; + return Span.Empty; + } + + int maxSize = GetMaxCompressedSize(input.Length); + var buffer = new byte[maxSize]; + var span = buffer.AsSpan(); + return CompressInternal(input, span, out compressedSize, format, level); } - private static Span Compress(ReadOnlySpan input, Span result, out int compressedSize, OodleFormat format, OodleCompressionLevel level) + /// + /// Try to compress into a caller-provided destination buffer. + /// + /// Uncompressed data. + /// Destination buffer (size must be at least GetMaxCompressedSize(input.Length)). + /// Exact compressed byte size (without alignment padding). + /// Format. + /// Compression level. + /// Slice (including alignment padding) on success. + /// True on success. + public static bool TryCompress(ReadOnlySpan input, Span destination, out int compressedSize, + out Span compressedSlice, + OodleFormat format = OodleFormat.Kraken, + OodleCompressionLevel level = OodleCompressionLevel.Optimal2) { - var encodedSize = OodleLZ_Compress(format, ref MemoryMarshal.GetReference(input), input.Length, ref MemoryMarshal.GetReference(result), level); + compressedSize = 0; + compressedSlice = default; - // Oodle's compressed result leaves data after the "compressed length" return index. - // Return an aligned span (ensuring length is a multiple of 4). - // Retaining these unused bytes matches the behavior observed in New Pokémon Snap DRPF files. - compressedSize = (int)encodedSize; - var align = (compressedSize + 3) & ~3; - return result[..align]; + if (input.Length == 0) + { + compressedSlice = destination[..0]; + return true; + } + + if (destination.Length < GetMaxCompressedSize(input.Length)) + return false; + + ref byte src = ref MemoryMarshal.GetReference(input); + ref byte dst = ref MemoryMarshal.GetReference(destination); + + long encoded = OodleLZ_Compress(format, ref src, input.Length, ref dst, level); + if (encoded <= 0 || encoded > destination.Length) + return false; + + compressedSize = (int)encoded; + int aligned = Align4(compressedSize); + if (aligned > destination.Length) + return false; + + compressedSlice = destination[..aligned]; + return true; } + private static bool DecompressInternal(ReadOnlySpan input, Span destination) + { + if (destination.Length == 0) + return input.Length == 0; + + if (input.Length == 0) + return false; + + ref byte src = ref MemoryMarshal.GetReference(input); + ref byte dst = ref MemoryMarshal.GetReference(destination); + + long decoded = OodleLZ_Decompress( + ref src, + input.Length, + ref dst, + destination.Length, + OodleFuzzSafe.Yes, + OodleCheckCrc.No, + OodleVerbosity.None, + 0, 0, 0, 0, 0, 0, + OodleThreadPhase.Unthreaded); + + return decoded > 0 && decoded <= destination.Length; + } + + private static Span CompressInternal(ReadOnlySpan input, Span destination, out int compressedSize, + OodleFormat format, OodleCompressionLevel level) + { + if (input.Length == 0) + { + compressedSize = 0; + return destination[..0]; + } + + ref byte src = ref MemoryMarshal.GetReference(input); + ref byte dst = ref MemoryMarshal.GetReference(destination); + + long encoded = OodleLZ_Compress(format, ref src, input.Length, ref dst, level); + if (encoded <= 0) + { + compressedSize = 0; + return Span.Empty; + } + + compressedSize = (int)encoded; + int aligned = Align4(compressedSize); + return destination[..aligned]; + } + + private static int Align4(int value) => (value + 3) & ~3; + /// /// Gets the dimension required to compress the data. /// - /// - /// - private static long GetCompressedBufferSizeNeeded(long inputSize) + public static int GetMaxCompressedSize(int inputSize) { - return inputSize + (274 * ((inputSize + 0x3FFFF) / 0x40000)); + if (inputSize < 0) + throw new ArgumentOutOfRangeException(nameof(inputSize)); + long val = inputSize + (274L * ((inputSize + 0x3FFFFL) / 0x40000L)); + if (val > int.MaxValue) + throw new ArgumentOutOfRangeException(nameof(inputSize), "Computed size exceeds supported range."); + return (int)val; } } diff --git a/pkNX.Containers/Misc/StructConverter.cs b/pkNX.Containers/Misc/StructConverter.cs index e5059ea5..54bdfa6e 100644 --- a/pkNX.Containers/Misc/StructConverter.cs +++ b/pkNX.Containers/Misc/StructConverter.cs @@ -5,13 +5,6 @@ namespace pkNX.Containers; internal static class StructConverter { - public static T ToStructure(this byte[] bytes) where T : struct - { - var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - try { return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T))!; } - finally { handle.Free(); } - } - public static T ToClass(this byte[] bytes) where T : class { var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); @@ -30,16 +23,4 @@ internal static class StructConverter Marshal.FreeHGlobal(ptr); return arr; } - - public static byte[] ToBytes(this T obj) where T : struct - { - int size = Marshal.SizeOf(obj); - byte[] arr = new byte[size]; - - IntPtr ptr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(obj, ptr, true); - Marshal.Copy(ptr, arr, 0, size); - Marshal.FreeHGlobal(ptr); - return arr; - } } diff --git a/pkNX.Containers/Misc/Zlib.cs b/pkNX.Containers/Misc/Zlib.cs new file mode 100644 index 00000000..29207d09 --- /dev/null +++ b/pkNX.Containers/Misc/Zlib.cs @@ -0,0 +1,109 @@ +using System; +using System.IO; +using System.IO.Compression; + +namespace pkNX.Containers; + +public static class Zlib +{ + // Helper: Zlib Decompression + public static byte[] Decompress(ReadOnlySpan compressed, int expectedLength) + { + if (expectedLength == 0) + return []; + + // Copy span to array for MemoryStream + using var ms = new MemoryStream(compressed.ToArray(), writable: false); + using var zs = new ZLibStream(ms, CompressionMode.Decompress, leaveOpen: true); + var result = new byte[expectedLength]; + int offset = 0; + while (offset < expectedLength) + { + int read = zs.Read(result, offset, expectedLength - offset); + if (read == 0) + break; // stream ended early + offset += read; + } + if (offset != expectedLength) + { + // If actual output shorter than expected, trim (avoid throwing to stay resilient) + if (offset == 0) + throw new InvalidDataException("Zlib decompression produced no data."); + if (offset < expectedLength) + Array.Resize(ref result, offset); + } + return result; + } + + // Overload: Decompress into a caller-provided destination span, return bytes written + public static int Decompress(ReadOnlySpan compressed, Span destination) + { + if (compressed.Length == 0) + return 0; + + using var ms = new MemoryStream(compressed.ToArray(), writable: false); + using var zs = new ZLibStream(ms, CompressionMode.Decompress, leaveOpen: true); + int total = 0; + while (total < destination.Length) + { + int read = zs.Read(destination[total..]); + if (read == 0) + break; + total += read; + } + + // If there is more data to decompress but destination is full, signal buffer too small. + if (total == destination.Length) + { + Span probe = stackalloc byte[1]; + int more = zs.Read(probe); + if (more > 0) + throw new ArgumentException("Destination buffer too small for decompressed data.", nameof(destination)); + } + + return total; + } + + // Helper: Zlib Compression + + public static byte[] Compress(ReadOnlySpan data) + { + if (data.Length == 0) + return []; + using var ms = new MemoryStream(); + using (var zs = new ZLibStream(ms, CompressionLevel.SmallestSize, leaveOpen: true)) + zs.Write(data); + return ms.ToArray(); + } + + // Overload: Compress into a caller-provided destination span, return bytes written + public static int Compress(ReadOnlySpan data, Span destination, CompressionLevel level = CompressionLevel.SmallestSize) + { + if (data.Length == 0) + return 0; + + using var ms = new MemoryStream(); + using (var zs = new ZLibStream(ms, level, leaveOpen: true)) + { + zs.Write(data); + } + + // Copy resulting compressed bytes into destination + int written = (int)ms.Length; + if (written > destination.Length) + throw new ArgumentException("Destination buffer too small for compressed data.", nameof(destination)); + + if (ms.TryGetBuffer(out var segment)) + { + segment.AsSpan(0, written).CopyTo(destination); + } + else + { + // Fallback if underlying buffer isn't directly accessible + var arr = ms.ToArray(); + arr.AsSpan().CopyTo(destination); + } + + return written; + } +} diff --git a/pkNX.Containers/NX/NSO.cs b/pkNX.Containers/NX/NSO.cs index a93c7d4b..762bb4c0 100644 --- a/pkNX.Containers/NX/NSO.cs +++ b/pkNX.Containers/NX/NSO.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using System.Linq; using System.Security.Cryptography; @@ -61,11 +62,7 @@ public static byte[] GetDecompressedSegment(BinaryReader br, SegmentHeader h, in return LZ4.Decode(data, h.DecompressedSize); } - public static byte[] Hash(byte[] data) - { - using var method = SHA256.Create(); - return method.ComputeHash(data); - } + public static byte[] Hash(ReadOnlySpan data) => SHA256.HashData(data); private void Decompress() { diff --git a/pkNX.Containers/Trinity/TrinityUtil.cs b/pkNX.Containers/Trinity/TrinityUtil.cs new file mode 100644 index 00000000..a488ce83 --- /dev/null +++ b/pkNX.Containers/Trinity/TrinityUtil.cs @@ -0,0 +1,25 @@ +using System; +using static System.Buffers.Binary.BinaryPrimitives; + +namespace pkNX.Containers; + +public static class TrinityUtil +{ + public static string GuessExtension(ReadOnlySpan data) + { + const string defaultExtension = "bin"; + if (data.Length < 8) + return defaultExtension; + var u32 = ReadUInt32LittleEndian(data); + if (ReadUInt32LittleEndian(data[4..8]) == 0x53424642) + return "bfbs"; + return u32 switch + { + AHTB.Magic => "ahtb", + 0x43524153 => "sarc", + 0x58544E42 => "bntx", + 0x63726173 => "sarc", + _ => defaultExtension, + }; + } +} diff --git a/pkNX.Game/Editors/DataCache.cs b/pkNX.Game/Editors/DataCache.cs index 13bbf7db..92f2d37d 100644 --- a/pkNX.Game/Editors/DataCache.cs +++ b/pkNX.Game/Editors/DataCache.cs @@ -11,7 +11,7 @@ public class DataCache(IList cache) : IDataEditor where T : class { public IFileContainer Data { protected get; set; } = null!; - public Func Create { private get; set; } = null!; + public Func, T> Create { private get; set; } = null!; public Func Write { protected get; set; } = null!; public DataCache(IFileContainer f) : this(new T[f.Count]) => Data = f; @@ -90,10 +90,10 @@ public class TableCache where TTable : class, IFlatBufferSerializable where TData : class { - public IFileContainer File { get; private set; } - public TTable Root { get; private set; } - public IList Table { get; private set; } - public DataCache Cache { get; private set; } + public IFileContainer File { get; } + public TTable Root { get; } + public IList Table { get; } + public DataCache Cache { get; } public TableCache(IFileContainer f, Func> sel) { diff --git a/pkNX.Game/Editors/TMEditorGG.cs b/pkNX.Game/Editors/TMEditorGG.cs index ca903da2..2bd0022c 100644 --- a/pkNX.Game/Editors/TMEditorGG.cs +++ b/pkNX.Game/Editors/TMEditorGG.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using pkNX.Containers; using pkNX.Structures; @@ -41,4 +41,4 @@ public void SetMoves(ushort[] finalMoves) public bool Valid => Offset > 0; public byte[] Write() => NSO.Write(); -} \ No newline at end of file +} diff --git a/pkNX.Game/Editors/TypeChartEditor.cs b/pkNX.Game/Editors/TypeChartEditor.cs index 21b6377e..a9d0ec2c 100644 --- a/pkNX.Game/Editors/TypeChartEditor.cs +++ b/pkNX.Game/Editors/TypeChartEditor.cs @@ -4,9 +4,9 @@ namespace pkNX.Game; -public class TypeChartEditor(byte[] data) +public class TypeChartEditor(Memory Raw) { - public byte[] Data = data; + public Span Data => Raw.Span; public int Width => (int)Math.Sqrt(Data.Length); public int Height => (int)Math.Sqrt(Data.Length); @@ -20,18 +20,15 @@ public void Randomize() } } - private static byte GetEffectiveness(int rv) + private static byte GetEffectiveness(int rv) => rv switch { - return rv switch - { - < 2 => (byte)TypeEffectiveness.Immune, // 2% - < 19 => (byte)TypeEffectiveness.NotVery, // 17% - < 36 => (byte)TypeEffectiveness.Super, // 17% - _ => (byte)TypeEffectiveness.Normal, - }; - } + < 2 => (byte)TypeEffectiveness.Immune, // 2% + < 19 => (byte)TypeEffectiveness.NotVery, // 17% + < 36 => (byte)TypeEffectiveness.Super, // 17% + _ => (byte)TypeEffectiveness.Normal, + }; - private static readonly uint[] Colors = + private static ReadOnlySpan Colors => [ 0xFF000000, 0, // unused @@ -42,7 +39,7 @@ private static byte GetEffectiveness(int rv) 0xFF008000, ]; - public static byte[] GetTypeChartImageData(int itemsize, int itemsPerRow, byte[] vals, out int width, out int height) + public static byte[] GetTypeChartImageData(int itemsize, int itemsPerRow, ReadOnlySpan vals, out int width, out int height) { width = itemsize * itemsPerRow; height = itemsize * vals.Length / itemsPerRow; diff --git a/pkNX.Game/File/GameFileMapping.cs b/pkNX.Game/File/GameFileMapping.cs index 53621b5c..64dc86ad 100644 --- a/pkNX.Game/File/GameFileMapping.cs +++ b/pkNX.Game/File/GameFileMapping.cs @@ -66,6 +66,7 @@ internal void SaveAll() SW or SH or SWSH => FilesSWSH, PLA => FilesPLA, SL or VL or SV => FilesSV, + ZA => FilesZA, _ => throw new ArgumentOutOfRangeException(nameof(game), game, null), }; @@ -435,4 +436,16 @@ internal void SaveAll() // new(EncounterTableTrade , SingleFile, "bin", "script_event_data", "field_trade.bin"), // Incorrect? ]; #endregion + #region Gen9a + + /// + /// Scarlet & Violet + /// + private static readonly GameFileReference[] FilesZA = + [ + new(DataTrpfd, SingleFile, "arc", "data.trpfd"), + new(DataTrpfs, SingleFile, "arc", "data.trpfs"), + ]; + + #endregion } diff --git a/pkNX.Game/GameLocation.cs b/pkNX.Game/GameLocation.cs index 79437955..ff6ec339 100644 --- a/pkNX.Game/GameLocation.cs +++ b/pkNX.Game/GameLocation.cs @@ -48,7 +48,7 @@ public static (GameLocation?, GameLoadResult) GetGame(string? dir, GameVersion g if (romfs == null) { - string selectedDir = Path.GetFileName(dir) ?? string.Empty; + string selectedDir = Path.GetFileName(dir); if (selectedDir.StartsWith("rom")) return (null, GameLoadResult.RomfsSelected); @@ -61,8 +61,8 @@ public static (GameLocation?, GameLoadResult) GetGame(string? dir, GameVersion g var result = GameLoadResult.Success; - if (exefs == null) // Add exefs not found result, but don't mark as failure - result |= GameLoadResult.ExefsNotFound; + if (exefs == null) + result = GameLoadResult.ExefsNotFound; return (new GameLocation(romfs, exefs, game), result); } @@ -73,12 +73,6 @@ private static GameVersion GetGameFromPath(string romfs, string? exefs) return GetGameFromCount(files.Length, romfs, exefs); } - private const int FILECOUNT_XY = 271; - private const int FILECOUNT_ORASDEMO = 301; - private const int FILECOUNT_ORAS = 299; - private const int FILECOUNT_SMDEMO = 239; - private const int FILECOUNT_SM = 311; - private const int FILECOUNT_USUM = 333; private const int FILECOUNT_GG = 27818; private const int FILECOUNT_SWSH = 41702; private const int FILECOUNT_SWSH_110 = 41951; // Ver. 1.1.0 (Galarian Slowpoke) @@ -94,82 +88,55 @@ private static GameVersion GetGameFromPath(string romfs, string? exefs) private const int FILECOUNT_SV_130 = 27; // Ver. 1.3.0 (Paradox x2 Bad Egg fix) private const int FILECOUNT_SV_201 = 28; // Ver. 2.0.1 (Teal Mask) 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 static GameVersion GetGameFromCount(int fileCount, string romfs, string? exefs) + private static ulong GetTitleID(string? exefs) { - string GetTitleID() => BitConverter.ToUInt64(File.ReadAllBytes(Path.Combine(exefs, "main.npdm")), 0x290).ToString("X16"); - - switch (fileCount) - { - case FILECOUNT_XY: return GameVersion.XY; - case FILECOUNT_ORASDEMO: return GameVersion.ORASDEMO; - case FILECOUNT_ORAS: return GameVersion.ORAS; - case FILECOUNT_SMDEMO: return GameVersion.SMDEMO; - case FILECOUNT_SM: - { - var encdata = Path.Combine(romfs, "a", "0", "8", "2"); - if (File.Exists(encdata) && new FileInfo(encdata).Length != 0) - return GameVersion.SN; - return GameVersion.MN; - } - - case FILECOUNT_USUM: - { - var encdata = Path.Combine(romfs, "a", "0", "8", "2"); - if (File.Exists(encdata) && new FileInfo(encdata).Length != 0) - return GameVersion.US; - return GameVersion.UM; - } - - case FILECOUNT_GG: - { - bool eevee = Directory.Exists(Path.Combine(romfs, "bin", "movies", "EEVEE_GO")); - if (eevee) - return GameVersion.GE; - return GameVersion.GP; - } - - case FILECOUNT_SWSH: - case FILECOUNT_SWSH_110: - case FILECOUNT_SWSH_120: - case FILECOUNT_SWSH_130: - case FILECOUNT_SWSH_132: - { - if (exefs == null) - return GameVersion.SWSH; - - return GetTitleID() switch - { - "0100ABF008968000" => GameVersion.SW, - "01008DB008C2C000" => GameVersion.SH, - _ => GameVersion.SWSH, // can't figure out Title ID, default to SWSH so that wild editor prompts for version selection - }; - } - - case FILECOUNT_LA or FILECOUNT_LA_101 or FILECOUNT_LA_110: - return GameVersion.PLA; - - case FILECOUNT_SV: - case FILECOUNT_SV_101: - case FILECOUNT_SV_120: - case FILECOUNT_SV_130: - case FILECOUNT_SV_201: - case FILECOUNT_SV_300: - { - if (exefs == null) - return GameVersion.SV; - - return GetTitleID() switch - { - // todo sv - "0100ABF008968000" => GameVersion.SL, - "01008DB008C2C000" => GameVersion.VL, - _ => GameVersion.SV, // can't figure out Title ID, default to SWSH so that wild editor prompts for version selection - }; - } - - default: - return GameVersion.Invalid; - } + if (exefs is null) + return 0; + var main = File.ReadAllBytes(Path.Combine(exefs, "main.npdm")); + var slice = main.AsSpan(0x290, 8); + return System.Buffers.Binary.BinaryPrimitives.ReadUInt64LittleEndian(slice); } + + private static GameVersion GetGameFromCount(int fileCount, string romfs, string? exefs) => fileCount switch + { + FILECOUNT_GG + => DetectGen7b(romfs), + + FILECOUNT_SWSH or FILECOUNT_SWSH_110 or FILECOUNT_SWSH_120 or FILECOUNT_SWSH_130 or FILECOUNT_SWSH_132 + => DetectGen8(exefs), + + FILECOUNT_LA or FILECOUNT_LA_101 or FILECOUNT_LA_110 + => GameVersion.PLA, + + 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 + => GameVersion.ZA, + + _ => GameVersion.Invalid + }; + + private static GameVersion DetectGen7b(string romfs) + { + bool eevee = Directory.Exists(Path.Combine(romfs, "bin", "movies", "EEVEE_GO")); + return eevee ? GameVersion.GE : GameVersion.GP; + } + + private static GameVersion DetectGen8(string? exefs) => GetTitleID(exefs) switch + { + 0x0100ABF008968000 => GameVersion.SW, + 0x01008DB008C2C000 => GameVersion.SH, + _ => GameVersion.SWSH, // can't figure out Title ID, default to SW/SH + }; + + private static GameVersion DetectGen9(string? exefs) => GetTitleID(exefs) switch + { + 0x0100ABF008968000 => GameVersion.SL, + 0x01008DB008C2C000 => GameVersion.VL, + _ => GameVersion.SV, // can't figure out Title ID, default to SV + }; } diff --git a/pkNX.Game/GameManager.cs b/pkNX.Game/GameManager.cs index 09e6684f..4541360e 100644 --- a/pkNX.Game/GameManager.cs +++ b/pkNX.Game/GameManager.cs @@ -113,6 +113,7 @@ public FolderContainer GetFilteredFolder(GameFile type, Func? filt SW or SH or SWSH => new GameManagerSWSH(loc, language), PLA => new GameManagerPLA(loc, language), SL or VL or SV => new GameManagerSV(loc, language), + ZA => new GameManager9a(loc, language), _ => throw new ArgumentException(nameof(loc.Game)), }; } diff --git a/pkNX.Game/GameManager9a.cs b/pkNX.Game/GameManager9a.cs new file mode 100644 index 00000000..4d4d4217 --- /dev/null +++ b/pkNX.Game/GameManager9a.cs @@ -0,0 +1,102 @@ +using System; +using System.IO; +using pkNX.Containers; +using pkNX.Structures.FlatBuffers.SV.Trinity; + +namespace pkNX.Game; + +public sealed class GameManager9a : GameManager, IFileInternal, IDisposable +{ + private readonly TrinityFileSystemManager Manager; + private string PathNPDM => Path.Combine(PathExeFS, "main.npdm"); + private string TitleID => BitConverter.ToUInt64(File.ReadAllBytes(PathNPDM), 0x290).ToString("X16"); + + public GameManager9a(GameLocation rom, int language) : base(rom, language) + { + // TODO: Use GameFileMapping? + + // Open the trpfs + var pathTrpfs = Path.Combine(PathRomFS, "arc/data.trpfs"); + var pathTrpfd = Path.Combine(PathRomFS, "arc/data.trpfd"); + Manager = new TrinityFileSystemManager(pathTrpfs, pathTrpfd); + } + + public bool HasFile(string path) => Manager.HasFile(path); + public bool HasFile(ulong hash) => Manager.HasFile(hash); + public byte[] GetPackedFile(string path) => Manager.GetPackedFile(path); + public byte[] GetPackedFile(ulong hash) => Manager.GetPackedFile(hash); + + /// + /// Generally useful game data that can be used by multiple editors. + /// + public GameData Data { get; private set; } = null!; + + protected override void SetMitm() + { + var basePath = Path.GetDirectoryName(ROM.RomFS); + if (basePath is null) + throw new InvalidDataException("Invalid ROMFS path."); + var tid = ROM.ExeFS != null ? TitleID : "0100A3D008C5C000"; // no way to differentiate without exefs, so default to Scarlet + var redirect = Path.Combine(basePath, tid); + FileMitm.SetRedirect(basePath, redirect); + } + + public override void Initialize() + { + base.Initialize(); + + // initialize gametext + //ResetText(); + + // initialize common structures + //var personal = GetFilteredFolder(GameFile.PersonalStats, z => Path.GetFileNameWithoutExtension(z) == "personal_total"); + //var learn = this[GameFile.Learnsets][0]; + //var splitLearn = learn.Split(0x104); + //Learn = new FakeContainer(splitLearn); + + //var move = this[GameFile.MoveStats]; + //((FolderContainer)move).Initialize(); + Data = new GameData + { + //MoveData = new DataCache(move) + //{ + // Create = FlatBufferConverter.DeserializeFrom, + // Write = z => FlatBufferConverter.SerializeFrom((Waza8)z), + //}, + //LevelUpData = new DataCache(Learn) + //{ + // Create = z => new Learnset8(z), + // Write = z => z.Write(), + //}, + + // folders + //PersonalData = new PersonalTable8SWSH(personal[0]), + //EvolutionData = new DataCache(GetFilteredFolder(GameFile.Evolutions)) + //{ + // Create = data => new EvolutionSet8(data), + // Write = evo => evo.Write(), + //}, + }; + } + + public void ResetMoves() => GetFilteredFolder(GameFile.MoveStats); + + public void ResetText() + { + GetFilteredFolder(GameFile.GameText, z => Path.GetExtension(z) == ".dat"); + } + + protected override void Terminate() + { + // Store Personal Data back in the file. Let the container detect if it is modified. + //var personal = this[GameFile.PersonalStats]; + //personal[0] = Data.PersonalData.Table.SelectMany(z => ((IPersonalInfoBin)z).Write()).ToArray(); + //var learn = this[GameFile.Learnsets]; + //learn[0] = Learn.Files.SelectMany(z => z).ToArray(); + } + + public void Dispose() + { + Manager.Dispose(); + } +} diff --git a/pkNX.Game/GameManagerGG.cs b/pkNX.Game/GameManagerGG.cs index face934e..928490c1 100644 --- a/pkNX.Game/GameManagerGG.cs +++ b/pkNX.Game/GameManagerGG.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using System.Linq; using pkNX.Containers; @@ -20,8 +21,7 @@ public class GameManagerGG(GameLocation rom, int language) : GameManager(rom, la protected override void SetMitm() { var basePath = Path.GetDirectoryName(ROM.RomFS); - if (basePath is null) - throw new InvalidDataException("Invalid RomFS path."); + ArgumentNullException.ThrowIfNull(basePath); // unlike SWSH, LGPE has a unique opening movie in romfs to differentiate between versions bool eevee = Directory.Exists(Path.Combine(PathRomFS, "bin", "movies", "EEVEE_GO")); ActualGame = eevee ? GameVersion.GE : GameVersion.GP; @@ -55,12 +55,12 @@ public override void Initialize() PersonalData = new PersonalTable7GG(personal[0]), MegaEvolutionData = new DataCache(GetFilteredFolder(GameFile.MegaEvolutions)) { - Create = MegaEvolutionSet.ReadArray, + Create = z => MegaEvolutionSet.ReadArray(z.Span), Write = MegaEvolutionSet.WriteArray, }, EvolutionData = new DataCache(GetFilteredFolder(GameFile.Evolutions)) { - Create = data => new EvolutionSet7(data), + Create = data => new EvolutionSet7(data.Span), Write = evo => evo.Write(), }, }; diff --git a/pkNX.Game/GameManagerSV.cs b/pkNX.Game/GameManagerSV.cs index 84b1a207..cc71de1d 100644 --- a/pkNX.Game/GameManagerSV.cs +++ b/pkNX.Game/GameManagerSV.cs @@ -5,7 +5,7 @@ namespace pkNX.Game; -public class GameManagerSV : GameManager, IFileInternal, IDisposable +public sealed class GameManagerSV : GameManager, IFileInternal, IDisposable { private readonly TrinityFileSystemManager Manager; private string PathNPDM => Path.Combine(PathExeFS, "main.npdm"); @@ -29,7 +29,7 @@ public GameManagerSV(GameLocation rom, int language) : base(rom, language) /// /// Generally useful game data that can be used by multiple editors. /// - public GameData Data { get; protected set; } = null!; + public GameData Data { get; private set; } = null!; protected override void SetMitm() { diff --git a/pkNX.Game/GameManagerSWSH.cs b/pkNX.Game/GameManagerSWSH.cs index 97cc8dfa..c2d729d6 100644 --- a/pkNX.Game/GameManagerSWSH.cs +++ b/pkNX.Game/GameManagerSWSH.cs @@ -23,8 +23,7 @@ public class GameManagerSWSH(GameLocation rom, int language) : GameManager(rom, protected override void SetMitm() { var basePath = Path.GetDirectoryName(ROM.RomFS); - if (basePath is null) - throw new InvalidDataException("Invalid ROMFS path."); + ArgumentNullException.ThrowIfNull(basePath); var tid = ROM.ExeFS != null ? TitleID : "0100ABF008968000"; // no way to differentiate without exefs, so default to Sword var redirect = Path.Combine(basePath, tid); FileMitm.SetRedirect(basePath, redirect); @@ -49,12 +48,12 @@ public override void Initialize() { MoveData = new DataCache(move) { - Create = bytes => (IMove)FlatBufferConverter.DeserializeFrom(bytes), + Create = FlatBufferConverter.DeserializeFrom, Write = z => ((Waza)z).SerializeFrom(), }, LevelUpData = new DataCache(Learn) { - Create = z => new Learnset8(z), + Create = z => new Learnset8(z.Span), Write = z => z.Write(), }, @@ -62,7 +61,7 @@ public override void Initialize() PersonalData = new PersonalTable8SWSH(personal[0]), EvolutionData = new DataCache(GetFilteredFolder(GameFile.Evolutions)) { - Create = data => new EvolutionSet8(data), + Create = data => new EvolutionSet8(data.Span), Write = evo => evo.Write(), }, }; diff --git a/pkNX.Game/Text/TextManager.cs b/pkNX.Game/Text/TextManager.cs index eb321cac..63efbed1 100644 --- a/pkNX.Game/Text/TextManager.cs +++ b/pkNX.Game/Text/TextManager.cs @@ -15,7 +15,7 @@ public class TextManager(GameVersion game, TextConfig? config = null) public void ClearCache() => Cache.Clear(); - internal string[] GetStrings(byte[] data, bool remap = false) + internal string[] GetStrings(ReadOnlySpan data, bool remap = false) { var txt = new TextFile(data, Config, remap); return txt.Lines; @@ -30,9 +30,9 @@ internal string[] GetStrings(TextName file, IFileContainer textFile, bool remap if (info == null) throw new ArgumentException($"Unknown {nameof(TextName)} provided.", file.ToString()); - byte[] data; + ReadOnlySpan data; if (textFile is FolderContainer c) - data = c.GetFileData(info.FileName) ?? throw new ArgumentException($"File not found: {info.FileName}", nameof(textFile)); + data = c.GetFileData(info.FileName); else data = textFile[info.Index]; diff --git a/pkNX.Game/Text/TextMapping.cs b/pkNX.Game/Text/TextMapping.cs index 7331fc1c..4357b739 100644 --- a/pkNX.Game/Text/TextMapping.cs +++ b/pkNX.Game/Text/TextMapping.cs @@ -18,6 +18,7 @@ public static class TextMapping SW or SH or SWSH => MapSWSH, PLA => MapPLA, SL or VL or SV => MapSV, + ZA => MapZA, _ => throw new System.ArgumentOutOfRangeException($"No text mapping for {game}"), }; @@ -219,4 +220,30 @@ public static class TextMapping new("ribbon.dat", RibbonMark), new("poke_memory_feeling.dat", MemoryFeelings), ]; + + private static readonly TextReference[] MapZA = + [ + new("iteminfo.dat", ItemFlavor), + new("itemname.dat", ItemNames), + new("monsname.dat", SpeciesNames), + new("place_name_indirect.dat", metlist_00000), + new("place_name_spe.dat", metlist_30000), + new("place_name_out.dat", metlist_40000), + new("place_name_per.dat", metlist_60000), + new("seikaku.dat", Natures), + new("tokusei.dat", AbilityNames), + new("tokuseiinfo.dat", AbilityFlavor), + new("trname.dat", TrainerNames), + new("trtype.dat", TrainerClasses), + new("trmsg.dat", TrainerText), + new("typename.dat", TypeNames), + new("wazainfo.dat", MoveFlavor), + new("wazaname.dat", MoveNames), + new("zkn_form.dat", Forms), + new("zkn_type.dat", SpeciesClassifications), + new("zukan_comment_A.dat", PokedexEntry1), + new("zukan_comment_B.dat", PokedexEntry2), + new("ribbon.dat", RibbonMark), + new("poke_memory_feeling.dat", MemoryFeelings), + ]; } diff --git a/pkNX.Randomization/Randomizers/FormRandomizer.cs b/pkNX.Randomization/Randomizers/FormRandomizer.cs index 8d238aef..6902dfab 100644 --- a/pkNX.Randomization/Randomizers/FormRandomizer.cs +++ b/pkNX.Randomization/Randomizers/FormRandomizer.cs @@ -27,10 +27,10 @@ public int GetRandomForm(int species, bool mega, bool fuse, int generation, IPer return (Species)species switch { Pikachu or Slowbro when generation >= 8 => GetValidForm(species, generation, t), - Unown or Deerling or Sawsbuck => 31, // pure random -- todo sv see if this behavior changed + Unown or Deerling or Sawsbuck => 31, // pure random Greninja when !mega => 0, // treat Ash-Greninja as a Mega - Scatterbug or Spewpa or Vivillon => 30, // save file specific -- todo sv see if this behavior changed - Zygarde when generation >= 7 => Util.Random.Next(4), // skip Complete Forme + Scatterbug or Spewpa or Vivillon => 30, // save file specific + Zygarde when generation >= 7 => Util.Random.Next(4), // skip Complete Form Minior => Util.Random.Next(7), // skip Core Forms _ when !mega && Legal.BattleMegas.Contains(species) => 0, diff --git a/pkNX.Randomization/Randomizers/MoveRandomizer.cs b/pkNX.Randomization/Randomizers/MoveRandomizer.cs index d7747611..03955f02 100644 --- a/pkNX.Randomization/Randomizers/MoveRandomizer.cs +++ b/pkNX.Randomization/Randomizers/MoveRandomizer.cs @@ -25,7 +25,7 @@ public MoveRandomizer(GameInfo config, IReadOnlyList moves, IPersonalTabl public override void Execute() => throw new Exception("Shouldn't be called."); - public static readonly int[] FixedDamageMoves = [49, 82]; + public static ReadOnlySpan FixedDamageMoves => [49, 82]; public void Initialize(MovesetRandSettings settings, int[] bannedMoves) { @@ -41,8 +41,6 @@ public void Initialize(MovesetRandSettings settings, int[] bannedMoves) var all = Enumerable.Range(1, Config.MaxMoveID - 1); var moves = all.Except(banned); - if (MoveData[0] is Move8Fake) - moves = moves.Where(z => ((Move8Fake)MoveData[z]).CanUseMove); RandMove = new GenericRandomizer(moves.ToArray()); } diff --git a/pkNX.Randomization/Randomizers/Personal/PersonalRandomizer.cs b/pkNX.Randomization/Randomizers/Personal/PersonalRandomizer.cs index bfd07e74..4f36bd7a 100644 --- a/pkNX.Randomization/Randomizers/Personal/PersonalRandomizer.cs +++ b/pkNX.Randomization/Randomizers/Personal/PersonalRandomizer.cs @@ -380,8 +380,8 @@ private void RandomizeTypeTutors(IMovesInfo_v1 z, int species) t[i] = Rand.Next(100) < Settings.LearnTypeTutorPercent; // Make sure Rayquaza can learn Dragon Ascent. - if (!Game.XY && species == (int)Species.Rayquaza) - t[7] = true; + //if (!Game.XY && species == (int)Species.Rayquaza) + // t[7] = true; z.TypeTutors = t; } diff --git a/pkNX.Structures/CodePattern.cs b/pkNX.Structures/CodePattern.cs index 2e89913d..8b215b5d 100644 --- a/pkNX.Structures/CodePattern.cs +++ b/pkNX.Structures/CodePattern.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; namespace pkNX.Structures; @@ -13,67 +12,12 @@ public static class CodePattern /// Starting offset to look from /// Amount of entries to look through /// Index the pattern occurs at; if not found, returns -1. - public static int IndexOfBytes(byte[] array, byte[] pattern, int startIndex = 0, int length = -1) + public static int IndexOfBytes(ReadOnlySpan array, ReadOnlySpan pattern, int startIndex = 0, int length = -1) { - int len = pattern.Length; - int endIndex = length > 0 - ? startIndex + length - : array.Length - len - startIndex; - - endIndex = Math.Min(array.Length - pattern.Length, endIndex); - - int i = startIndex; - int j = 0; - while (true) - { - if (pattern[j] != array[i + j]) - { - if (++i == endIndex) - return -1; - j = 0; - } - else if (++j == len) - { - return i; - } - } - } - - /// - /// Finds a provided within the supplied . - /// - /// Array to look in - /// Pattern to look for - /// Wildcard byte to be ignored, incrementally as bitflags. - /// Starting offset to look from - /// Amount of entries to look through - /// Index the pattern occurs at; if not found, returns -1. - public static int IndexOfPattern(byte[] array, byte[] pattern, ulong wildCard, int startIndex = 0, int length = -1) - { - Debug.Assert(pattern.Length <= 8*sizeof(ulong)); - - int len = pattern.Length; - int endIndex = length > 0 - ? startIndex + length - : array.Length - len - startIndex; - - endIndex = Math.Min(array.Length - pattern.Length, endIndex); - - int i = startIndex; - int j = 0; - while (true) - { - if (pattern[j] != array[i + j] && ((wildCard >> j) & 1) == 0) - { - if (++i == endIndex) - return -1; - j = 0; - } - else if (++j == len) - { - return i; - } - } + var span = array[startIndex..]; + if (length > 0 && length < span.Length) + span = span[..length]; + return span.IndexOf(pattern) + startIndex; } /// diff --git a/pkNX.Structures/EggMove/EggMoves2.cs b/pkNX.Structures/EggMove/EggMoves2.cs deleted file mode 100644 index 508b5a6b..00000000 --- a/pkNX.Structures/EggMove/EggMoves2.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Linq; - -namespace pkNX.Structures; - -public sealed class EggMoves2 : EggMoves -{ - private EggMoves2(byte[] data) : base(data.Select(i => (int)i).ToArray()) { } - - public static EggMoves[] GetArray(byte[] data, int count) - { - int[] ptrs = new int[count + 1]; - int baseOffset = (data[1] << 8 | data[0]) - (count * 2); - for (int i = 1; i < ptrs.Length; i++) - { - var ofs = (i - 1) * 2; - ptrs[i] = (data[ofs + 1] << 8 | data[ofs]) - baseOffset; - } - - EggMoves[] entries = new EggMoves[count + 1]; - entries[0] = new EggMoves2([]); - for (int i = 1; i < entries.Length; i++) - entries[i] = new EggMoves2(data.Skip(ptrs[i]).TakeWhile(b => b != 0xFF).ToArray()); - - return entries; - } -} diff --git a/pkNX.Structures/EggMove/EggMoves6.cs b/pkNX.Structures/EggMove/EggMoves6.cs deleted file mode 100644 index bd825279..00000000 --- a/pkNX.Structures/EggMove/EggMoves6.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; - -namespace pkNX.Structures; - -public sealed class EggMoves6 : EggMoves -{ - private static readonly EggMoves6 None = new([]); - - private EggMoves6(int[] moves) : base(moves) { } - - private static EggMoves6 Get(byte[] data) - { - if (data.Length < 2 || data.Length % 2 != 0) - return None; - - int count = BitConverter.ToInt16(data, 0); - var moves = new int[count]; - for (int i = 0; i < moves.Length; i++) - moves[i] = BitConverter.ToInt16(data, 2 + (i * 2)); - return new EggMoves6(moves); - } - - public static EggMoves6[] GetArray(byte[][] entries) - { - EggMoves6[] data = new EggMoves6[entries.Length]; - for (int i = 0; i < data.Length; i++) - data[i] = Get(entries[i]); - return data; - } -} diff --git a/pkNX.Structures/Encounter/EncounterStatic.cs b/pkNX.Structures/Encounter/EncounterStatic.cs index 27913301..1b60cadd 100644 --- a/pkNX.Structures/Encounter/EncounterStatic.cs +++ b/pkNX.Structures/Encounter/EncounterStatic.cs @@ -1,11 +1,12 @@ +using System; using System.Linq; namespace pkNX.Structures; -public abstract class EncounterStatic(byte[] data) +public abstract class EncounterStatic(Memory raw) { - protected readonly byte[] Data = data; - public virtual byte[] Write() => (byte[])Data.Clone(); + protected Span Data => raw.Span; + public virtual byte[] Write() => Data.ToArray(); public abstract Species Species { get; set; } public virtual int HeldItem { get; set; } diff --git a/pkNX.Structures/Encounter/Gen6/EncounterGift6AO.cs b/pkNX.Structures/Encounter/Gen6/EncounterGift6AO.cs deleted file mode 100644 index 65fbf951..00000000 --- a/pkNX.Structures/Encounter/Gen6/EncounterGift6AO.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; - -namespace pkNX.Structures; - -public class EncounterGift6AO(byte[] data) : EncounterGift(data) -{ - public const int SIZE = 0x24; - public EncounterGift6AO() : this(new byte[SIZE]) { } - - public override Species Species { get => (Species)BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); } - public int Unk02 { get => BitConverter.ToUInt16(Data, 0x02); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x02); } - public override int Form { get => Data[0x04]; set => Data[0x04] = (byte)value; } - public override int Level { get => Data[0x05]; set => Data[0x05] = (byte)value; } - public override int Ability { get => (sbyte)Data[0x06]; set => Data[0x06] = (byte)value; } - public override Nature Nature { get => (Nature)Data[0x07]; set => Data[0x07] = (byte)value; } - public override Shiny Shiny { get => (Shiny)Data[0x08]; set => Data[0x08] = (byte)value; } - - // padding? - public int Unk09 { get => Data[0x09]; set => Data[0x09] = (byte)value; } - public int Unk0A { get => Data[0x0A]; set => Data[0x0A] = (byte)value; } - public int Unk0B { get => Data[0x0B]; set => Data[0x0B] = (byte)value; } - - public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); } - public override FixedGender Gender { get => (FixedGender)Data[0x10]; set => Data[0x10] = (byte)value; } - - // padding? - public int Unk11 { get => (sbyte)Data[0x11]; set => Data[0x11] = (byte)value; } - public short MetLocation { get => BitConverter.ToInt16(Data, 0x12); set => BitConverter.GetBytes(value).CopyTo(Data, 0x12); } - public int Move { get => BitConverter.ToUInt16(Data, 0x14); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14); } - - public override int IV_HP { get => (sbyte)Data[0x16]; set => Data[0x16] = (byte)value; } - public override int IV_ATK { get => (sbyte)Data[0x17]; set => Data[0x17] = (byte)value; } - public override int IV_DEF { get => (sbyte)Data[0x18]; set => Data[0x18] = (byte)value; } - public override int IV_SPA { get => (sbyte)Data[0x19]; set => Data[0x19] = (byte)value; } - public override int IV_SPD { get => (sbyte)Data[0x1A]; set => Data[0x1A] = (byte)value; } - public override int IV_SPE { get => (sbyte)Data[0x1B]; set => Data[0x1B] = (byte)value; } - - public int CNT_Cool { get => (sbyte)Data[0x1C]; set => Data[0x1C] = (byte)value; } - public int CNT_Beauty { get => (sbyte)Data[0x1D]; set => Data[0x1D] = (byte)value; } - public int CNT_Cute { get => (sbyte)Data[0x1E]; set => Data[0x1E] = (byte)value; } - public int CNT_Smart { get => (sbyte)Data[0x1F]; set => Data[0x1F] = (byte)value; } - public int CNT_Tough { get => (sbyte)Data[0x20]; set => Data[0x20] = (byte)value; } - public int CNT_Sheen { get => (sbyte)Data[0x21]; set => Data[0x21] = (byte)value; } - - public int Unk22 { get => (sbyte)Data[0x22]; set => Data[0x22] = (byte)value; } -} diff --git a/pkNX.Structures/Encounter/Gen6/EncounterGift6XY.cs b/pkNX.Structures/Encounter/Gen6/EncounterGift6XY.cs deleted file mode 100644 index 132dc9d1..00000000 --- a/pkNX.Structures/Encounter/Gen6/EncounterGift6XY.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -namespace pkNX.Structures; - -public class EncounterGift6XY(byte[] data) : EncounterGift(data) -{ - public const int SIZE = 0x18; - public EncounterGift6XY() : this(new byte[SIZE]) { } - - public override Species Species { get => (Species)BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); } - public int Unk_02 { get => BitConverter.ToUInt16(Data, 0x02); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x02); } - public override int Form { get => Data[0x04]; set => Data[0x04] = (byte) value; } - public override int Level { get => Data[0x05]; set => Data[0x05] = (byte)value; } - public override int Ability { get => (sbyte)Data[0x06]; set => Data[0x06] = (byte)value; } - public override Nature Nature { get => (Nature)Data[0x07]; set => Data[0x07] = (byte)value; } - public override Shiny Shiny { get => (Shiny)Data[0x08]; set => Data[0x08] = (byte)value; } - - // padding - public int Unk_09 { get => Data[0x09]; set => Data[0x09] = (byte)value; } - public int Unk_0A { get => Data[0x0A]; set => Data[0x0A] = (byte)value; } - public int Unk_0B { get => Data[0x0B]; set => Data[0x0B] = (byte)value; } - - public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); } - public override FixedGender Gender { get => (FixedGender)Data[0x10]; set => Data[0x10] = (byte)value; } - - public override int IV_HP { get => (sbyte)Data[0x11]; set => Data[0x11] = (byte)value; } - public override int IV_ATK { get => (sbyte)Data[0x12]; set => Data[0x12] = (byte)value; } - public override int IV_DEF { get => (sbyte)Data[0x13]; set => Data[0x13] = (byte)value; } - public override int IV_SPA { get => (sbyte)Data[0x14]; set => Data[0x14] = (byte)value; } - public override int IV_SPD { get => (sbyte)Data[0x15]; set => Data[0x15] = (byte)value; } - public override int IV_SPE { get => (sbyte)Data[0x16]; set => Data[0x16] = (byte)value; } - - // padding - public int Unk_17 { get => (sbyte)Data[0x17]; set => Data[0x17] = (byte)value; } -} diff --git a/pkNX.Structures/Encounter/Gen6/EncounterStatic6.cs b/pkNX.Structures/Encounter/Gen6/EncounterStatic6.cs deleted file mode 100644 index f6facc92..00000000 --- a/pkNX.Structures/Encounter/Gen6/EncounterStatic6.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; - -namespace pkNX.Structures.Encounter; - -public sealed class EncounterStatic6(byte[] data) : EncounterStatic(data) -{ - private const int SIZE = 0xC; - public EncounterStatic6() : this(new byte[SIZE]) { } - - public override Species Species { get => (Species)BitConverter.ToUInt16(Data, 0x0); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0); } - public override int Form { get => Data[0x2]; set => Data[0x2] = (byte)value; } - public override int Level { get => Data[0x3]; set => Data[0x3] = (byte)value; } - - public override int HeldItem - { - get => Math.Max(0, (int)BitConverter.ToInt16(Data, 0x4)); - set => BitConverter.GetBytes((short)(value <= 0 ? -1 : value)).CopyTo(Data, 0x4); - } - - public override Shiny Shiny - { - get => (Shiny)(Data[0x6] & 3); - set => Data[0x6] = (byte)((Data[0x6] & ~3) | ((byte)value & 3)); - } - - public override FixedGender Gender - { - get => (FixedGender)((Data[0x6] & 0x0C) >> 2); - set => Data[0x6] = (byte)((Data[0x6] & ~0xC) | (((byte)value & 3) << 2)); - } - - public override int Ability - { - get => (Data[0x6] & 0x70) >> 4; - set => Data[0x6] = (byte)((Data[0x6] & ~0x70) | ((value & 7) << 4)); - } - - public override bool IV3 - { - get => (Data[0x7] & 1) >> 0 == 1; - set => Data[0x7] = (byte)((Data[0x7] & ~1) | (value ? 1 : 0)); - } - - public bool IV3_1 - { - get => (Data[0x7] & 2) >> 1 == 1; - set => Data[0x7] = (byte)((Data[0x7] & ~2) | (value ? 2 : 0)); - } -} diff --git a/pkNX.Structures/Encounter/Gen7/EncounterGift7.cs b/pkNX.Structures/Encounter/Gen7/EncounterGift7.cs deleted file mode 100644 index 26c9f09e..00000000 --- a/pkNX.Structures/Encounter/Gen7/EncounterGift7.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; - -namespace pkNX.Structures; - -public class EncounterGift7(byte[] data) : EncounterGift(data) -{ - public const int SIZE = 0x14; - public EncounterGift7() : this(new byte[SIZE]) { } - - public override Species Species { get => (Species)BitConverter.ToUInt16(Data, 0x0); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0); } - public override int Form { get => Data[0x2]; set => Data[0x2] = (byte)value; } - public override int Level { get => Data[0x3]; set => Data[0x3] = (byte)value; } - - public override Shiny Shiny { get => (Shiny)Data[0x4]; set => Data[0x4] = (byte)value; } - public override FixedGender Gender { get => (FixedGender)Data[0x5]; set => Data[0x5] = (byte)value; } - public override int Ability { get => (sbyte)Data[0x6]; set => Data[0x6] = (byte)value; } - public override Nature Nature { get => (Nature)Data[0x7]; set => Data[0x7] = (byte)value; } - - public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x8); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x8); } - - public bool IsEgg { get => Data[0xA] == 1; set => Data[0xA] = value ? (byte)1 : (byte)0; } - - public int SpecialMove { get => BitConverter.ToUInt16(Data, 0xC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xC); } - - public override bool IV3 => (sbyte)Data[0xE] < 0 && (sbyte)Data[0xE] + 1 == -3; - public override int IV_HP { get; set; } = -1; - public override int IV_ATK { get; set; } = -1; - public override int IV_DEF { get; set; } = -1; - public override int IV_SPE { get; set; } = -1; - public override int IV_SPA { get; set; } = -1; - public override int IV_SPD { get; set; } = -1; -} diff --git a/pkNX.Structures/Encounter/Gen7/EncounterStatic7.cs b/pkNX.Structures/Encounter/Gen7/EncounterStatic7.cs deleted file mode 100644 index 3c56dde1..00000000 --- a/pkNX.Structures/Encounter/Gen7/EncounterStatic7.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; - -namespace pkNX.Structures; - -public sealed class EncounterStatic7(byte[] data) : EncounterStatic(data) -{ - public const int SIZE = 0x38; - public EncounterStatic7() : this(new byte[SIZE]) { } - - public override Species Species - { - get => (Species)BitConverter.ToUInt16(Data, 0x0); - set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0); - } - - public override int Form - { - get => Data[0x2]; - set => Data[0x2] = (byte)value; - } - - public override int Level - { - get => Data[0x3]; - set => Data[0x3] = (byte)value; - } - - public override int HeldItem - { - get => Math.Max(0, (int)BitConverter.ToInt16(Data, 0x4)); - set => BitConverter.GetBytes((short)(value <= 0 ? -1 : value)).CopyTo(Data, 0x4); - } - - public override Shiny Shiny - { - get => (Shiny) (Data[0x6] & 3); - set => Data[0x6] = (byte)((Data[0x6] & ~3) | ((byte)value & 3)); - } - - public override FixedGender Gender - { - get => (FixedGender)((Data[0x6] & 0x0C) >> 2); - set => Data[0x6] = (byte)((Data[0x6] & ~0xC) | (((byte)value & 3) << 2)); - } - - public override int Ability - { - get => (Data[0x6] & 0x70) >> 4; - set => Data[0x6] = (byte)((Data[0x6] & ~0x70) | ((value & 7) << 4)); - } - - public bool Unk7_0 - { - get => (Data[0x7] & 1) >> 0 == 1; - set => Data[0x7] = (byte)((Data[0x7] & ~1) | (value ? 1 : 0)); - } - - public bool Unk7_1 - { - get => (Data[0x7] & 2) >> 1 == 1; - set => Data[0x7] = (byte)((Data[0x7] & ~2) | (value ? 2 : 0)); - } - - public int Map - { - get => BitConverter.ToInt16(Data, 0x8) - 1; - set => BitConverter.GetBytes((short)(value + 1)).CopyTo(Data, 0x8); - } - - public override int[] RelearnMoves - { - get => - [ - BitConverter.ToUInt16(Data, 0xC), - BitConverter.ToUInt16(Data, 0xE), - BitConverter.ToUInt16(Data, 0x10), - BitConverter.ToUInt16(Data, 0x12), - ]; - set - { - if (value.Length != 4) - return; - for (int i = 0; i < 4; i++) - BitConverter.GetBytes((ushort)value[i]).CopyTo(Data, 0xC + (i * 2)); - } - } - - public override Nature Nature - { - get => (Nature)Data[0x14]; - set => Data[0x14] = (byte)value; - } - - public override int IV_HP { get => (sbyte)Data[0x15]; set => Data[0x15] = (byte)value; } - public override int IV_ATK { get => (sbyte)Data[0x16]; set => Data[0x16] = (byte)value; } - public override int IV_DEF { get => (sbyte)Data[0x17]; set => Data[0x17] = (byte)value; } - public override int IV_SPA { get => (sbyte)Data[0x18]; set => Data[0x18] = (byte)value; } - public override int IV_SPD { get => (sbyte)Data[0x19]; set => Data[0x19] = (byte)value; } - public override int IV_SPE { get => (sbyte)Data[0x1A]; set => Data[0x1A] = (byte)value; } - - public override int EV_HP { get => (sbyte)Data[0x1B]; set => Data[0x1B] = (byte)value; } - public override int EV_ATK { get => (sbyte)Data[0x1C]; set => Data[0x1C] = (byte)value; } - public override int EV_DEF { get => (sbyte)Data[0x1D]; set => Data[0x1D] = (byte)value; } - public override int EV_SPA { get => (sbyte)Data[0x1E]; set => Data[0x1E] = (byte)value; } - public override int EV_SPD { get => (sbyte)Data[0x1F]; set => Data[0x1F] = (byte)value; } - public override int EV_SPE { get => (sbyte)Data[0x20]; set => Data[0x20] = (byte)value; } - - public int Aura - { - get => Data[0x25]; - set => Data[0x25] = (byte)value; - } - - public int Allies - { - get => Data[0x27]; - set => Data[0x27] = (byte)value; - } - - public int Ally1 - { - get => Data[0x28]; - set => Data[0x28] = (byte)value; - } - - public int Ally2 - { - get => Data[0x2C]; - set => Data[0x2C] = (byte)value; - } - - public override bool IV3 => (sbyte)Data[0x15] < 0 && (sbyte)Data[0x15] + 1 == -3; -} diff --git a/pkNX.Structures/Encounter/Gen7/EncounterStatic7b.cs b/pkNX.Structures/Encounter/Gen7/EncounterStatic7b.cs index 602b9e30..c675dd70 100644 --- a/pkNX.Structures/Encounter/Gen7/EncounterStatic7b.cs +++ b/pkNX.Structures/Encounter/Gen7/EncounterStatic7b.cs @@ -1,20 +1,15 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; -public sealed class EncounterStatic7b(byte[] data) : EncounterStatic(data) +public sealed class EncounterStatic7b(Memory raw) : EncounterStatic(raw) { public const int SIZE = 0x40; public EncounterStatic7b() : this(new byte[SIZE]) { } - public ulong Hash => BitConverter.ToUInt64(Data, 0); - - public override Species Species - { - get => (Species)BitConverter.ToUInt16(Data, 0x08); - set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); - } - + public ulong Hash { get => ReadUInt64LittleEndian(Data); set => WriteUInt64LittleEndian(Data, value); } + public override Species Species { get => (Species)ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], (ushort)value); } public override int Form { get => Data[0x0A]; set => Data[0x0A] = (byte)value; } public override int Level { get => Data[0x0B]; set => Data[0x0B] = (byte)value; } @@ -33,47 +28,39 @@ public override Species Species public override Nature Nature { get => (Nature)Data[0x0E]; set => Data[0x0E] = (byte)value; } // 25 = random (sets the nature rand to 1) public override int Ability { get => Data[0x0F]; set => Data[0x0F] = (byte)value; } - public uint[] Ptrs // 0x10-0x1F -- are these text line references? - { - get => - [ - BitConverter.ToUInt32(Data, 0x10), - BitConverter.ToUInt32(Data, 0x14), - BitConverter.ToUInt32(Data, 0x18), - BitConverter.ToUInt32(Data, 0x1C), - ]; - set { } - } + // 0x10-0x1F -- are these text line references? + public uint Ptr0 { get => ReadUInt32LittleEndian(Data[0x10..]); set => WriteUInt32LittleEndian(Data[0x10..], value); } + public uint Ptr1 { get => ReadUInt32LittleEndian(Data[0x14..]); set => WriteUInt32LittleEndian(Data[0x14..], value); } + public uint Ptr2 { get => ReadUInt32LittleEndian(Data[0x18..]); set => WriteUInt32LittleEndian(Data[0x18..], value); } + public uint Ptr3 { get => ReadUInt32LittleEndian(Data[0x1C..]); set => WriteUInt32LittleEndian(Data[0x1C..], value); } + + public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x20..]); set => WriteUInt16LittleEndian(Data[0x20..], value); } + public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x22..]); set => WriteUInt16LittleEndian(Data[0x22..], value); } + public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[0x24..]); set => WriteUInt16LittleEndian(Data[0x24..], value); } + public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[0x26..]); set => WriteUInt16LittleEndian(Data[0x26..], value); } public override int[] RelearnMoves // 0x20-0x27 -- these are actually just moves { get => [ - BitConverter.ToUInt16(Data, 0x20), - BitConverter.ToUInt16(Data, 0x22), - BitConverter.ToUInt16(Data, 0x24), - BitConverter.ToUInt16(Data, 0x26), + RelearnMove1, + RelearnMove2, + RelearnMove3, + RelearnMove4 ]; set { if (value.Length != 4) return; - for (int i = 0; i < 4; i++) - BitConverter.GetBytes((ushort)value[i]).CopyTo(Data, 0x20 + (i * 2)); + RelearnMove1 = (ushort)value[0]; + RelearnMove2 = (ushort)value[1]; + RelearnMove3 = (ushort)value[2]; + RelearnMove4 = (ushort)value[3]; } } - public int V1 - { - get => BitConverter.ToInt16(Data, 0x28); - set => BitConverter.GetBytes((short)value).CopyTo(Data, 0x28); - } - - public int V2 - { - get => BitConverter.ToInt16(Data, 0x2A); - set => BitConverter.GetBytes((short)value).CopyTo(Data, 0x2A); - } + public ushort V1 { get => ReadUInt16LittleEndian(Data[0x28..]); set => WriteUInt16LittleEndian(Data[0x28..], value); } + public ushort V2 { get => ReadUInt16LittleEndian(Data[0x2A..]); set => WriteUInt16LittleEndian(Data[0x2A..], value); } // 0x2C-0x31 public override int IV_HP { get => (sbyte)Data[0x2C]; set => Data[0x2C] = (byte)value; } diff --git a/pkNX.Structures/Evolution/EvolutionSet6.cs b/pkNX.Structures/Evolution/EvolutionSet6.cs deleted file mode 100644 index 392b1d5a..00000000 --- a/pkNX.Structures/Evolution/EvolutionSet6.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace pkNX.Structures; - -/// -/// Generation 6 Evolution Branch Entries -/// -public class EvolutionSet6 : EvolutionSet -{ - private const int ENTRY_SIZE = 6; - private const int ENTRY_COUNT = 8; - public const int SIZE = ENTRY_COUNT * ENTRY_SIZE; - private static readonly HashSet argEvos = [6, 8, 16, 17, 18, 19, 20, 21, 22, 29, 30, 32, 33, 34]; - - public EvolutionSet6(byte[] data) - { - if (data.Length != SIZE) - return; - PossibleEvolutions = data.GetArray(GetEvo, SIZE); - } - - private static EvolutionMethod GetEvo(byte[] data, int offset) - { - var method = (EvolutionType)BitConverter.ToUInt16(data, offset + 0); - var level = (byte)BitConverter.ToUInt16(data, offset + 2); - - var evo = new EvolutionMethod - { - Method = method, - Argument = (argEvos.Contains((int)method) ? (byte)0 : level), // Argument is used by both Level argument and Item/Move/etc. Clear if appropriate. - Species = BitConverter.ToUInt16(data, offset + 4), - Level = level, - }; - - return evo; - } - - public override byte[] Write() - { - using var ms = new MemoryStream(); - using var bw = new BinaryWriter(ms); - foreach (EvolutionMethod evo in PossibleEvolutions) - { - bw.Write((ushort)evo.Method); - bw.Write((ushort)evo.Argument); - bw.Write((ushort)evo.Species); - } - return ms.ToArray(); - } -} diff --git a/pkNX.Structures/Evolution/EvolutionType.cs b/pkNX.Structures/Evolution/EvolutionType.cs index abdc8689..6979ef84 100644 --- a/pkNX.Structures/Evolution/EvolutionType.cs +++ b/pkNX.Structures/Evolution/EvolutionType.cs @@ -157,7 +157,7 @@ public static class EvolutionTypeExtensions LevelUpKnowMoveEC25 => true, LevelUpRecoilDamageMale => true, LevelUpRecoilDamageFemale => true, - Hisui => false, // todo sv + Hisui => false, UseItemFullMoon => false, UseMoveAgileStyle => false, diff --git a/pkNX.Structures/Evolution/SeedPokeTable.cs b/pkNX.Structures/Evolution/SeedPokeTable.cs index f70d5c02..9997551d 100644 --- a/pkNX.Structures/Evolution/SeedPokeTable.cs +++ b/pkNX.Structures/Evolution/SeedPokeTable.cs @@ -9,11 +9,11 @@ public sealed class SeedPokeTable { private readonly ushort[] Table; - public SeedPokeTable(byte[] data) + public SeedPokeTable(ReadOnlySpan data) { Table = new ushort[data.Length/2]; for (int i = 0; i < Table.Length; i++) - Table[i] = BitConverter.ToUInt16(data, i * 2); + Table[i] = BitConverter.ToUInt16(data.Slice(i * 2, 2)); } public ushort this[int index] => Table[index]; diff --git a/pkNX.Structures/Evolution/ZukanEvolutionTable.cs b/pkNX.Structures/Evolution/ZukanEvolutionTable.cs index ed42f530..4b590d15 100644 --- a/pkNX.Structures/Evolution/ZukanEvolutionTable.cs +++ b/pkNX.Structures/Evolution/ZukanEvolutionTable.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; @@ -9,17 +10,17 @@ public sealed class ZukanEvolutionTable private const int SIZE = 0x14; private readonly ushort[][] Table; - public ZukanEvolutionTable(byte[] data) + public ZukanEvolutionTable(ReadOnlySpan data) { if (data.Length % SIZE != 0) - throw new ArgumentException(nameof(data) + " length should be a multiple of " + SIZE); + throw new ArgumentException($"{nameof(data)} length should be a multiple of {SIZE}"); Table = new ushort[data.Length / SIZE][]; for (int i = 0; i < Table.Length; i++) { - var evos = new ushort[(SIZE / 2) - 1]; + var evos = Table[i] = new ushort[(SIZE / 2) - 1]; for (int j = 0; j < evos.Length; j++) - evos[i] = BitConverter.ToUInt16(data, (i * SIZE) + (j * 2)); + evos[i] = ReadUInt16LittleEndian(data.Slice((i * SIZE) + (j * 2), 2)); } } diff --git a/pkNX.Structures/GameUtil.cs b/pkNX.Structures/GameUtil.cs index 7add85d6..27eed47e 100644 --- a/pkNX.Structures/GameUtil.cs +++ b/pkNX.Structures/GameUtil.cs @@ -1,5 +1,3 @@ -using System; -using System.Linq; using static pkNX.Structures.GameVersion; namespace pkNX.Structures; @@ -9,67 +7,6 @@ namespace pkNX.Structures; /// public static class GameUtil { - /// - /// List of possible values that are stored in PKM data. - /// - /// Ordered roughly by most recent games first. - public static readonly GameVersion[] GameVersions = ((GameVersion[])Enum.GetValues(typeof(GameVersion))).Where(z => z is < RB and > 0).Reverse().ToArray(); - - /// - /// Indicates if the value is a value used by the games or is an aggregate indicator. - /// - /// Game to check - public static bool IsValidSavedVersion(this GameVersion game) => game is > 0 and <= RB; - - /// Determines the Version Grouping of an input Version ID - /// Version of which to determine the group - /// Version Group Identifier or Invalid if type cannot be determined. - public static GameVersion GetMetLocationVersionGroup(GameVersion Version) => Version switch - { - // Side games - CXD => CXD, - GO => GO, - - // VC Transfers - RD or BU or YW or GN or GD or SI or C => USUM, - - // Gen2 -- PK2 - GS or GSC => GSC, - - // Gen3 - R or S => RS, - E => E, - FR or LG => FR, - - // Gen4 - D or P => DP, - Pt => Pt, - HG or SS => HGSS, - - // Gen5 - B or W => BW, - B2 or W2 => B2W2, - - // Gen6 - X or Y => XY, - OR or AS => ORAS, - - // Gen7 - SN or MN => SM, - US or UM => USUM, - GP or GE => GG, - - // Gen8 - SW or SH => SWSH, - BD or SP => BDSP, - PLA => PLA, - - // Gen9 - SL or VL => SV, - - _ => Invalid, - }; - /// /// Gets a Version ID from the end of that Generation /// @@ -136,6 +73,9 @@ public static int GetMaxSpeciesID(this GameVersion game) return Legal.MaxSpeciesID_8a; } + if (game is ZA) + return Legal.MaxSpeciesID_9a; + if (Gen9.Contains(game)) { return Legal.MaxSpeciesID_9; @@ -203,15 +143,10 @@ public static bool Contains(this GameVersion g1, GameVersion g2) Gen8 => SWSH.Contains(g2) || PLA.Contains(g2), SV => g2 is SL or VL, - Gen9 => SV.Contains(g2), + ZA => g2 is ZA, + Gen9 => SV.Contains(g2) || ZA.Contains(g2), _ => false, }; } - - /// - /// List of possible values within the provided . - /// - /// Generation to look within - public static GameVersion[] GetVersionsInGeneration(int generation) => GameVersions.Where(z => z.GetGeneration() == generation).ToArray(); } diff --git a/pkNX.Structures/GameVersion.cs b/pkNX.Structures/GameVersion.cs index 2feca0e1..c038aefe 100644 --- a/pkNX.Structures/GameVersion.cs +++ b/pkNX.Structures/GameVersion.cs @@ -230,6 +230,10 @@ public enum GameVersion /// VL = 51, + /// + /// Pokémon Legends: (Z-A) (NX) + /// + ZA = 52, #endregion // The following values are not actually stored values in pkm data, diff --git a/pkNX.Structures/Havok/HavokCollision.cs b/pkNX.Structures/Havok/HavokCollision.cs index 0d37e1b7..bfc66b45 100644 --- a/pkNX.Structures/Havok/HavokCollision.cs +++ b/pkNX.Structures/Havok/HavokCollision.cs @@ -94,24 +94,38 @@ public static AABBTree ParseAABBTree(ReadOnlySpan trcol) ofs = variantField.Type.AlignUp(ofs + variantField.Offset); Debug.Assert(variantField.Type.FormatType == FormatType.Pointer); + var meshItem = item[ReadInt32LittleEndian(data[(int)ofs..])]; ofs = meshItem.Offset; - Debug.Assert(meshItem.Type.Name == "hknpCompressedMeshShape"); - Debug.Assert(meshItem.Type.Fields.Count == 5); - Debug.Assert(meshItem.Type.Fields[0].Name == "data"); - var dataField = meshItem.Type.Fields[0]; - ofs = dataField.Type.AlignUp(ofs + dataField.Offset); - Debug.Assert(dataField.Type.FormatType == FormatType.Pointer); + var simdTreeField = new HavokField(); + if (meshItem.Type.Name == "hknpCompressedMeshShape") + { + Debug.Assert(meshItem.Type.Name == "hknpCompressedMeshShape"); + Debug.Assert(meshItem.Type.Fields.Count == 5); + Debug.Assert(meshItem.Type.Fields[0].Name == "data"); - var dataItem = item[ReadInt32LittleEndian(data[(int)ofs..])]; - ofs = dataItem.Offset; - Debug.Assert(dataItem.Type.Name == "hknpCompressedMeshShapeData"); - Debug.Assert(dataItem.Type.Fields.Count == 4); - Debug.Assert(dataItem.Type.Fields[1].Name == "simdTree"); + var dataField = meshItem.Type.Fields[0]; + ofs = dataField.Type.AlignUp(ofs + dataField.Offset); + Debug.Assert(dataField.Type.FormatType == FormatType.Pointer); + + var dataItem = item[ReadInt32LittleEndian(data[(int)ofs..])]; + ofs = dataItem.Offset; + Debug.Assert(dataItem.Type.Name == "hknpCompressedMeshShapeData"); + Debug.Assert(dataItem.Type.Fields.Count == 4); + Debug.Assert(dataItem.Type.Fields[1].Name == "simdTree"); + simdTreeField = dataItem.Type.Fields[1]; + ofs = simdTreeField.Type.AlignUp(ofs + simdTreeField.Offset); + } + else + { + Debug.Assert(meshItem.Type.Name == "hknpMeshShape"); + Debug.Assert(meshItem.Type.Fields.Count == 5); + Debug.Assert(meshItem.Type.Fields[2].Name == "topLevelTree"); + simdTreeField = meshItem.Type.Fields[2]; + ofs = simdTreeField.Type.AlignUp(ofs + simdTreeField.Offset); + } - var simdTreeField = dataItem.Type.Fields[1]; - ofs = simdTreeField.Type.AlignUp(ofs + simdTreeField.Offset); Debug.Assert(simdTreeField.Type.Name == "hkcdSimdTree"); Debug.Assert(simdTreeField.Type.FormatType == FormatType.Record); Debug.Assert(simdTreeField.Type.Fields.Count == 2); @@ -457,6 +471,11 @@ public AABBTree(List nodes) } BoundingBoxRectangles = new Rectangle3D[NumBoundingBoxes]; + ReloadBoundingBoxRectangles(); + } + + private void ReloadBoundingBoxRectangles() + { var n = 0; foreach (var node in Nodes) { @@ -474,11 +493,117 @@ public AABBTree(List nodes) } } + public void Scale(float x, float y, float z) + { + // Non-uniform scale about the origin. Ensure min <= max per axis after scaling. + foreach (var node in Nodes) + { + for (var i = 0; i < hkcdSimdTreeNode.NodeCount; i++) + { + if (!node.IsBound(i)) + continue; + + var lx = node.LoX[i] * x; var hx = node.HiX[i] * x; + if (lx <= hx) { node.LoX[i] = lx; node.HiX[i] = hx; } else { node.LoX[i] = hx; node.HiX[i] = lx; } + + var ly = node.LoY[i] * y; var hy = node.HiY[i] * y; + if (ly <= hy) { node.LoY[i] = ly; node.HiY[i] = hy; } else { node.LoY[i] = hy; node.HiY[i] = ly; } + + var lz = node.LoZ[i] * z; var hz = node.HiZ[i] * z; + if (lz <= hz) { node.LoZ[i] = lz; node.HiZ[i] = hz; } else { node.LoZ[i] = hz; node.HiZ[i] = lz; } + } + } + ReloadBoundingBoxRectangles(); + } + + /// + /// Rotate the AABB tree about the origin by Euler angles (X=Pitch, Y=Yaw, Z=Roll) in radians. + /// + /// X angle in radians + /// Y angle in radians + /// Z angle in radians + public void Rotate(float x, float y, float z) + { + var rot = Quaternion.CreateFromYawPitchRoll(y, x, z); + var rMat = Matrix4x4.CreateFromQuaternion(rot); + + // Absolute value of rotation matrix for extents transform + var m11 = MathF.Abs(rMat.M11); var m12 = MathF.Abs(rMat.M12); var m13 = MathF.Abs(rMat.M13); + var m21 = MathF.Abs(rMat.M21); var m22 = MathF.Abs(rMat.M22); var m23 = MathF.Abs(rMat.M23); + var m31 = MathF.Abs(rMat.M31); var m32 = MathF.Abs(rMat.M32); var m33 = MathF.Abs(rMat.M33); + + foreach (var node in Nodes) + { + for (var i = 0; i < hkcdSimdTreeNode.NodeCount; i++) + { + if (!node.IsBound(i)) + continue; + + var min = new Vector3(node.LoX[i], node.LoY[i], node.LoZ[i]); + var max = new Vector3(node.HiX[i], node.HiY[i], node.HiZ[i]); + + var center = (min + max) * 0.5f; + var extents = (max - min) * 0.5f; + + var rc = Vector3.Transform(center, rot); + var e = new Vector3( + (m11 * extents.X) + (m12 * extents.Y) + (m13 * extents.Z), + (m21 * extents.X) + (m22 * extents.Y) + (m23 * extents.Z), + (m31 * extents.X) + (m32 * extents.Y) + (m33 * extents.Z)); + + var newMin = rc - e; + var newMax = rc + e; + + node.LoX[i] = newMin.X; + node.LoY[i] = newMin.Y; + node.LoZ[i] = newMin.Z; + + node.HiX[i] = newMax.X; + node.HiY[i] = newMax.Y; + node.HiZ[i] = newMax.Z; + } + } + + ReloadBoundingBoxRectangles(); + } + + /// + /// Translate the AABB tree by the given amounts. + /// + /// Amount to translate via X axis. + /// Amount to translate via Y axis. + /// Amount to translate via Z axis. + public void Translate(float x, float y, float z) + { + // Update the collider nodes + foreach (var node in Nodes) + { + for (var i = 0; i < hkcdSimdTreeNode.NodeCount; i++) + { + if (!node.IsBound(i)) + continue; + + node.LoX[i] += x; + node.LoY[i] += y; + node.LoZ[i] += z; + + node.HiX[i] += x; + node.HiY[i] += y; + node.HiZ[i] += z; + } + } + ReloadBoundingBoxRectangles(); + } + // Official logic for area-containment checks for y intersection between y+1 and y-10000.0 public bool ContainsPoint(float x, float y, float z) => ContainsPointInNode(1, x, y - 10000, y + 1, z); public bool ContainsPoint(float x, float y, float z, float toleranceX, float toleranceY, float toleranceZ) => ContainsPointInNode(1, x, y - 10000, y + 1, z, toleranceX, toleranceY, toleranceZ); + public bool ContainsPointDirect(float x, float y, float z) => ContainsPointInNode(1, x, y, y, z); + public bool ContainsPointDirect(float x, float y, float z, float toleranceX, float toleranceY, float toleranceZ) + => ContainsPointInNode(1, x, y, y, z, toleranceX, toleranceY, toleranceZ); + private bool ContainsPointInNode(int nodeIndex, float x, float ly, float hy, float z, float tx = 0f, float ty = 0f, float tz = 0f) { if (nodeIndex == 0) @@ -491,8 +616,8 @@ private bool ContainsPointInNode(int nodeIndex, float x, float ly, float hy, flo continue; if (node.LoZ[i] > node.HiZ[i] || !(node.LoZ[i] - tz <= z) || !(node.HiZ[i] + tz >= z)) continue; - if (node.LoY[i] > node.HiY[i] || !(node.LoY[i] - ty <= hy) || !(node.HiY[i] + ty >= ly)) - continue; + //if (node.LoY[i] < node.HiY[i] && (!(node.LoY[i] - ty <= hy) || !(node.HiY[i] + ty >= ly))) + // continue; if (node.IsLeaf) return true; if (ContainsPointInNode((int)node.Data[i], x, ly, hy, z, tx, ty, tz)) @@ -501,6 +626,61 @@ private bool ContainsPointInNode(int nodeIndex, float x, float ly, float hy, flo return false; } + /// + /// Attempts to find the floor Y beneath the given point by raycasting downward (y+1 to y-10000). + /// Returns true and outputs the highest LoY that is <= y when an intersecting leaf is found. + /// + public bool TryGetFloorY(float x, float y, float z, out float floorY) + { + var ly = y - 10000f; + var hy = y + 1f; + return TryFindFloorYInNode(1, x, ly, hy, z, out floorY); + } + + private bool TryFindFloorYInNode(int nodeIndex, float x, float ly, float hy, float z, out float floorY) + { + floorY = float.NegativeInfinity; + if (nodeIndex == 0) + return false; + + var node = Nodes[nodeIndex]; + var found = false; + for (var i = 0; i < hkcdSimdTreeNode.NodeCount; i++) + { + // X / Z slab tests + if (node.LoX[i] > node.HiX[i] || !(node.LoX[i] <= x) || !(node.HiX[i] >= x)) + continue; + if (node.LoZ[i] > node.HiZ[i] || !(node.LoZ[i] <= z) || !(node.HiZ[i] >= z)) + continue; + // Y overlap with ray range + if (node.LoY[i] > node.HiY[i] || node.LoY[i] > hy || node.HiY[i] < ly) + continue; + + if (node.IsLeaf) + { + var candidate = node.LoY[i]; + var y0 = hy - 1f; // original y + if (candidate <= y0 && candidate > floorY) + { + floorY = candidate; + found = true; + } + } + else + { + if (TryFindFloorYInNode((int)node.Data[i], x, ly, hy, z, out var childY)) + { + if (childY > floorY) + { + floorY = childY; + } + found = true; + } + } + } + return found; + } + public bool ContainedBy(IContainsV3f other) => other.ContainsPoint(BoundingBoxRectangles[0].X, BoundingBoxRectangles[0].Y, BoundingBoxRectangles[0].Z); } @@ -602,7 +782,7 @@ private struct HavokTemplateParam public int IntValue; public HavokTypeObject TypeValue; - public bool IsType => Name.StartsWith('t'); + public readonly bool IsType => Name.StartsWith('t'); } private struct HavokField diff --git a/pkNX.Structures/Item/Item.cs b/pkNX.Structures/Item/Item.cs index 50573225..7b511b7b 100644 --- a/pkNX.Structures/Item/Item.cs +++ b/pkNX.Structures/Item/Item.cs @@ -1,150 +1,128 @@ +using System; using System.ComponentModel; -using System.Runtime.InteropServices; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; -[StructLayout(LayoutKind.Sequential)] +/// +/// Span-backed lazy access Item definition. Properties read/write directly to underlying data. +/// public class Item { - public byte[] Write() => this.ToBytesClass(); - public static Item FromBytes(byte[] data) => data.ToClass(); + private readonly Memory Raw; + private Span Data => Raw.Span; + public const int SIZE = 0x24; // 36 bytes + + // Category names private const string Battle = "Battle"; private const string Field = "Field"; private const string Mart = "Mart"; private const string Heal = "Heal"; - #region Structure - private ushort Price; + public Item() : this(new byte[SIZE]) { } + private Item(Memory data) + { + if (data.Length < SIZE) + throw new ArgumentException($"Item data must be >= {SIZE} bytes", nameof(data)); + Raw = data[..SIZE]; + } - [Category(Battle)] - public byte HeldEffect { get; set; } + public static Item FromBytes(Memory data) => new(data); + public byte[] Write() => Data.ToArray(); - public byte HeldArgument { get; set; } - public byte NaturalGiftEffect { get; set; } - public byte FlingEffect { get; set; } - public byte FlingPower { get; set; } - public byte NaturalGiftPower { get; set; } - public ushort Packed { get; set; } - - [Category(Field), Description("Routine # to call when used; 0=unusable.")] - public byte EffectField { get; set; } - - [Category(Battle), Description("Routine # to call when used; 0=unusable.")] - public byte EffectBattle { get; set; } // Battle Type - - public byte Unk_0xC { get; set; } // 0 or 1 - public byte Unk_0xD { get; set; } // Classification (0-3 Battle, 4 Balls, 5 Mail) - private byte Consumable { get; set; } - public byte SortIndex { get; set; } - public BattleStatusFlags CureInflict { get; set; } // Bitflags - private byte Boost0; // Revive 1, Sacred Ash 3, Rare Candy 5, EvoStone 8, upper4 for BoostAtk - private byte Boost1; // DEF, SPA - private byte Boost2; // SPD, SPE - private byte Boost3; // ACC, CRIT PPUpFlags - public ItemFlags1 FunctionFlags0 { get; set; } - public ItemFlags2 FunctionFlags1 { get; set; } - - [Category(Field), Description("Adds EVs to the HP stat.")] - public sbyte EVHP { get; set; } - - [Category(Field), Description("Adds EVs to the Attack stat.")] - public sbyte EVATK { get; set; } - - [Category(Field), Description("Adds EVs to the Defense stat.")] - public sbyte EVDEF { get; set; } - - [Category(Field), Description("Adds EVs to the Speed stat.")] - public sbyte EVSPE { get; set; } - - [Category(Field), Description("Adds EVs to the Sp. Attack stat.")] - public sbyte EVSPA { get; set; } - - [Category(Field), Description("Adds EVs to the Sp. Defense stat.")] - public sbyte EVSPD { get; set; } - - [Category(Heal), Description("Determines the healing percent, or if a flat value is used."), RefreshProperties(RefreshProperties.All)] - public Heal HealAmount { get; set; } - - [Category(Field), Description("PP to be added to the move's current PP if used.")] - public byte PPGain { get; set; } - - public sbyte Friendship1 { get; set; } - public sbyte Friendship2 { get; set; } - public sbyte Friendship3 { get; set; } - public byte _0x23, _0x24; + #region Primitive Field Accessors (inline offsets) + private ushort Price { get => ReadUInt16LittleEndian(Data[0x00..]); set => WriteUInt16LittleEndian(Data[0x00..], value); } + private ushort Packed { get => ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], value); } + private byte Boost0 { get => Data[0x11]; set => Data[0x11] = value; } + private byte Boost1 { get => Data[0x12]; set => Data[0x12] = value; } + private byte Boost2 { get => Data[0x13]; set => Data[0x13] = value; } + private byte Boost3 { get => Data[0x14]; set => Data[0x14] = value; } + private byte Consumable { get => Data[0x0E]; set => Data[0x0E] = value; } #endregion + #region Structure + [Category(Battle)] public byte HeldEffect { get => Data[0x02]; set => Data[0x02] = value; } + public byte HeldArgument { get => Data[0x03]; set => Data[0x03] = value; } + public byte NaturalGiftEffect { get => Data[0x04]; set => Data[0x04] = value; } + public byte FlingEffect { get => Data[0x05]; set => Data[0x05] = value; } + public byte FlingPower { get => Data[0x06]; set => Data[0x06] = value; } + public byte NaturalGiftPower { get => Data[0x07]; set => Data[0x07] = value; } + + [Category(Field), Description("Routine # to call when used; 0=unusable.")] + public byte EffectField { get => Data[0x0A]; set => Data[0x0A] = value; } + + [Category(Battle), Description("Routine # to call when used; 0=unusable.")] + public byte EffectBattle { get => Data[0x0B]; set => Data[0x0B] = value; } + + public byte Unk_0xC { get => Data[0x0C]; set => Data[0x0C] = value; } + public byte Unk_0xD { get => Data[0x0D]; set => Data[0x0D] = value; } + public byte SortIndex { get => Data[0x0F]; set => Data[0x0F] = value; } + public BattleStatusFlags CureInflict { get => (BattleStatusFlags)Data[0x10]; set => Data[0x10] = (byte)value; } + public ItemFlags1 FunctionFlags0 { get => (ItemFlags1)Data[0x15]; set => Data[0x15] = (byte)value; } + public ItemFlags2 FunctionFlags1 { get => (ItemFlags2)Data[0x16]; set => Data[0x16] = (byte)value; } + + [Category(Field), Description("Adds EVs to the HP stat.")] + public sbyte EVHP { get => (sbyte)Data[0x17]; set => Data[0x17] = (byte)value; } + [Category(Field), Description("Adds EVs to the Attack stat.")] + public sbyte EVATK { get => (sbyte)Data[0x18]; set => Data[0x18] = (byte)value; } + [Category(Field), Description("Adds EVs to the Defense stat.")] + public sbyte EVDEF { get => (sbyte)Data[0x19]; set => Data[0x19] = (byte)value; } + [Category(Field), Description("Adds EVs to the Speed stat.")] + public sbyte EVSPE { get => (sbyte)Data[0x1A]; set => Data[0x1A] = (byte)value; } + [Category(Field), Description("Adds EVs to the Sp. Attack stat.")] + public sbyte EVSPA { get => (sbyte)Data[0x1B]; set => Data[0x1B] = (byte)value; } + [Category(Field), Description("Adds EVs to the Sp. Defense stat.")] + public sbyte EVSPD { get => (sbyte)Data[0x1C]; set => Data[0x1C] = (byte)value; } + + [Category(Heal), Description("Determines the healing percent, or if a flat value is used."), RefreshProperties(RefreshProperties.All)] + public Heal HealAmount { get => (Heal)Data[0x1D]; set => Data[0x1D] = (byte)value; } + + [Category(Field), Description("PP to be added to the move's current PP if used.")] + public byte PPGain { get => Data[0x1E]; set => Data[0x1E] = value; } + + public sbyte Friendship1 { get => (sbyte)Data[0x1F]; set => Data[0x1F] = (byte)value; } + public sbyte Friendship2 { get => (sbyte)Data[0x20]; set => Data[0x20] = (byte)value; } + public sbyte Friendship3 { get => (sbyte)Data[0x21]; set => Data[0x21] = (byte)value; } + public byte _0x22 { get => Data[0x22]; set => Data[0x22] = value; } + public byte _0x23 { get => Data[0x23]; set => Data[0x23] = value; } + #endregion + + #region Derived Properties [Category(Mart), RefreshProperties(RefreshProperties.All)] public int BuyPrice { get => Price * 10; set => Price = (ushort)(value / 10); } [Category(Mart), ReadOnly(true)] public int SellPrice { get => Price * 5; set => Price = (ushort)(value / 5); } - [Category(Battle)] - public int NaturalGiftType { get => Packed & 0x1F; set => Packed = (ushort)((NaturalGiftEffect & ~0x1F) | value); } + [Category(Battle)] public int NaturalGiftType { get => Packed & 0x1F; set => Packed = (ushort)((NaturalGiftEffect & ~0x1F) | value); } + [Category(Battle)] public bool Flag1 { get => ((Packed >> 5) & 1) == 1; set => Packed = (ushort)((Packed & ~(1 << 5)) | ((value ? 1 : 0) << 5)); } + [Category(Battle)] public bool Flag2 { get => ((Packed >> 6) & 1) == 1; set => Packed = (ushort)((Packed & ~(1 << 6)) | ((value ? 1 : 0) << 6)); } + [Category(Field)] public int PocketField { get => (Packed >> 7) & 0xF; set => Packed = (ushort)((Packed & 0xF87F) | ((value & 0xF) << 7)); } + [Category(Battle)] public BattlePocket PocketBattle { get => (BattlePocket)(Packed >> 11); set => Packed = (ushort)((Packed & 0x077F) | (((byte)value & 0x1F) << 11)); } - [Category(Battle)] - public bool Flag1 { get => ((Packed >> 5) & 1) == 1; set => Packed = (ushort)((Packed & ~(1 << 5)) | ((value ? 1 : 0) << 5)); } + [Category(Field)] public bool Revive { get => ((Boost0 >> 0) & 1) == 0; set => Boost0 = (byte)((Boost0 & ~(1 << 0)) | ((value ? 1 : 0) << 0)); } + [Category(Field)] public bool ReviveAll { get => ((Boost0 >> 1) & 1) == 1; set => Boost0 = (byte)((Boost0 & ~(1 << 1)) | ((value ? 1 : 0) << 1)); } + [Category(Field)] public bool LevelUp { get => ((Boost0 >> 2) & 1) == 1; set => Boost0 = (byte)((Boost0 & ~(1 << 2)) | ((value ? 1 : 0) << 2)); } + [Category(Field)] public bool EvoStone { get => ((Boost0 >> 3) & 1) == 1; set => Boost0 = (byte)((Boost0 & ~(1 << 3)) | ((value ? 1 : 0) << 3)); } - [Category(Battle)] - public bool Flag2 { get => ((Packed >> 6) & 1) == 1; set => Packed = (ushort)((Packed & ~(1 << 6)) | ((value ? 1 : 0) << 6)); } - - [Category(Field)] - public int PocketField { get => (Packed >> 7) & 0xF; set => Packed = (ushort)((Packed & 0xF87F) | ((value & 0xF) << 7)); } - - [Category(Battle)] - public BattlePocket PocketBattle { get => (BattlePocket)(Packed >> 11); set => Packed = (ushort)((Packed & 0x077F) | (((byte)value & 0x1F) << 11)); } - - [Category(Field)] - public bool Revive { get => ((Boost0 >> 0) & 1) == 0; set => Boost0 = (byte)((Boost0 & ~(1 << 0)) | ((value ? 1 : 0) << 0)); } - - [Category(Field)] - public bool ReviveAll { get => ((Boost0 >> 1) & 1) == 1; set => Boost0 = (byte)((Boost0 & ~(1 << 1)) | ((value ? 1 : 0) << 1)); } - - [Category(Field)] - public bool LevelUp { get => ((Boost0 >> 2) & 1) == 1; set => Boost0 = (byte)((Boost0 & ~(1 << 2)) | ((value ? 1 : 0) << 2)); } - - [Category(Field)] - public bool EvoStone { get => ((Boost0 >> 3) & 1) == 1; set => Boost0 = (byte)((Boost0 & ~(1 << 3)) | ((value ? 1 : 0) << 3)); } - - [Category(Battle)] - public int BoostATK { get => Boost0 >> 4; set => Boost0 = (byte)((Boost0 & 0xF) | (value << 4)); } - - [Category(Battle)] - public int BoostDEF { get => Boost1 & 0xF; set => Boost1 = (byte)((Boost1 & ~0xF) | (value & 0xF)); } - - [Category(Battle)] - public int BoostSPA { get => Boost1 >> 4; set => Boost1 = (byte)((Boost1 & 0xF) | (value << 4)); } - - [Category(Battle)] - public int BoostSPD { get => Boost2 & 0xF; set => Boost2 = (byte)((Boost2 & ~0xF) | (value & 0xF)); } - - [Category(Battle)] - public int BoostSPE { get => Boost2 >> 4; set => Boost2 = (byte)((Boost2 & 0xF) | (value << 4)); } - - [Category(Battle)] - public int BoostACC { get => Boost3 & 0xF; set => Boost3 = (byte)((Boost3 & ~0xF) | (value & 0xF)); } - - [Category(Battle)] - public int BoostCRIT { get => (Boost3 >> 4) & 3; set => Boost3 = (byte)((Boost3 & ~0x30) | ((value & 3) << 4)); } - - [Category(Battle)] - public int BoostPP1 { get => (Boost3 >> 6) & 1; set => Boost3 = (byte)((Boost3 & 0xBF) | ((value & 1) << 6)); } - - [Category(Battle)] - public int BoostPPMax { get => (Boost3 >> 7) & 1; set => Boost3 = (byte)((Boost3 & 0x7F) | ((value & 1) << 7)); } + [Category(Battle)] public int BoostATK { get => Boost0 >> 4; set => Boost0 = (byte)((Boost0 & 0xF) | (value << 4)); } + [Category(Battle)] public int BoostDEF { get => Boost1 & 0xF; set => Boost1 = (byte)((Boost1 & ~0xF) | (value & 0xF)); } + [Category(Battle)] public int BoostSPA { get => Boost1 >> 4; set => Boost1 = (byte)((Boost1 & 0xF) | (value << 4)); } + [Category(Battle)] public int BoostSPD { get => Boost2 & 0xF; set => Boost2 = (byte)((Boost2 & ~0xF) | (value & 0xF)); } + [Category(Battle)] public int BoostSPE { get => Boost2 >> 4; set => Boost2 = (byte)((Boost2 & 0xF) | (value << 4)); } + [Category(Battle)] public int BoostACC { get => Boost3 & 0xF; set => Boost3 = (byte)((Boost3 & ~0xF) | (value & 0xF)); } + [Category(Battle)] public int BoostCRIT { get => (Boost3 >> 4) & 3; set => Boost3 = (byte)((Boost3 & ~0x30) | ((value & 3) << 4)); } + [Category(Battle)] public int BoostPP1 { get => (Boost3 >> 6) & 1; set => Boost3 = (byte)((Boost3 & 0xBF) | ((value & 1) << 6)); } + [Category(Battle)] public int BoostPPMax { get => (Boost3 >> 7) & 1; set => Boost3 = (byte)((Boost3 & 0x7F) | ((value & 1) << 7)); } [Category(Heal), Description("Raw value of the Heal enum."), RefreshProperties(RefreshProperties.All)] - public int HealValue - { - get => (int)HealAmount; - set => HealAmount = (Heal)value; - } + public int HealValue { get => (int)HealAmount; set => HealAmount = (Heal)value; } [Category(Heal), Description("Item is consumed when used."), RefreshProperties(RefreshProperties.All)] public bool UseConsume { get => (Consumable & 0xF) != 0; set => Consumable = (byte)((Consumable & 0xF0) | (value ? 1 : 0)); } [Category(Heal), Description("Item is not consumed when used."), RefreshProperties(RefreshProperties.All)] public bool UseKeep { get => (Consumable & 0xF0) != 0; set => Consumable = (byte)((Consumable & 0x0F) | (value ? 0x10 : 0)); } + #endregion } diff --git a/pkNX.Structures/Item/Item8.cs b/pkNX.Structures/Item/Item8.cs index 220510bb..b2deac72 100644 --- a/pkNX.Structures/Item/Item8.cs +++ b/pkNX.Structures/Item/Item8.cs @@ -1,29 +1,21 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; -public class Item8(int id, byte[] data) +public class Item8(int id, Memory Raw) { + public Span Data => Raw.Span; + private const int SIZE = 0x30; public readonly int ItemID = id; - public readonly byte[] Data = data; - - public uint Price - { - get => BitConverter.ToUInt32(Data, 0x00); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); - } - - public uint PriceWatts - { - get => BitConverter.ToUInt32(Data, 0x04); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); - } + public uint Price { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); } + public uint PriceWatts { get => ReadUInt16LittleEndian(Data[0x04..]); set => WriteUInt32LittleEndian(Data[0x04..], value); } public uint PriceAlternate // BP, Dynite Ore { - get => BitConverter.ToUInt32(Data, 0x08); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x08); + get => ReadUInt16LittleEndian(Data[(0x08)..]); + set => WriteUInt32LittleEndian(Data[(0x08)..], value); } public PouchID Pouch @@ -40,8 +32,8 @@ public byte EffectField public int ItemSprite { - get => BitConverter.ToInt16(Data, 0x1A); - set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x1A); + get => BitConverter.ToUInt16(Data.Slice(0x1A, 2)); + set => BitConverter.GetBytes((ushort)value).CopyTo(Data.Slice(0x1A, 2)); } public GroupIndexType GroupType @@ -86,40 +78,47 @@ public byte Boost3 set => Data[0x22] = value; } - public static Item8[] GetArray(byte[] bin) + public static Item8[] GetArray(ReadOnlySpan bin) { - int numEntries = BitConverter.ToUInt16(bin, 0); - int maxEntryIndex = BitConverter.ToUInt16(bin, 4); - int entriesStart = (int)BitConverter.ToUInt32(bin, 0x40); + int numEntries = ReadUInt16LittleEndian(bin); + int maxEntryIndex = ReadUInt16LittleEndian(bin[4..]); + int entriesStart = ReadInt32LittleEndian(bin[0x40..]); var result = new Item8[numEntries]; for (var i = 0; i < result.Length; i++) { - var entryIndex = BitConverter.ToUInt16(bin, 0x44 + (2 * i)); - if (entryIndex >= maxEntryIndex) { throw new IndexOutOfRangeException(); } - result[i] = new Item8(i, bin.Slice(entriesStart + (entryIndex * SIZE), SIZE)); + var entryIndex = ReadUInt16LittleEndian(bin[(0x44 + (2 * i))..]); + if (entryIndex >= maxEntryIndex) + throw new IndexOutOfRangeException(); + + var ofs = entriesStart + (entryIndex * SIZE); + result[i] = new Item8(i, bin.Slice(ofs, SIZE).ToArray()); } return result; } - public static byte[] SetArray(Item8[] array, byte[] bin) + public static byte[] SetArray(ReadOnlySpan array, ReadOnlySpan bin) { - bin = (byte[])bin.Clone(); - if (array.Length != BitConverter.ToInt16(bin, 0)) + int numEntries = ReadUInt16LittleEndian(bin); + if (array.Length != numEntries) throw new ArgumentException("Incompatible sizes"); - int maxEntryIndex = BitConverter.ToUInt16(bin, 4); - int entriesStart = (int)BitConverter.ToUInt32(bin, 0x40); + var result = bin.ToArray(); + int maxEntryIndex = ReadUInt16LittleEndian(bin[4..]); + int entriesStart = ReadInt32LittleEndian(bin[0x40..]); for (int i = 0; i < array.Length; i++) { - var entryIndex = BitConverter.ToUInt16(bin, 0x44 + (2 * i)); - if (entryIndex >= maxEntryIndex) { throw new IndexOutOfRangeException(); } + var entryIndex = ReadUInt16LittleEndian(bin[(0x44 + (2 * i))..]); + if (entryIndex >= maxEntryIndex) + throw new IndexOutOfRangeException(); var data = array[i].Data; - data.CopyTo(bin, entriesStart + (entryIndex * SIZE)); + var ofs = entriesStart + (entryIndex * SIZE); + var span = result.AsSpan(ofs, SIZE); + data.CopyTo(span); } - return bin; + return result; } public enum PouchID : byte diff --git a/pkNX.Structures/Item/Item8a.cs b/pkNX.Structures/Item/Item8a.cs index d8f69eca..ae8266eb 100644 --- a/pkNX.Structures/Item/Item8a.cs +++ b/pkNX.Structures/Item/Item8a.cs @@ -1,22 +1,23 @@ using System; using System.ComponentModel; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; -public class Item8a(int id, byte[] data) +public class Item8a(int id, Memory Raw) { + public Span Data => Raw.Span; private const int SIZE = 0x3C; public readonly int ItemID = id; - public readonly byte[] Data = data; private const string Battle = "Battle"; private const string Field = "Field"; private const string Mart = "Mart"; private const string Heal = "Heal"; - public uint Price { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); } - public uint PriceWatts { get => BitConverter.ToUInt32(Data, 0x04); set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); } - public uint MeritPrice { get => BitConverter.ToUInt32(Data, 0x08); set => BitConverter.GetBytes(value).CopyTo(Data, 0x08); } + public uint Price { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); } + public uint PriceWatts { get => ReadUInt16LittleEndian(Data[0x04..]); set => WriteUInt32LittleEndian(Data[0x04..], value); } + public uint MeritPrice { get => ReadUInt16LittleEndian(Data[(0x08)..]); set => WriteUInt32LittleEndian(Data[(0x08)..], value); } public byte BattleEffect { get => Data[0x0C]; set => Data[0x0C] = value; } public byte BattleArg { get => Data[0x0D]; set => Data[0x0D] = value; } public byte BerryValue { get => Data[0x0F]; set => Data[0x0F] = value; } @@ -41,9 +42,9 @@ public ItemFlags8a Unknown public byte Unk_0x17 { get => Data[0x17]; set => Data[0x17] = value; } public byte SortIndex { get => Data[0x18]; set => Data[0x18] = value; } // 0x19 align - public short ItemSprite { get => BitConverter.ToInt16(Data, 0x1A); set => BitConverter.GetBytes(value).CopyTo(Data, 0x1A); } - public ushort MaxQuantity { get => BitConverter.ToUInt16(Data, 0x1C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x1C); } - public ushort Percentage { get => BitConverter.ToUInt16(Data, 0x1E); set => BitConverter.GetBytes(value).CopyTo(Data, 0x1E); } + public short ItemSprite { get => ReadInt16LittleEndian(Data[0x1A..]); set => WriteInt16LittleEndian(Data[0x1A..], value); } + public ushort MaxQuantity { get => ReadUInt16LittleEndian(Data[0x1C..]); set => WriteUInt16LittleEndian(Data[0x1C..], value); } + public ushort Percentage { get => ReadUInt16LittleEndian(Data[(0x1E)..]); set => WriteUInt32LittleEndian(Data[(0x1E)..], value); } public ItemClass8a ItemGroup { get => (ItemClass8a)Data[0x20]; set => Data[0x20] = (byte)value; } public byte Variant { get => Data[0x21]; set => Data[0x21] = value; } // 22 unused @@ -74,40 +75,47 @@ public ItemFlags8a Unknown public sbyte StatChangeAmount { get => (sbyte)Data[0x3A]; set => Data[0x3A] = (byte)value; } // 0x1B unused - public static Item8a[] GetArray(byte[] bin) + public static Item8a[] GetArray(ReadOnlySpan bin) { - int numEntries = BitConverter.ToUInt16(bin, 0); - int maxEntryIndex = BitConverter.ToUInt16(bin, 4); - int entriesStart = (int)BitConverter.ToUInt32(bin, 0x48); + int numEntries = ReadUInt16LittleEndian(bin); + int maxEntryIndex = ReadUInt16LittleEndian(bin[4..]); + int entriesStart = ReadInt32LittleEndian(bin[0x48..]); var result = new Item8a[numEntries]; for (var i = 0; i < result.Length; i++) { - var entryIndex = BitConverter.ToUInt16(bin, 0x4C + (2 * i)); - if (entryIndex >= maxEntryIndex) { throw new IndexOutOfRangeException(); } - result[i] = new Item8a(i, bin.Slice(entriesStart + (entryIndex * SIZE), SIZE)); + var entryIndex = ReadUInt16LittleEndian(bin[(0x4C + (2 * i))..]); + if (entryIndex >= maxEntryIndex) + throw new IndexOutOfRangeException(); + + var ofs = entriesStart + (entryIndex * SIZE); + result[i] = new Item8a(i, bin.Slice(ofs, SIZE).ToArray()); } return result; } - public static byte[] SetArray(Item8a[] array, byte[] bin) + public static byte[] SetArray(Item8a[] array, ReadOnlySpan bin) { - bin = (byte[])bin.Clone(); - if (array.Length != BitConverter.ToInt16(bin, 0)) + int numEntries = ReadUInt16LittleEndian(bin); + if (array.Length != numEntries) throw new ArgumentException("Incompatible sizes"); - int maxEntryIndex = BitConverter.ToUInt16(bin, 4); - int entriesStart = (int)BitConverter.ToUInt32(bin, 0x48); + var result = bin.ToArray(); + int maxEntryIndex = ReadUInt16LittleEndian(bin[4..]); + int entriesStart = ReadInt32LittleEndian(bin[0x48..]); for (int i = 0; i < array.Length; i++) { - var entryIndex = BitConverter.ToUInt16(bin, 0x4C + (2 * i)); - if (entryIndex >= maxEntryIndex) { throw new IndexOutOfRangeException(); } + var entryIndex = ReadUInt16LittleEndian(bin[(0x4C + (2 * i))..]); + if (entryIndex >= maxEntryIndex) + throw new IndexOutOfRangeException(); var data = array[i].Data; - data.CopyTo(bin, entriesStart + (entryIndex * SIZE)); + var ofs = entriesStart + (entryIndex * SIZE); + var span = result.AsSpan(ofs, SIZE); + data.CopyTo(span); } - return bin; + return result; } [Category(Field)] public bool Revive { get => ((Boost0 >> 0) & 1) == 0; set => Boost0 = (byte)((Boost0 & ~(1 << 0)) | ((value ? 1 : 0) << 0)); } diff --git a/pkNX.Structures/Learnset/Learnset6.cs b/pkNX.Structures/Learnset/Learnset6.cs index 0bcbb7b5..44a6c775 100644 --- a/pkNX.Structures/Learnset/Learnset6.cs +++ b/pkNX.Structures/Learnset/Learnset6.cs @@ -1,22 +1,29 @@ +using System; using System.IO; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; public class Learnset6 : Learnset { - public Learnset6(byte[] data) + public Learnset6(Memory data) : this(data.Span) + { + } + + public Learnset6(Span data) { if (data.Length < 4 || data.Length % 4 != 0) { Count = 0; Levels = Moves = []; return; } Count = (data.Length / 4) - 1; Moves = new int[Count]; Levels = new int[Count]; - using var ms = new MemoryStream(data); - using var br = new BinaryReader(ms); + + int ofs = 0; for (int i = 0; i < Count; i++) { - Moves[i] = br.ReadInt16(); - Levels[i] = br.ReadInt16(); + Moves[i] = ReadInt16LittleEndian(data.Slice(ofs, 2)); + Levels[i] = ReadInt16LittleEndian(data.Slice(ofs + 2, 2)); + ofs += 4; } } @@ -36,9 +43,9 @@ public override byte[] Write() public static Learnset[] GetArray(byte[][] entries) { - Learnset[] data = new Learnset[entries.Length]; + var data = new Learnset[entries.Length]; for (int i = 0; i < data.Length; i++) - data[i] = new Learnset6(entries[i]); + data[i] = new Learnset6(entries[i].AsSpan()); return data; } } diff --git a/pkNX.Structures/Learnset/Learnset8.cs b/pkNX.Structures/Learnset/Learnset8.cs index 6c9c0420..57fc1dad 100644 --- a/pkNX.Structures/Learnset/Learnset8.cs +++ b/pkNX.Structures/Learnset/Learnset8.cs @@ -1,18 +1,19 @@ -using System.IO; +using System; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; public class Learnset8 : Learnset { - private const int SIZE = 0x104; + private const int SIZE = 0x104; // 65 entries * 4 bytes per (move, level) - public Learnset8(byte[] data) + public Learnset8(ReadOnlySpan data) { - // scan for count int count = 0; for (; count < SIZE / 4; count++) { - if (data[(count * 4) + 3] == 0xFF) // check 3rd byte of each u16/u16 tuple, level is never > 255 + // 3rd byte of each (u16 move, u16 level) tuple + if (data[(count * 4) + 3] == 0xFF) break; } @@ -25,41 +26,51 @@ public Learnset8(byte[] data) Moves = new int[Count]; Levels = new int[Count]; - using var ms = new MemoryStream(data); - using var br = new BinaryReader(ms); + + var span = data[..(Count * 4)]; for (int i = 0; i < Count; i++) { - Moves[i] = br.ReadInt16(); - Levels[i] = br.ReadInt16(); + var off = i * 4; + Moves[i] = ReadInt16LittleEndian(span[off..]); + Levels[i] = ReadInt16LittleEndian(span[(off + 2)..]); } } public override byte[] Write() { - Count = (ushort)Moves.Length; - using var ms = new MemoryStream(); - using var bw = new BinaryWriter(ms); + Count = Moves.Length; + var buffer = new byte[SIZE]; + var span = buffer.AsSpan(); + int off = 0; for (int i = 0; i < Count; i++) { - bw.Write((short)Moves[i]); - bw.Write((short)Levels[i]); + WriteInt16LittleEndian(span[off..], (short)Moves[i]); + WriteInt16LittleEndian(span[(off + 2)..], (short)Levels[i]); + off += 4; } - while (bw.BaseStream.Length != SIZE) - bw.Write(-1); - return ms.ToArray(); + // Fill remaining space with sentinel pairs (0xFFFF, 0xFFFF) + while (off < SIZE) + { + WriteUInt32LittleEndian(span[off..], 0xFFFFFFFF); + off += 4; + } + return buffer; } public byte[] WriteAsLearn6() { - using var ms = new MemoryStream(); - using var br = new BinaryWriter(ms); - for (int j = 0; j < Moves.Length; j++) + // For Learn6: write pairs then a single sentinel pair (0xFFFF, 0xFFFF) + int len = (Moves.Length * 4) + 4; // + sentinel + var buffer = new byte[len]; + var span = buffer.AsSpan(); + int off = 0; + for (int i = 0; i < Moves.Length; i++) { - br.Write((ushort)Moves[j]); - br.Write((ushort)Levels[j]); + WriteUInt16LittleEndian(span[off..], (ushort)Moves[i]); + WriteUInt16LittleEndian(span[(off + 2)..], (ushort)Levels[i]); + off += 4; } - - br.Write(-1); - return ms.ToArray(); + WriteUInt32LittleEndian(span[off..], 0xFFFFFFFF); + return buffer; } } diff --git a/pkNX.Structures/Legality/GameInfo.cs b/pkNX.Structures/Legality/GameInfo.cs index f0c0e024..89a95375 100644 --- a/pkNX.Structures/Legality/GameInfo.cs +++ b/pkNX.Structures/Legality/GameInfo.cs @@ -16,14 +16,11 @@ public class GameInfo public ushort[] HeldItems { get; private set; } = []; public int MaxAbilityID { get; private set; } - public bool XY { get; private set; } - public bool AO { get; private set; } - public bool SM { get; private set; } - public bool USUM { get; private set; } public bool GG { get; private set; } public bool SWSH { get; private set; } public bool PLA { get; private set; } public bool SV { get; private set; } + public bool ZA { get; private set; } public GameInfo(GameVersion game) { @@ -34,12 +31,6 @@ public GameInfo(GameVersion game) private Action GetInitMethod(GameVersion game) => game switch { - GameVersion.XY => LoadXY, - GameVersion.ORASDEMO => LoadAO, - GameVersion.ORAS => LoadAO, - GameVersion.SMDEMO => LoadSM, - GameVersion.SM => LoadSM, - GameVersion.USUM => LoadUSUM, GameVersion.GP => LoadGG, GameVersion.GE => LoadGG, GameVersion.GG => LoadGG, @@ -48,49 +39,10 @@ public GameInfo(GameVersion game) GameVersion.SWSH => LoadSWSH, GameVersion.PLA => LoadPLA, GameVersion.SV => LoadSV, + GameVersion.ZA => LoadZA, _ => throw new ArgumentOutOfRangeException(nameof(game), game, null), }; - private void LoadXY() - { - XY = true; - MaxSpeciesID = Legal.MaxSpeciesID_6; - MaxMoveID = Legal.MaxMoveID_6_XY; - MaxItemID = Legal.MaxItemID_6_XY; - HeldItems = Legal.HeldItem_XY; - MaxAbilityID = Legal.MaxAbilityID_6_XY; - } - - private void LoadAO() - { - AO = true; - MaxSpeciesID = Legal.MaxSpeciesID_6; - MaxMoveID = Legal.MaxMoveID_6_AO; - MaxItemID = Legal.MaxItemID_6_AO; - HeldItems = Legal.HeldItem_AO; - MaxAbilityID = Legal.MaxAbilityID_6_AO; - } - - private void LoadSM() - { - SM = true; - MaxSpeciesID = Legal.MaxSpeciesID_7_SM; - MaxMoveID = Legal.MaxMoveID_7_SM; - MaxItemID = Legal.MaxItemID_7_SM; - HeldItems = Legal.HeldItems_SM; - MaxAbilityID = Legal.MaxAbilityID_7_SM; - } - - private void LoadUSUM() - { - USUM = true; - MaxSpeciesID = Legal.MaxSpeciesID_7_USUM; - MaxMoveID = Legal.MaxMoveID_7_USUM; - MaxItemID = Legal.MaxItemID_7_USUM; - HeldItems = Legal.HeldItems_USUM; - MaxAbilityID = Legal.MaxAbilityID_7_USUM; - } - private void LoadGG() { GG = true; @@ -130,4 +82,14 @@ private void LoadSV() HeldItems = Legal.HeldItems_SV; MaxAbilityID = Legal.MaxAbilityID_9; } + + private void LoadZA() + { + ZA = true; + MaxSpeciesID = Legal.MaxSpeciesID_9a; + MaxMoveID = Legal.MaxMoveID_9a; + MaxItemID = Legal.MaxItemID_9a; + HeldItems = Legal.HeldItems_SV; + MaxAbilityID = Legal.MaxAbilityID_9a; + } } diff --git a/pkNX.Structures/Legality/Legal.cs b/pkNX.Structures/Legality/Legal.cs index 38d0ad25..3fccc8b3 100644 --- a/pkNX.Structures/Legality/Legal.cs +++ b/pkNX.Structures/Legality/Legal.cs @@ -20,15 +20,6 @@ public static int GetModifiedLevel(int level, double factor) public static int[] GetRandomItemList(GameVersion game) { - if (GameVersion.XY.Contains(game)) - return Items_HeldXY.Concat(Items_Ball).Where(i => i != 0).ToArray(); - - if (GameVersion.ORAS.Contains(game) || game == GameVersion.ORASDEMO) - return Items_HeldAO.Concat(Items_Ball).Where(i => i != 0).ToArray(); - - if (GameVersion.SM.Contains(game) || GameVersion.USUM.Contains(game)) - return HeldItemsBuy_SM.Select(i => (int)i).Concat(Items_Ball).Where(i => i != 0).ToArray(); - if (GameVersion.GG.Contains(game)) return HeldItems_GG.Select(i => (int)i).Where(i => i != 0).ToArray(); diff --git a/pkNX.Structures/Legality/Tables/Tables6.cs b/pkNX.Structures/Legality/Tables/Tables6.cs index db57af6b..796627e6 100644 --- a/pkNX.Structures/Legality/Tables/Tables6.cs +++ b/pkNX.Structures/Legality/Tables/Tables6.cs @@ -1,555 +1,6 @@ -using System.Collections.Generic; - namespace pkNX.Structures; public static partial class Legal { public const int MaxSpeciesID_6 = 721; - public const int MaxMoveID_6_XY = 617; - public const int MaxMoveID_6_AO = 621; - public const int MaxItemID_6_XY = 717; - public const int MaxItemID_6_AO = 775; - public const int MaxAbilityID_6_XY = 188; - public const int MaxAbilityID_6_AO = 191; - public const int MaxBallID_6 = 0x19; - public const int MaxGameID_6 = 27; // OR - - #region Met Locations - public static readonly int[] Met_XYc = [0, 60002, 30002]; - - public static readonly int[] Met_XY_0 = - [ - /* XY */ - 2, 6, 8, 10, 12, 14, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, - 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 82, 84, 86, 88, - 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, - 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, /* ORAS */ 170, 172, - 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, - 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, - 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, - 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, - 350, 352, 354, - ]; - - public static readonly int[] Met_XY_3 = - [ - 30001, 30003, 30004, 30005, 30006, 30007, 30008, 30009, 30010, 30011, - ]; - - public static readonly int[] Met_XY_4 = - [ - 40001, 40002, 40003, 40004, 40005, 40006, 40007, 40008, 40009, 40010, - 40011, 40012, 40013, 40014, 40015, 40016, 40017, 40018, 40019, 40020, 40021, 40022, 40023, 40024, 40025, - 40026, 40027, 40028, 40029, 40030, 40031, 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039, 40040, - 40041, 40042, 40043, 40044, 40045, 40046, 40047, 40048, 40049, 40050, 40051, 40052, 40053, 40054, 40055, - 40056, 40057, 40058, 40059, 40060, 40061, 40062, 40063, 40064, 40065, 40066, 40067, 40068, 40069, 40070, - 40071, 40072, 40073, 40074, 40075, 40076, 40077, 40078, 40079, - ]; - - public static readonly int[] Met_XY_6 = [/* XY */ 60001, 60003, /* ORAS */ 60004]; - - public static readonly int[] EggLocations6 = [60002, 30002]; - - public static readonly HashSet ValidMet_XY = - [ - 006, 008, 009, 010, 012, 013, 014, 016, 017, 018, 020, 021, 022, 024, 026, 028, 029, 030, 032, 034, 035, 036, - 038, 039, 040, 042, 043, 044, 046, 047, 048, 050, 051, 052, 054, 055, 056, 058, 060, 062, 063, 064, 066, 067, - 068, 069, 070, 072, 074, 075, 076, 078, 079, 082, 084, 085, 086, 088, 089, 090, 092, 093, 094, 096, 097, 098, - 100, 101, 102, 103, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 135, 136, - 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, - ]; - - public static readonly HashSet ValidMet_AO = - [ - 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, - 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, - 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, - 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, - 332, 334, 336, 338, 340, 342, 344, 346, 350, 352, 354, - ]; - - public static readonly int[] FriendSafari = - [ - 190, 206, 216, 506, 294, 352, 531, 572, 113, 132, 133, 235, - 012, 046, 165, 415, 267, 284, 313, 314, 049, 127, 214, 666, - 262, 274, 624, 629, 215, 332, 342, 551, 302, 359, 510, 686, - 444, 611, 148, 372, 714, 621, 705, - 101, 417, 587, 702, 025, 125, 618, 694, 310, 404, 523, 596, - 175, 209, 281, 702, 039, 303, 682, 684, 035, 670, - 056, 067, 307, 619, 538, 539, 674, 236, 286, 297, 447, - 058, 077, 126, 513, 005, 218, 636, 668, 038, 654, 662, - 016, 021, 083, 084, 163, 520, 527, 581, 357, 627, 662, 701, - 353, 608, 708, 710, 356, 426, 442, 623, - 043, 114, 191, 511, 002, 541, 548, 586, 556, 651, 673, - 027, 194, 231, 328, 051, 105, 290, 323, 423, 536, 660, - 225, 361, 363, 459, 215, 614, 712, 087, 091, 131, 221, - 014, 044, 268, 336, 049, 168, 317, 569, 089, 452, 454, 544, - 063, 096, 326, 517, 202, 561, 677, 178, 203, 575, 578, - 299, 525, 557, 095, 219, 222, 247, 112, 213, 689, - 082, 303, 597, 205, 227, 375, 600, 437, 530, 707, - 098, 224, 400, 515, 008, 130, 195, 419, 061, 184, 657, - ]; - #endregion - - #region Inventory Pouch - - public static readonly ushort[] Pouch_Items_XY = - [ - 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016, 055, 056, - 057, 058, 059, 060, 061, 062, 063, 064, 065, 066, 067, 068, 069, 070, 071, 072, 073, 074, 075, - 076, 077, 078, 079, 080, 081, 082, 083, 084, 085, 086, 087, 088, 089, 090, 091, 092, 093, 094, - 099, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 116, 117, 118, 119, 135, 136, - 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 492, 493, 494, 495, 496, 497, 498, 499, 500, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, - 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 571, - 572, 573, 576, 577, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 639, 640, 644, 646, - 647, 648, 649, 650, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, - 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, - 699, 704, 710, 711, 715, - ]; - - public static readonly ushort[] Pouch_Items_AO = - [ - 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016, 055, 056, - 057, 058, 059, 060, 061, 062, 063, 064, 068, 069, 070, 071, 072, 073, 074, 075, - 076, 077, 078, 079, 080, 081, 082, 083, 084, 085, 086, 087, 088, 089, 090, 091, 092, 093, 094, - 099, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 116, 117, 118, 119, 135, 136, - 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 492, 493, 494, 495, 496, 497, 498, 499, 500, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, - 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 571, - 572, 573, 576, 577, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 639, 640, 644, 646, - 647, 648, 649, 650, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, - 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, - 699, 704, 710, 711, 715, - - // ORAS - 534, 535, - 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 767, 768, 769, 770, - ]; - - public static readonly ushort[] Pouch_Key_XY = - [ - 216, 431, 442, 445, 446, 447, 450, 465, 466, 471, 628, - 629, 631, 632, 638, 641, 642, 643, 689, 695, 696, 697, 698, - 700, 701, 702, 703, 705, 712, 713, 714, - - // Illegal - // 716, 717, 706, 707, - ]; - - public static readonly ushort[] Pouch_Key_AO = - [ - 216, 445, 446, 447, 465, 466, 471, 628, - 629, 631, 632, 638, 697, - - // Illegal - // 716, 717, 723, 745, 746, 747, 748, 749, 750, 766, - - // ORAS - 457, 474, 503, - - 718, 719, - 720, 721, 722, 724, 725, 726, 727, 728, 729, - 730, 731, 732, 733, 734, 735, 736, 738, 739, - 740, 741, 742, 743, 744, - 751, - 765, 771, 772, 774, 775, - ]; - - public static readonly ushort[] Pouch_TMHM_XY = - [ - 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, 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, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, - 418, 419, 618, 619, 620, 690, 691, 692, 693, 694, - - 420, 421, 422, 423, 424, - ]; - - public static readonly ushort[] Pouch_TMHM_AO = - [ - 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, 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, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, - 418, 419, 618, 619, 620, 690, 691, 692, 693, 694, - - 420, 421, 422, 423, 424, - - // ORAS - 425, 737, - ]; - - public static readonly ushort[] Pouch_Medicine_XY = - [ - 017, 018, 019, 020, 021, 022, 023, 024, 025, 026, 027, 028, 029, 030, 031, 032, 033, - 034, 035, 036, 037, 038, 039, 040, 041, 042, 043, 044, 045, 046, 047, 048, 049, 050, 051, - 052, 053, 054, 134, 504, 565, 566, 567, 568, 569, 570, 571, 591, 645, 708, 709, - ]; - - public static readonly ushort[] Pouch_Medicine_AO = - [ - 017, 018, 019, 020, 021, 022, 023, 024, 025, 026, 027, 028, 029, 030, 031, 032, 033, - 034, 035, 036, 037, 038, 039, 040, 041, 042, 043, 044, 045, 046, 047, 048, 049, 050, 051, - 052, 053, 054, 134, 504, 565, 566, 567, 568, 569, 570, 571, 591, 645, 708, 709, - - //ORAS - 065, 066, 067, - ]; - - public static readonly ushort[] Pouch_Berry_XY = - [ - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 686, 687, 688, - ]; - - public static readonly ushort[] HeldItem_XY = [.. Pouch_Items_XY, .. Pouch_Medicine_XY, .. Pouch_Berry_XY]; - public static readonly ushort[] HeldItem_AO = [.. Pouch_Items_AO, .. Pouch_Medicine_AO, .. Pouch_Berry_XY]; - #endregion - - #region TMHM - - public static readonly int[] TMHM_AO = - [ - 468, 337, 473, 347, 046, 092, 258, 339, 474, 237, - 241, 269, 058, 059, 063, 113, 182, 240, 355, 219, - 218, 076, 479, 085, 087, 089, 216, 091, 094, 247, - 280, 104, 115, 482, 053, 188, 201, 126, 317, 332, - 259, 263, 488, 156, 213, 168, 490, 496, 497, 315, - 211, 411, 412, 206, 503, 374, 451, 507, 510, 511, - 261, 512, 373, 153, 421, 371, 514, 416, 397, 148, - 444, 521, 086, 360, 014, 522, 244, 523, 524, 157, - 404, 525, 611, 398, 138, 447, 207, 214, 369, 164, - 430, 433, 528, 290, 555, 267, 399, 612, 605, 590, - - 15, 19, 57, 70, 127, 249, 291, - ]; - - public static readonly int[] TMHM_XY = - [ - 468, 337, 473, 347, 046, 092, 258, 339, 474, 237, - 241, 269, 058, 059, 063, 113, 182, 240, 355, 219, - 218, 076, 479, 085, 087, 089, 216, 091, 094, 247, - 280, 104, 115, 482, 053, 188, 201, 126, 317, 332, - 259, 263, 488, 156, 213, 168, 490, 496, 497, 315, - 211, 411, 412, 206, 503, 374, 451, 507, 510, 511, - 261, 512, 373, 153, 421, 371, 514, 416, 397, 148, - 444, 521, 086, 360, 014, 522, 244, 523, 524, 157, - 404, 525, 611, 398, 138, 447, 207, 214, 369, 164, - 430, 433, 528, 249, 555, 267, 399, 612, 605, 590, - - 15, 19, 57, 70, 127, - ]; - - public static readonly int[] TypeTutor6 = [520, 519, 518, 338, 307, 308, 434, 620]; - - public static readonly int[][] Tutors_AO = - [ - [450, 343, 162, 530, 324, 442, 402, 529, 340, 067, 441, 253, 009, 007, 008], - [277, 335, 414, 492, 356, 393, 334, 387, 276, 527, 196, 401, 399, 428, 406, 304, 231], - [020, 173, 282, 235, 257, 272, 215, 366, 143, 220, 202, 409, 355, 264, 351, 352], - [380, 388, 180, 495, 270, 271, 478, 472, 283, 200, 278, 289, 446, 214, 285], - ]; - - #endregion - - public static readonly int[] CosplayPikachuMoves = [309, 556, 577, 604, 560, 0]; - public static readonly int[] WildPokeballs6 = [0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F]; - - public static readonly int[] Ban_NoHidden6 = - [ - //Not avaliable at Friend Safari or Horde Encounter - 669 + (2 << 11), //Flabébé-Orange - 670 + (2 << 11), //Floette-Orange - 671 + (2 << 11), //Florges-Orange - 669 + (4 << 11), //Flabébé-White - 670 + (4 << 11), //Floette-White - 671 + (4 << 11), //Florges-White - - 710 + (1 << 11), //Pumpkaboo-Small - 711 + (1 << 11), //Gourgeist-Small - 710 + (2 << 11), //Pumpkaboo-Large - 711 + (2 << 11), //Gourgeist-Large - //Super Size can be obtained as a Pumpkaboo from event distributions - ]; - - #region Ball Table - public static readonly int[] Inherit_Sport = - [ - 010, 013, 046, 048, 123, 127, 265, 290, 314, 401, 415, - - 313, // Via Illumise - ]; - - public static readonly int[] Inherit_Safari = - [ - 016, 019, 020, 021, 022, 023, 024, 025, 027, 029, 035, 039, 041, - 043, 046, 048, 050, 054, 055, 060, 063, 066, 069, 070, 074, 077, 079, 080, 083, 084, 088, 092, 095, 096, 098, - 099, 102, 104, 108, 109, 111, 113, 114, 115, 118, 122, 123, 125, 126, 127, 129, 131, 147, 161, 163, 165, 167, - 177, 179, 183, 187, 189, 190, 191, 193, 194, 198, 200, 202, 203, 204, 207, 209, 213, 214, 216, 223, 228, 229, - 231, 234, 235, 241, 246, 263, 264, 270, 271, 273, 283, 284, 285, 286, 288, 298, 299, 304, 305, 307, 308, 309, - 310, 314, 315, 316, 318, 324, 327, 328, 331, 332, 335, 336, 339, 341, 352, 353, 354, 355, 356, 357, 358, 363, - 364, 371, 372, 397, 399, 400, 403, 404, 406, 417, 418, 419, 433, 443, 447, 449, 451, 453, 455, - - 032, // Via Nidoran-F - 313, // Via Illumise - - 173, // Via Clefairy - 239, // Via Electabuzz - 240, // Via Magmar - 298, // Via Marill - 360, // Via Wobbuffet - 406, // Via Roselia - 433, // Via Chimecho - 439, // Via Mr. Mime - 440, // Via Chansey - ]; - - public static readonly int[] Inherit_Dream = - [ - 010, 013, 016, 019, 021, 023, 027, 029, 037, 041, 043, 046, 048, 050, 052, 054, 056, 058, 060, 063, 066, 069, - 072, 074, 077, 079, 083, 084, 086, 088, 090, 092, 095, 096, 098, 102, 104, 108, 109, 111, 113, 114, 115, 116, - 118, 122, 123, 127, 129, 131, 133, 138, 140, 142, 143, 147, 161, 163, 165, 167, 170, 173, 174, 175, 177, 179, - 183, 185, 187, 190, 191, 193, 194, 198, 200, 202, 203, 204, 206, 207, 209, 211, 213, 214, 215, 216, 218, 220, - 222, 223, 225, 226, 227, 228, 231, 234, 235, 238, 239, 240, 241, 246, 261, 263, 265, 270, 273, 276, 278, 280, - 283, 285, 287, 290, 293, 296, 299, 300, 302, 303, 304, 307, 309, 311, 312, 314, 315, 316, 318, 320, 322, 324, - 325, 327, 328, 331, 333, 335, 336, 339, 341, 345, 347, 349, 351, 352, 353, 355, 357, 358, 359, 361, 363, 366, - 369, 370, 371, 396, 399, 401, 403, 408, 410, 412, 415, 417, 418, 420, 422, 425, 427, 431, 434, 441, 442, 443, - 447, 449, 451, 453, 455, 456, 459, 517, 519, 525, 529, 531, 533, 535, 545, 546, 548, 550, 553, 556, 558, 559, - 561, 564, 578, 580, 583, 587, 588, 594, 596, 605, 610, 616, 618, 621, 624, 631, 632, - - 032, // Via Nidoran-F - 313, // Via Illumise - - // Via Evolution - 524, // Roggenrola - 532, // Timburr - 543, // Venipede - 551, // Sandile - 557, // Dwebble - 577, // Solosis - 582, // Vanillite - 595, // Joltik - - // Via Incense Breeding - 298, 360, 406, 433, 438, 439, 440, 446, 458, - ]; - - public static readonly int[] Ban_DreamHidden = - [ - 311, // Plusle - 312, // Minun - 352, // Kecleon - 355, // Duskull - - // Via Pre-Evolution - 356, // Dusclops - 477, // Dusknoir - ]; - - public static readonly int[] Ban_Gen3Ball = - [ - 252, 255, 258, //1 - Treeko, Torchic, Mudkip - 253, 256, 259, //2 - 254, 257, 260, //3 - 387, 390, 393, //1 - Turtwig, Chimchar, Piplup - 388, 391, 394, //2 - 389, 392, 395, //3 - 495, 498, 501, //1 - Snivy, Tepig, Oshawott - 496, 499, 502, //2 - 497, 500, 503, //3 - 566, 567, 696, 697, 698, 699, // Fossil Only obtain - ]; - - public static readonly int[] Ban_Gen3BallHidden = - [ - // can have HA and can be in gen 3 ball as eggs but can not at same time. - 152, 155, 158, //1 - Gen2 Starters - 153, 156, 159, //2 - 154, 157, 160, //3 - 585 + (1 << 11), //Deerling-Summer - 586 + (1 << 11), //Sawsbuck-Summer - 585 + (2 << 11), //Deerling-Autumn - 586 + (2 << 11), //Sawsbuck-Autumn - 585 + (3 << 11), //Deerling-Winter - 586 + (3 << 11), //Sawsbuck-Winter - 710 + (3 << 11), //Pumpkaboo-Super - 711 + (3 << 11), //Gourgeist-Super - ]; - - public static readonly int[] Ban_Gen4Ball_6 = - [ - 152, 155, 158, //1 - Chikorita, Cyndaquil, Totodile - 153, 156, 159, //2 - 154, 157, 160, //3 - 252, 255, 258, //1 - Treeko, Torchic, Mudkip - 253, 256, 259, //2 - 254, 257, 260, //3 - 387, 390, 393, //1 - Turtwig, Chimchar, Piplup - 388, 391, 394, //2 - 389, 392, 395, //3 - 495, 498, 501, //1 - Snivy, Tepig, Oshawott - 496, 499, 502, //2 - 497, 500, 503, //3 - 566, 567, 696, 697, 698, 699, // Fossil Only obtain - ]; - - public static readonly int[] WurmpleEvolutions = - [ - 266, 267, // Silcoon Beautifly - 268, 269, // Cascoon Dustox - ]; - #endregion - #region Memory Table - public static readonly int[] Memory_NotXY = - [ - 65, // {0} was with {1} when (he/she) built a Secret Base. {4} that {3}. - 66, // {0} participated in a contest with {1} and impressed many people. {4} that {3}. - 67, // {0} participated in a contest with {1} and won the title. {4} that {3}. - 68, // {0} soared through the sky with {1} and went to many different places. {4} that {3}. - 69, // {1} asked {0} to dive. Down it went, deep into the ocean, to explore the bottom of the sea. {4} that {3}. - ]; - - public static readonly int[] Memory_NotAO = - [ - 11, // {0} went clothes shopping with {1}. {4} that {3}. - 43, // {0} was impressed by the speed of the train it took with {1}. {4} that {3}. - 44, // {0} encountered {2} with {1} using the Poké Radar. {4} that {3}. - 56, // {0} was with {1} when (he/she) went to a boutique and tried on clothes, but (he/she) left the boutique without buying anything. {4} that {3}. - 57, // {0} went to a nice restaurant with {1} and ate until it got totally full. {4} that {3}. - 62, // {0} saw itself in a mirror in a mirror cave that it went to with {1}. {4} that {3}. - ]; - - public static readonly int[][] MoveSpecificMemories = - [ - [ - 20, // {0} surfed across the water, carrying {1} on its back. {4} that {3}. - 24, // {0} flew, carrying {1} on its back, to {2}. {4} that {3}. - 35, // {0} proudly used Strength at {1}’s instruction in... {2}. {4} that {3}. - 36, // {0} proudly used Cut at {1}’s instruction in... {2}. {4} that {3}. - 37, // {0} shattered rocks to its heart’s content at {1}’s instruction in... {2}. {4} that {3}. - 38, // {0} used Waterfall while carrying {1} on its back in... {2}. {4} that {3}. - 69, // {1} asked {0} to dive. Down it went, deep into the ocean, to explore the bottom of the sea. {4} that {3}. - ], - [57, 19, 70, 15, 249, 127, 291], // Move IDs - ]; - - public static readonly int[][] LocationsWithPKCenter = - [ - [ - // Kalos locations with a PKMN CENTER - 18, // Santalune City - 22, // Lumiose City - 30, // Camphrier Town - 40, // Cyllage City - 44, // Ambrette Town - 52, // Geosenge Towny - 58, // Shalour City - 64, // Coumarine City - 70, // Laverre City - 76, // Dendemille Town - 86, // Anistar City - 90, // Couriway Town - 94, // Snowbelle City - 106, // Pokémon League (X/Y) - // Hoenn locations with a PKMN CENTER - 172, // Oldale Town - 174, // Dewford Town - 176, // Lavaridge Town - 178, // Fallarbor Town - 180, // Verdanturf Town - 182, // Pacifidlog Town - 184, // Petalburg City - 186, // Slateport City - 188, // Mauville City - 190, // Rustboro City - 192, // Fortree City - 194, // Lilycove City - 196, // Mossdeep City - 198, // Sootopolis City - 200, // Ever Grande City - 202, // Pokémon League (OR/AS) - ], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // Region matching - ]; - - public static readonly HashSet MemoryGeneral = [1, 2, 3, 4, 19, 24, 31, 32, 33, 35, 36, 37, 38, 39, 42, 52, 59]; - public static readonly HashSet MemorySpecific = [6]; - public static readonly HashSet MemoryMove = [12, 16, 48, 49]; - public static readonly HashSet MemoryItem = [5, 15, 26, 34, 40, 51]; - public static readonly HashSet MemorySpecies = [7, 9, 13, 14, 17, 21, 18, 25, 29, 44, 45, 50, 60]; - #endregion - - public static readonly int[] MovePP_XY = - [ - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 25, 15, 10, 20, 25, 10, 35, 30, 15, 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 20, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 10, - 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, 10, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, 15, - 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, - 10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, 10, 15, 10, 20, 10, 15, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, 10, - 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, - 05, 10, 05, 05, 15, 10, 05, 05, 05, 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, 20, - 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, 05, 05, - ]; - - public static readonly bool[] ReleasedHeldItems_6 = GetPermitList(MaxItemID_6_AO, HeldItem_AO, stackalloc ushort[] - { - 005, // Safari Ball - 016, // Cherish Ball - 492, // Fast Ball - 493, // Level Ball - 494, // Lure Ball - 495, // Heavy Ball - 496, // Love Ball - 497, // Friend Ball - 498, // Moon Ball - 499, // Sport Ball - 500, // Park Ball - 548, // Fire Gem - 549, // Water Gem - 550, // Electric Gem - 551, // Grass Gem - 552, // Ice Gem - 553, // Fighting Gem - 554, // Poison Gem - 555, // Ground Gem - 556, // Flying Gem - 557, // Psychic Gem - 558, // Bug Gem - 559, // Rock Gem - 560, // Ghost Gem - 561, // Dragon Gem - 562, // Dark Gem - 563, // Steel Gem - 576, // Dream Ball - 584, // Relic Copper - 585, // Relic Silver - 587, // Relic Vase - 588, // Relic Band - 589, // Relic Statue - 590, // Relic Crown - 715, // Fairy Gem - }); } diff --git a/pkNX.Structures/Legality/Tables/Tables7.cs b/pkNX.Structures/Legality/Tables/Tables7.cs index e9773124..6a752fa8 100644 --- a/pkNX.Structures/Legality/Tables/Tables7.cs +++ b/pkNX.Structures/Legality/Tables/Tables7.cs @@ -1,70 +1,14 @@ using System.Collections.Generic; -using System.Linq; using static pkNX.Structures.Species; namespace pkNX.Structures; public static partial class Legal { - public const int MaxSpeciesID_7_SM = 802; - public const int MaxMoveID_7_SM = 719; - public const int MaxItemID_7_SM = 920; - public const int MaxAbilityID_7_SM = 232; - public const int MaxBallID_7_SM = (int)Ball.Beast; - public const int MaxGameID_7_SM = (int)GameVersion.C; - public const int MaxSpeciesID_7_USUM = 807; - public const int MaxMoveID_7_USUM = 728; - public const int MaxItemID_7_USUM = 959; public const int MaxAbilityID_7_USUM = 233; #region Inventory Pouch - public static readonly ushort[] Pouch_Regular_SM = // 00 - [ - 068, 069, 070, 071, 072, 073, 074, 075, 076, 077, 078, 079, 080, 081, 082, 083, 084, 085, 086, 087, - 088, 089, 090, 091, 092, 093, 094, 099, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 116, 117, 118, 119, 135, 136, 137, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 499, 534, 535, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, - 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 571, 572, 573, 580, 581, 582, 583, - 584, 585, 586, 587, 588, 589, 590, 639, 640, 644, 646, 647, 648, 649, 650, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, - 680, 681, 682, 683, 684, 685, 699, 704, 710, 711, 715, 752, 753, 754, 755, 756, 757, 758, 759, 760, - 761, 762, 763, 764, 767, 768, 769, 770, 795, 796, 844, 849, 853, 854, 855, 856, 879, 880, 881, 882, - 883, 884, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, - ]; - - public static readonly ushort[] Pouch_Ball_SM = [ // 08 - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 492, 493, 494, 495, 496, 497, 498, 576, - 851, - ]; - - public static readonly ushort[] Pouch_Battle_SM = [ // 16 - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 577, - 846, - ]; - - public static readonly ushort[] Pouch_Items_SM = [.. Pouch_Regular_SM, .. Pouch_Ball_SM, .. Pouch_Battle_SM]; - - public static readonly ushort[] Pouch_Key_SM = [ - 216, 465, 466, 628, 629, 631, 632, 638, - 705, 706, 765, 773, 797, - 841, 842, 843, 845, 847, 850, 857, 858, 860, - ]; - - public static readonly ushort[] Pouch_Key_USUM = [.. Pouch_Key_SM, - 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, - 440, - ]; - - public static readonly ushort[] Pouch_Roto_USUM = [ - 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, - ]; - public static readonly ushort[] Pouch_TMHM_SM = [ // 02 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, @@ -74,206 +18,7 @@ public static partial class Legal 418, 419, 618, 619, 620, 690, 691, 692, 693, 694, ]; - public static readonly ushort[] Pouch_Medicine_SM = [ // 32 - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 65, 66, 67, 134, - 504, 565, 566, 567, 568, 569, 570, 591, 645, 708, 709, - 852, - ]; - - public static readonly ushort[] Pouch_Berries_SM = [ - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, - 686, 687, 688, - ]; - - public static readonly ushort[] Pouch_ZCrystal_SM = [ // Bead - 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, - ]; - - public static readonly ushort[] Pouch_ZCrystalHeld_SM = [ // Piece - 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 798, 799, 800, 801, 802, 803, 804, 805, 806, 836, - ]; - - public static readonly ushort[] Pouch_ZCrystal_USUM = [.. Pouch_ZCrystal_SM, // Bead - 927, 928, 929, 930, 931, 932, - ]; - - public static readonly ushort[] Pouch_ZCrystalHeld_USUM = [.. Pouch_ZCrystalHeld_SM, // Piece - 921, 922, 923, 924, 925, 926, - ]; - - public static readonly Dictionary ZCrystalDictionary = GetDictionary(Pouch_ZCrystal_USUM, Pouch_ZCrystalHeld_USUM); - - private static Dictionary GetDictionary(IReadOnlyList key, IReadOnlyList held) - { - var result = new Dictionary(held.Count); - for (int i = 0; i < key.Count; i++) - result.Add(key[i], held[i]); - return result; - } - - public static readonly ushort[] HeldItems_SM = [.. Pouch_Items_SM, .. Pouch_Berries_SM, .. Pouch_Medicine_SM, .. Pouch_ZCrystalHeld_SM]; - public static readonly ushort[] HeldItems_USUM = [.. Pouch_Items_SM, .. Pouch_Berries_SM, .. Pouch_Medicine_SM, .. Pouch_ZCrystalHeld_USUM, .. Pouch_Roto_USUM]; #endregion - - public static readonly HashSet AlolanOriginForms = - [ - (int)Rattata, - (int)Raticate, - (int)Sandshrew, - (int)Sandslash, - (int)Vulpix, - (int)Ninetales, - (int)Diglett, - (int)Dugtrio, - (int)Meowth, - (int)Persian, - (int)Geodude, - (int)Graveler, - (int)Golem, - (int)Grimer, - (int)Muk, - ]; - - public static readonly HashSet AlolanVariantEvolutions12 = - [ - (int)Raichu, - (int)Exeggutor, - (int)Marowak, - ]; - - public static readonly HashSet EvolveToAlolanForms = - [..AlolanVariantEvolutions12.Concat(AlolanOriginForms)]; - - public static readonly HashSet PastGenAlolanNatives = - [ - 010, 011, 012, 019, 020, 021, 022, 025, 026, 027, 028, 035, 036, 037, 038, 039, 040, 041, 042, 046, 047, 050, - 051, 052, 053, 054, 055, 056, 057, 058, 059, 060, 061, 062, 063, 064, 065, 066, 067, 068, 072, 073, 074, 075, - 076, 079, 080, 081, 082, 088, 089, 090, 091, 092, 093, 094, 096, 097, 102, 103, 104, 105, 113, 115, 118, 119, - 120, 121, 123, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 142, 143, 147, 148, 149, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 185, 186, 196, 197, 198, 199, 200, 209, 210, 212, 215, 222, 225, - 227, 233, 235, 239, 240, 241, 242, 278, 279, 283, 284, 296, 297, 299, 302, 318, 319, 320, 321, 324, 327, 328, - 329, 330, 339, 340, 349, 350, 351, 359, 361, 362, 369, 370, 371, 372, 373, 374, 375, 376, 408, 409, 410, 411, - 422, 423, 425, 426, 429, 430, 438, 440, 443, 444, 445, 446, 447, 448, 456, 457, 461, 462, 466, 467, 470, 471, - 474, 476, 478, 506, 507, 508, 524, 525, 526, 546, 547, 548, 549, 551, 552, 553, 564, 565, 566, 567, 568, 569, - 582, 583, 584, 587, 594, 627, 628, 629, 630, 661, 662, 663, 674, 675, 700, 703, 704, 705, 706, 707, 708, 709, - 718, - - // Regular - 023, 086, 108, 122, 138, 140, 163, 177, 179, 190, 204, - 206, 214, 223, 228, 238, 246, 303, 309, 341, 343, - 345, 347, 352, 353, 357, 366, 427, 439, 458, 550, - 559, 570, 572, 592, 605, 619, 621, 622, 624, 636, - 667, 669, 676, 686, 690, 692, 696, 698, 701, 702, - 714, - - // Wormhole - 333, 334, // Altaria - 193, 469, // Yanmega - 561, // Sigilyph - 580, 581, // Swanna - 276, 277, // Swellow - 451, 452, // Drapion - 531, // Audino - 694, 695, // Heliolisk - 273, 274, 275, // Nuzleaf - 325, 326, // Gumpig - 459, 460, // Abomasnow - 307, 308, // Medicham - 449, 450, // Hippowdon - 557, 558, // Crustle - 218, 219, // Magcargo - 688, 689, // Barbaracle - 270, 271, 272, // Lombre - 618, // Stunfisk - 418, 419, // Floatzel - 194, 195, // Quagsire - - 100, 101, // Voltorb & Electrode - ]; - - public static readonly HashSet ValidMet_SM = - [ - 006, 008, 010, 012, 014, 016, 018, 020, 022, 024, 026, 028, 030, 032, 034, 036, 038, 040, 042, 044, 046, 048, - 050, 052, 054, 056, 058, 060, 062, 064, 068, 070, 072, 074, 076, 078, 082, 084, 086, 088, 090, 092, 094, - 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, - 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, - - 30016, - ]; - - public static readonly HashSet ValidMet_USUM = - [ - ..ValidMet_SM, 198, - 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, - ]; - - #region Unreleased Items - public static readonly bool[] ReleasedHeldItems_7 = GetPermitList(MaxItemID_7_USUM, HeldItems_USUM, stackalloc ushort[] - { - 005, // Safari Ball - 016, // Cherish Ball - 064, // Fluffy Tail - 065, // Blue Flute - 066, // Yellow Flute - 067, // Red Flute - 068, // Black Flute - 069, // White Flute - 070, // Shoal Salt - 071, // Shoal Shell - 103, // Old Amber - 111, // Odd Keystone - 164, // Razz Berry - 166, // Nanab Berry - 167, // Wepear Berry - 175, // Cornn Berry - 176, // Magost Berry - 177, // Rabuta Berry - 178, // Nomel Berry - 179, // Spelon Berry - 180, // Pamtre Berry - 181, // Watmel Berry - 182, // Durin Berry - 183, // Belue Berry - //208, // Enigma Berry - //209, // Micle Berry - //210, // Custap Berry - //211, // Jaboca Berry - //212, // Rowap Berry - 215, // Macho Brace - 260, // Red Scarf - 261, // Blue Scarf - 262, // Pink Scarf - 263, // Green Scarf - 264, // Yellow Scarf - 499, // Sport Ball - 548, // Fire Gem - 549, // Water Gem - 550, // Electric Gem - 551, // Grass Gem - 552, // Ice Gem - 553, // Fighting Gem - 554, // Poison Gem - 555, // Ground Gem - 556, // Flying Gem - 557, // Psychic Gem - 558, // Bug Gem - 559, // Rock Gem - 560, // Ghost Gem - 561, // Dragon Gem - 562, // Dark Gem - 563, // Steel Gem - 576, // Dream Ball - 584, // Relic Copper - 585, // Relic Silver - 587, // Relic Vase - 588, // Relic Band - 589, // Relic Statue - 590, // Relic Crown - 699, // Discount Coupon - 715, // Fairy Gem - }); - #endregion - public static readonly HashSet Totem_Alolan = [ (int)Raticate, // (Normal, Alolan, Totem) @@ -281,25 +26,6 @@ public static partial class Legal (int)Mimikyu, // (Normal, Busted, Totem, Totem_Busted) ]; - public static readonly HashSet Totem_NoTransfer = - [ - (int)Marowak, - (int)Araquanid, - (int)Togedemaru, - (int)Ribombee, - ]; - public static readonly HashSet Totem_SM = - [ - (int)Raticate, - (int)Gumshoos, - // (int)Wishiwashi, - (int)Salazzle, - (int)Lurantis, - (int)Vikavolt, - (int)Mimikyu, - (int)Kommoo, - ]; - public static readonly HashSet Totem_USUM = [ (int)Raticate, @@ -315,6 +41,4 @@ public static partial class Legal (int)Togedemaru, (int)Ribombee, ]; - - public static readonly ushort[] HeldItemsBuy_SM = [.. Pouch_Items_SM, .. Pouch_Medicine_SM]; } diff --git a/pkNX.Structures/Legality/Tables/Tables7b.cs b/pkNX.Structures/Legality/Tables/Tables7b.cs index 301e9a29..71d5f050 100644 --- a/pkNX.Structures/Legality/Tables/Tables7b.cs +++ b/pkNX.Structures/Legality/Tables/Tables7b.cs @@ -1,5 +1,3 @@ -using System; - namespace pkNX.Structures; public static partial class Legal @@ -7,45 +5,9 @@ public static partial class Legal public const int MaxSpeciesID_7_GG = 809; // Melmetal public const int MaxMoveID_7_GG = 742; // Double Iron Bash public const int MaxItemID_7_GG = 1057; // Magmar Candy - public const int MaxBallID_7_GG = (int)Ball.Beast; - public const int MaxGameID_7_GG = (int)GameVersion.GE; public const int MaxAbilityID_7_GG = MaxAbilityID_7_USUM; public const byte AwakeningMax = 200; - #region Met Locations - - public static readonly int[] Met_GG_0 = - [ - 002, // Invalid - 003, 004, 005, 006, 007, 008, 009, - 010, 011, 012, 012, 013, 014, 015, 016, 017, 018, 019, - 020, 021, 022, 022, 023, 024, 025, 026, 027, 028, 029, - 030, 031, 032, 032, 033, 034, 035, 036, 037, 038, 039, - 040, 041, 042, 042, 043, 044, 045, 046, 047, 048, 049, - 050, 051, 052, 053, - ]; - - public static readonly int[] Met_GG_3 = - [ - 30001, 30003, 30004, 30005, 30006, 30007, 30008, 30009, 30010, 30011, 30012, 30013, 30014, 30015, 30016, 30017, - ]; - - public static readonly int[] Met_GG_4 = - [ - 40001, 40002, 40003, 40004, 40005, 40006, 40007, 40008, 40009, - 40010, 40011, 40012, 40013, 40014, 40015, 40016, 40017, 40018, 40019, - 40020, 40021, 40022, 40023, 40024, 40025, 40026, 40027, 40028, 40029, - 40030, 40031, 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039, - 40040, 40041, 40042, 40043, 40044, 40045, 40046, 40047, 40048, 40049, - 40050, 40051, 40052, 40053, 40054, 40055, 40056, 40057, 40058, 40059, - 40060, 40061, 40062, 40063, 40064, 40065, 40066, 40067, 40068, 40069, - 40070, 40071, 40072, 40073, 40074, 40075, 40076, 40077, - ]; - - public static readonly int[] Met_GG_6 = [/* XY */ 60001, 60003, /* ORAS */ 60004]; - - #endregion - #region Items public static readonly ushort[] Pouch_Candy_GG_Regular = @@ -77,16 +39,6 @@ public static partial class Legal 017, 018, 019, 020, 021, 022, 023, 024, 025, 026, 027, 028, 029, 030, 031, 032, 038, 039, 040, 041, 709, 903, ]; - public static readonly ushort[] Pouch_TM_GG = - [ - 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, 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, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, - ]; - public static readonly ushort[] Pouch_PowerUp_GG = [ 051, 053, 081, 082, 083, 084, 085, @@ -142,51 +94,12 @@ public static partial class Legal 902, // Max Lure ]; - public static readonly ushort[] Pouch_Regular_GG_Key = - [ - 113, // Tea - 115, // Autograph - 121, // Pokémon Box - 122, // Medicine Pocket - 123, // TM Case - 124, // Candy Jar - 125, // Power-Up Pocket - 126, // Clothing Trunk - 127, // Catching Pocket - 128, // Battle Pocket - 442, // Town Map - 632, // Shiny Charm - 651, // Poké Flute - - 872, // Secret Key - 873, // S.S. Ticket - 874, // Silph Scope - 875, // Parcel - 876, // Card Key - 877, // Gold Teeth - 878, // Lift Key - 885, // Stretchy Spring - 886, // Chalky Stone - 887, // Marble - 888, // Lone Earring - 889, // Beach Glass - 890, // Gold Leaf - 891, // Silver Leaf - 892, // Polished Mud Ball - 893, // Tropical Shell - 894, // Leaf Letter (P) - 895, // Leaf Letter (E) - 896, // Small Bouquet - ]; - public static readonly ushort[] HeldItems_GG = [.. Pouch_Candy_GG, .. Pouch_Medicine_GG, .. Pouch_PowerUp_GG, .. Pouch_Catching_GG, .. Pouch_Battle_GG, .. Pouch_Regular_GG_Item]; #endregion #region Moves - public static bool IsAllowedMoveGG(ushort move) => Array.BinarySearch(AllowedMovesGG, move) >= 0; - private static readonly int[] AllowedMovesGG = [ 000, 001, 002, 003, 004, 005, 006, 007, 008, 009, @@ -216,29 +129,6 @@ public static partial class Legal 740, 742, ]; - public static readonly int[] MovePP_GG = - [ - // Absorb: 25 -> 15 (damage buffed from 20->40) - // Mega Drain: 15 -> 10 (damage buffed from 40->75) - - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 15, 10, 10, 20, 25, 10, 35, 30, 15, 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, 20, 10, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 20, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 10, - 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, 10, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, 15, - 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, - 10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, 10, - 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, - 05, 10, 05, 05, 15, 10, 05, 05, 05, 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, 20, - 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 01, 01, 01, 01, 01, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 40, 15, 20, 30, 20, 15, 15, 20, 10, 15, 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, 05, 15, 05, 01, 01, 01, 01, 01, 01, 15, 15, 15, 20, 15, 15, 15, 15, 15, 15, 15, 15, 20, 05, - ]; - public static readonly ushort[] TMHM_GG = [ 029, 269, 270, 100, 156, 113, 182, 164, 115, 091, @@ -252,26 +142,5 @@ public static partial class Legal // No HMs ]; - public static readonly int[] Tutor_StarterPikachu = - [ - 729, // Zippy Zap - 730, // Splishy Splash - 731, // Floaty Fall - 732, // Pika Papow - ]; - - public static readonly int[] Tutor_StarterEevee = - [ - 733, // Bouncy Bubble - 734, // Buzzy Buzz - 735, // Sizzly Slide - 736, // Glitzy Glow - 737, // Baddy Bad - 738, // Sappy Seed - 739, // Freezy Frost - 740, // Sparkly Swirl - 741, // Veevee Volley - ]; - #endregion } diff --git a/pkNX.Structures/Legality/Tables/Tables8.cs b/pkNX.Structures/Legality/Tables/Tables8.cs index 96e83b09..1f7bfdec 100644 --- a/pkNX.Structures/Legality/Tables/Tables8.cs +++ b/pkNX.Structures/Legality/Tables/Tables8.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; -using System.Linq; using static pkNX.Structures.Species; namespace pkNX.Structures; @@ -33,91 +31,6 @@ public static partial class Legal public const int MaxBallID_8 = 0x1A; // 26 Beast public const int MaxGameID_8 = 45; // Shield - #region Met Locations - public static readonly int[] Met_SWSH_0 = - [ - 002, 004, 006, 008, - 012, 014, 016, 018, - 020, 022, 024, 028, - 030, 032, 034, 036, - 040, 044, 046, 048, - 052, 054, 056, 058, - 060, 064, 066, 068, - 070, 072, 076, 078, - 080, 084, 086, 088, - 090, 092, 094, 096, 098, - 102, 104, 106, 108, - 110, 112, 114, 116, 118, - 120, 122, 124, 126, 128, - 130, 132, 134, 136, 138, - 140, 142, 144, 146, 148, - 150, 152, 154, 156, 158, - 160, 162, 164, 166, 168, - 170, 172, 174, 176, 178, - 180, 182, 184, 186, 188, - 190, 192, 194, 196, 198, - 200, 202, - - 204, 206, 208, - 210, 212, 214, 216, 218, - 220, 222, 224, 226, 228, - 230, 232, 234, 236, 238, - 240, 242, 244, 246, - ]; - - public static readonly int[] Met_SWSH_3 = - [ - 30001, 30003, 30004, 30005, 30006, 30007, 30008, 30009, 30010, 30011, 30012, 30013, 30014, 30015, 30016, 30017, 30018, - ]; - - public static readonly int[] Met_SWSH_4 = - [ - 40001, 40002, 40003, 40005, 40006, 40007, 40008, 40009, 40010, - 40011, 40012, 40013, 40014, 40016, 40017, 40018, 40019, 40020, - 40021, 40022, 40024, 40025, 40026, 40027, 40028, 40029, 40030, - 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039, 40040, - 40041, 40042, 40043, 40044, 40045, 40047, 40048, 40049, 40050, - 40051, 40052, 40053, 40055, 40056, 40057, 40058, 40059, 40060, - 40061, 40063, 40064, 40065, 40066, 40067, 40068, 40069, 40070, - 40071, 40072, 40074, 40075, 40076, 40077, 40078, 40079, 40080, - 40081, 40082, 40083, 40084, 40085, 40086, - ]; - - public static readonly int[] Met_SWSH_6 = [/* XY */ 60001, 60003, /* ORAS */ 60004]; - - public static readonly HashSet ValidMet_SWSH = - [ - 006, 008, - 012, 014, 016, 018, - 020, 022, 024, 028, - 030, 032, 034, 036, - 040, 044, 046, 048, - 052, 054, 056, 058, - 060, 064, 066, 068, - 070, 072, 076, 078, - 080, 084, 086, 088, - 090, 092, 094, 096, 098, - 102, 104, 106, 108, - 110, 112, 114, 116, 118, - 120, 122, 124, 126, 128, - 130, 132, 134, 136, 138, - 140, 142, 144, 146, 148, - 150, 152, 154, 156, 158, - 160, 164, 166, 168, - 170, 172, 174, 176, 178, - 180, 182, 184, 186, 188, - 190, 192, 194, 196, 198, - 200, - - 202, 204, 206, 208, 210, - 212, 214, 216, 218, 220, - 222, 224, 226, 228, 230, - 232, 234, 236, 238, 240, - 242, 244, 246, - ]; - - #endregion - #region Inventory Pouch public static readonly ushort[] Dynamax_Crystals_SWSH = [ @@ -181,20 +94,6 @@ public static partial class Legal public static readonly ushort[] Pouch_Items_SWSH = [.. Pouch_Regular_SWSH, .. Pouch_Ball_SWSH, .. Pouch_Battle_SWSH]; - public static readonly ushort[] Pouch_Key_SWSH = - [ - 078, - 628, 629, 631, 632, 638, - 703, - 847, - 943, 944, 945, 946, - 1074, 1075, 1076, 1077, 1080, 1081, 1100, 1255, 1266, 1267, - 1269, 1270, 1271, 1278, 1583, 1584, 1585, 1586, 1587, 1589, - - // DLC 2 - 1590, 1591, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1605, 1607, - ]; - public static readonly ushort[] Pouch_TM_SWSH = [ 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, @@ -338,41 +237,6 @@ public static partial class Legal #endregion - public static readonly HashSet GalarOriginForms = - [ - (int)Meowth, - (int)Ponyta, - (int)Rapidash, - (int)Slowpoke, - (int)Farfetchd, - (int)MrMime, - (int)Corsola, - (int)Zigzagoon, - (int)Linoone, - (int)Yamask, - (int)Darumaka, - (int)Darmanitan, - (int)Stunfisk, - ]; - - public static readonly HashSet GalarVariantFormEvolutions = - [ - (int)MrMime, - (int)Weezing, - ]; - - public static readonly HashSet GalarForm0Evolutions = - [ - (int)Obstagoon, - (int)Perrserker, - (int)Cursola, - (int)Sirfetchd, - (int)MrRime, - (int)Runerigus, - ]; - - public static readonly HashSet EvolveToGalarForms = [..GalarVariantFormEvolutions.Concat(GalarOriginForms)]; - public static readonly int[] GigantamaxForms = [ (int)Charizard, diff --git a/pkNX.Structures/Legality/Tables/Tables9.cs b/pkNX.Structures/Legality/Tables/Tables9.cs index b28464db..ad163014 100644 --- a/pkNX.Structures/Legality/Tables/Tables9.cs +++ b/pkNX.Structures/Legality/Tables/Tables9.cs @@ -2,6 +2,13 @@ namespace pkNX.Structures; public static partial class Legal { + public const int MaxSpeciesID_9a = 1010; + public const int MaxMoveID_9a = (int)Move.MalignantChain; + public const int MaxItemID_9a = 2557; // Briar's Book + public const int MaxBallID_9a = (int)Ball.LAOrigin; + public const int MaxGameID_9a = (int)GameVersion.ZA; + public const int MaxAbilityID_9a = 310; // Poison Puppeteer + public const int MaxSpeciesID_9 = 1025; public const int MaxMoveID_9 = (int)Move.MalignantChain; public const int MaxItemID_9 = 2557; // Briar's Book diff --git a/pkNX.Structures/Maison/Maison6.cs b/pkNX.Structures/Maison/Maison6.cs deleted file mode 100644 index 95a5814f..00000000 --- a/pkNX.Structures/Maison/Maison6.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.IO; - -namespace pkNX.Structures; - -public class Maison6Trainer -{ - public ushort Class { get; set; } - public ushort Count { get; set; } - public ushort[] Choices { get; set; } - - public Maison6Trainer() - { - Choices = []; - } - - public Maison6Trainer(byte[] data) - { - Class = BitConverter.ToUInt16(data, 0); - Count = BitConverter.ToUInt16(data, 2); - Choices = new ushort[Count]; - for (int i = 0; i < Count; i++) - Choices[i] = BitConverter.ToUInt16(data, 4 + (2 * i)); - } - - public byte[] Write() - { - using var ms = new MemoryStream(); - using var bw = new BinaryWriter(ms); - bw.Write(Class); - bw.Write(Count); - foreach (ushort Choice in Choices) - bw.Write(Choice); - return ms.ToArray(); - } -} - -public class Maison6Pokemon -{ - public ushort Species; - public readonly ushort[] Moves = new ushort[4]; - private readonly byte EV; - public readonly bool[] EVs = new bool[6]; - public byte Nature; - public ushort Item; - public ushort Form; - - public int Move1 { get => Moves[0]; set => Moves[0] = (ushort)value; } - public int Move2 { get => Moves[1]; set => Moves[1] = (ushort)value; } - public int Move3 { get => Moves[2]; set => Moves[2] = (ushort)value; } - public int Move4 { get => Moves[3]; set => Moves[3] = (ushort)value; } - public bool HP { get => EVs[0]; set => EVs[0] = value; } - public bool ATK { get => EVs[1]; set => EVs[1] = value; } - public bool DEF { get => EVs[2]; set => EVs[2] = value; } - public bool SPE { get => EVs[3]; set => EVs[3] = value; } - public bool SPA { get => EVs[4]; set => EVs[4] = value; } - public bool SPD { get => EVs[5]; set => EVs[5] = value; } - - public Maison6Pokemon(byte[] data) - { - Species = BitConverter.ToUInt16(data, 0); - for (int i = 0; i < 4; i++) - Moves[i] = BitConverter.ToUInt16(data, 2 + (2 * i)); - EV = data[0xA]; - for (int i = 0; i < 6; i++) - EVs[i] = ((EV >> i) & 1) == 1; - Nature = data[0xB]; - Item = BitConverter.ToUInt16(data, 0xC); - Form = BitConverter.ToUInt16(data, 0xE); - } - - public byte[] Write() - { - using var ms = new MemoryStream(); - using var bw = new BinaryWriter(ms); - bw.Write(Species); - foreach (ushort Move in Moves) - bw.Write(Move); - - int ev = EV & 0xC0; - for (int i = 0; i < EVs.Length; i++) - ev |= EVs[i] ? 1 << i : 0; - bw.Write((byte)ev); - - bw.Write(Nature); - bw.Write(Item); - bw.Write(Form); - return ms.ToArray(); - } -} diff --git a/pkNX.Structures/MegaEvolution/MegaEvolutionSet.cs b/pkNX.Structures/MegaEvolution/MegaEvolutionSet.cs index 9e233e47..55f63764 100644 --- a/pkNX.Structures/MegaEvolution/MegaEvolutionSet.cs +++ b/pkNX.Structures/MegaEvolution/MegaEvolutionSet.cs @@ -1,65 +1,43 @@ using System; -using System.Diagnostics; -using System.Linq; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; -public class MegaEvolutionSet +public class MegaEvolutionSet(Memory Raw) { - private readonly byte[] Data; - private const int OFS_FORM = 0; - private const int OFS_METHOD = 2; - private const int OFS_ARGUMENT = 4; + public Span Data => Raw.Span; + public const int SIZE = 8; - public MegaEvolutionSet(byte[] data, int index) + public MegaEvolutionSet(ReadOnlySpan data) : this(data[..SIZE].ToArray().AsMemory()) { - Debug.Assert(data.Length % SIZE == 0); - Data = new byte[SIZE]; - Array.Copy(data, index*SIZE, Data, 0, SIZE); } - public static MegaEvolutionSet[] ReadArray(byte[] data) + public static MegaEvolutionSet[] ReadArray(ReadOnlySpan data) { var count = data.Length / SIZE; var result = new MegaEvolutionSet[count]; for (int i = 0; i < count; i++) - result[i] = new MegaEvolutionSet(data, i); + result[i] = new MegaEvolutionSet(data[(i * SIZE)..]); return result; } public static byte[] WriteArray(MegaEvolutionSet[] data) { - return data.SelectMany(z => z.Write()).ToArray(); + var result = new byte[SIZE * data.Length]; + var span = result.AsSpan(); + for (int i = 0; i < data.Length; i++) + data[i].Data.CopyTo(span[(i * SIZE)..]); + return result; } - public int ToForm - { - get => BitConverter.ToUInt16(Data, OFS_FORM); - set => BitConverter.GetBytes((ushort) value).CopyTo(Data, OFS_FORM); - } + public int ToForm { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, (ushort)value); } + public int Method {get => ReadUInt16LittleEndian(Data[2..]); set => WriteUInt16LittleEndian(Data[2..], (ushort)value); } + public int Argument { get => ReadUInt16LittleEndian(Data[4..]); set => WriteUInt16LittleEndian(Data[4..], (ushort)value); } - public int Method - { - get => BitConverter.ToUInt16(Data, OFS_METHOD); - set => BitConverter.GetBytes((ushort)value).CopyTo(Data, OFS_METHOD); - } - - public int Argument - { - get => BitConverter.ToUInt16(Data, OFS_ARGUMENT); - set => BitConverter.GetBytes((ushort)value).CopyTo(Data, OFS_ARGUMENT); - } - - public void Clear() - { - for (int i = 0; i < Data.Length; i++) - Data[i] = 0; - } - - public byte[] Write() => (byte[])Data.Clone(); - - public void Write(byte[] data, int index) => Data.CopyTo(data, index * SIZE); + public void Clear() => Data.Clear(); + public byte[] Write() => Data.ToArray(); + public void Write(Span dest) => Data.CopyTo(dest); public void RemoveRestrictions() { diff --git a/pkNX.Structures/Move/Move.cs b/pkNX.Structures/Move/Move.cs index cd248b0b..09e6710f 100644 --- a/pkNX.Structures/Move/Move.cs +++ b/pkNX.Structures/Move/Move.cs @@ -1,11 +1,13 @@ +using System; + namespace pkNX.Structures; -public abstract class Move3DS(byte[] data) : IMove +public abstract class Move3DS(Memory raw) : IMove { - protected readonly byte[] Data = data; + protected Span Data => raw.Span; protected abstract int SIZE { get; } - public byte[] Write() => Data; + public byte[] Write() => Data.ToArray(); public abstract int Type { get; set; } public abstract int Quality { get; set; } diff --git a/pkNX.Structures/Move/Move6.cs b/pkNX.Structures/Move/Move6.cs index dc8015e2..33e4e569 100644 --- a/pkNX.Structures/Move/Move6.cs +++ b/pkNX.Structures/Move/Move6.cs @@ -1,8 +1,9 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; -public class Move6(byte[] data) : Move3DS(data) +public class Move6(Memory data) : Move3DS(data) { private const int Size = 0x22; protected override int SIZE => Size; @@ -17,14 +18,14 @@ public class Move6(byte[] data) : Move3DS(data) public override int Priority { get => Data[0x06]; set => Data[0x06] = (byte)value; } public override int HitMin { get => Data[0x07] & 0xF; set => Data[0x07] = (byte)(HitMax << 4 | value); } public override int HitMax { get => Data[0x07] >> 4; set => Data[0x07] = (byte)(value << 4 | HitMin); } - public override int Inflict { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); } + public override int Inflict { get => ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], (ushort)value); } public override int InflictPercent { get => Data[0x0A]; set => Data[0x0A] = (byte)value; } public override MoveInflictDuration InflictCount { get => (MoveInflictDuration)Data[0x0B]; set => Data[0x0B] = (byte)value; } public override int TurnMin { get => Data[0x0C]; set => Data[0x0C] = (byte)value; } public override int TurnMax { get => Data[0x0D]; set => Data[0x0D] = (byte)value; } public override int CritStage { get => Data[0x0E]; set => Data[0x0E] = (byte)value; } public override int Flinch { get => Data[0x0F]; set => Data[0x0F] = (byte)value; } - public override int EffectSequence { get => BitConverter.ToUInt16(Data, 0x10); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x10); } + public override int EffectSequence { get => ReadUInt16LittleEndian(Data[0x10..]); set => WriteUInt16LittleEndian(Data[0x10..], (ushort)value); } public override int Recoil { get => Data[0x12]; set => Data[0x12] = (byte)value; } public override Heal Healing { get => (Heal)Data[0x13]; set => Data[0x13] = (byte)value; } public override MoveTarget Target { get => (MoveTarget)Data[0x14]; set => Data[0x14] = (byte)value; } @@ -38,5 +39,5 @@ public class Move6(byte[] data) : Move3DS(data) public override int Stat2Percent { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } public override int Stat3Percent { get => Data[0x1D]; set => Data[0x1D] = (byte)value; } - public MoveFlag6 Flags { get => (MoveFlag6)BitConverter.ToUInt32(Data, 0x1E); set => BitConverter.GetBytes((uint)value).CopyTo(Data, 0x1E); } + public MoveFlag6 Flags { get => (MoveFlag6)ReadUInt32LittleEndian(Data[0x1E..]); set => WriteUInt32LittleEndian(Data[0x1E..], (uint)value); } } diff --git a/pkNX.Structures/Move/Move7.cs b/pkNX.Structures/Move/Move7.cs index 4ec6ed0f..8f30c299 100644 --- a/pkNX.Structures/Move/Move7.cs +++ b/pkNX.Structures/Move/Move7.cs @@ -1,8 +1,9 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; -public class Move7(byte[] data) : Move3DS(data) +public class Move7(Memory data) : Move3DS(data) { private const int Size = 0x28; protected override int SIZE => Size; @@ -17,14 +18,14 @@ public class Move7(byte[] data) : Move3DS(data) public override int Priority { get => Data[0x06]; set => Data[0x06] = (byte)value; } public override int HitMin { get => Data[0x07] & 0xF; set => Data[0x07] = (byte)(HitMax << 4 | value); } public override int HitMax { get => Data[0x07] >> 4; set => Data[0x07] = (byte)(value << 4 | HitMin); } - public override int Inflict { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); } + public override int Inflict { get => ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], (ushort)value); } public override int InflictPercent { get => Data[0x0A]; set => Data[0x0A] = (byte)value; } public override MoveInflictDuration InflictCount { get => (MoveInflictDuration)Data[0x0B]; set => Data[0x0B] = (byte)value; } public override int TurnMin { get => Data[0x0C]; set => Data[0x0C] = (byte)value; } public override int TurnMax { get => Data[0x0D]; set => Data[0x0D] = (byte)value; } public override int CritStage { get => Data[0x0E]; set => Data[0x0E] = (byte)value; } public override int Flinch { get => Data[0x0F]; set => Data[0x0F] = (byte)value; } - public override int EffectSequence { get => BitConverter.ToUInt16(Data, 0x10); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x10); } + public override int EffectSequence { get => ReadUInt16LittleEndian(Data[0x10..]); set => WriteUInt16LittleEndian(Data[0x10..], (ushort)value); } public override int Recoil { get => Data[0x12]; set => Data[0x12] = (byte)value; } public override Heal Healing { get => (Heal)Data[0x13]; set => Data[0x13] = (byte)value; } public override MoveTarget Target { get => (MoveTarget)Data[0x14]; set => Data[0x14] = (byte)value; } @@ -38,19 +39,12 @@ public class Move7(byte[] data) : Move3DS(data) public override int Stat2Percent { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } public override int Stat3Percent { get => Data[0x1D]; set => Data[0x1D] = (byte)value; } - public int ZMove { get => BitConverter.ToUInt16(Data, 0x1E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x1E); } // 32 + public int ZMove { get => ReadUInt16LittleEndian(Data[0x1E..]); set => WriteUInt16LittleEndian(Data[0x1E..], (ushort)value); } // 32 public int ZPower { get => Data[0x20]; set => Data[0x20] = (byte)value; } // 33 public int ZEffect { get => Data[0x21]; set => Data[0x21] = (byte)value; } // 34 public RefreshType RefreshAfflictType { get => (RefreshType)Data[0x22]; set => Data[0x22] = (byte)value; } // 35 public int RefreshAfflictPercent { get => Data[0x23]; set => Data[0x23] = (byte)value; } // 36 - public MoveFlag7 Flags { get => (MoveFlag7)BitConverter.ToUInt32(Data, 0x24); set => BitConverter.GetBytes((uint)value).CopyTo(Data, 0x24); } -} - -public class Move8Fake : Move7 -{ - public uint Version { get; set; } - public uint MoveID { get; set; } - public bool CanUseMove { get; set; } + public MoveFlag7 Flags { get => (MoveFlag7)ReadUInt32LittleEndian(Data[0x24..]); set => WriteUInt32LittleEndian(Data[0x24..], (uint)value); } // 37-40 } diff --git a/pkNX.Structures/Personal/Info/PersonalInfo5B2W2.cs b/pkNX.Structures/Personal/Info/PersonalInfo5B2W2.cs index a364e025..807e9ab0 100644 --- a/pkNX.Structures/Personal/Info/PersonalInfo5B2W2.cs +++ b/pkNX.Structures/Personal/Info/PersonalInfo5B2W2.cs @@ -7,35 +7,36 @@ namespace pkNX.Structures; /// /// Personal Info class with values from the Black 2 & White 2 games. /// -public sealed class PersonalInfo5B2W2(byte[] data) : IPersonalInfoB2W2 +public sealed class PersonalInfo5B2W2(Memory raw) : IPersonalInfoB2W2 { public const int SIZE = 0x4C; + public Span Data => raw.Span; - public bool[] TMHM { get; set; } = GetBits(data.AsSpan(0x28, 0x10)); - public bool[] TypeTutors { get; set; } = GetBits(data.AsSpan(0x38, 0x4)); - public bool[] SpecialTutors { get; set; } = GetBits(data.AsSpan(0x3C, 0x16)); // 0x3C - 0x43 + public bool[] TMHM { get; set; } = GetBits(raw.Span.Slice(0x28, 0x10)); + public bool[] TypeTutors { get; set; } = GetBits(raw.Span.Slice(0x38, 0x4)); + public bool[] SpecialTutors { get; set; } = GetBits(raw.Span.Slice(0x3C, 0x16)); // 0x3C - 0x43 // Unpack TMHM & Tutors public byte[] Write() { - SetBits(TMHM, data.AsSpan(0x28)); - SetBits(TypeTutors, data.AsSpan(0x38)); - SetBits(SpecialTutors, data.AsSpan(0x3C)); - return data; + SetBits(TMHM, Data[0x28..]); + SetBits(TypeTutors, Data[0x38..]); + SetBits(SpecialTutors, Data[0x3C..]); + return Data.ToArray(); } - public int HP { get => data[0x00]; set => data[0x00] = (byte)value; } - public int ATK { get => data[0x01]; set => data[0x01] = (byte)value; } - public int DEF { get => data[0x02]; set => data[0x02] = (byte)value; } - public int SPE { get => data[0x03]; set => data[0x03] = (byte)value; } - public int SPA { get => data[0x04]; set => data[0x04] = (byte)value; } - public int SPD { get => data[0x05]; set => data[0x05] = (byte)value; } - public Types Type1 { get => (Types)data[0x06]; set => data[0x06] = (byte)value; } - public Types Type2 { get => (Types)data[0x07]; set => data[0x07] = (byte)value; } - public int CatchRate { get => data[0x08]; set => data[0x08] = (byte)value; } - public int EvoStage { get => data[0x09]; set => data[0x09] = (byte)value; } - private int EVYield { get => ReadUInt16LittleEndian(data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(data.AsSpan(0x0A), (ushort)value); } + public int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } + public int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } + public int DEF { get => Data[0x02]; set => Data[0x02] = (byte)value; } + public int SPE { get => Data[0x03]; set => Data[0x03] = (byte)value; } + public int SPA { get => Data[0x04]; set => Data[0x04] = (byte)value; } + public int SPD { get => Data[0x05]; set => Data[0x05] = (byte)value; } + public Types Type1 { get => (Types)Data[0x06]; set => Data[0x06] = (byte)value; } + public Types Type2 { get => (Types)Data[0x07]; set => Data[0x07] = (byte)value; } + public int CatchRate { get => Data[0x08]; set => Data[0x08] = (byte)value; } + public int EvoStage { get => Data[0x09]; set => Data[0x09] = (byte)value; } + private int EVYield { get => ReadUInt16LittleEndian(Data[0x0A..]); set => WriteUInt16LittleEndian(Data[0x0A..], (ushort)value); } public int EV_HP { get => (EVYield >> 0) & 0x3; set => EVYield = (EVYield & ~(0x3 << 0)) | ((value & 0x3) << 0); } public int EV_ATK { get => (EVYield >> 2) & 0x3; set => EVYield = (EVYield & ~(0x3 << 2)) | ((value & 0x3) << 2); } public int EV_DEF { get => (EVYield >> 4) & 0x3; set => EVYield = (EVYield & ~(0x3 << 4)) | ((value & 0x3) << 4); } @@ -43,30 +44,30 @@ public byte[] Write() public int EV_SPA { get => (EVYield >> 8) & 0x3; set => EVYield = (EVYield & ~(0x3 << 8)) | ((value & 0x3) << 8); } public int EV_SPD { get => (EVYield >> 10) & 0x3; set => EVYield = (EVYield & ~(0x3 << 10)) | ((value & 0x3) << 10); } public bool Telekenesis { get => ((EVYield >> 12) & 1) == 1; set => EVYield = (EVYield & ~(0x1 << 12)) | ((value ? 1 : 0) << 12); } - public int Item1 { get => ReadInt16LittleEndian(data.AsSpan(0x0C)); set => WriteInt16LittleEndian(data.AsSpan(0x0C), (short)value); } - public int Item2 { get => ReadInt16LittleEndian(data.AsSpan(0x0E)); set => WriteInt16LittleEndian(data.AsSpan(0x0E), (short)value); } - public int Item3 { get => ReadInt16LittleEndian(data.AsSpan(0x10)); set => WriteInt16LittleEndian(data.AsSpan(0x10), (short)value); } - public int Gender { get => data[0x12]; set => data[0x12] = (byte)value; } - public byte HatchCycles { get => data[0x13]; set => data[0x13] = value; } - public int BaseFriendship { get => data[0x14]; set => data[0x14] = (byte)value; } - public int EXPGrowth { get => data[0x15]; set => data[0x15] = (byte)value; } - public int EggGroup1 { get => data[0x16]; set => data[0x16] = (byte)value; } - public int EggGroup2 { get => data[0x17]; set => data[0x17] = (byte)value; } - public int Ability1 { get => data[0x18]; set => data[0x18] = (byte)value; } - public int Ability2 { get => data[0x19]; set => data[0x19] = (byte)value; } - public int AbilityH { get => data[0x1A]; set => data[0x1A] = (byte)value; } + public int Item1 { get => ReadInt16LittleEndian(Data[0x0C..]); set => WriteInt16LittleEndian(Data[0x0C..], (short)value); } + public int Item2 { get => ReadInt16LittleEndian(Data[0x0E..]); set => WriteInt16LittleEndian(Data[0x0E..], (short)value); } + public int Item3 { get => ReadInt16LittleEndian(Data[0x10..]); set => WriteInt16LittleEndian(Data[0x10..], (short)value); } + public int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public int EXPGrowth { get => Data[0x15]; set => Data[0x15] = (byte)value; } + public int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } + public int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } + public int Ability1 { get => Data[0x18]; set => Data[0x18] = (byte)value; } + public int Ability2 { get => Data[0x19]; set => Data[0x19] = (byte)value; } + public int AbilityH { get => Data[0x1A]; set => Data[0x1A] = (byte)value; } - public int EscapeRate { get => data[0x1B]; set => data[0x1B] = (byte)value; } - public int FormStatsIndex { get => ReadUInt16LittleEndian(data.AsSpan(0x1C)); set => WriteUInt16LittleEndian(data.AsSpan(0x1C), (ushort)value); } - public int FormSprite { get => ReadUInt16LittleEndian(data.AsSpan(0x1E)); set => WriteUInt16LittleEndian(data.AsSpan(0x1E), (ushort)value); } - public byte FormCount { get => data[0x20]; set => data[0x20] = value; } - public int Color { get => data[0x21] & 0x3F; set => data[0x21] = (byte)((data[0x21] & 0xC0) | (value & 0x3F)); } - public bool SpriteFlip { get => ((data[0x21] >> 6) & 1) == 1; set => data[0x21] = (byte)((data[0x21] & ~0x40) | (value ? 0x40 : 0)); } - public bool SpriteForm { get => ((data[0x21] >> 7) & 1) == 1; set => data[0x21] = (byte)((data[0x21] & ~0x80) | (value ? 0x80 : 0)); } + public int EscapeRate { get => Data[0x1B]; set => Data[0x1B] = (byte)value; } + public int FormStatsIndex { get => ReadUInt16LittleEndian(Data[0x1C..]); set => WriteUInt16LittleEndian(Data[0x1C..], (ushort)value); } + public int FormSprite { get => ReadUInt16LittleEndian(Data[0x1E..]); set => WriteUInt16LittleEndian(Data[0x1E..], (ushort)value); } + public byte FormCount { get => Data[0x20]; set => Data[0x20] = value; } + public int Color { get => Data[0x21] & 0x3F; set => Data[0x21] = (byte)((Data[0x21] & 0xC0) | (value & 0x3F)); } + public bool SpriteFlip { get => ((Data[0x21] >> 6) & 1) == 1; set => Data[0x21] = (byte)((Data[0x21] & ~0x40) | (value ? 0x40 : 0)); } + public bool SpriteForm { get => ((Data[0x21] >> 7) & 1) == 1; set => Data[0x21] = (byte)((Data[0x21] & ~0x80) | (value ? 0x80 : 0)); } - public int BaseEXP { get => ReadUInt16LittleEndian(data.AsSpan(0x22)); set => WriteUInt16LittleEndian(data.AsSpan(0x22), (ushort)value); } - public int Height { get => ReadUInt16LittleEndian(data.AsSpan(0x24)); set => WriteUInt16LittleEndian(data.AsSpan(0x24), (ushort)value); } - public int Weight { get => ReadUInt16LittleEndian(data.AsSpan(0x26)); set => WriteUInt16LittleEndian(data.AsSpan(0x26), (ushort)value); } + public int BaseEXP { get => ReadUInt16LittleEndian(Data[0x22..]); set => WriteUInt16LittleEndian(Data[0x22..], (ushort)value); } + public int Height { get => ReadUInt16LittleEndian(Data[0x24..]); set => WriteUInt16LittleEndian(Data[0x24..], (ushort)value); } + public int Weight { get => ReadUInt16LittleEndian(Data[0x26..]); set => WriteUInt16LittleEndian(Data[0x26..], (ushort)value); } public int AbilityCount => 3; public int GetIndexOfAbility(int abilityID) => abilityID == Ability1 ? 0 : abilityID == Ability2 ? 1 : abilityID == AbilityH ? 2 : -1; diff --git a/pkNX.Structures/Personal/Info/PersonalInfo7SM.cs b/pkNX.Structures/Personal/Info/PersonalInfo7SM.cs index 472f1629..c20c67e1 100644 --- a/pkNX.Structures/Personal/Info/PersonalInfo7SM.cs +++ b/pkNX.Structures/Personal/Info/PersonalInfo7SM.cs @@ -7,29 +7,21 @@ namespace pkNX.Structures; /// /// Personal Info class with values from the Sun & Moon games. /// -public sealed class PersonalInfo7SM : IPersonalInfoSM +public sealed class PersonalInfo7SM(Memory raw) : IPersonalInfoSM { public const int SIZE = 0x54; - private readonly byte[] Data; - public bool[] TMHM { get; set; } - public bool[] TypeTutors { get; set; } - public bool[] SpecialTutors { get; set; } + public Span Data => raw.Span; - public PersonalInfo7SM(byte[] data) - { - Data = data; - TMHM = GetBits(Data.AsSpan(0x28, 0x10)); // 36-39 - TypeTutors = GetBits(Data.AsSpan(0x38, 0x4)); // 40 - - SpecialTutors = GetBits(Data.AsSpan(0x3C, 0x0A)); - } + public bool[] TMHM { get; set; } = GetBits(raw.Span.Slice(0x28, 0x10)); + public bool[] TypeTutors { get; set; } = GetBits(raw.Span.Slice(0x38, 0x4)); + public bool[] SpecialTutors { get; set; } = GetBits(raw.Span.Slice(0x3C, 0x0A)); // 0x3C - 0x43 public byte[] Write() { - SetBits(TMHM, Data.AsSpan(0x28)); - SetBits(TypeTutors, Data.AsSpan(0x38)); - SetBits(SpecialTutors, Data.AsSpan(0x3C)); - return Data; + SetBits(TMHM, Data[0x28..]); + SetBits(TypeTutors, Data[0x38..]); + SetBits(SpecialTutors, Data[0x3C..]); + return Data.ToArray(); } public int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } @@ -42,7 +34,7 @@ public byte[] Write() public Types Type2 { get => (Types)Data[0x07]; set => Data[0x07] = (byte)value; } public int CatchRate { get => Data[0x08]; set => Data[0x08] = (byte)value; } public int EvoStage { get => Data[0x09]; set => Data[0x09] = (byte)value; } - private int EVYield { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } + private int EVYield { get => ReadUInt16LittleEndian(Data[0x0A..]); set => WriteUInt16LittleEndian(Data[0x0A..], (ushort)value); } public int EV_HP { get => (EVYield >> 0) & 0x3; set => EVYield = (EVYield & ~(0x3 << 0)) | ((value & 0x3) << 0); } public int EV_ATK { get => (EVYield >> 2) & 0x3; set => EVYield = (EVYield & ~(0x3 << 2)) | ((value & 0x3) << 2); } public int EV_DEF { get => (EVYield >> 4) & 0x3; set => EVYield = (EVYield & ~(0x3 << 4)) | ((value & 0x3) << 4); } @@ -50,9 +42,9 @@ public byte[] Write() public int EV_SPA { get => (EVYield >> 8) & 0x3; set => EVYield = (EVYield & ~(0x3 << 8)) | ((value & 0x3) << 8); } public int EV_SPD { get => (EVYield >> 10) & 0x3; set => EVYield = (EVYield & ~(0x3 << 10)) | ((value & 0x3) << 10); } public bool Telekenesis { get => ((EVYield >> 12) & 1) == 1; set => EVYield = (EVYield & ~(0x1 << 12)) | ((value ? 1 : 0) << 12); } - public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } - public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } - public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } + public int Item1 { get => ReadInt16LittleEndian(Data[0x0C..]); set => WriteInt16LittleEndian(Data[0x0C..], (short)value); } + public int Item2 { get => ReadInt16LittleEndian(Data[0x0E..]); set => WriteInt16LittleEndian(Data[0x0E..], (short)value); } + public int Item3 { get => ReadInt16LittleEndian(Data[0x10..]); set => WriteInt16LittleEndian(Data[0x10..], (short)value); } public int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } public byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } public int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } @@ -64,19 +56,19 @@ public byte[] Write() public int AbilityH { get => Data[0x1A]; set => Data[0x1A] = (byte)value; } public int EscapeRate { get => Data[0x1B]; set => Data[0x1B] = (byte)value; } - public int FormStatsIndex { get => ReadUInt16LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1C), (ushort)value); } - public int FormSprite { get => ReadUInt16LittleEndian(Data.AsSpan(0x1E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1E), (ushort)value); } + public int FormStatsIndex { get => ReadUInt16LittleEndian(Data[0x1C..]); set => WriteUInt16LittleEndian(Data[0x1C..], (ushort)value); } + public int FormSprite { get => ReadUInt16LittleEndian(Data[0x1E..]); set => WriteUInt16LittleEndian(Data[0x1E..], (ushort)value); } public byte FormCount { get => Data[0x20]; set => Data[0x20] = value; } public int Color { get => Data[0x21] & 0x3F; set => Data[0x21] = (byte)((Data[0x21] & 0xC0) | (value & 0x3F)); } public bool SpriteFlip { get => ((Data[0x21] >> 6) & 1) == 1; set => Data[0x21] = (byte)((Data[0x21] & ~0x40) | (value ? 0x40 : 0)); } public bool SpriteForm { get => ((Data[0x21] >> 7) & 1) == 1; set => Data[0x21] = (byte)((Data[0x21] & ~0x80) | (value ? 0x80 : 0)); } - public int BaseEXP { get => ReadUInt16LittleEndian(Data.AsSpan(0x22)); set => WriteUInt16LittleEndian(Data.AsSpan(0x22), (ushort)value); } - public int Height { get => ReadUInt16LittleEndian(Data.AsSpan(0x24)); set => WriteUInt16LittleEndian(Data.AsSpan(0x24), (ushort)value); } - public int Weight { get => ReadUInt16LittleEndian(Data.AsSpan(0x26)); set => WriteUInt16LittleEndian(Data.AsSpan(0x26), (ushort)value); } + public int BaseEXP { get => ReadUInt16LittleEndian(Data[0x22..]); set => WriteUInt16LittleEndian(Data[0x22..], (ushort)value); } + public int Height { get => ReadUInt16LittleEndian(Data[0x24..]); set => WriteUInt16LittleEndian(Data[0x24..], (ushort)value); } + public int Weight { get => ReadUInt16LittleEndian(Data[0x26..]); set => WriteUInt16LittleEndian(Data[0x26..], (ushort)value); } - public int SpecialZ_Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x4C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x4C), (ushort)value); } - public int SpecialZ_BaseMove { get => ReadUInt16LittleEndian(Data.AsSpan(0x4E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x4E), (ushort)value); } - public int SpecialZ_ZMove { get => ReadUInt16LittleEndian(Data.AsSpan(0x50)); set => WriteUInt16LittleEndian(Data.AsSpan(0x50), (ushort)value); } + public int SpecialZ_Item { get => ReadUInt16LittleEndian(Data[0x4C..]); set => WriteUInt16LittleEndian(Data[0x4C..], (ushort)value); } + public int SpecialZ_BaseMove { get => ReadUInt16LittleEndian(Data[0x4E..]); set => WriteUInt16LittleEndian(Data[0x4E..], (ushort)value); } + public int SpecialZ_ZMove { get => ReadUInt16LittleEndian(Data[0x50..]); set => WriteUInt16LittleEndian(Data[0x50..], (ushort)value); } public bool IsRegionalForm { get => Data[0x52] == 1; set => Data[0x52] = value ? (byte)1 : (byte)0; } } diff --git a/pkNX.Structures/Personal/Table/PersonalTable5B2W2.cs b/pkNX.Structures/Personal/Table/PersonalTable5B2W2.cs deleted file mode 100644 index 18d69980..00000000 --- a/pkNX.Structures/Personal/Table/PersonalTable5B2W2.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using static pkNX.Structures.Species; - -namespace pkNX.Structures; - -/// -/// Personal Table storing used in Generation 5 games. -/// -public sealed class PersonalTable5B2W2 : IPersonalTable, IPersonalTable -{ - public PersonalInfo5B2W2[] Table { get; } - private const int SIZE = PersonalInfo5B2W2.SIZE; - private const int MaxSpecies = 649; - public int MaxSpeciesID => MaxSpecies; - - public PersonalTable5B2W2(ReadOnlySpan data) - { - Table = new PersonalInfo5B2W2[data.Length / SIZE]; - var count = data.Length / SIZE; - for (int i = 0, ofs = 0; i < count; i++, ofs += SIZE) - { - var slice = data.Slice(ofs, SIZE).ToArray(); - Table[i] = new PersonalInfo5B2W2(slice); - } - } - - public void Save() - { - throw new NotImplementedException(); - } - - public PersonalInfo5B2W2 this[int index] => Table[(uint)index < Table.Length ? index : 0]; - public PersonalInfo5B2W2 this[ushort species, byte form] => Table[GetFormIndex(species, form)]; - public PersonalInfo5B2W2 GetFormEntry(ushort species, byte form) => Table[GetFormIndex(species, form)]; - - public int GetFormIndex(ushort species, byte form) - { - if ((uint)species <= MaxSpecies) - return Table[species].FormIndex(species, form); - return 0; - } - - public bool IsSpeciesInGame(ushort species) => (uint)species <= MaxSpecies; - public bool IsPresentInGame(ushort species, byte form) - { - if (!IsSpeciesInGame(species)) - return false; - if (form == 0) - return true; - if (Table[species].HasForm(form)) - return true; - return species switch - { - (int)Unown => form < 28, - (int)Burmy => form < 3, - (int)Mothim => form < 3, - (int)Cherrim => form == 1, - (int)Shellos or (int)Gastrodon => form == 1, - (int)Arceus => form < 17, - (int)Deerling or (int)Sawsbuck => form < 4, - (int)Genesect => form <= 4, - _ => false, - }; - } - - IPersonalInfo[] IPersonalTable.Table => Table; - IPersonalInfo IPersonalTable.this[int index] => this[index]; - IPersonalInfo IPersonalTable.this[ushort species, byte form] => this[species, form]; - IPersonalInfo IPersonalTable.GetFormEntry(ushort species, byte form) => GetFormEntry(species, form); -} diff --git a/pkNX.Structures/Personal/Table/PersonalTable5BW.cs b/pkNX.Structures/Personal/Table/PersonalTable5BW.cs deleted file mode 100644 index a47f5441..00000000 --- a/pkNX.Structures/Personal/Table/PersonalTable5BW.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using static pkNX.Structures.Species; - -namespace pkNX.Structures; - -/// -/// Personal Table storing used in Generation 5 games. -/// -public sealed class PersonalTable5BW : IPersonalTable, IPersonalTable -{ - public PersonalInfo5BW[] Table { get; } - private const int SIZE = PersonalInfo5BW.SIZE; - private const int MaxSpecies = 649; - public int MaxSpeciesID => MaxSpecies; - - public PersonalTable5BW(ReadOnlySpan data) - { - Table = new PersonalInfo5BW[data.Length / SIZE]; - var count = data.Length / SIZE; - for (int i = 0, ofs = 0; i < count; i++, ofs += SIZE) - { - var slice = data.Slice(ofs, SIZE).ToArray(); - Table[i] = new PersonalInfo5BW(slice); - } - } - - public void Save() - { - throw new NotImplementedException(); - } - - public PersonalInfo5BW this[int index] => Table[(uint)index < Table.Length ? index : 0]; - public PersonalInfo5BW this[ushort species, byte form] => Table[GetFormIndex(species, form)]; - public PersonalInfo5BW GetFormEntry(ushort species, byte form) => Table[GetFormIndex(species, form)]; - - public int GetFormIndex(ushort species, byte form) - { - if ((uint)species <= MaxSpecies) - return Table[species].FormIndex(species, form); - return 0; - } - - public bool IsSpeciesInGame(ushort species) => (uint)species <= MaxSpecies; - public bool IsPresentInGame(ushort species, byte form) - { - if (!IsSpeciesInGame(species)) - return false; - if (form == 0) - return true; - if (Table[species].HasForm(form)) - return true; - return species switch - { - (int)Unown => form < 28, - (int)Burmy => form < 3, - (int)Mothim => form < 3, - (int)Cherrim => form == 1, - (int)Shellos or (int)Gastrodon => form == 1, - (int)Arceus => form < 17, - (int)Deerling or (int)Sawsbuck => form < 4, - (int)Genesect => form <= 4, - _ => false, - }; - } - - IPersonalInfo[] IPersonalTable.Table => Table; - IPersonalInfo IPersonalTable.this[int index] => this[index]; - IPersonalInfo IPersonalTable.this[ushort species, byte form] => this[species, form]; - IPersonalInfo IPersonalTable.GetFormEntry(ushort species, byte form) => GetFormEntry(species, form); -} diff --git a/pkNX.Structures/Personal/Table/PersonalTable6AO.cs b/pkNX.Structures/Personal/Table/PersonalTable6AO.cs deleted file mode 100644 index 769b45ca..00000000 --- a/pkNX.Structures/Personal/Table/PersonalTable6AO.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using static pkNX.Structures.Species; - -namespace pkNX.Structures; - -/// -/// Personal Table storing used in Generation 6 games. -/// -public sealed class PersonalTable6AO : IPersonalTable, IPersonalTable -{ - public PersonalInfo6AO[] Table { get; } - private const int SIZE = PersonalInfo6AO.SIZE; - private const int MaxSpecies = Legal.MaxSpeciesID_6; - public int MaxSpeciesID => MaxSpecies; - - public PersonalTable6AO(ReadOnlySpan data) - { - Table = new PersonalInfo6AO[data.Length / SIZE]; - var count = data.Length / SIZE; - for (int i = 0, ofs = 0; i < count; i++, ofs += SIZE) - { - var slice = data.Slice(ofs, SIZE).ToArray(); - Table[i] = new PersonalInfo6AO(slice); - } - } - - public void Save() - { - throw new NotImplementedException(); - } - - public PersonalInfo6AO this[int index] => Table[(uint)index < Table.Length ? index : 0]; - public PersonalInfo6AO this[ushort species, byte form] => Table[GetFormIndex(species, form)]; - public PersonalInfo6AO GetFormEntry(ushort species, byte form) => Table[GetFormIndex(species, form)]; - - public int GetFormIndex(ushort species, byte form) - { - if ((uint)species <= MaxSpeciesID) - return Table[species].FormIndex(species, form); - return 0; - } - - public bool IsSpeciesInGame(ushort species) => (uint)species <= MaxSpecies; - public bool IsPresentInGame(ushort species, byte form) - { - if (!IsSpeciesInGame(species)) - return false; - if (form == 0) - return true; - if (Table[species].HasForm(form)) - return true; - return species switch - { - (int)Unown => form < 28, - (int)Burmy => form < 3, - (int)Mothim => form < 3, - (int)Shellos or (int)Gastrodon => form == 1, - (int)Arceus => form < 18, - (int)Deerling or (int)Sawsbuck => form < 4, - (int)Genesect => form < 5, - (int)Scatterbug or (int)Spewpa => form < 18, - (int)Vivillon => form <= 19, - (int)Flabébé or (int)Florges => form < 5, - (int)Floette => form <= 5, - (int)Xerneas => form == 1, - _ => false, - }; - } - - IPersonalInfo[] IPersonalTable.Table => Table; - IPersonalInfo IPersonalTable.this[int index] => this[index]; - IPersonalInfo IPersonalTable.this[ushort species, byte form] => this[species, form]; - IPersonalInfo IPersonalTable.GetFormEntry(ushort species, byte form) => GetFormEntry(species, form); -} diff --git a/pkNX.Structures/Personal/Table/PersonalTable6XY.cs b/pkNX.Structures/Personal/Table/PersonalTable6XY.cs deleted file mode 100644 index 0c2f74ec..00000000 --- a/pkNX.Structures/Personal/Table/PersonalTable6XY.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using static pkNX.Structures.Species; - -namespace pkNX.Structures; - -/// -/// Personal Table storing used in Generation 6 games. -/// -public sealed class PersonalTable6XY : IPersonalTable, IPersonalTable -{ - public PersonalInfo6XY[] Table { get; } - private const int SIZE = PersonalInfo6XY.SIZE; - private const int MaxSpecies = Legal.MaxSpeciesID_6; - public int MaxSpeciesID => MaxSpecies; - - public PersonalTable6XY(ReadOnlySpan data) - { - Table = new PersonalInfo6XY[data.Length / SIZE]; - var count = data.Length / SIZE; - for (int i = 0, ofs = 0; i < count; i++, ofs += SIZE) - { - var slice = data.Slice(ofs, SIZE).ToArray(); - Table[i] = new PersonalInfo6XY(slice); - } - } - - public void Save() - { - throw new NotImplementedException(); - } - - public PersonalInfo6XY this[int index] => Table[(uint)index < Table.Length ? index : 0]; - public PersonalInfo6XY this[ushort species, byte form] => Table[GetFormIndex(species, form)]; - public PersonalInfo6XY GetFormEntry(ushort species, byte form) => Table[GetFormIndex(species, form)]; - - public int GetFormIndex(ushort species, byte form) - { - if ((uint)species <= MaxSpecies) - return Table[species].FormIndex(species, form); - return 0; - } - - public bool IsSpeciesInGame(ushort species) => (uint)species <= MaxSpecies; - public bool IsPresentInGame(ushort species, byte form) - { - if (!IsSpeciesInGame(species)) - return false; - if (form == 0) - return true; - if (Table[species].HasForm(form)) - return true; - return species switch - { - (int)Unown => form < 28, - (int)Burmy => form < 3, - (int)Mothim => form < 3, - (int)Shellos or (int)Gastrodon => form == 1, - (int)Arceus => form < 18, - (int)Deerling or (int)Sawsbuck => form < 4, - (int)Genesect => form < 5, - (int)Scatterbug or (int)Spewpa => form < 18, - (int)Vivillon => form <= 19, - (int)Flabébé or (int)Florges => form < 5, - (int)Floette => form <= 5, - (int)Xerneas => form == 1, - _ => false, - }; - } - - IPersonalInfo[] IPersonalTable.Table => Table; - IPersonalInfo IPersonalTable.this[int index] => this[index]; - IPersonalInfo IPersonalTable.this[ushort species, byte form] => this[species, form]; - IPersonalInfo IPersonalTable.GetFormEntry(ushort species, byte form) => GetFormEntry(species, form); -} diff --git a/pkNX.Structures/StringSearch.cs b/pkNX.Structures/StringSearch.cs new file mode 100644 index 00000000..83b46ca3 --- /dev/null +++ b/pkNX.Structures/StringSearch.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace pkNX.Structures; + +public static class StringSearch +{ + public static StringResultBucket[] SearchFiles(IEnumerable files, params ReadOnlySpan patterns) + { + var buckets = new StringResultBucket[patterns.Length]; + for (var i = 0; i < patterns.Length; i++) + { + var ascii = Encoding.ASCII.GetBytes(patterns[i]); + buckets[i] = new StringResultBucket(ascii); + } + + foreach (var file in files) + { + var data = File.ReadAllBytes(file).AsSpan(); + for (var i = 0; i < patterns.Length; i++) + { + var bucket = buckets[i]; + ScanForPattern(bucket.Ascii, data, bucket, file); + } + } + return buckets; + } + + private static void ScanForPattern(ReadOnlySpan pattern, ReadOnlySpan data, StringResultBucket bucket, string file) + { + while (true) + { + int index = data.IndexOf(pattern); + if (index == -1) + break; + // get the length of the result. is the length of the pattern plus any ascii bytes + var length = pattern.Length; + while (index + length < data.Length && data[index + length] is >= 0x20 and <= 0x7E) + length++; + // Check backwards too + while (index > 0 && data[index - 1] is >= 0x20 and <= 0x7E) + { + index--; + length++; + } + + var result = Encoding.ASCII.GetString(data.Slice(index, length)); + bucket.List.Add(new StringResult(file, result, index)); + data = data[(index + length)..]; + } + } +} + +public class StringResultBucket(byte[] ascii) +{ + public ReadOnlySpan Ascii => ascii; + public List List { get; } = []; +} + +// ReSharper disable NotAccessedPositionalProperty.Global +public sealed record StringResult(string File, string Result, int Offset); diff --git a/pkNX.Structures/StructConverter.cs b/pkNX.Structures/StructConverter.cs deleted file mode 100644 index af2388ef..00000000 --- a/pkNX.Structures/StructConverter.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace pkNX.Structures; - -internal static class StructConverter -{ - public static T ToStructure(this byte[] bytes) where T : struct - { - var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - try { return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T))!; } - finally { handle.Free(); } - } - - public static T ToClass(this byte[] bytes) where T : class - { - var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - try { return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T))!; } - finally { handle.Free(); } - } - - public static byte[] ToBytesClass(this T obj) where T : class - { - int size = Marshal.SizeOf(obj); - byte[] arr = new byte[size]; - - IntPtr ptr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(obj, ptr, true); - Marshal.Copy(ptr, arr, 0, size); - Marshal.FreeHGlobal(ptr); - return arr; - } - - public static byte[] ToBytes(this T obj) where T : struct - { - int size = Marshal.SizeOf(obj); - byte[] arr = new byte[size]; - - IntPtr ptr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(obj, ptr, true); - Marshal.Copy(ptr, arr, 0, size); - Marshal.FreeHGlobal(ptr); - return arr; - } -} diff --git a/pkNX.Structures/TableUtil.cs b/pkNX.Structures/TableUtil.cs index cd184d42..7315f9c4 100644 --- a/pkNX.Structures/TableUtil.cs +++ b/pkNX.Structures/TableUtil.cs @@ -35,6 +35,20 @@ public static class TableUtil return string.Join(Environment.NewLine, list); } + public static string GetNamedTable(IList arr, IList names, Func index, string? name = null) where T : notnull + { + var list = GetTableRaw(arr).ToArray(); + + // slap in name to column header + list[0] = $"Index{sep}{name ?? typeof(T).Name}{sep}{list[0]}"; + + // slap in row name to row + for (int i = 1; i < list.Length; i++) + list[i] = $"{i - 1}{sep}{names[index(arr[i - 1])]}{sep}{list[i]}"; + + return string.Join(Environment.NewLine, list); + } + public static string GetNamedTypeTable(IList arr, IList names, string? name = null) where T : notnull { var t = arr[0].GetType(); @@ -111,6 +125,6 @@ private static string GetFormattedString(object? obj) private static IEnumerable JoinEnumerator(IEnumerator x) { while (x.MoveNext()) - yield return x.Current; + yield return x.Current!; } } diff --git a/pkNX.Structures/Text/TextFile.cs b/pkNX.Structures/Text/TextFile.cs index d633e27d..13724bcb 100644 --- a/pkNX.Structures/Text/TextFile.cs +++ b/pkNX.Structures/Text/TextFile.cs @@ -131,7 +131,7 @@ public byte[][] LineData { // rebuild LineInfo var lines = new TextLine[value.Length]; - int bytesUsed = sizeof(uint) + value.Length * 8; // SectionLength + LineOffsets + int bytesUsed = sizeof(uint) + (value.Length * 8); // SectionLength + LineOffsets for (int i = 0; i < lines.Length; i++) { lines[i] = new TextLine { Offset = bytesUsed, Length = (ushort)(value[i].Length / 2) }; diff --git a/pkNX.Structures/Util.cs b/pkNX.Structures/Util.cs index 263c6a04..baaaf3ad 100644 --- a/pkNX.Structures/Util.cs +++ b/pkNX.Structures/Util.cs @@ -1,31 +1,11 @@ using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; namespace pkNX.Structures; public static class Util { public static Random Rand { get; set; } = new(); - internal static uint Rand32() => (uint)Rand.Next(1 << 30) << 2 | (uint)Rand.Next(1 << 2); - - private static T[] GetArray(IReadOnlyList entries, Func del) - { - var data = new T[entries.Count]; - for (int i = 0; i < data.Length; i++) - data[i] = del(entries[i]); - return data; - } - - public static T[] GetArray(byte[][] entries, Func del, int size) - { - var data = new T[entries.Length / size]; - for (int i = 0; i < data.Length; i++) - data[i] = del(entries[i]); - return data; - } public static T[] GetArray(this byte[] entries, Func del, int size) { @@ -40,7 +20,7 @@ public static T[] GetArray(this byte[] entries, Func del, int public static T[] GetArray(this byte[] entries, Func del, int size) { - if (entries == null || entries.Length < size) + if (entries.Length < size) return []; var data = new T[entries.Length / size]; @@ -69,40 +49,4 @@ public static T[] GetArray(this ReadOnlySpan entries, FromBytesConstruc } return array; } - - public static T[] GetArray(this Task task, Func del) - { - return GetArray(task.Result, del); - } - - public static T[] GetArray(this Task task, Func del, int size) => GetArray(task.Result, del, size); - - public static string[] GetHexLines(byte[] data, int count = 4) - { - if (data == null) - return []; - - // Generates an x-byte wide space separated string array; leftovers included at the end. - string[] s = new string[(data.Length / count) + (data.Length % count > 0 ? 1 : 0)]; - for (int i = 0; i < s.Length; i++) - s[i] = BitConverter.ToString(data.Skip(i * count).Take(count).ToArray()).Replace('-', ' '); - return s; - } - - public static string[] GetHexLines(uint[] data) => GetHexLines(GetBytes(data)); - - public static byte[] GetBytes(uint[] data) - { - byte[] result = new byte[data.Length * 4]; - for (int i = 0; i < data.Length; i++) - { - int o = i * 4; - var val = data[i]; - result[o + 0] = (byte)(val >> 0); - result[o + 1] = (byte)(val >> 8); - result[o + 2] = (byte)(val >> 16); - result[o + 3] = (byte)(val >> 24); - } - return result; - } } diff --git a/pkNX.Structures/VsTrainer/3DS/TrData6.cs b/pkNX.Structures/VsTrainer/3DS/TrData6.cs deleted file mode 100644 index f1bd5b12..00000000 --- a/pkNX.Structures/VsTrainer/3DS/TrData6.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; - -namespace pkNX.Structures; - -public abstract class TrData6 : TrainerData -{ - protected abstract int Format { get; set; } - public bool HasItem { get => (Format & 1) == 1; set => Format = (ushort)((Format & ~1) | (value ? 1 : 0)); } - public bool HasMoves { get => (Format & 2) == 2; set => Format = (ushort)((Format & ~2) | (value ? 2 : 0)); } - - protected TrData6(byte[] trData, byte[] trPoke) : base(trData) => Team = GetTeam(trPoke); - protected TrData6(byte[] trData) : base(trData) => Team = []; - - public TrPoke6[] Team { get; set; } - - public byte[] WriteTeam() => WriteTeam(Team, HasItem, HasMoves); - public TrPoke6[] GetTeam(byte[] trPoke) => GetTeam(trPoke, NumPokemon, HasItem, HasMoves); - - public static byte[] WriteTeam(TrPoke6[] team, bool HasItem, bool HasMoves) - { - if (team.Length == 0) - return []; - var first = team[0].Write(HasItem, HasMoves); - byte[] result = new byte[first.Length * team.Length]; - first.CopyTo(result, 0); - for (int i = 1; i < team.Length; i++) - team[i].Write(HasItem, HasMoves).CopyTo(result, first.Length * i); - return result; - } - - public static TrPoke6[] GetTeam(byte[] trPoke, int numPokemon, bool item, bool moves) - { - var team = new TrPoke6[numPokemon]; - byte[][] teamData = new byte[numPokemon][]; - int dataLen = trPoke.Length / numPokemon; - for (int i = 0; i < teamData.Length; i++) - { - var arr = teamData[i] = new byte[dataLen]; - Array.Copy(trPoke, i * dataLen, arr, 0, dataLen); - } - - for (int i = 0; i < numPokemon; i++) - team[i] = new TrPoke6(teamData[i], item, moves); - return team; - } -} diff --git a/pkNX.Structures/VsTrainer/3DS/TrData6AO.cs b/pkNX.Structures/VsTrainer/3DS/TrData6AO.cs deleted file mode 100644 index c096d1d3..00000000 --- a/pkNX.Structures/VsTrainer/3DS/TrData6AO.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace pkNX.Structures; - -public sealed class TrData6AO(byte[] data) : TrData6(data) -{ - private const int Size = 0x18; - public override int SIZE => Size; - public TrData6AO() : this(new byte[Size]) { } - - protected override int Format { get => BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); } - public override int Class { get => BitConverter.ToUInt16(Data, 0x02); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x02); } - public ushort Unused { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); } - public override BattleMode Mode { get => (BattleMode) Data[0x06]; set => Data[0x06] = (byte) value; } - public override int NumPokemon { get => Data[0x07]; set => Data[0x07] = (byte)value; } - public override int Item1 { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); } - public override int Item2 { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); } - public override int Item3 { get => BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); } - public override int Item4 { get => BitConverter.ToUInt16(Data, 0x0E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E); } - public override uint AI { get => BitConverter.ToUInt32(Data, 0x10); set => BitConverter.GetBytes(value).CopyTo(Data, 0x10); } - public override bool Heal { get => Data[0x14] == 1; set => Data[0x14] = value ? (byte)1 : (byte)0; } - public override int Money { get => Data[0x15]; set => Data[0x15] = (byte)value; } - public override int Gift { get => BitConverter.ToUInt16(Data, 0x16); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x16); } -} diff --git a/pkNX.Structures/VsTrainer/3DS/TrData6XY.cs b/pkNX.Structures/VsTrainer/3DS/TrData6XY.cs deleted file mode 100644 index 39fefc8c..00000000 --- a/pkNX.Structures/VsTrainer/3DS/TrData6XY.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace pkNX.Structures; - -public sealed class TrData6XY(byte[] data) : TrData6(data) -{ - private const int Size = 0x14; - public override int SIZE => Size; - public TrData6XY() : this(new byte[Size]) { } - - protected override int Format { get => Data[0x00]; set => Data[0x00] = (byte) value; } - public override int Class { get => Data[0x01]; set => Data[0x01] = (byte)value; } - public override BattleMode Mode { get => (BattleMode)Data[0x02]; set => Data[0x02] = (byte)value; } - public override int NumPokemon { get => Data[0x03]; set => Data[0x03] = (byte)value; } - public override int Item1 { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x04); } - public override int Item2 { get => BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x06); } - public override int Item3 { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); } - public override int Item4 { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); } - public override uint AI { get => BitConverter.ToUInt32(Data, 0x0C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x0C); } - public override bool Heal { get => Data[0x10] == 1; set => Data[0x10] = value ? (byte)1 : (byte)0; } - public override int Money { get => Data[0x11]; set => Data[0x11] = (byte)value; } - public override int Gift { get => BitConverter.ToUInt16(Data, 0x12); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x12); } -} diff --git a/pkNX.Structures/VsTrainer/3DS/TrPoke6.cs b/pkNX.Structures/VsTrainer/3DS/TrPoke6.cs deleted file mode 100644 index 8fde70db..00000000 --- a/pkNX.Structures/VsTrainer/3DS/TrPoke6.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.IO; - -namespace pkNX.Structures; - -public class TrPoke6 -{ - public byte IVs; - public byte PID; - public ushort Level; - public ushort Species; - public ushort Form; - public int Ability; - public int Gender; - public int uBit; - public ushort Item; - public ushort[] Moves = new ushort[4]; - - public TrPoke6(byte[] data, bool HasItem, bool HasMoves) - { - using var ms = new MemoryStream(data); - using var br = new BinaryReader(ms); - IVs = br.ReadByte(); - PID = br.ReadByte(); - Level = br.ReadUInt16(); - Species = br.ReadUInt16(); - Form = br.ReadUInt16(); - - Ability = PID >> 4; - Gender = PID & 3; - uBit = (PID >> 3) & 1; - - if (HasItem) - Item = br.ReadUInt16(); - - if (!HasMoves) - return; - - for (int i = 0; i < 4; i++) - Moves[i] = br.ReadUInt16(); - } - - public byte[] Write(bool HasItem, bool HasMoves) - { - using var ms = new MemoryStream(); - using var bw = new BinaryWriter(ms); - bw.Write(IVs); - PID = (byte)(((Ability & 0xF) << 4) | ((uBit & 1) << 3) | (Gender & 0x7)); - bw.Write(PID); - bw.Write(Level); - bw.Write(Species); - bw.Write(Form); - - if (HasItem) - bw.Write(Item); - if (!HasMoves) - return ms.ToArray(); - - foreach (ushort Move in Moves) - bw.Write(Move); - - return ms.ToArray(); - } -} diff --git a/pkNX.Structures/VsTrainer/3DS/TrainerClass6.cs b/pkNX.Structures/VsTrainer/3DS/TrainerClass6.cs deleted file mode 100644 index 717a2766..00000000 --- a/pkNX.Structures/VsTrainer/3DS/TrainerClass6.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace pkNX.Structures; - -public class TrainerClass6 -{ - // todo -} diff --git a/pkNX.Structures/VsTrainer/Base/TrainerData.cs b/pkNX.Structures/VsTrainer/Base/TrainerData.cs index 1045997d..287ab11f 100644 --- a/pkNX.Structures/VsTrainer/Base/TrainerData.cs +++ b/pkNX.Structures/VsTrainer/Base/TrainerData.cs @@ -1,9 +1,11 @@ +using System; + namespace pkNX.Structures; -public abstract class TrainerData(byte[] trData) +public abstract class TrainerData(Memory raw) { public abstract int SIZE { get; } - protected byte[] Data = trData; + protected Span Data => raw.Span; public abstract int Class { get; set; } public abstract BattleMode Mode { get; set; } @@ -21,5 +23,5 @@ public abstract class TrainerData(byte[] trData) // derived public bool HasAllyTrainer => (AI & 8) != 0; - public byte[] Write() => Data; + public byte[] Write() => Data.ToArray(); } diff --git a/pkNX.Structures/VsTrainer/GG/TrainerData7b.cs b/pkNX.Structures/VsTrainer/GG/TrainerData7b.cs index b6f0c162..7b0c8cb1 100644 --- a/pkNX.Structures/VsTrainer/GG/TrainerData7b.cs +++ b/pkNX.Structures/VsTrainer/GG/TrainerData7b.cs @@ -1,27 +1,25 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; -public sealed class TrainerData7b(byte[] data) : TrainerData(data) +public sealed class TrainerData7b(Memory data) : TrainerData(data) { private const int Size = 0x17; public override int SIZE => Size; public TrainerData7b() : this(new byte[Size]) { } - public override int Class { get => BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); } + public override int Class { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, (ushort)value); } public override BattleMode Mode { get => (BattleMode)Data[2]; set => Data[2] = (byte)value; } // Not sure public override int NumPokemon { get => Data[3]; set => Data[3] = (byte)(value % 7); } - public override int Item1 { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x04); } - public override int Item2 { get => BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x06); } - public override int Item3 { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); } - public override int Item4 { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); } - - public override uint AI { get => BitConverter.ToUInt32(Data, 0x0C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x0C); } + public override int Item1 { get => ReadUInt16LittleEndian(Data[0x04..]); set => WriteUInt16LittleEndian(Data[0x04..], (ushort)value); } + public override int Item2 { get => ReadUInt16LittleEndian(Data[0x06..]); set => WriteUInt16LittleEndian(Data[0x06..], (ushort)value); } + public override int Item3 { get => ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], (ushort)value); } + public override int Item4 { get => ReadUInt16LittleEndian(Data[0x0A..]); set => WriteUInt16LittleEndian(Data[0x0A..], (ushort)value); } + public override uint AI { get => ReadUInt32LittleEndian(Data[0x0C..]); set => WriteUInt32LittleEndian(Data[0x0C..], value); } public override bool Heal { get => Data[0x10] == 1; set => Data[0x10] = value ? (byte)1 : (byte)0; } // unused? public override int Money { get => Data[0x11]; set => Data[0x11] = (byte)value; } - // 12 unused - - public override int Gift { get => BitConverter.ToUInt16(Data, 0x14); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14); } + public override int Gift { get => ReadUInt16LittleEndian(Data[0x14..]); set => WriteUInt16LittleEndian(Data[0x14..], (ushort)value); } public int GiftQuantity { get => Data[0x16]; set => Data[0x16] = (byte)value; } } diff --git a/pkNX.Structures/VsTrainer/GG/TrainerData8.cs b/pkNX.Structures/VsTrainer/GG/TrainerData8.cs index f9f49ffc..687df557 100644 --- a/pkNX.Structures/VsTrainer/GG/TrainerData8.cs +++ b/pkNX.Structures/VsTrainer/GG/TrainerData8.cs @@ -1,24 +1,30 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; namespace pkNX.Structures; -public sealed class TrainerData8(byte[] data) : TrainerData(data) +public sealed class TrainerData8(Memory data) : TrainerData(data) { private const int Size = 0x14; public override int SIZE => Size; public TrainerData8() : this(new byte[Size]) { } - public override int Class { get => BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); } + public override int Class + { + get => ReadUInt16LittleEndian(Data[0x00..]); + set => WriteUInt16LittleEndian(Data[0x00..], (ushort)value); + } + public override BattleMode Mode { get => (BattleMode)Data[2]; set => Data[2] = (byte)value; } // Not sure public override int NumPokemon { get => Data[3]; set => Data[3] = (byte)(value % 7); } - public override int Item1 { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x04); } - public override int Item2 { get => BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x06); } - public override int Item3 { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); } - public override int Item4 { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); } + public override int Item1 { get => ReadUInt16LittleEndian(Data[0x04..]); set => WriteUInt16LittleEndian(Data[0x04..], (ushort)value); } + public override int Item2 { get => ReadUInt16LittleEndian(Data[0x06..]); set => WriteUInt16LittleEndian(Data[0x06..], (ushort)value); } + public override int Item3 { get => ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], (ushort)value); } + public override int Item4 { get => ReadUInt16LittleEndian(Data[0x0A..]); set => WriteUInt16LittleEndian(Data[0x0A..], (ushort)value); } - public override uint AI { get => BitConverter.ToUInt32(Data, 0x0C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x0C); } + public override uint AI { get => ReadUInt32LittleEndian(Data[0x0C..]); set => WriteUInt32LittleEndian(Data[0x0C..], value); } public override bool Heal { get => Data[0x10] == 1; set => Data[0x10] = value ? (byte)1 : (byte)0; } // unused? public override int Money { get => Data[0x11]; set => Data[0x11] = (byte)value; } - public override int Gift { get => BitConverter.ToUInt16(Data, 0x12); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x12); } // unused? + public override int Gift { get => ReadUInt16LittleEndian(Data[0x12..]); set => WriteUInt16LittleEndian(Data[0x12..], (ushort)value); } // unused? } diff --git a/pkNX.Tests/pkNX.Tests.FileSystem/pkNX.Tests.FileSystem.csproj b/pkNX.Tests/pkNX.Tests.FileSystem/pkNX.Tests.FileSystem.csproj index 5ac2132f..3f60a929 100644 --- a/pkNX.Tests/pkNX.Tests.FileSystem/pkNX.Tests.FileSystem.csproj +++ b/pkNX.Tests/pkNX.Tests.FileSystem/pkNX.Tests.FileSystem.csproj @@ -7,11 +7,11 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/pkNX.Tests/pkNX.Tests.SourceGen/pkNX.Tests.SourceGen.csproj b/pkNX.Tests/pkNX.Tests.SourceGen/pkNX.Tests.SourceGen.csproj index 1bbcd2d7..5870c2ce 100644 --- a/pkNX.Tests/pkNX.Tests.SourceGen/pkNX.Tests.SourceGen.csproj +++ b/pkNX.Tests/pkNX.Tests.SourceGen/pkNX.Tests.SourceGen.csproj @@ -10,11 +10,11 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/pkNX.Tests/pkNX.Tests.Trinity/pkNX.Tests.Trinity.csproj b/pkNX.Tests/pkNX.Tests.Trinity/pkNX.Tests.Trinity.csproj index 609eb0db..f13618f9 100644 --- a/pkNX.Tests/pkNX.Tests.Trinity/pkNX.Tests.Trinity.csproj +++ b/pkNX.Tests/pkNX.Tests.Trinity/pkNX.Tests.Trinity.csproj @@ -7,11 +7,11 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/pkNX.WinForms/Dumping/DumperSWSH.Designer.cs b/pkNX.WinForms/Dumping/Gen8/DumperSWSH.Designer.cs similarity index 100% rename from pkNX.WinForms/Dumping/DumperSWSH.Designer.cs rename to pkNX.WinForms/Dumping/Gen8/DumperSWSH.Designer.cs diff --git a/pkNX.WinForms/Dumping/DumperSWSH.cs b/pkNX.WinForms/Dumping/Gen8/DumperSWSH.cs similarity index 100% rename from pkNX.WinForms/Dumping/DumperSWSH.cs rename to pkNX.WinForms/Dumping/Gen8/DumperSWSH.cs diff --git a/pkNX.WinForms/Dumping/DumperSWSH.resx b/pkNX.WinForms/Dumping/Gen8/DumperSWSH.resx similarity index 100% rename from pkNX.WinForms/Dumping/DumperSWSH.resx rename to pkNX.WinForms/Dumping/Gen8/DumperSWSH.resx diff --git a/pkNX.WinForms/Dumping/GameDumperSWSH.cs b/pkNX.WinForms/Dumping/Gen8/GameDumperSWSH.cs similarity index 99% rename from pkNX.WinForms/Dumping/GameDumperSWSH.cs rename to pkNX.WinForms/Dumping/Gen8/GameDumperSWSH.cs index f9639d86..0edf5751 100644 --- a/pkNX.WinForms/Dumping/GameDumperSWSH.cs +++ b/pkNX.WinForms/Dumping/Gen8/GameDumperSWSH.cs @@ -185,15 +185,6 @@ public void DumpAHTB() File.WriteAllLines(outname3, gf); } - public static Dictionary ReadAHTB(byte[] data) - { - if (!AHTB.IsAHTB(data)) - throw new ArgumentException("Provided data is not an AHTB file", nameof(data)); - - var tbl = new AHTB(data); - return tbl.ToDictionary(); - } - private TrainerEditor GetTrainerEditor() { var editor = new TrainerEditor @@ -286,7 +277,7 @@ public void DumpItems() var table = GetPath("ItemData.txt"); var bin = GetPath("ItemData.bin"); File.WriteAllText(table, lines); - File.WriteAllBytes(bin, array.SelectMany(z => z.Data).ToArray()); + File.WriteAllBytes(bin, array.SelectMany(z => z.Data.ToArray()).ToArray()); } public void DumpMoves() diff --git a/pkNX.WinForms/Dumping/DumperPLA.Designer.cs b/pkNX.WinForms/Dumping/Gen8a/DumperPLA.Designer.cs similarity index 100% rename from pkNX.WinForms/Dumping/DumperPLA.Designer.cs rename to pkNX.WinForms/Dumping/Gen8a/DumperPLA.Designer.cs diff --git a/pkNX.WinForms/Dumping/DumperPLA.cs b/pkNX.WinForms/Dumping/Gen8a/DumperPLA.cs similarity index 100% rename from pkNX.WinForms/Dumping/DumperPLA.cs rename to pkNX.WinForms/Dumping/Gen8a/DumperPLA.cs diff --git a/pkNX.WinForms/Dumping/DumperPLA.resx b/pkNX.WinForms/Dumping/Gen8a/DumperPLA.resx similarity index 100% rename from pkNX.WinForms/Dumping/DumperPLA.resx rename to pkNX.WinForms/Dumping/Gen8a/DumperPLA.resx diff --git a/pkNX.WinForms/Dumping/GameDumperPLA.cs b/pkNX.WinForms/Dumping/Gen8a/GameDumperPLA.cs similarity index 99% rename from pkNX.WinForms/Dumping/GameDumperPLA.cs rename to pkNX.WinForms/Dumping/Gen8a/GameDumperPLA.cs index 76a6a666..1e681c94 100644 --- a/pkNX.WinForms/Dumping/GameDumperPLA.cs +++ b/pkNX.WinForms/Dumping/Gen8a/GameDumperPLA.cs @@ -256,7 +256,7 @@ public void DumpItems() var table = GetPath("ItemData.txt"); var bin = GetPath("ItemData.bin"); File.WriteAllText(table, lines); - File.WriteAllBytes(bin, array.SelectMany(z => z.Data).ToArray()); + File.WriteAllBytes(bin, array.SelectMany(z => z.Data.ToArray()).ToArray()); } public void DumpMoves() @@ -626,17 +626,14 @@ public void DumpPlacement() private Dictionary GetPlaceNameMap() { - var map = new Dictionary(); var place_names = rom.GetStrings(TextName.metlist_00000); var scriptFolder = new FolderContainer(((FolderContainer)rom.GetFile(GameFile.StoryText)).FilePath!); scriptFolder.Initialize(); - var locationNames = scriptFolder.GetFileData("place_name.tbl")!; + var locationNames = scriptFolder.GetFileData("place_name.tbl"); var ahtb = new AHTB(locationNames); - for (var i = 0; i < place_names.Length; i++) - map[ahtb.Entries[i].Name] = (place_names[i], i); - return map; + return ahtb.ToIndexedDictionary(place_names); } private static IReadOnlyList GetLocationBoundLines(string areaName, @@ -1065,7 +1062,7 @@ public void DumpEventTriggers() var curLines = new List { $"File: {Path.GetFileName(f)}" }; - foreach (var line in TriggerUtil.GetTriggerTableSummary(table)) + foreach (var line in pkNX.Structures.FlatBuffers.Arceus.TriggerUtil.GetTriggerTableSummary(table)) curLines.Add($"\t{line}"); File.WriteAllLines(GetPath(outFolder, $"trigger_{Path.GetFileNameWithoutExtension(f).Replace("trigger_", string.Empty)}.txt"), curLines); diff --git a/pkNX.WinForms/Dumping/SV/BoxCollision9.cs b/pkNX.WinForms/Dumping/Gen9/BoxCollision9.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/BoxCollision9.cs rename to pkNX.WinForms/Dumping/Gen9/BoxCollision9.cs diff --git a/pkNX.WinForms/Dumping/DumperSV.Designer.cs b/pkNX.WinForms/Dumping/Gen9/DumperSV.Designer.cs similarity index 100% rename from pkNX.WinForms/Dumping/DumperSV.Designer.cs rename to pkNX.WinForms/Dumping/Gen9/DumperSV.Designer.cs diff --git a/pkNX.WinForms/Dumping/DumperSV.cs b/pkNX.WinForms/Dumping/Gen9/DumperSV.cs similarity index 100% rename from pkNX.WinForms/Dumping/DumperSV.cs rename to pkNX.WinForms/Dumping/Gen9/DumperSV.cs diff --git a/pkNX.WinForms/Dumping/DumperSV.resx b/pkNX.WinForms/Dumping/Gen9/DumperSV.resx similarity index 100% rename from pkNX.WinForms/Dumping/DumperSV.resx rename to pkNX.WinForms/Dumping/Gen9/DumperSV.resx diff --git a/pkNX.WinForms/Dumping/SV/Encounter/EncounterDumpConfigSV.cs b/pkNX.WinForms/Dumping/Gen9/Encounter/EncounterDumpConfigSV.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Encounter/EncounterDumpConfigSV.cs rename to pkNX.WinForms/Dumping/Gen9/Encounter/EncounterDumpConfigSV.cs diff --git a/pkNX.WinForms/Dumping/SV/Encounter/EncounterDumperSV.cs b/pkNX.WinForms/Dumping/Gen9/Encounter/EncounterDumperSV.cs similarity index 91% rename from pkNX.WinForms/Dumping/SV/Encounter/EncounterDumperSV.cs rename to pkNX.WinForms/Dumping/Gen9/Encounter/EncounterDumperSV.cs index 0b04a2d4..9a1a2ece 100644 --- a/pkNX.WinForms/Dumping/SV/Encounter/EncounterDumperSV.cs +++ b/pkNX.WinForms/Dumping/Gen9/Encounter/EncounterDumperSV.cs @@ -126,17 +126,4 @@ private static void DumpField(PaldeaFieldModel field, string path) 124 => false, // Area Zero _ => true, }; - - public static Dictionary GetInternalStringLookup(ReadOnlySpan text, AHTB ahtb) - { - var result = new Dictionary(); - for (var i = 0; i < text.Length; i++) - { - var entry = ahtb.Entries[i]; - var name = entry.Name; - var value = (text[i], i); - result.Add(name, value); - } - return result; - } } diff --git a/pkNX.WinForms/Dumping/SV/Encounter/EncounterExtensions9.cs b/pkNX.WinForms/Dumping/Gen9/Encounter/EncounterExtensions9.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Encounter/EncounterExtensions9.cs rename to pkNX.WinForms/Dumping/Gen9/Encounter/EncounterExtensions9.cs diff --git a/pkNX.WinForms/Dumping/SV/Encounter/EncounterSlotDumper9.cs b/pkNX.WinForms/Dumping/Gen9/Encounter/EncounterSlotDumper9.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Encounter/EncounterSlotDumper9.cs rename to pkNX.WinForms/Dumping/Gen9/Encounter/EncounterSlotDumper9.cs diff --git a/pkNX.WinForms/Dumping/SV/Encounter/FixedSymbolDumper9.cs b/pkNX.WinForms/Dumping/Gen9/Encounter/FixedSymbolDumper9.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Encounter/FixedSymbolDumper9.cs rename to pkNX.WinForms/Dumping/Gen9/Encounter/FixedSymbolDumper9.cs diff --git a/pkNX.WinForms/Dumping/SV/Encounter/GimmighoulDumper.cs b/pkNX.WinForms/Dumping/Gen9/Encounter/GimmighoulDumper.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Encounter/GimmighoulDumper.cs rename to pkNX.WinForms/Dumping/Gen9/Encounter/GimmighoulDumper.cs diff --git a/pkNX.WinForms/Dumping/SV/Encounter/PaldeaEncounter.cs b/pkNX.WinForms/Dumping/Gen9/Encounter/PaldeaEncounter.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Encounter/PaldeaEncounter.cs rename to pkNX.WinForms/Dumping/Gen9/Encounter/PaldeaEncounter.cs diff --git a/pkNX.WinForms/Dumping/GameDumperSV.cs b/pkNX.WinForms/Dumping/Gen9/GameDumperSV.cs similarity index 99% rename from pkNX.WinForms/Dumping/GameDumperSV.cs rename to pkNX.WinForms/Dumping/Gen9/GameDumperSV.cs index 20468c16..628f9a94 100644 --- a/pkNX.WinForms/Dumping/GameDumperSV.cs +++ b/pkNX.WinForms/Dumping/Gen9/GameDumperSV.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Windows; using FlatSharp; using pkNX.Containers; using pkNX.Game; @@ -185,15 +186,7 @@ private void RipLanguage(TextConfig textConfig, string type, string lang, string var ahtbData = File.ReadAllBytes(ahtb); var table = new AHTB(ahtbData); - var detailed = new string[table.Count]; - for (int i = 0; i < lines.Length; i++) - { - var entry = table.Entries[i]; - var hash = entry.Hash; - var name = entry.Name; - var line = lines[i]; - detailed[i] = $"{i:000}\t{hash:X16}\t{name}\t{line}"; - } + var detailed = table.MergeFlat(lines); var pathAHTB = GetPath("textFull", dest); File.WriteAllLines(pathAHTB, detailed); @@ -647,7 +640,7 @@ public void DumpEncounters() var cfg = new TextConfig(GameVersion.SV); var ahtb = GetCommonAHTB("place_name", language); var place_names = GetCommonText("place_name", language, cfg); - var nameDict = EncounterDumperSV.GetInternalStringLookup(place_names, ahtb); + var nameDict = ahtb.ToIndexedDictionary(place_names); var config = new EncounterDumpConfigSV { @@ -1453,7 +1446,14 @@ public void DumpHashReflectionBFBS() public void DumpArchives() { - TrinityPakExtractor.DumpArchives(rom.PathRomFS, GetPath(DumpArchive)); + var dirRootDump = GetPath(DumpArchive); + if (Directory.Exists(dirRootDump)) + { + var dr = WinFormsUtil.Prompt(MessageBoxButton.YesNo, "Archive dump folder already exists -- are you sure you want to dump again?"); + if (dr != MessageBoxResult.Yes) + return; + } + TrinityPakExtractor.DumpArchives(rom.PathRomFS, dirRootDump); Debug.WriteLine("Loaded"); } diff --git a/pkNX.WinForms/Dumping/SV/Location/AreaWeather9.cs b/pkNX.WinForms/Dumping/Gen9/Location/AreaWeather9.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Location/AreaWeather9.cs rename to pkNX.WinForms/Dumping/Gen9/Location/AreaWeather9.cs diff --git a/pkNX.WinForms/Dumping/SV/Location/LocationDatabase.cs b/pkNX.WinForms/Dumping/Gen9/Location/LocationDatabase.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Location/LocationDatabase.cs rename to pkNX.WinForms/Dumping/Gen9/Location/LocationDatabase.cs diff --git a/pkNX.WinForms/Dumping/SV/Location/LocationPointDetail.cs b/pkNX.WinForms/Dumping/Gen9/Location/LocationPointDetail.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Location/LocationPointDetail.cs rename to pkNX.WinForms/Dumping/Gen9/Location/LocationPointDetail.cs diff --git a/pkNX.WinForms/Dumping/SV/Location/LocationStorage.cs b/pkNX.WinForms/Dumping/Gen9/Location/LocationStorage.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Location/LocationStorage.cs rename to pkNX.WinForms/Dumping/Gen9/Location/LocationStorage.cs diff --git a/pkNX.WinForms/Dumping/MassOutbreakRipper.cs b/pkNX.WinForms/Dumping/Gen9/MassOutbreakRipper.cs similarity index 98% rename from pkNX.WinForms/Dumping/MassOutbreakRipper.cs rename to pkNX.WinForms/Dumping/Gen9/MassOutbreakRipper.cs index f977008f..2b36a416 100644 --- a/pkNX.WinForms/Dumping/MassOutbreakRipper.cs +++ b/pkNX.WinForms/Dumping/Gen9/MassOutbreakRipper.cs @@ -22,7 +22,7 @@ public static class MassOutbreakRipper private static int FolderIndex; private static Dictionary NameDict = []; - private static Dictionary PopCoordinates = []; + private static readonly Dictionary PopCoordinates = []; private readonly record struct DistSpecForm(int Index, ushort Species, byte Form); private readonly record struct DistPopCoordinate(float X, float Z); @@ -59,7 +59,7 @@ public static void DumpDeliveryOutbreaks(IFileInternal ROM, string path, string var place_names = GetCommonText(ROM, "place_name", "English", cfg); var data = ROM.GetPackedFile("message/dat/English/common/place_name.tbl"); var ahtb = new AHTB(data); - NameDict = EncounterDumperSV.GetInternalStringLookup(place_names, ahtb); + NameDict = ahtb.ToIndexedDictionary(place_names); var dirs = Directory.GetDirectories(path, "*", SearchOption.AllDirectories).Order(); foreach (var dir in dirs) @@ -393,13 +393,7 @@ private static void AddToJar(IEnumerable encs) Parent = enc, Species = species, Form = form, - Gender = pk.Sex switch - { - SexType.DEFAULT => 0xFF, - SexType.MALE => 0, - SexType.FEMALE => 1, - _ => throw new ArgumentOutOfRangeException(nameof(SexType), pk.Sex, "Unknown Gender"), - }, + Gender = GetRemappedGender(pk.Sex), Ribbon = unchecked((RibbonIndex)(pk.AddRibbonPercentage == 0 ? -1 : (int)pk.AddRibbonType - 1)), ForceScaleRange = pk.EnableScaleRange, @@ -413,6 +407,14 @@ private static void AddToJar(IEnumerable encs) } } + private static byte GetRemappedGender(SexType pkSex) => pkSex switch + { + SexType.DEFAULT => 0xFF, + SexType.MALE => 0, + SexType.FEMALE => 1, + _ => throw new ArgumentOutOfRangeException(nameof(pkSex), pkSex, "Unknown Gender"), + }; + private static (UInt128 Met, int Boost) GetMetFlags(PaldeaSceneModel scene, Dictionary placeNameMap, PaldeaFieldIndex fieldIndex, byte baseMet, List areaNames, Dictionary areas, OutbreakPointData point, Dictionary atlantis) { diff --git a/pkNX.WinForms/Dumping/SV/Models/PaldeaCoinSymbolModel.cs b/pkNX.WinForms/Dumping/Gen9/Models/PaldeaCoinSymbolModel.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Models/PaldeaCoinSymbolModel.cs rename to pkNX.WinForms/Dumping/Gen9/Models/PaldeaCoinSymbolModel.cs diff --git a/pkNX.WinForms/Dumping/SV/Models/PaldeaCoinSymbolPoint.cs b/pkNX.WinForms/Dumping/Gen9/Models/PaldeaCoinSymbolPoint.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Models/PaldeaCoinSymbolPoint.cs rename to pkNX.WinForms/Dumping/Gen9/Models/PaldeaCoinSymbolPoint.cs diff --git a/pkNX.WinForms/Dumping/SV/Models/PaldeaFieldModel.cs b/pkNX.WinForms/Dumping/Gen9/Models/PaldeaFieldModel.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Models/PaldeaFieldModel.cs rename to pkNX.WinForms/Dumping/Gen9/Models/PaldeaFieldModel.cs diff --git a/pkNX.WinForms/Dumping/SV/Models/PaldeaFixedSymbolModel.cs b/pkNX.WinForms/Dumping/Gen9/Models/PaldeaFixedSymbolModel.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Models/PaldeaFixedSymbolModel.cs rename to pkNX.WinForms/Dumping/Gen9/Models/PaldeaFixedSymbolModel.cs diff --git a/pkNX.WinForms/Dumping/SV/Models/PaldeaFixedSymbolPoint.cs b/pkNX.WinForms/Dumping/Gen9/Models/PaldeaFixedSymbolPoint.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Models/PaldeaFixedSymbolPoint.cs rename to pkNX.WinForms/Dumping/Gen9/Models/PaldeaFixedSymbolPoint.cs diff --git a/pkNX.WinForms/Dumping/SV/Models/PaldeaSceneModel.cs b/pkNX.WinForms/Dumping/Gen9/Models/PaldeaSceneModel.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Models/PaldeaSceneModel.cs rename to pkNX.WinForms/Dumping/Gen9/Models/PaldeaSceneModel.cs diff --git a/pkNX.WinForms/Dumping/SV/Models/PaldeaSpawnModel.cs b/pkNX.WinForms/Dumping/Gen9/Models/PaldeaSpawnModel.cs similarity index 100% rename from pkNX.WinForms/Dumping/SV/Models/PaldeaSpawnModel.cs rename to pkNX.WinForms/Dumping/Gen9/Models/PaldeaSpawnModel.cs diff --git a/pkNX.WinForms/Dumping/TeraRaidRipper.cs b/pkNX.WinForms/Dumping/Gen9/TeraRaidRipper.cs similarity index 99% rename from pkNX.WinForms/Dumping/TeraRaidRipper.cs rename to pkNX.WinForms/Dumping/Gen9/TeraRaidRipper.cs index 5bb56746..0c9dd6e1 100644 --- a/pkNX.WinForms/Dumping/TeraRaidRipper.cs +++ b/pkNX.WinForms/Dumping/Gen9/TeraRaidRipper.cs @@ -306,10 +306,6 @@ private static void AddToList(IReadOnlyCollection table, private static void TryAddToPickle(RaidEnemyInfo enc, ICollection list, RaidSerializationFormat format, ReadOnlySpan totalS, ReadOnlySpan totalV, ReadOnlySpan minS, ReadOnlySpan minV) { - // not catchable - if (enc.CaptureRate is 0) - return; - using var ms = new MemoryStream(); using var bw = new BinaryWriter(ms); @@ -458,8 +454,8 @@ private static void DumpPretty(IFileInternal ROM, DeliveryRaidEnemyTableArray ta var capture = entry.Info.CaptureRate switch { + // 0 never // 1 always - 0 => "Never", 2 => "Only Once", _ => $"{entry.Info.CaptureRate}", }; @@ -662,14 +658,13 @@ public static string GetFormName(IFileInternal ROM, ushort species, byte form) for (int i = 0; i < text.Length; i++) { - var entry = ahtb.Entries[i]; - var name = entry.Name; - var line = text[i]; - if (species is (int)Scatterbug or (int)Spewpa) // workaround to get Vivillon form strings species = (int)Vivillon; + + var entry = ahtb.Entries[i]; + var name = entry.Name; if (name == $"ZKN_FORM_{species:000}_{form:000}") - return line; + return text[i]; } return ""; diff --git a/pkNX.WinForms/Dumping/Gen9a/DumpHelper9a.cs b/pkNX.WinForms/Dumping/Gen9a/DumpHelper9a.cs new file mode 100644 index 00000000..d3f8654f --- /dev/null +++ b/pkNX.WinForms/Dumping/Gen9a/DumpHelper9a.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using pkNX.Containers; +using pkNX.Structures.FlatBuffers.ZA; + +namespace pkNX.WinForms; + +public sealed class DumpHelper9a +{ + public required string[] SpeciesNames { get; init; } + public required string[] AbilityNames { get; init; } + public required string[] MoveNames { get; init; } + public required string[] NatureNames { get; init; } + public required string[] FormNames { get; init; } + + public required PersonalTable Personal { get; init; } + public required AHTB Forms { get; init; } + + public string GetAbilityName(DevID species, short form, TokuseiType type) + => PrettyDumpUtil.GetAbilityName(species, form, AbilityNames, Personal, type); + + public string GetMoveText(WazaSet waza) => PrettyDumpUtil.GetMoveText(waza, MoveNames); + public List GetCurrentMoves(DevID species, short form, byte level) + => PrettyDumpUtil.GetCurrentMoves(species, form, level, Personal); + public string GetEVSpread(ReadOnlySpan evs) => PrettyDumpUtil.GetEVSpread(evs); + + + public string GetFormName(ushort species, short form) => species switch + { + 0128 when form is not 0 => $"Paldean Form / {TaurosForms[form]}", // Tauros + 0201 => $"Unown {UnownForms[form]}", // Unown + 0382 or 0383 or 0479 or 0646 or 0649 when form is 0 => string.Empty, // Kyogre, Groudon, Rotom, Kyurem, Genesect + 0658 when form is 1 => "Battle Bond", // Greninja + 0744 when form is 1 => "Own Tempo", // Rockruff + 0774 when form <= 6 => $"{MiniorForms[form]} Meteor Form", // Minior + _ => PrettyDumpUtil.GetFormString(species, form, FormNames, Forms), + }; + + public string GetFormDisplay(short form, string name) => PrettyDumpUtil.GetFormDisplay(form, name); + public string GetGender(int gender) => PrettyDumpUtil.GetGender(gender); + public string GetNature(int nature) => PrettyDumpUtil.GetNature(NatureNames, nature); + + + private static readonly string[] TaurosForms = ["", "Combat Breed", "Blaze Breed", "Aqua Breed"]; + private static ReadOnlySpan UnownForms => "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?"; + private static readonly string[] MiniorForms = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]; +} diff --git a/pkNX.WinForms/Dumping/Gen9a/Dumper9a.Designer.cs b/pkNX.WinForms/Dumping/Gen9a/Dumper9a.Designer.cs new file mode 100644 index 00000000..f35cb7e8 --- /dev/null +++ b/pkNX.WinForms/Dumping/Gen9a/Dumper9a.Designer.cs @@ -0,0 +1,475 @@ +namespace pkNX.WinForms +{ + partial class Dumper9a + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + TC_Options = new System.Windows.Forms.TabControl(); + Tab_General = new System.Windows.Forms.TabPage(); + flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + B_ParsePKMDetails = new System.Windows.Forms.Button(); + B_PKText = new System.Windows.Forms.Button(); + B_Trainers = new System.Windows.Forms.Button(); + B_Encount = new System.Windows.Forms.Button(); + B_DumpMovesAbilities = new System.Windows.Forms.Button(); + B_Mega = new System.Windows.Forms.Button(); + B_DumpItems = new System.Windows.Forms.Button(); + B_DumpPokeData = new System.Windows.Forms.Button(); + B_DumpEncountData = new System.Windows.Forms.Button(); + Tab_Misc = new System.Windows.Forms.TabPage(); + flowLayoutPanel3 = new System.Windows.Forms.FlowLayoutPanel(); + B_DumpPath = new System.Windows.Forms.Button(); + B_DumpSpecific = new System.Windows.Forms.Button(); + B_DumpFromTextFile = new System.Windows.Forms.Button(); + B_DumpHash = new System.Windows.Forms.Button(); + B_DumpArc = new System.Windows.Forms.Button(); + B_SearchPattern = new System.Windows.Forms.Button(); + B_Misc = new System.Windows.Forms.Button(); + B_Scrubbed = new System.Windows.Forms.Button(); + B_DumpTriggers = 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(); + 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(); + TC_Options.SuspendLayout(); + Tab_General.SuspendLayout(); + flowLayoutPanel1.SuspendLayout(); + Tab_Misc.SuspendLayout(); + flowLayoutPanel3.SuspendLayout(); + Tab_PKHeX.SuspendLayout(); + flowLayoutPanel2.SuspendLayout(); + Tab_Future.SuspendLayout(); + SuspendLayout(); + // + // TC_Options + // + TC_Options.Controls.Add(Tab_General); + TC_Options.Controls.Add(Tab_Misc); + TC_Options.Controls.Add(Tab_PKHeX); + TC_Options.Controls.Add(Tab_Future); + TC_Options.Dock = System.Windows.Forms.DockStyle.Fill; + TC_Options.Location = new System.Drawing.Point(0, 0); + TC_Options.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + TC_Options.Name = "TC_Options"; + TC_Options.SelectedIndex = 0; + TC_Options.Size = new System.Drawing.Size(484, 364); + TC_Options.TabIndex = 0; + // + // Tab_General + // + Tab_General.Controls.Add(flowLayoutPanel1); + Tab_General.Location = new System.Drawing.Point(4, 26); + Tab_General.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + Tab_General.Name = "Tab_General"; + Tab_General.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + Tab_General.Size = new System.Drawing.Size(476, 334); + Tab_General.TabIndex = 0; + Tab_General.Text = "General"; + Tab_General.UseVisualStyleBackColor = true; + // + // flowLayoutPanel1 + // + flowLayoutPanel1.Controls.Add(B_ParsePKMDetails); + flowLayoutPanel1.Controls.Add(B_PKText); + flowLayoutPanel1.Controls.Add(B_Trainers); + flowLayoutPanel1.Controls.Add(B_Encount); + flowLayoutPanel1.Controls.Add(B_DumpMovesAbilities); + flowLayoutPanel1.Controls.Add(B_Mega); + flowLayoutPanel1.Controls.Add(B_DumpItems); + flowLayoutPanel1.Controls.Add(B_DumpPokeData); + flowLayoutPanel1.Controls.Add(B_DumpEncountData); + flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + flowLayoutPanel1.Location = new System.Drawing.Point(4, 3); + flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + flowLayoutPanel1.Name = "flowLayoutPanel1"; + flowLayoutPanel1.Size = new System.Drawing.Size(468, 328); + flowLayoutPanel1.TabIndex = 1; + // + // B_ParsePKMDetails + // + B_ParsePKMDetails.Location = new System.Drawing.Point(4, 3); + B_ParsePKMDetails.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_ParsePKMDetails.Name = "B_ParsePKMDetails"; + B_ParsePKMDetails.Size = new System.Drawing.Size(144, 71); + B_ParsePKMDetails.TabIndex = 1; + B_ParsePKMDetails.Text = "Personal Stats"; + B_ParsePKMDetails.UseVisualStyleBackColor = true; + B_ParsePKMDetails.Click += B_ParsePKMDetails_Click; + // + // B_PKText + // + B_PKText.Location = new System.Drawing.Point(156, 3); + B_PKText.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_PKText.Name = "B_PKText"; + B_PKText.Size = new System.Drawing.Size(144, 71); + B_PKText.TabIndex = 17; + B_PKText.Text = "Text Files"; + B_PKText.UseVisualStyleBackColor = true; + B_PKText.Click += B_PKText_Click; + // + // B_Trainers + // + B_Trainers.Location = new System.Drawing.Point(308, 3); + B_Trainers.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Trainers.Name = "B_Trainers"; + B_Trainers.Size = new System.Drawing.Size(144, 71); + B_Trainers.TabIndex = 18; + B_Trainers.Text = "Trainers"; + B_Trainers.UseVisualStyleBackColor = true; + B_Trainers.Click += B_Trainers_Click; + // + // B_Encount + // + B_Encount.Location = new System.Drawing.Point(4, 80); + B_Encount.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Encount.Name = "B_Encount"; + B_Encount.Size = new System.Drawing.Size(144, 71); + B_Encount.TabIndex = 19; + B_Encount.Text = "Encounters"; + B_Encount.UseVisualStyleBackColor = true; + B_Encount.Click += B_Encount_Click; + // + // B_DumpMovesAbilities + // + B_DumpMovesAbilities.Location = new System.Drawing.Point(156, 80); + B_DumpMovesAbilities.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpMovesAbilities.Name = "B_DumpMovesAbilities"; + B_DumpMovesAbilities.Size = new System.Drawing.Size(144, 71); + B_DumpMovesAbilities.TabIndex = 20; + B_DumpMovesAbilities.Text = "Moves/Abilities"; + B_DumpMovesAbilities.UseVisualStyleBackColor = true; + B_DumpMovesAbilities.Click += B_DumpMovesAbilities_Click; + // + // B_Mega + // + B_Mega.Location = new System.Drawing.Point(308, 80); + B_Mega.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Mega.Name = "B_Mega"; + B_Mega.Size = new System.Drawing.Size(144, 71); + B_Mega.TabIndex = 25; + B_Mega.Text = "Mega"; + B_Mega.UseVisualStyleBackColor = true; + B_Mega.Click += B_Mega_Click; + // + // B_DumpItems + // + B_DumpItems.Location = new System.Drawing.Point(4, 157); + B_DumpItems.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpItems.Name = "B_DumpItems"; + B_DumpItems.Size = new System.Drawing.Size(144, 71); + B_DumpItems.TabIndex = 26; + B_DumpItems.Text = "Items"; + B_DumpItems.UseVisualStyleBackColor = true; + B_DumpItems.Click += B_DumpItems_Click; + // + // B_DumpPokeData + // + B_DumpPokeData.Location = new System.Drawing.Point(156, 157); + B_DumpPokeData.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpPokeData.Name = "B_DumpPokeData"; + B_DumpPokeData.Size = new System.Drawing.Size(144, 71); + B_DumpPokeData.TabIndex = 27; + B_DumpPokeData.Text = "PokeData"; + B_DumpPokeData.UseVisualStyleBackColor = true; + B_DumpPokeData.Click += B_DumpPokeData_Click; + // + // B_DumpEncountData + // + B_DumpEncountData.Location = new System.Drawing.Point(308, 157); + B_DumpEncountData.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpEncountData.Name = "B_DumpEncountData"; + B_DumpEncountData.Size = new System.Drawing.Size(144, 71); + B_DumpEncountData.TabIndex = 28; + B_DumpEncountData.Text = "EncountData"; + B_DumpEncountData.UseVisualStyleBackColor = true; + B_DumpEncountData.Click += B_DumpEncountData_Click; + // + // Tab_Misc + // + Tab_Misc.Controls.Add(flowLayoutPanel3); + Tab_Misc.Location = new System.Drawing.Point(4, 26); + Tab_Misc.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + Tab_Misc.Name = "Tab_Misc"; + Tab_Misc.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + Tab_Misc.Size = new System.Drawing.Size(476, 334); + Tab_Misc.TabIndex = 2; + Tab_Misc.Text = "Misc"; + Tab_Misc.UseVisualStyleBackColor = true; + // + // flowLayoutPanel3 + // + flowLayoutPanel3.Controls.Add(B_DumpPath); + flowLayoutPanel3.Controls.Add(B_DumpSpecific); + flowLayoutPanel3.Controls.Add(B_DumpFromTextFile); + flowLayoutPanel3.Controls.Add(B_DumpHash); + flowLayoutPanel3.Controls.Add(B_DumpArc); + flowLayoutPanel3.Controls.Add(B_SearchPattern); + flowLayoutPanel3.Controls.Add(B_Misc); + flowLayoutPanel3.Controls.Add(B_Scrubbed); + flowLayoutPanel3.Controls.Add(B_DumpTriggers); + flowLayoutPanel3.Controls.Add(B_DumpConfig); + 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); + flowLayoutPanel3.Name = "flowLayoutPanel3"; + flowLayoutPanel3.Size = new System.Drawing.Size(468, 328); + flowLayoutPanel3.TabIndex = 2; + // + // B_DumpPath + // + B_DumpPath.Location = new System.Drawing.Point(4, 3); + B_DumpPath.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpPath.Name = "B_DumpPath"; + B_DumpPath.Size = new System.Drawing.Size(144, 71); + B_DumpPath.TabIndex = 21; + B_DumpPath.Text = "Specific File..."; + B_DumpPath.UseVisualStyleBackColor = true; + B_DumpPath.Click += B_DumpPath_Click; + // + // B_DumpSpecific + // + B_DumpSpecific.Location = new System.Drawing.Point(156, 3); + B_DumpSpecific.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpSpecific.Name = "B_DumpSpecific"; + B_DumpSpecific.Size = new System.Drawing.Size(144, 71); + B_DumpSpecific.TabIndex = 19; + B_DumpSpecific.Text = "Specific Reflection"; + B_DumpSpecific.UseVisualStyleBackColor = true; + B_DumpSpecific.Click += B_DumpSpecific_Click; + // + // B_DumpFromTextFile + // + B_DumpFromTextFile.Location = new System.Drawing.Point(308, 3); + B_DumpFromTextFile.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpFromTextFile.Name = "B_DumpFromTextFile"; + B_DumpFromTextFile.Size = new System.Drawing.Size(144, 71); + B_DumpFromTextFile.TabIndex = 23; + B_DumpFromTextFile.Text = "From Text File..."; + B_DumpFromTextFile.UseVisualStyleBackColor = true; + B_DumpFromTextFile.Click += B_DumpFromTextFile_Click; + // + // B_DumpHash + // + B_DumpHash.Location = new System.Drawing.Point(4, 80); + B_DumpHash.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpHash.Name = "B_DumpHash"; + B_DumpHash.Size = new System.Drawing.Size(144, 71); + B_DumpHash.TabIndex = 14; + B_DumpHash.Text = "Hash Tables (AHTB)"; + B_DumpHash.UseVisualStyleBackColor = true; + B_DumpHash.Click += B_DumpHash_Click; + // + // B_DumpArc + // + B_DumpArc.Location = new System.Drawing.Point(156, 80); + B_DumpArc.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpArc.Name = "B_DumpArc"; + B_DumpArc.Size = new System.Drawing.Size(144, 71); + B_DumpArc.TabIndex = 18; + B_DumpArc.Text = "Archives (Slow)"; + B_DumpArc.UseVisualStyleBackColor = true; + B_DumpArc.Click += B_DumpArc_Click; + // + // B_SearchPattern + // + B_SearchPattern.Location = new System.Drawing.Point(308, 80); + B_SearchPattern.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_SearchPattern.Name = "B_SearchPattern"; + B_SearchPattern.Size = new System.Drawing.Size(144, 71); + B_SearchPattern.TabIndex = 24; + B_SearchPattern.Text = "Search Pattern (Slow)"; + B_SearchPattern.UseVisualStyleBackColor = true; + B_SearchPattern.Click += B_SearchPattern_Click; + // + // B_Misc + // + B_Misc.Location = new System.Drawing.Point(4, 157); + B_Misc.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Misc.Name = "B_Misc"; + B_Misc.Size = new System.Drawing.Size(144, 71); + B_Misc.TabIndex = 20; + B_Misc.Text = "Misc"; + B_Misc.UseVisualStyleBackColor = true; + B_Misc.Click += B_DumpMisc_Click; + // + // B_Scrubbed + // + B_Scrubbed.Location = new System.Drawing.Point(156, 157); + B_Scrubbed.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Scrubbed.Name = "B_Scrubbed"; + B_Scrubbed.Size = new System.Drawing.Size(144, 71); + B_Scrubbed.TabIndex = 25; + B_Scrubbed.Text = "Scrubbed"; + B_Scrubbed.UseVisualStyleBackColor = true; + B_Scrubbed.Click += B_DumpScrubbed_Click; + // + // B_DumpTriggers + // + B_DumpTriggers.Location = new System.Drawing.Point(308, 157); + B_DumpTriggers.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_DumpTriggers.Name = "B_DumpTriggers"; + B_DumpTriggers.Size = new System.Drawing.Size(144, 71); + B_DumpTriggers.TabIndex = 27; + B_DumpTriggers.Text = "Triggers"; + B_DumpTriggers.UseVisualStyleBackColor = true; + B_DumpTriggers.Click += B_Triggers_Click; + // + // Tab_PKHeX + // + Tab_PKHeX.Controls.Add(flowLayoutPanel2); + Tab_PKHeX.Location = new System.Drawing.Point(4, 26); + Tab_PKHeX.Name = "Tab_PKHeX"; + Tab_PKHeX.Padding = new System.Windows.Forms.Padding(3); + Tab_PKHeX.Size = new System.Drawing.Size(476, 334); + Tab_PKHeX.TabIndex = 4; + Tab_PKHeX.Text = "PKHeX"; + Tab_PKHeX.UseVisualStyleBackColor = true; + // + // flowLayoutPanel2 + // + flowLayoutPanel2.Controls.Add(B_Locations); + 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); + flowLayoutPanel2.Name = "flowLayoutPanel2"; + flowLayoutPanel2.Size = new System.Drawing.Size(470, 328); + flowLayoutPanel2.TabIndex = 4; + // + // B_Locations + // + B_Locations.Location = new System.Drawing.Point(4, 3); + B_Locations.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Locations.Name = "B_Locations"; + B_Locations.Size = new System.Drawing.Size(144, 71); + B_Locations.TabIndex = 21; + B_Locations.Text = "Locations"; + B_Locations.UseVisualStyleBackColor = true; + B_Locations.Click += B_Locations_Click; + // + // Tab_Future + // + Tab_Future.Controls.Add(flowLayoutPanel4); + Tab_Future.Location = new System.Drawing.Point(4, 26); + Tab_Future.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + Tab_Future.Name = "Tab_Future"; + Tab_Future.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + Tab_Future.Size = new System.Drawing.Size(476, 334); + Tab_Future.TabIndex = 3; + Tab_Future.Text = "Future"; + Tab_Future.UseVisualStyleBackColor = true; + // + // flowLayoutPanel4 + // + flowLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill; + flowLayoutPanel4.Location = new System.Drawing.Point(4, 3); + flowLayoutPanel4.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + flowLayoutPanel4.Name = "flowLayoutPanel4"; + flowLayoutPanel4.Size = new System.Drawing.Size(468, 328); + flowLayoutPanel4.TabIndex = 3; + // + // B_OpenFolder + // + B_OpenFolder.Location = new System.Drawing.Point(376, -1); + B_OpenFolder.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_OpenFolder.Name = "B_OpenFolder"; + B_OpenFolder.Size = new System.Drawing.Size(88, 31); + B_OpenFolder.TabIndex = 2; + B_OpenFolder.Text = "Open Folder"; + B_OpenFolder.UseVisualStyleBackColor = true; + B_OpenFolder.Click += B_OpenFolder_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; + // + // Dumper9a + // + AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + ClientSize = new System.Drawing.Size(484, 364); + Controls.Add(B_OpenFolder); + Controls.Add(TC_Options); + Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + MaximizeBox = false; + Name = "Dumper9a"; + StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + Text = "ZADump"; + TC_Options.ResumeLayout(false); + Tab_General.ResumeLayout(false); + flowLayoutPanel1.ResumeLayout(false); + Tab_Misc.ResumeLayout(false); + flowLayoutPanel3.ResumeLayout(false); + Tab_PKHeX.ResumeLayout(false); + flowLayoutPanel2.ResumeLayout(false); + Tab_Future.ResumeLayout(false); + ResumeLayout(false); + } + + #endregion + + private System.Windows.Forms.TabControl TC_Options; + private System.Windows.Forms.TabPage Tab_General; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; + private System.Windows.Forms.Button B_ParsePKMDetails; + private System.Windows.Forms.TabPage Tab_Misc; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel3; + private System.Windows.Forms.Button B_DumpHash; + private System.Windows.Forms.Button B_OpenFolder; + private System.Windows.Forms.TabPage Tab_Future; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel4; + private System.Windows.Forms.Button B_DumpArc; + private System.Windows.Forms.Button B_DumpSpecific; + private System.Windows.Forms.Button B_PKText; + private System.Windows.Forms.Button B_Trainers; + private System.Windows.Forms.Button B_Misc; + private System.Windows.Forms.Button B_Encount; + private System.Windows.Forms.Button B_DumpMovesAbilities; + private System.Windows.Forms.Button B_DumpPath; + private System.Windows.Forms.Button B_DumpFromTextFile; + private System.Windows.Forms.TabPage Tab_PKHeX; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2; + private System.Windows.Forms.Button B_Locations; + private System.Windows.Forms.Button B_Mega; + private System.Windows.Forms.Button B_SearchPattern; + private System.Windows.Forms.Button B_DumpItems; + private System.Windows.Forms.Button B_DumpPokeData; + private System.Windows.Forms.Button B_DumpEncountData; + private System.Windows.Forms.Button B_Scrubbed; + private System.Windows.Forms.Button B_DumpTriggers; + private System.Windows.Forms.Button B_DumpConfig; + } +} diff --git a/pkNX.WinForms/Dumping/Gen9a/Dumper9a.cs b/pkNX.WinForms/Dumping/Gen9a/Dumper9a.cs new file mode 100644 index 00000000..46556b15 --- /dev/null +++ b/pkNX.WinForms/Dumping/Gen9a/Dumper9a.cs @@ -0,0 +1,193 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Windows.Forms; +using pkNX.Game; + +namespace pkNX.WinForms; + +public partial class Dumper9a : Form +{ + private readonly GameManager9a Game; + private readonly GameDumper9a Dumper; + + public Dumper9a(GameManager9a rom) + { + InitializeComponent(); + Dumper = new GameDumper9a(Game = rom); + } + + private void B_OpenFolder_Click(object sender, EventArgs e) => Process.Start("explorer.exe", Dumper.DumpFolder); + + #region Tab 1 + private void B_ParsePKMDetails_Click(object sender, EventArgs e) + { + Dumper.DumpPersonal(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_PKText_Click(object sender, EventArgs e) + { + Dumper.DumpStrings(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Trainers_Click(object sender, EventArgs e) + { + Dumper.DumpTrainers(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpMovesAbilities_Click(object sender, EventArgs e) + { + Dumper.DumpMoves(); + Dumper.DumpAbilities(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpItems_Click(object sender, EventArgs e) + { + Dumper.DumpItems(); + Dumper.DumpFieldItems(); + Dumper.DumpHiddenItems(); + Dumper.DumpMegaCrystals(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpPokeData_Click(object sender, EventArgs e) + { + Dumper.DumpPokemonData(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpConfig_Click(object sender, EventArgs e) + { + Dumper.DumpConfig(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpEncountData_Click(object sender, EventArgs e) + { + Dumper.DumpEncountData(); + System.Media.SystemSounds.Asterisk.Play(); + } + #endregion + + #region Tab 2 + private void B_DumpHash_Click(object sender, EventArgs e) + { + Dumper.DumpAHTB(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpArc_Click(object sender, EventArgs e) + { + Dumper.DumpArchives(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpSpecific_Click(object sender, EventArgs e) + { + Dumper.DumpHashReflectionBFBS(); + Dumper.DumpSpecific(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpMisc_Click(object sender, EventArgs e) + { + Dumper.DumpMisc(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpScrubbed_Click(object sender, EventArgs e) + { + Dumper.DumpScrubbedInfo(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpPath_Click(object sender, EventArgs e) + { + using var f = new TextInput(Game.HasFile); + while (true) + { + f.ShowDialog(); + if (f.DialogResult != DialogResult.OK) + return; // cancel + var path = f.Result; + if (string.IsNullOrWhiteSpace(path)) + return; // silent quit + + if (!Game.HasFile(path)) + { + WinFormsUtil.Alert("File not found in the game."); + continue; + } + + var data = Game.GetPackedFile(path); + var ext = Path.GetExtension(path); + if (ext.EndsWith("bfbs")) + Dumper.RipBFBS(path); + + // Prompt for a path to export, then save file. + using var sfd = new SaveFileDialog(); + sfd.FileName = Path.GetFileName(path); + sfd.Filter = "All Files (*.*)|*.*"; + + if (sfd.ShowDialog() != DialogResult.OK) + continue; + File.WriteAllBytes(sfd.FileName, data); + System.Media.SystemSounds.Asterisk.Play(); + break; + } + } + + private void B_DumpFromTextFile_Click(object sender, EventArgs e) + { + const string fileName = "filepaths.txt"; + var path = Path.Combine(Directory.GetCurrentDirectory(), fileName); + if (!File.Exists(path)) + { + WinFormsUtil.Alert($"{fileName} not found in the current directory."); + return; + } + + Dumper.DumpFromTextFile(path); + System.Media.SystemSounds.Asterisk.Play(); + } + + #endregion + + #region Tab - Future + // Placeholder for future dumpers + #endregion + + private void B_Encount_Click(object sender, EventArgs e) + { + Dumper.DumpEncounters(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Mega_Click(object sender, EventArgs e) + { + Dumper.DumpMegaInfo(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Locations_Click(object sender, EventArgs e) + { + Dumper.DumpLocationNames(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_SearchPattern_Click(object sender, EventArgs e) + { + Dumper.ScanPatterns(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Triggers_Click(object sender, EventArgs e) + { + Dumper.DumpEventTriggers(); + System.Media.SystemSounds.Asterisk.Play(); + } +} diff --git a/pkNX.WinForms/Dumping/Gen9a/Dumper9a.resx b/pkNX.WinForms/Dumping/Gen9a/Dumper9a.resx new file mode 100644 index 00000000..4edf53f8 --- /dev/null +++ b/pkNX.WinForms/Dumping/Gen9a/Dumper9a.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/pkNX.WinForms/Dumping/Gen9a/Encounter/EncounterDumper9a.cs b/pkNX.WinForms/Dumping/Gen9a/Encounter/EncounterDumper9a.cs new file mode 100644 index 00000000..3f27558a --- /dev/null +++ b/pkNX.WinForms/Dumping/Gen9a/Encounter/EncounterDumper9a.cs @@ -0,0 +1,31 @@ +using pkNX.Containers; +using pkNX.Structures.FlatBuffers.SV; // TODO ZA +using System.Collections.Generic; +using System.IO; + +namespace pkNX.Structures.FlatBuffers; + +public static class EncounterDumper9a +{ + public static void Dump(IFileInternal rom, EncounterDumpConfig9a config) + { + if (!Directory.Exists(config.Path)) + Directory.CreateDirectory(config.Path); + + // TODO ZA + } +} + +public record EncounterDumpConfig9a +{ + public required string Path { get; init; } + public required string[] SpecNamesInternal { get; init; } + public required string[] MoveNames { get; init; } + public required Dictionary PlaceNameMap { get; init; } + + public bool WriteText { get; init; } = true; + public bool WritePickle { get; init; } = true; + + public string this[WazaSet move] => MoveNames[(int)move.WazaId]; + public string this[DevID species] => SpecNamesInternal[(int)species]; +} diff --git a/pkNX.WinForms/Dumping/Gen9a/GameDumper9a.cs b/pkNX.WinForms/Dumping/Gen9a/GameDumper9a.cs new file mode 100644 index 00000000..c5c5ec11 --- /dev/null +++ b/pkNX.WinForms/Dumping/Gen9a/GameDumper9a.cs @@ -0,0 +1,2673 @@ +using FlatSharp; +using pkNX.Containers; +using pkNX.Game; +using pkNX.Structures; +using pkNX.Structures.FlatBuffers; +using pkNX.Structures.FlatBuffers.ZA; +using pkNX.Structures.FlatBuffers.ZA.Trinity; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json.Serialization; +using System.Windows; +using Schema = pkNX.Structures.FlatBuffers.Reflection; +using Trigger = pkNX.Structures.FlatBuffers.ZA.Trigger; + +// ReSharper disable StringLiteralTypo + +namespace pkNX.WinForms; + +public class GameDumper9a(GameManager9a rom) +{ + public string DumpFolder + { + get + { + var parent = Directory.GetParent(rom.PathRomFS) ?? throw new DirectoryNotFoundException($"Unable to find parent directory of {rom.PathRomFS}"); + return Path.Combine(parent.FullName, "Dump"); + } + } + + private const string message = "ik_message"; // ik_messagedat + private const string DumpArchive = "archive"; + private const string DumpArchiveExtracted = TrinityPakExtractor.DumpArchiveExtracted; + + /// + /// Message string language names/folders which contain the text localizations. + /// + private static readonly string[] LanguageEnglishNames = + [ + "JPN", + "JPN_KANJI", + "English", + "French", + "Italian", + "German", + "Spanish", + "Korean", + "Simp_Chinese", + "Trad_Chinese", + "LATAM", + ]; + + private string[] GetCommonText(string name, string lang, TextConfig cfg) + { + var data = rom.GetPackedFile($"{message}/dat/{lang}/common/{name}.dat"); + return new TextFile(data, cfg).Lines; + } + + private ushort[] GetCommonTextFlags(string name, string lang, TextConfig cfg) + { + var data = rom.GetPackedFile($"{message}/dat/{lang}/common/{name}.dat"); + return new TextFile(data, cfg).Flags; + } + + private AHTB GetCommonAHTB(string name, string lang) + { + var data = rom.GetPackedFile($"{message}/dat/{lang}/common/{name}.tbl"); + return new AHTB(data); + } + + private string GetPath(params ReadOnlySpan folders) + { + Directory.CreateDirectory(DumpFolder); + var result = Path.Combine(DumpFolder, Path.Combine(folders)); + var parent = Directory.GetParent(result) ?? throw new DirectoryNotFoundException($"Unable to get parent directory of {result}"); + Directory.CreateDirectory(parent.FullName); // double check :( + return result; + } + + public void DumpAHTB() + { + var arcPath = GetPath(DumpArchive, DumpArchiveExtracted); + if (!Directory.Exists(arcPath)) + { + WinFormsUtil.Alert("Archive not extracted yet. Please extract the archive first."); + return; + } + var files = Directory.EnumerateFiles(arcPath, "*.ahtb", SearchOption.AllDirectories); + + var result = new HashSet(); + var list = new List(); + foreach (var f in files) + { + try + { + var bytes = File.ReadAllBytes(f); + var tbl = new AHTB(bytes); + var summaries = tbl.Summary; + foreach (var t in tbl.ShortSummary) + result.Add(t); + var fn = Path.GetFileName(f); + list.Add(fn); + list.AddRange(summaries); + } + catch + { + } + } + + var outname = GetPath("ahtb.txt"); + var outname2 = GetPath("ahtblist.txt"); + File.WriteAllLines(outname, result); + File.WriteAllLines(outname2, list); + } + + public void DumpStrings() + { + var textConfig = new TextConfig(GameVersion.ZA); + ReadOnlySpan groups = ["ik_messagedat"]; + ReadOnlySpan types = ["script", "common"]; + foreach (var group in groups) + { + foreach (var type in types) + GetStrings(textConfig, type, group); + } + } + + private void GetStrings(TextConfig textConfig, string type, string messageGroup) + { + var arcPath = Path.Combine(GetPath(DumpArchive, DumpArchiveExtracted), "arc"); + foreach (var lang in LanguageEnglishNames) + RipLanguage(textConfig, type, lang, arcPath, messageGroup); + } + + private void RipLanguage(TextConfig textConfig, string type, string lang, string arcPath, string messageGroup) + { + var prefix = $"{messageGroup}{lang}"; + const string suffix = ".trpak"; + var pattern = $"{prefix}*{suffix}"; + List<(string File, string[] Lines)> text = []; + List<(string File, string[] Lines)> full = []; + var folders = Directory.EnumerateDirectories(arcPath, pattern, SearchOption.TopDirectoryOnly); + foreach (var folder in folders) + { + // Get the file name out from the pattern we specified above. + var name = Path.GetFileName(folder).AsSpan(); + var textFile = name.Slice(prefix.Length, name.Length - prefix.Length - suffix.Length); + if (!textFile.StartsWith(type)) + continue; + var fn = Path.ChangeExtension(textFile[type.Length..].ToString(), null); + var (shortText, fullText) = GetTextTuple(textConfig, lang, folder, type, fn); + text.Add(new(fn, shortText)); + full.Add(new(fn, fullText)); + } + + DumpTotalFiles(type, lang, text, full); + } + + private (string[] Text, string[] Full) GetTextTuple(TextConfig textConfig, string lang, string dumped, string folder, string file) + { + var files = Directory.GetFiles(dumped); + if (files.Length != 2) + { + if (files.Length == 1 && !files[0].EndsWith("ahtb")) + { + var dat = files.Single(z => !z.EndsWith("ahtb")); + var dest = Path.Combine(lang, folder, $"{file}.txt"); + var pathLines = GetPath("text", dest); + var textData = File.ReadAllBytes(dat); + var lines = TextFile.GetStrings(textData, textConfig)!; + File.WriteAllLines(pathLines, lines); + return (lines, lines); + } + return (Array.Empty(), Array.Empty()); + } + + { + var dat = files.Single(z => !z.EndsWith("ahtb")); + var ahtb = files.Single(z => z.EndsWith("ahtb")); + + var dest = Path.Combine(lang, folder, $"{file}.txt"); + var pathLines = GetPath("text", dest); + var textData = File.ReadAllBytes(dat); + var lines = TextFile.GetStrings(textData, textConfig)!; + File.WriteAllLines(pathLines, lines); + + var ahtbData = File.ReadAllBytes(ahtb); + var table = new AHTB(ahtbData); + var detailed = table.MergeFlat(lines); + + var pathAHTB = GetPath("textFull", dest); + File.WriteAllLines(pathAHTB, detailed); + return (lines, detailed); + } + } + + private void DumpTotalFiles(string type, string lang, + IReadOnlyList<(string File, string[] Lines)> text, + IReadOnlyList<(string File, string[] Lines)> full) + { + var outText = GetPath("text", Path.Combine(lang, $"{type}.txt")); + using var swt = File.CreateText(outText); + var outFull = GetPath("text", Path.Combine(lang, $"{type}Full.txt")); + using var swf = File.CreateText(outFull); + for (var i = 0; i < text.Count; i++) + { + static void WriteFileHeader(string file, TextWriter s) + { + s.WriteLine("~~~~~~~~~~~~~~~"); + s.WriteLine($"Text File : {file}.dat"); + s.WriteLine("~~~~~~~~~~~~~~~"); + } + + var (fn, lines) = full[i]; + WriteFileHeader(fn, swf); + foreach (var line in lines) + swf.WriteLine(line); + + (fn, lines) = text[i]; + WriteFileHeader(fn, swt); + foreach (var line in lines) + swt.WriteLine(line); + } + } + + private void Dump(ulong hash, Func> sel) + where TTable : class, IFlatBufferSerializable + where TEntry : notnull + { + var flat = Get(hash); + var path = GetPath(hash.ToString("X16")); + Dump(sel, flat, path); + } + + private TTable Dump(string f, Func> sel) + where TTable : class, IFlatBufferSerializable + where TEntry : notnull + { + var flat = Get(f); + var path = GetRawPath(f); + Dump(sel, flat, path); + return flat; + } + + private string GetRawPath(string fileName) => GetPath("raw", fileName.Replace('/', Path.DirectorySeparatorChar)); + + private static void Dump(Func> sel, TTable flat, string path) + where TTable : class, IFlatBufferSerializable where TEntry : notnull + { + DumpJson(flat, path); + var table = sel(flat); + var dump = TableUtil.GetTable(table); + + var fileName = Path.ChangeExtension(path, ".txt"); + File.WriteAllText(fileName, dump); + } + + private TTable Get(ulong hash) + where TTable : class, IFlatBufferSerializable + { + var bin = rom.GetPackedFile(hash); + return Get(bin); + } + + private TTable Get(string f) + where TTable : class, IFlatBufferSerializable + { + var bin = rom.GetPackedFile(f.Replace("bfbs", "bin")); + return Get(bin); + } + + private static TTable Get(Memory bin) where TTable : class, IFlatBufferSerializable => FlatBufferConverter.DeserializeFrom(bin); + + private void DumpSel(string f, Func> sel, string prefix = "sel") + where TTable : class, IFlatBufferSerializable + where TEntry : notnull + { + var bin = rom.GetPackedFile(f.Replace("bfbs", "bin")); + var path = GetPath("raw", f.Replace('/', Path.DirectorySeparatorChar)); + DumpSel(sel, prefix, bin, path); + } + + private static void DumpSel(Func> sel, string prefix, Memory bin, string path) + where TTable : class, IFlatBufferSerializable where TEntry : notnull + { + var flat = FlatBufferConverter.DeserializeFrom(bin); + var table = sel(flat); + var dump = TableUtil.GetTable(table); + + var fileName = Path.ChangeExtension(path, $".{prefix}.txt"); + try + { + File.WriteAllText(fileName, dump); + } + catch + { + // Ignore. File likely already exists and is open in an editor. + } + } + + private void DumpX(string f, Func> sel, Func> sel2) + where TTable : class, IFlatBufferSerializable + where TEntry : class + where TSub : notnull + { + var bin = rom.GetPackedFile(f.Replace("bfbs", "bin")); + var flat = FlatBufferConverter.DeserializeFrom(bin); + + var path = GetPath("raw", f.Replace('/', Path.DirectorySeparatorChar)); + DumpJson(flat, path); + + var arr = sel(flat); + for (int i = 0; i < arr.Count; i++) + { + var entry = sel2(arr[i]); + var dump = TableUtil.GetTable(entry); + + var folder = Path.GetDirectoryName(path); + var fileName = Path.Combine(folder!, $"{typeof(TEntry).Name}_{i}.txt"); + File.WriteAllText(fileName, dump); + } + } + + private T DumpJson(string f) where T : class, IFlatBufferSerializable + { + var bin = rom.GetPackedFile(f.Replace("bfbs", "bin")); + var flat = FlatBufferConverter.DeserializeFrom(bin); + + var path = GetPath("raw", f.Replace('/', Path.DirectorySeparatorChar)); + DumpJson(flat, path); + return flat; + } + + + private static readonly System.Text.Json.JsonSerializerOptions Options = new() + { + WriteIndented = true, + IncludeFields = true, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, + }; + + private static void DumpJson(T flat, string filePath) where T : class + { + var json = System.Text.Json.JsonSerializer.Serialize(flat, Options); + + var fileName = Path.ChangeExtension(filePath, ".json"); + File.WriteAllText(fileName, json); + } + + public void DumpSpecific() + { + string[] files = + [ + "world/ik_data/ui/pokedex/black_list_main/black_list_main_array.bfbs", + "world/ik_data/rank_battle/reward/reward_array.bfbs", + + "world/ik_data/field/area_jump/field_area_jump_point/field_area_jump_point_array.bfbs", + + "world/ik_data/field/area/field_main_area/field_main_area_array.bfbs", + "world/ik_data/field/area/field_sub_area/field_sub_area_array.bfbs", + "world/ik_data/field/area/field_location/field_location_array.bfbs", + "world/ik_data/field/area/field_battle_zone/field_battle_zone_array.bfbs", + "world/ik_data/field/area/field_wild_zone/field_wild_zone_array.bfbs", + "world/ik_data/field/area/field_scene_area/field_scene_area_array.bfbs", + + "world/ik_data/field/area/area_config/area_config_data.bfbs", + "world/ik_data/field/config/field_config/field_config_data.bfbs", + + "world/ik_data/field/map_replace/map_replace_data/map_replace_data_array.bfbs", + + "world/ik_data/field/data/field_data_config/field_data_config_array.bfbs", + + "world/ik_data/field/pokemon_spawner/pokemon_spawner_data/pokemon_spawner_data_array.bfbs", + "world/ik_data/field/spawner_transform_data/pokemon_spawner_transform/pokemon_spawner_transform/pokemon_spawner_transform_array.bfbs", + + "world/ik_data/field/weather/field_weather_table/field_weather_table.bfbs", + + "world/ik_data/playreport/playreport_types/key_to_data_types.bfbs", + "world/ik_data/field/landscape/field_landscape_terrain_layer_table/field_landscape_terrain_layer_table_array.bfbs", + "world/ik_data/audio/engine/poke_type_to_audio_group/poke_type_to_audio_group_array.bfbs", + "world/ik_data/ui/ruby_description/ruby_description_data.bfbs", + "world/ik_data/playreport/playreport_events/playreport_events_array.bfbs", + "world/ik_data/field/landscape/field_landscape_attribute_table/field_landscape_attribute_table_array.bfbs", + "world/ik_data/audio/engine/init_settings/init_settings_data.bfbs", + "world/ik_data/audio/engine/group_settings/group_settings_array.bfbs", + + "world/ik_data/field/pokemon/pokemon_data/pokemon_data/pokemon_data_array.bfbs", + "world/ik_data/field/pokemon/encount_data/encount_data/encount_data_array.bfbs", + + "world/ik_data/field/oyabun/oyabun_waza/oyabun_waza.bfbs", + + "world/ik_data/field/item_ball/item_ball_spawner_data/item_ball_spawner_data/item_ball_spawner_data_array.bfbs", + "world/ik_data/field/spawner_transform_data/pokemon_spawner_transform/pokemon_spawner_transform/pokemon_spawner_transform_array.bfbs", + + "world/ik_data/field/npc/npc_asset_data/npc_asset_data/npc_asset_data.bfbs", + + "world/ik_data/field/random_pop_item/random_pop_item_table/random_pop_item_table_data/random_pop_item_table_data_array.bfbs", + "world/ik_data/field/random_pop_item_spawner/random_pop_item_spawner_data/random_pop_item_spawner_data_array.bfbs", + "world/ik_data/field/field_wazagimmick_spawner/wazagimmick_spawner_data/wazagimmick_spawner_data_array.bfbs", + + "ik_event/bin/flag/temp_work.bin", + "ik_event/bin/flag/quest_work.bin", + "ik_event/bin/flag/system_flag.bin", + "ik_event/bin/flag/momiji_work.bin", + "ik_event/bin/flag/system_work.bin", + "ik_event/bin/flag/event_flag.bin", + "ik_event/bin/flag/temp_flag.bin", + "ik_event/bin/momiji_count/momiji_count.bin", + + "ik_event/bin/mission_card/mission_card.bin", + "ik_event/bin/xconst/event_xconst.bin", + "ik_event/bin/quest/main_quest.bin", + "ik_event/bin/quest/sub_quest.bin", + "ik_event/bin/quest/momiji_quest.bin", + "ik_event/bin/phase/phase.bin", + "ik_event/bin/flower/flower.bin", + "ik_event/bin/event_control/event_control.bin", + + "world/exl/dungeon_map_ui_data/dungeon_map_ui_data/dungeon_map_ui_data.bin", + + "world/ik_data/field/weather/weather_schedule_table/weather_schedule_table/weather_schedule_table.bfbs", + "world/ik_data/field/weather/field_weather_table/field_weather_table.bfbs", + "world/ik_data/field/weather/weather_happening/weather_happening_array.bfbs", + ]; + foreach (var f in files) + RipBFBS(f); + } + + public void RipBFBS(string f) + { + DumpPackedFile(f); + DumpPackedFile(Path.ChangeExtension(f, ".bin")); + } + + public void DumpFromTextFile(string path) + { + var files = File.ReadAllLines(path); + foreach (var f in files) + { + if (!rom.HasFile(f)) + continue; + DumpPackedFile(f); + } + } + + private void DumpPackedFile(string f) + { + var path = GetPath("raw", f.Replace('/', Path.DirectorySeparatorChar)); + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + var data = rom.GetPackedFile(f); + File.WriteAllBytes(path, data); + + var ext = Path.GetExtension(f); + if (ext == ".bfbs") + { + var settings = new Schema.SchemaDumpSettings { FileNamespace = "pkNX.Structures.FlatBuffers.ZA", EmitGeneratedCountComments = false }; + var schema = Schema.SchemaDump.HandleReflection(data, path, dir, settings); + DumpJson(schema, Path.ChangeExtension(path, ".schema.json")); + } + } + + public void DumpHashReflectionBFBS() + { + ulong[] files = + [ + // This isn't really needed as the game has very leaky file names. Leave in for future reference. + ]; + foreach (var f in files) + { + if (!rom.HasFile(f)) + continue; + + var path = GetPath("hashFile", f.ToString("X16")); + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + var data = rom.GetPackedFile(f); + File.WriteAllBytes(path, data); + try + { + var settings = new Schema.SchemaDumpSettings(); + var schema = Schema.SchemaDump.HandleReflection(data, path, dir, settings); + DumpJson(schema, Path.ChangeExtension(path, ".schema.json")); + } + catch + { + } + } + } + + public void DumpArchives() + { + var dirRootDump = GetPath(DumpArchive); + if (Directory.Exists(dirRootDump)) + { + var dr = WinFormsUtil.Prompt(MessageBoxButton.YesNo, "Archive dump folder already exists -- are you sure you want to dump again?"); + if (dr != MessageBoxResult.Yes) + return; + } + TrinityPakExtractor.DumpArchives(rom.PathRomFS, dirRootDump); + Debug.WriteLine("Loaded"); + } + + public void DumpMisc() + { + Dump("world/ik_data/rank_battle/reward/reward_array.bfbs", z => z.Table); + Dump("world/ik_data/ui/pokedex/black_list_main/black_list_main_array.bfbs", z => z.Table); + + DumpJson("world/ik_data/capture/capture_ball_data/capture_ball_data.bin"); + DumpJson("world/ik_data/capture/capture_data/capture_data.bin"); + DumpJson("world/ik_data/capture/capture_zarank_data/capture_zarank_data.bin"); + + Dump("ik_event/bin/za_reward_item_data/za_reward_item_data.bin", z => z.Table); + Dump("ik_event/bin/event_trainer_battle_data/trainer_btl_data_global.bin", z => z.Table); + Dump("world/exl/shop/shop_item_lineup/shop_item_lineup.bin", z => z.Table); + Dump("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); + Dump("world/ik_data/field/random_pop_item_spawner/random_pop_item_spawner_data/random_pop_item_spawner_data_array.bfbs", z => z.Table); + Dump("ik_event/bin/medal_rate/defeat_bonus.bin", z => z.Table); + + Dump("world/exl/hologram/hud_shopping/hud_shopping.bin", z => z.Table); + + Dump("ik_event/bin/xconst/event_xconst.bin", z => z.Table); + Dump("ik_event/bin/event_control/event_control.bin", z => z.Table); + + Dump("ik_event/bin/title/title.bin", z => z.Table); + Dump("ik_event/bin/title_count/title_count.bin", z => z.Table); + + DumpJson("world/ik_data/field/weather/field_weather_table/field_weather_table.bin"); + Dump("world/ik_data/field/weather/weather_happening/weather_happening_array.bin", z => z.Table); + + DumpDressUp(); + } + + private void DumpDressUp() + { + var groups = Dump("world/exl/dress_up_data/dress_up_group_data/dress_up_group_data.bin", z => z.Table); + const string ens = "world/exl/dress_up_data/dress_up_ensemble_data/dress_up_ensemble_data.bin"; + Dump(ens, z => z.Table); + DumpSel(ens, z => z.Table.SelectMany(e => e.Ensemble), "ens"); + var dress = Dump("world/exl/dress_up_data/dress_up_data/dress_up_data.bin", z => z.Table); + foreach (var language in LanguageEnglishNames) + DumpLabels(dress.Table, groups.Table, language); + + var hm = Dump("world/exl/hair_make_data/hair_make_data/hair_make_data.bin", z => z.Table); + } + + private void DumpLabels(IList dress, IList groups, string language) + { + const string textFileNameLabel = "dressup_item_name"; // .dat + var config = new TextConfig(GameVersion.ZA); + var text = GetCommonText(textFileNameLabel, language, config); + var ahtb = GetCommonAHTB(textFileNameLabel, language); + var dictionary = ahtb.ToDictionary(text); + + // Name->Group + var groupGet = new Dictionary(groups.Count); + foreach (var group in groups) + { + var hash = FnvHash.HashFnv1a_64(group.Group); + var localized = dictionary[hash]; + var tuple = (group.Group, localized); + groupGet.Add(group.Name, tuple); + } + + var result = new string[dress.Count]; + for (int i = 0; i < dress.Count; i++) + { + var d = dress[i]; + var name = d.Name; + var color1 = d.Color1; + var color2 = d.Color2; + bool hasColor2 = color2 != "dressup_item_color_null"; + var colorString = dictionary[FnvHash.HashFnv1a_64(color1)]; + if (hasColor2) + colorString += $", {dictionary[FnvHash.HashFnv1a_64(color2)]}"; + + var (_, localized) = groupGet[name]; + + var nameString = $"{localized} ({colorString})"; + var line = $"{d.MagicValue:D8}\t{nameString}"; + result[i] = line; + } + + var file = GetPath(language, "dressup_labels.txt"); + File.WriteAllLines(file, result); + } + + public void DumpScrubbedInfo() + { + DumpScrubbedPokedexEntries(); + DumpScrubbedItemInfo(); + DumpScrubbedMoveInfo(); + DumpScrubbedPokedexCategories(); + DumpScrubbedDressupItemNames(); + } + + public void DumpFieldItems() + { + var files = new string[] + { + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_item_ball_spawner_/t1_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i004a/sub_scene/t1_i004a_gimmick/t1_i004a_item_ball_spawner_/t1_i004a_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i004b/sub_scene/t1_i004b_gimmick/t1_i004b_item_ball_spawner_/t1_i004b_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i004c/sub_scene/t1_i004c_gimmick/t1_i004c_item_ball_spawner_/t1_i004c_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i004d/sub_scene/t1_i004d_gimmick/t1_i004d_item_ball_spawner_/t1_i004d_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i006_2/sub_scene/t1_i006_2_gimmick/t1_i006_2_item_ball_spawner_/t1_i006_2_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i006_3/sub_scene/t1_i006_3_gimmick/t1_i006_3_item_ball_spawner_/t1_i006_3_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i007a/sub_scene/t1_i007a_gimmick/t1_i007a_item_ball_spawner_/t1_i007a_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i008_1/sub_scene/t1_i008_1_gimmick/t1_i008_1_item_ball_spawner_/t1_i008_1_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i011/sub_scene/t1_i011_gimmick/t1_i011_item_ball_spawner_/t1_i011_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i012_1/sub_scene/t1_i012_1_gimmick/t1_i012_1_item_ball_spawner_/t1_i012_1_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i012_2/sub_scene/t1_i012_2_gimmick/t1_i012_2_item_ball_spawner_/t1_i012_2_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_i014_1/sub_scene/t1_i014_1_gimmick/t1_i014_1_item_ball_spawner_/t1_i014_1_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t1_last_battle/sub_scene/t1_lb_gimmick/t1_lb_item_ball_spawner_/t1_lb_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t2/sub_scene/t2_gimmick/t2_item_ball_spawner_/t2_item_ball_spawner_0.trscn", + "world/ik_scene/field/area/t3/sub_scene/t3_gimmick/t3_item_ball_spawnwer_/t3_item_ball_spawnwer_0.trscn", + "world/ik_scene/field/area/t3_2/sub_scene/t3_2_gimmick/t3_2_item_ball_spawnwer_/t3_2_item_ball_spawnwer_0.trscn", + }; + + var fileSpawners = rom.GetPackedFile("world/ik_data/field/item_ball/item_ball_spawner_data/item_ball_spawner_data/item_ball_spawner_data_array.bin"); + var objSpawners = FlatBufferConverter.DeserializeFrom(fileSpawners); + List<(string FieldItemID, string ItemID)> spawners = []; + + const string path = "world/exl/item_data/item_data/item_data.bin"; + var itemTable = Get(path).Table; + + bool IsTM(int id) + { + var item = itemTable.FirstOrDefault(z => z.Id == id); + if (item is null) + return false; + return item.MachineIndex > -1; + } + + int GetTMIndex(int id) + { + var item = itemTable.FirstOrDefault(z => z.Id == id); + if (item is null) + return -1; + return item.MachineIndex + 1; + } + + const string lang = "English"; + var cfg = new TextConfig(GameVersion.ZA); + var names = GetCommonText("itemname", lang, cfg); + + foreach (var spawner in objSpawners.Table) + { + var data = spawner.Table; + foreach (var item in data) + { + var fieldItemID = item.Id.StartsWith("itd_") ? item.Id : item.Id[(item.Id.IndexOf('_') + 1)..]; + foreach (var info in item.TableInfoList) + spawners.Add((fieldItemID, info.TableId!)); + } + } + + foreach (var file in files) + { + var area = file.Split('/')[4]; + var fileScene = rom.GetPackedFile(file); + var objScene = FlatBufferConverter.DeserializeFrom(fileScene); + List result = + [ + "Spawner\tItem ID\tItem Name\tX\tY\tZ" + ]; + + foreach (var t in objScene.Objects.Where(z => z.Type is "trinity_ObjectTemplate")) + { + var obj = FlatBufferConverter.DeserializeFrom(t.Data); + var pos = FlatBufferConverter.DeserializeFrom(obj.Data).Position.Translation; + var name = obj.ObjectTemplateName; + var item = spawners.FirstOrDefault(z => z.FieldItemID == name); + + // dummy items, not associated to any spawners + if (item.ItemID is null) + continue; + + var itemID = int.Parse(item.ItemID[16..20]); + var itemName = IsTM(itemID) ? $"TM{GetTMIndex(itemID):000}" : names[itemID]; + result.Add($"{name}\t{itemID:0000}\t{itemName}\t{pos.X}\t{pos.Y}\t{pos.Z}"); + } + + if (result.Count > 1) + File.WriteAllLines(GetPath("field_items", $"field_items_{area}.txt"), result); + } + } + + public void DumpHiddenItems() + { + var files = new[] + { + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_random_pop_item_spawner_/t1_random_pop_item_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_random_pop_item_spawner/t1_center_random_pop_item_sapwner_/t1_center_random_pop_item_sapwner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_random_pop_item_spawner/t1_rouge_random_pop_item_spawner_/t1_rouge_random_pop_item_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_random_pop_item_spawner/t1_rose_random_pop_item_spawner_/t1_rose_random_pop_item_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_random_pop_item_spawner/t1_jaune_random_pop_item_spawner_/t1_jaune_random_pop_item_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_random_pop_item_spawner/t1_blue_random_pop_item_spawner_/t1_blue_random_pop_item_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_random_pop_item_spawner/t1_veil_random_pop_item_spawner_/t1_veil_random_pop_item_spawner_0.trscn", + "world/ik_scene/field/area/t2/sub_scene/t2_gimmick/t2_random_pop_item_spawner_/t2_random_pop_item_spawner_0.trscn", + "world/ik_scene/field/area/t3/sub_scene/t3_gimmick/t3_random_pop_item_spawner_/t3_random_pop_item_spawner_0.trscn", + "world/ik_scene/field/area/t3_2/sub_scene/t3_2_gimmick/t3_2_random_pop_item_spawner_/t3_2_random_pop_item_spawner_0.trscn", + }; + + // get all hidden item tables + var itemTable = rom.GetPackedFile("world/ik_data/field/random_pop_item/random_pop_item_table/random_pop_item_table_data/random_pop_item_table_data_array.bin"); + var objItem = FlatBufferConverter.DeserializeFrom(itemTable); + List tables = []; + List> items = []; + + foreach (var t in objItem.Table) + { + var data = t.Data; + foreach (var i in data) + tables.Add(i.Id); + } + + foreach (var t in objItem.Table) + { + foreach (var d in t.Data) + { + List<(string ItemID, int ItemWeight)> result = []; + foreach (var i in d.ItemLotteryDataList) + result.Add((i.ItemId, i.Weight)); + items.Add(result); + } + } + + // get all hidden item spawner objects + var spawnerTable = rom.GetPackedFile("world/ik_data/field/random_pop_item_spawner/random_pop_item_spawner_data/random_pop_item_spawner_data_array.bin"); + var objSpawner = FlatBufferConverter.DeserializeFrom(spawnerTable); + List<(string ObjectName, string TableID)> spawners = []; + foreach (var t in objSpawner.Table) + { + var data = t.Table; + foreach (var i in data) + { + var objectName = i.AppearanceSpawnerObjectInfoList[0].ObjectName; + var tableID = i.TableInfoList[0].TableId; + spawners.Add((objectName, tableID)); + } + } + + // get all hidden item spawner coordinates + List<(string TableID, PackedVec3f Coordinates)> coordinates = []; + foreach (var file in files) + { + var fileScene = rom.GetPackedFile(file); + var objScene = FlatBufferConverter.DeserializeFrom(fileScene); + foreach (var t in objScene.Objects.Where(z => z.Type is "trinity_ObjectTemplate")) + { + var obj = FlatBufferConverter.DeserializeFrom(t.Data); + var pos = FlatBufferConverter.DeserializeFrom(obj.Data).Position.Translation; + var name = obj.ObjectTemplateName; + coordinates.Add((name, pos)); + } + } + + const string lang = "English"; + var cfg = new TextConfig(GameVersion.ZA); + var names = GetCommonText("itemname", lang, cfg); + + // output to a table! + List output = []; + foreach (var (objectName, tableID) in spawners) + { + var (tableId, pos) = coordinates.FirstOrDefault(z => z.TableID == objectName); + var (_, s) = spawners.FirstOrDefault(z => z.TableID == tableID); + + if (s.Contains("_test_")) + continue; + + output.Add($"Table ID: {s}"); + output.Add($"Hidden Item Table: {tableId}"); + output.Add($"Coordinates: V3f({pos.X}, {pos.Y}, {pos.Z})"); + + var itemTableIndex = tables.IndexOf(s); + var itemList = items[itemTableIndex].OrderByDescending(z => z.ItemWeight).ToList(); + float totalWeight = 0; + + foreach (var item in itemList) + totalWeight += item.ItemWeight; + + foreach (var item in itemList) + { + float rate = (float)(Math.Round((item.ItemWeight / totalWeight) * 100f, 2)); + var itemID = int.Parse(item.ItemID); + output.Add($"- {rate:00.00}% {names[itemID]}"); + } + + output.Add(""); + } + + File.WriteAllLines(GetPath("field_items", "hidden_items.txt"), output); + } + + public void DumpMegaCrystals() + { + var files = new[] + { + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_waza_gimmick/t1_waza_gimmick_blue_/t1_waza_gimmick_blue_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_waza_gimmick/t1_waza_gimmick_center_/t1_waza_gimmick_center_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_waza_gimmick/t1_waza_gimmick_jaune_/t1_waza_gimmick_jaune_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_waza_gimmick/t1_waza_gimmick_rose_/t1_waza_gimmick_rose_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_waza_gimmick/t1_waza_gimmick_rouge_/t1_waza_gimmick_rouge_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_waza_gimmick/t1_waza_gimmick_veil_/t1_waza_gimmick_veil_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_waza_gimmick_/t1_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0101_w01/t1_wild_a0101_w01_waza_gimmick_/t1_wild_a0101_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0102_w01/t1_wild_a0102_w01_waza_gimmick_/t1_wild_a0102_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0103_w01/t1_wild_a0103_w01_waza_gimmick_/t1_wild_a0103_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0201_w01/t1_wild_a0201_w01_waza_gimmick_/t1_wild_a0201_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0202_w01/t1_wild_a0202_w01_waza_gimmick_/t1_wild_a0202_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0202_w02/t1_wild_a0202_w02_waza_gimmick_/t1_wild_a0202_w02_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0203_w01/t1_wild_a0203_w01_waza_gimmick_/t1_wild_a0203_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0301_w01/t1_wild_a0301_w01_waza_gimmick_/t1_wild_a0301_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0301_w02/t1_wild_a0301_w02_waza_gimmick_/t1_wild_a0301_w02_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0302_w01/t1_wild_a0302_w01_waza_gimmick_/t1_wild_a0302_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0303_w01/t1_wild_a0303_w01_waza_gimmick_/t1_wild_a0303_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0401_w01/t1_wild_a0401_w01_waza_gimmick_/t1_wild_a0401_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0402_w01/t1_wild_a0402_w01_waza_gimmick_/t1_wild_a0402_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0403_w01/t1_wild_a0403_w01_waza_gimmick_/t1_wild_a0403_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0501_w01/t1_wild_a0501_w01_waza_gimmick_/t1_wild_a0501_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0501_w02/t1_wild_a0501_w02_waza_gimmick_/t1_wild_a0501_w02_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0502_w01/t1_wild_a0502_w01_waza_gimmick_/t1_wild_a0502_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0502_w02/t1_wild_a0502_w02_waza_gimmick_/t1_wild_a0502_w02_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0503_w01/t1_wild_a0503_w01_waza_gimmick_/t1_wild_a0503_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0601_w01/t1_wild_a0601_w01_waza_gimmick_/t1_wild_a0601_w01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0601_w01_v01/t1_wild_a0601_w01_v01_waza_gimmick_/t1_wild_a0601_w01_v01_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0601_w01_v02/t1_wild_a0601_w01_v02_waza_gimmick_/t1_wild_a0601_w01_v02_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0601_w01_v03/t1_wild_a0601_w01_v03_waza_gimmick_/t1_wild_a0601_w01_v03_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t2/sub_scene/t2_gimmick/t2_waza_gimmick_/t2_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t3/sub_scene/t3_gimmick/t3_waza_gimmick_/t3_waza_gimmick_0.trscn", + "world/ik_scene/field/area/t3_2/sub_scene/t3_2_gimmick/t3_2_waza_gimmick_/t3_2_waza_gimmick_0.trscn", + }; + + const string wgp = "world/ik_data/field/field_wazagimmick_private/field_wazagimmick_private/field_wazagimmick_private_array.bin"; + const string wsd = "world/ik_data/field/field_wazagimmick_spawner/wazagimmick_spawner_data/wazagimmick_spawner_data_array.bin"; + var wgd = rom.GetPackedFile(wgp); + var wgt = Get(wgd).Table; + Dump(wgp, z => z.Table); + Dump(wsd, z => z.Table); + List<(string Identifier, PackedVec3f Coordinates)> gimmicks = []; + + foreach (var file in files) + { + var scene = rom.GetPackedFile(file); + var objScene = FlatBufferConverter.DeserializeFrom(scene); + + foreach (var t in objScene.Objects.Where(z => z.Type is "trinity_ObjectTemplate")) + { + var obj = FlatBufferConverter.DeserializeFrom(t.Data); + var pos = FlatBufferConverter.DeserializeFrom(obj.Data).Position.Translation; + var name = obj.ObjectTemplateName; + var coords = new PackedVec3f { X = pos.X, Y = pos.Y, Z = pos.Z }; + + if (name.StartsWith("spn_")) + name = name[4..]; + + gimmicks.Add((name, coords)); + } + } + + List Result = + [ + "Object Name\tCluster Type\tX\tY\tZ" + ]; + foreach (var (identifier, pos) in gimmicks) + { + foreach (var t in wgt) + { + var tbl = t.Table; + var cluster = tbl.FirstOrDefault(z => z.ObjectName.Contains(identifier)); + if (cluster is null) + continue; + var id = cluster.Extension.ItemPopId; + if (!IsMegaCrystalCluster(id)) + continue; + + foreach (var c in cluster.ObjectName) + Result.Add($"{c}\t{id}\t{pos.X}\t{pos.Y}\t{pos.Z}"); + } + } + + File.WriteAllLines(GetPath("field_items", "mega_crystals.txt"), Result); + return; + static bool IsMegaCrystalCluster(string? id) => id is "id_wazagim_item_spn_mega_01" or "id_wazagim_item_spn_mega_11"; + } + + public void DumpMoves() + { + const string language = "English"; + + const string wazaPath = "avalon/data/waza_array.bin"; + Dump(wazaPath, z => z.Table); + var table = Get(wazaPath); + var outPath = GetPath("pkhex"); + + var pp = table.Table.Select(z => z.PP).Select(z => $"{z:00}"); + File.WriteAllText(Path.Combine(outPath, "move_pp.txt"), string.Join(',', pp)); + + var types = table.Table.Select(z => z.Type).Select(z => $"{z:00}"); + File.WriteAllText(Path.Combine(outPath, "move_type.txt"), string.Join(',', types)); + + // get dummied moves + var cfg = new TextConfig(rom.Game); + string[] GetText(string name) => GetCommonText(name, language, cfg); + + var moveNames = GetText("wazaname"); + var moveDesc = GetText("wazainfo"); + + var moves = table.Table; + var snapped = new List(moves.Count); + for (int i = 1; i < moveNames.Length; i++) + { + var move = moves.FirstOrDefault(m => m.MoveID == i); + if (move?.CanUseMove != true) + snapped.Add((ushort)i); + } + + var path = GetPath("snappedMoves.txt"); + var tuple = snapped.Select(z => $"{z:000}\t{moveNames[z]}"); + File.WriteAllLines(path, tuple); // rest in peace + + var snap2 = GetPath("snappedID.txt"); + var snapMove = string.Join(", ", snapped.Select(z => $"{z:000}")); + File.WriteAllText(snap2, snapMove); + + var dummied = new byte[(snapped[^1] >> 3) + 1]; + foreach (var value in snapped) + dummied[value >> 3] |= (byte)(1 << (value & 7)); + var dumb = GetPath("dummied.txt"); + var dummiedList = string.Join(',', dummied.Select(z => $"0x{z:X2}")); + File.WriteAllText(dumb, dummiedList); + + // actual move info + const string pwpa = "param_ai/data/battle/personal_waza_param/personal_waza_param_array.bfbs"; + Dump(pwpa, z => z.Table); + DumpSel(pwpa, z => z.Table.SelectMany(x => x.Table), "x"); + + const string wpa = "param_ai/data/ai/waza/waza_param/waza_param_array.bin"; + Dump(wpa, z => z.Table); + DumpSel(wpa, z => z.Table.SelectMany(x => x.Table), "x"); + } + + public void DumpPersonal() + { + const string suffix = "za"; + var ident = "za"u8; + const string personalPath = "avalon/data/personal_array.bin"; + Dump(personalPath, z => z.Table); + + var perbin = rom.GetPackedFile(personalPath); + var pt = new PersonalTable9ZA(new FakeContainer([perbin])); + + const string alphaMovesPath = "world/ik_data/field/oyabun/oyabun_waza/oyabun_waza.bin"; + var alphaMoves = Dump(alphaMovesPath, z => z.Table) + .Table; + + foreach (var alpha in alphaMoves) + { + foreach (var form in alpha.FormTableList) + pt[SpeciesConverterZA.GetNational9(alpha.DevNo), (byte)form.FormNo].AlphaMove = form.WazaNo; + } + + var bin = pt.Write(); + var path2 = GetPath("pkhex", "personal_za"); + File.WriteAllBytes(path2, bin); + + var learnsets = SerializeLearnsetPickle(pt); + File.WriteAllBytes(GetPath("pkhex", $"lvlmove_{suffix}.pkl"), BinLinkerWriter.Write16(learnsets, ident)); + var plus = SerializePlusPickle(pt); + File.WriteAllBytes(GetPath("pkhex", $"plus_{suffix}.pkl"), BinLinkerWriter.Write16(plus, ident)); + //var egg = SerializeU16Pickle(pt, z => z.EggMoves); + //File.WriteAllBytes(GetPath("pkhex", $"eggmove_{suffix}.pkl"), BinLinkerWriter.Write16(egg, ident)); + //var remind = SerializeU16Pickle(pt, z => z.ReminderMoves); + //File.WriteAllBytes(GetPath("pkhex", $"reminder_{suffix}.pkl"), BinLinkerWriter.Write16(remind, ident)); + var evos = SerializeEvolutionPickle(pt); + File.WriteAllBytes(GetPath("pkhex", $"evos_{suffix}.pkl"), BinLinkerWriter.Write16(evos, ident)); + + // No need to dump the species remap table; unchanged from S/V. + // List<(ushort Internal, ushort National)> map = []; + // for (ushort i = 0; i <= (ushort)DevID.DEV_MATCHA2; i++) + // { + // var pi = pt[i]; + // var info = pi.FB.Info; + // map.Add((info.SpeciesInternal, info.SpeciesNational)); + // } + // File.WriteAllText(GetPath("pkhex", "national dex.txt"), string.Join(Environment.NewLine, map.Select(z => $"{z.Internal},{z.National}"))); + + foreach (var lang in LanguageEnglishNames) + RipPersonal(pt, lang); + } + + private void RipPersonal(PersonalTable9ZA pt, string lang) + { + var cfg = new TextConfig(rom.Game); + string[] GetText(string name) => GetCommonText(name, lang, cfg); + var specNames = GetText("monsname"); + var moveNames = GetText("wazaname"); + var abilNames = GetText("tokusei"); + var itemNames = GetText("itemname"); + var zukanA = GetText("zukan_comment_A"); + var zukanB = GetText("zukan_comment_B"); + var zukanAHTB = rom.GetPackedFile($"{message}/dat/{lang}/common/zukan_comment_A.tbl"); + var pd = new PersonalDumper9a + { + Species = specNames, + Moves = moveNames, + Abilities = abilNames, + Items = itemNames, + ZukanA = zukanA, + ZukanB = zukanB, + ZukanAHTB = new(zukanAHTB), + + Types = GetText("typename"), + Colors = Enum.GetNames(), + EggGroups = Enum.GetNames(), + ExpGroups = Enum.GetNames(), + }; + + var lines = pd.Dump(pt); + File.WriteAllLines(GetPath(lang, "personal.txt"), lines); + + var moveLines = pd.MoveSpeciesLearn + .Select((z, i) => $"{i:000}\t{moveNames[i]}\t{string.Join(", ", z.Distinct())}"); + 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) + .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]}"); + File.WriteAllText(GetPath(lang, "dex.txt"), string.Join(Environment.NewLine, pc)); + + var foreign = pt.Table + .Where(z => z.FB.Dex == 0 && z.IsPresentInGame) + .GroupBy(z => z.FB.Info.SpeciesNational) + .Select(z => z.First()); + + var fl = foreign + .Select(z => $"{z.FB.Info.SpeciesNational:000}\t{specNames[z.FB.Info.SpeciesInternal]}"); + File.WriteAllText(GetPath(lang, "foreign.txt"), string.Join(Environment.NewLine, fl)); + + File.WriteAllLines(GetPath(lang, "species.txt"), SpeciesConverterZA.GetRearrangedAsNational(specNames)); + File.WriteAllLines(GetPath(lang, "abilities.txt"), abilNames); + File.WriteAllLines(GetPath(lang, "items.txt"), itemNames); + File.WriteAllLines(GetPath(lang, "moves.txt"), moveNames); + File.WriteAllLines(GetPath(lang, "ZukanA.txt"), zukanA); + File.WriteAllLines(GetPath(lang, "ZukanB.txt"), zukanB); + + var tms = PersonalDumper9a.TMIndexes; + var tmNames = new string[tms.Length]; + for (int i = 0; i < tms.Length; i++) + tmNames[i] = $"TM{i + 1:000}\t{moveNames[tms[i]]}"; + File.WriteAllText(GetPath(lang, "tm.txt"), string.Join(Environment.NewLine, tmNames)); + } + + + private static byte[][] SerializeU16Pickle(PersonalTable9ZA pt, Func> sel) + { + var t = pt.Table; + var result = new byte[t.Length][]; + for (int i = 0; i < t.Length; i++) + { + var p = t[i].FB; + if (!p.IsPresentInGame) + result[i] = []; + else + result[i] = Write(sel(p)); + } + return result; + + static byte[] Write(IList moves) + { + using var ms = new MemoryStream(); + using var bw = new BinaryWriter(ms); + foreach (var m in moves.Order()) // just in case + bw.Write(m); + return ms.ToArray(); + } + } + + private static byte[][] SerializeEvolutionPickle(PersonalTable9ZA pt) + { + var t = pt.Table; + var result = new byte[t.Length][]; + for (int i = 0; i < t.Length; i++) + result[i] = GetPickle(t[i]); + return result; + + static byte[] GetPickle(PersonalInfo9ZA e) + { + if (!e.IsPresentInGame) + return []; + return Write(e.FB.Info.SpeciesNational, e.FB.Evolutions); + } + + static byte[] Write(int species, IEnumerable 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. + + foreach (var m in list) // just in case + { + var method = ((EvolutionType)m.Method); + if (method == EvolutionType.Hisui) + continue; // skip: no evolution + + // ReSharper disable RedundantCast + bw.Write((byte)method); + bool levelRequired = method.IsLevelUpRequired(); + bw.Write(levelRequired); + bw.Write(GetArg(method, m.Argument)); + bw.Write(SpeciesConverterZA.GetNational9(m.SpeciesInternal)); + bw.Write((byte)m.Form); + bw.Write((byte)m.Level); + // ReSharper restore RedundantCast + + static ushort GetArg(EvolutionType type, ushort arg) + { + if (type.IsPlibUseItemType()) + return Plib9.PlibToItem[arg]; + return arg; + } + } + return ms.ToArray(); + } + } + + private static byte[][] SerializeLearnsetPickle(PersonalTable9ZA pt) + { + var t = pt.Table; + var result = new byte[t.Length][]; + for (int i = 0; i < t.Length; i++) + { + var p = t[i]; + if (!p.IsPresentInGame) + { + result[i] = []; + continue; + } + var learn = p.FB.Learnset; + result[i] = Write(learn); + } + + return result; + + static byte[] Write(IList fbLearnset) + { + using var ms = new MemoryStream(4 * fbLearnset.Count); + using var bw = new BinaryWriter(ms); + foreach (var m in fbLearnset) + bw.Write(m.Move); + foreach (var m in fbLearnset) + { + var lvl = m.Level is (-3 or -2) ? 0 : m.Level; // Evo or Relearn + bw.Write((byte)lvl); + } + + return ms.ToArray(); + } + } + + private static byte[][] SerializePlusPickle(PersonalTable9ZA pt) + { + var t = pt.Table; + var result = new byte[t.Length][]; + for (int i = 0; i < t.Length; i++) + { + var p = t[i]; + if (!p.IsPresentInGame) + { + result[i] = []; + continue; + } + var learn = p.FB.Learnset; + result[i] = Write(learn); + } + return result; + + static byte[] Write(IList fbLearnset) + { + using var ms = new MemoryStream(4 + (4 * fbLearnset.Count)); + using var bw = new BinaryWriter(ms); + foreach (var m in fbLearnset) + bw.Write(m.Move); + foreach (var m in fbLearnset) + { + var lvl = m.LevelPlus; + bw.Write((byte)lvl); + } + return ms.ToArray(); + } + } + + public void DumpTrainers() + { + const string trd = "world/ik_data/trainer/trdata/trdata_array.bfbs"; + const string trt = "world/ik_data/trainer/trtype/trtype_array.bfbs"; + const string tre = "world/ik_data/trainer/trenv/trenv_array.bfbs"; + const string npc = "world/ik_data/field/npc/npc_asset_data/npc_asset_data/npc_asset_data.bfbs"; + const string btl = "ik_event/bin/event_trainer_battle_data/trainer_btl_data_global.bin"; + RipBFBS(trd); + RipBFBS(trt); + RipBFBS(tre); + Dump(trd, z => z.Table); + Dump(tre, z => z.Table); + Dump(trt, z => z.Table); + DumpX(trd, z => z.Table, z => [z.Poke1, z.Poke2, z.Poke3, z.Poke4, z.Poke5, z.Poke6]); + + var trainers = Get(trd); + var classes = Get(trt); + var npcs = Get(npc).Table; + var trBtlData = Get(btl).Table; + List<(string TrainerBattleID, string NPCAssetID)> trBtls = trBtlData.Select(z => (z.TrainerBattleID, z.NPCAssetID)).ToList()!; + + // pretty + List result = []; + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + var names = GetCommonText("monsname", lang, cfg); + var items = GetCommonText("itemname", lang, cfg); + var abilities = GetCommonText("tokusei", lang, cfg); + var natures = GetCommonText("seikaku", lang, cfg); + var moves = GetCommonText("wazaname", lang, cfg); + var trNames = GetCommonText("trname", lang, cfg); + var trTypes = GetCommonText("trtype", lang, cfg); + var trTypesFlags = GetCommonTextFlags("trtype", lang, cfg); + + var personal = rom.GetPackedFile("avalon/data/personal_array.bin"); + var personalTable = Get(personal); + + var ahtbNames = new AHTB(rom.GetPackedFile($"ik_message/dat/{lang}/common/trname.tbl")); + var ahtbTypes = new AHTB(rom.GetPackedFile($"ik_message/dat/{lang}/common/trtype.tbl")); + + foreach (var t in trainers.Table) + { + var team = new[] { t.Poke1, t.Poke2, t.Poke3, t.Poke4, t.Poke5, t.Poke6 }; + var trName = GetTrainerName(t.TrId); + var trClass = ahtbTypes.GetString(t.TrType, trTypes); + var trClassIndex = Array.IndexOf(trTypes, trClass); + var trClassFlags = trTypesFlags[trClassIndex]; + var trNameFormatted = GetTrainerNameFormatted(trClass, trName, trClassFlags); + result.Add("==="); + result.Add($"{trNameFormatted} ({t.TrId})"); + + if (t.MoneyRate is not 0) + result.Add($"Prize Money: ${GetPrizePayout(team, t.MoneyRate):N0}"); + + if (t.ZARank is not (0 or ZARank.Infinite)) + result.Add($"Z-A Royale Rank: {(char)('Z' - ((int)t.ZARank - 1))}"); + else if (t.ZARank is ZARank.Infinite) + result.Add("Z-A Royale Rank: Infinite"); + + result.Add("==="); + + foreach (var pk in team.Where(z => z.DevId is not DevID.DEV_NULL)) + { + var name = names[(int)pk.DevId]; + var form = pk.FormId is 0 ? string.Empty : $"-{pk.FormId}"; + var gender = pk.Sex is 0 ? string.Empty : pk.Sex is SexType.MALE ? " (♂)" : " (♀)"; + + var level = $" (Lv. {pk.Level})"; + 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); + var move2 = PrettyDumpUtil.GetMoveText(pk.Waza2, moves); + var move3 = PrettyDumpUtil.GetMoveText(pk.Waza3, moves); + var move4 = PrettyDumpUtil.GetMoveText(pk.Waza4, moves); + + // standard level up + if (pk.Waza1.WazaId is 0) + { + var empty = PrettyDumpUtil.GetCurrentMoves(pk.DevId, pk.FormId, (byte)pk.Level, personalTable); + move1 = moves[empty[0]]; + move2 = moves[empty[1]]; + move3 = moves[empty[2]]; + move4 = moves[empty[3]]; + } + + var moveset = new[] { move1, move2, move3, move4 }; + var moveOutput = $" (Moves: {string.Join(" / ", moveset.Where(z => z != moves[0] && !string.IsNullOrWhiteSpace(z)))})"; + var abilName = PrettyDumpUtil.GetAbilityName(pk.DevId, pk.FormId, abilities, personalTable, pk.Tokusei); + var ability = pk.Tokusei is TokuseiType.RANDOM_12 or TokuseiType.RANDOM_123 ? string.Empty : $" (Ability: {abilName[..(abilName.IndexOf('(') - 1)]})"; + var nature = pk.Seikaku is 0 ? string.Empty : $" (Nature: {natures[(int)pk.Seikaku - 1]})"; + var ball = $" (Ball: {(Ball)pk.BallId})"; + + var ivs = pk.TalentValue; + var textIVs = $" (IVs: {ivs.HP}/{ivs.ATK}/{ivs.DEF}/{ivs.SPA}/{ivs.SPD}/{ivs.SPE})"; + + var eff = pk.EffortValue; + ReadOnlySpan 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}"; + result.Add(line); + } + + result.Add(""); + } + + File.WriteAllLines(GetPath("pretty", "trainers_pretty.txt"), result); + + static int GetPrizePayout(PokeDataBattle[] team, int pay) + { + var target = team.MaxBy(z => z.Level)!.Level; + return target * pay * 4; + } + + static string GetTrainerNameFormatted(string type, string name, ushort flags) + { + bool article = ((flags >> 9) & 1) == 0; + 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 => "{0} {1}", + 1 when article => "{1} of the {0}", + 1 => "{1} of {0}", + 2 => "{1} the {0}", + _ => throw new ArgumentOutOfRangeException(nameof(format), format, null), + }; + + // edge case for the longest trainer name in history + if (name is "representative") + display = display.Insert(0, "The "); + + return string.Format(display, type, name); + } + + string GetTrainerName(string id) + { + // Z-A Royale Trainers + if (id.StartsWith("za_rank")) + { + id = id.Insert(2, "_trainer_asset"); + var check = npcs.FirstOrDefault(z => z.AssetId == id); + if (check is null) + return "NO TEXT FOUND"; + return ahtbNames.GetString(FnvHash.HashFnv1a_64(check.NpcInfoList[0].Name), trNames); + } + + if (id.EndsWith("kusa") || id.EndsWith("hono") || id.EndsWith("mizu")) + { + var rivalF = ahtbNames.GetString(FnvHash.HashFnv1a_64("rival_01"), trNames); // Taunie + var rivalM = ahtbNames.GetString(FnvHash.HashFnv1a_64("rival_02"), trNames); // Urbain + return $"{rivalF}/{rivalM}"; + } + + var (trainerBattleId, npcAssetId) = trBtls.FirstOrDefault(z => z.TrainerBattleID == id); + if (trainerBattleId is null) + { + var fallback = GetFallbackTrainerName(id); + return ahtbNames.GetString(FnvHash.HashFnv1a_64(fallback), trNames); + } + + // special name format + if (npcAssetId.Contains("rest_trainer")) + { + var restName = ahtbNames.GetString(FnvHash.HashFnv1a_64(npcAssetId.Replace("_trainer", "")), trNames); + return restName; + } + + var target = npcs.FirstOrDefault(z => z.AssetId == npcAssetId)!; + var name = target.NpcInfoList.Where(z => !string.IsNullOrWhiteSpace(z.Name)).ToArray()[0].Name; + return ahtbNames.GetString(FnvHash.HashFnv1a_64(name), trNames); + } + + string GetFallbackTrainerName(string id) => id switch + { + "00_test_data" => "TR_NONE", + "Ev_m04_boss_0071_multi" or "Ev_m05_boss_0354_multi" or "Ev_m06_boss_0181_multi" or "Ev_m07_boss_0478_multi" or "Ev_m08_boss_0248_multi" or "Ev_m09_1135_multi_02" => "friend_01", // Naveen + "Ev_m04_boss_0323_multi" or "Ev_m05_boss_0701_multi" or "Ev_m06_boss_0689_multi" or "Ev_m07_boss_0334_multi" or "Ev_m08_boss_0121_multi" or "Ev_m09_1135_multi_01" => "friend_02", // Lida + "Ev_m06_multi" or "Ev_m09_2300_multi_01" => "boss03", // Corbeau + "Ev_m09_2000_multi_01" => "boss02", // Ivor + "Ev_m09_2000_multi_02" => "executive02", // Gwynn + "Ev_m09_2100_multi_01" => "boss01", // Canari + "Ev_m09_2200_multi_01" => "executive04", // Lebanne + "Ev_m09_2400_multi_01" => "boss05", // Grisham + "Ev_m09_2400_multi_02" => "executive05", // Griselle + "Ev_sub_103_multi" => "alias01", // Andi + "Ev_sub_114_multi" => "battleg", // Josée + _ => throw new ArgumentOutOfRangeException(nameof(id), id, null), + }; + } + + public void DumpAbilities() + { + const string tokuseiPath = "avalon/data/tokusei_array.bin"; + Dump(tokuseiPath, z => z.Table); + } + + public void DumpEncounters() + { + const string language = "English"; + + var cfg = new TextConfig(GameVersion.ZA); + var ahtb = GetCommonAHTB("place_name", language); + var place_names = GetCommonText("place_name", language, cfg); + var nameDict = ahtb.ToIndexedDictionary(place_names); + + var config = new EncounterDumpConfig9a + { + PlaceNameMap = nameDict, + SpecNamesInternal = GetCommonText("monsname", language, cfg), + MoveNames = GetCommonText("wazaname", language, cfg), + Path = GetPath("encounters"), + }; + EncounterDumper9a.Dump(rom, config); + } + + public void DumpMegaInfo() + { + const string mega = "world/exl/pokemon/megaevo_data/megaevo_data.bin"; + var table = Dump(mega, z => z.Table); + + // pretty + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + var names = GetCommonText("monsname", lang, cfg); + var items = GetCommonText("itemname", lang, cfg); + + // pretty + + var result = table.Table.Select(z => + $"{names[(int)z.Species]}-{z.FromForm} => {z.ToForm} @ {items[(int)z.Item]} ({z.Type} & {z.Short})"); + var path = GetPath("pkhex", "mega.txt"); + File.WriteAllLines(path, result); + } + + public void DumpLocationNames() + { + foreach (var lang in LanguageEnglishNames) + RipLocationNames(lang); + } + + // Language Set => Language codes for PKHeX + private static string GetLanguageCode(string lang) => lang switch + { + "JPN" => "ja", + "JPN_KANJI" => "ja", + "English" => "en", + "French" => "fr", + "Italian" => "it", + "German" => "de", + "Spanish" => "es", + "Korean" => "ko", + "Simp_Chinese" => "zh-Hans", + "Trad_Chinese" => "zh-Hant", + "LATAM" => "es-419", + _ => throw new ArgumentOutOfRangeException(nameof(lang), lang, null), + }; + + private void RipLocationNames(string lang) + { + const string g = "za"; + var cfg = new TextConfig(rom.Game); + string GetText(string name) => string.Join('\n', GetCommonText(name, lang, cfg)); + var code = GetLanguageCode(lang); + File.WriteAllText(GetPath("pkhex", "locations", $"text_{g}_00000_{code}.txt"), GetText("place_name")); + File.WriteAllText(GetPath("pkhex", "locations", $"text_{g}_30000_{code}.txt"), "\n" + GetText("place_name_spe")); + File.WriteAllText(GetPath("pkhex", "locations", $"text_{g}_40000_{code}.txt"), "\n" + GetText("place_name_out")); + File.WriteAllText(GetPath("pkhex", "locations", $"text_{g}_60000_{code}.txt"), "\n" + GetText("place_name_per")); + } + + public void ScanPatterns() + { + var root = GetPath("archive", "extracted"); + var files = Directory.EnumerateFiles(root, "*.*", SearchOption.AllDirectories); + + (string Pattern, bool Include)[] patterns = + [ + ("SYS_", true), // system work + ("flag_", true), // system flag, event flag + ("DBG_", true), // debug flag, debug work + ("TEMP_", true), + ("momiji", true), + ("MOMIJI", true), + ("Momiji", true), + ("FLAG", true), + ("Flag", true), + ("QUEST_", true), + ("debug_", true), + ("DEBUG", true), + ("sys_", true), + ("dbg_", true), + ("spawner_", true), + ("random_", true), + ("sub_", true), + ("main_", true), + ("event_", true), + ("play", true), + ("report", true), + ("itb_", true), // item ball + ("spn_", true), // spawn + ("traffic", true), + ("rnd_", true), + ("TITLE_", true), + ("itd_", true), + + ("rso_", false), // royale card spawn + ("t1_", false), + (".bfbs", false), + ("_condition", false), + ]; + + const string outRoot = "pattern"; + + var results = StringSearch.SearchFiles(files, patterns.Select(z => z.Pattern).ToArray()); + var outPath = GetPath(outRoot); + if (!Directory.Exists(outPath)) + Directory.CreateDirectory(outPath); + + var saveHashHits = new HashSet(); + for (var i = 0; i < results.Length; i++) + { + var result = results[i]; + var (pattern, include) = patterns[i]; + var hits = result.List; + + var path = Path.Combine(outPath, $"{pattern}.txt"); + using var fs = new FileStream(path, FileMode.Create, FileAccess.Write); + using var sw = new StreamWriter(fs); + foreach (var hit in hits) + { + sw.WriteLine(hit); + if (include) + saveHashHits.Add(hit.Result); + } + } + CreateSaveHashDump(saveHashHits, outPath); + + System.Media.SystemSounds.Asterisk.Play(); + } + + private void CreateSaveHashDump(IEnumerable saveHashHits, string outPath) + { + string[] extra = + [ + ..FromFile("ik_event/bin/flag/system_flag.bin").Table.Select(z => z.Name), + ..FromFile("ik_event/bin/flag/event_flag.bin").Table.Select(z => z.Name), + ..FromFile("ik_event/bin/flag/system_work.bin").Table.Select(z => z.Name), + ..FromFile("ik_event/bin/flag/quest_work.bin").Table.Select(z => z.Name), + ..FromFile("ik_event/bin/flag/momiji_work.bin").Table.Select(z => z.Name), + ..FromFile("ik_event/bin/flag/temp_flag.bin").Table.Select(z => z.Name), + ..FromFile("ik_event/bin/flag/temp_work.bin").Table.Select(z => z.Name), + + ..FromFile("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("ik_event/bin/momiji_count/momiji_count.bin").Table.Select(z => z.Name), + ]; + + // Gotta hash em all! + var all = saveHashHits.Concat(extra) + .Where(z => IsSaveBlockLabel(z)) + .Distinct() + .Order(); + + var hashed = Path.Combine(outPath, "SAV9ZA_flagwork.txt"); + var text = all.Select(z => $"{FnvHash.HashFnv1a_64(z):X16}\t{z}"); + File.WriteAllLines(hashed, text); + return; + + T FromFile(string path) where T : class, IFlatBufferSerializable => DumpJson(path); + } + + private static bool IsSaveBlockLabel(ReadOnlySpan input) + { + foreach (char c in input) + { + // Check if character is A-Z, a-z, 0-9, or _ + if (c is ((>= 'A' and <= 'Z') or (>= 'a' and <= 'z') or (>= '0' and <= '9') or '_' or '-')) + continue; + return false; + } + return true; // All characters are valid + } + + public void DumpItems() + { + const string language = "English"; + + const string path = "world/exl/item_data/item_data/item_data.bin"; + Dump(path, z => z.Table); + var table = Get(path); + var outPath = GetPath("pkhex"); + var cfg = new TextConfig(rom.Game); + var itemNames = GetCommonText("itemname", language, cfg); + var moveNames = GetCommonText("wazaname", language, cfg); + var labeled = TableUtil.GetNamedTable(table.Table, itemNames, z => z.Id, "Item"); + File.WriteAllText(Path.Combine(outPath, "item_table.txt"), labeled); + + var groups = table.Table.GroupBy(z => z.Pocket); + var sb = new StringBuilder(); + foreach (var group in groups) + { + // Dump in sets of 10. + int i = 0; + foreach (var item in group) + { + sb.Append($"{item.Id:0000}, "); + if (++i % 10 != 0) + continue; + sb.AppendLine(); + i = 0; + } + File.WriteAllText(Path.Combine(outPath, $"pouch_{group.Key}.txt"), sb.ToString()); + sb.Clear(); + } + + // TM-BitFlag Indexes + var tms = table.Table.Where(z => z.MachineIndex >= 0) + .OrderBy(z => z.MachineIndex).ToArray(); + const string prefix = "000, "; // TM001 is the first TM, and indexes start at 0. + var tmString = prefix + string.Join(", ", tms.Select(z => $"{(int)z.MachineWaza:000}")); + File.WriteAllText(Path.Combine(outPath, "tm.txt"), tmString); + + // TM-Actual Move IDs + var tmByName = tms.Select(z => (Item: z, Name: itemNames[z.Id])) + .OrderBy(z => z.Name) + .Select(z => $"{z.Name}\t{z.Item.MachineIndex+1:000}\t{(int)z.Item.MachineWaza:000}\t{moveNames[(int)z.Item.MachineWaza]}") + ; + File.WriteAllLines(Path.Combine(outPath, "tm_by_name.txt"), tmByName); + + var tmDisplay = tms + .Select(z => (int)z.MachineWaza); + var asDisplay = "000, " + string.Concat(tmDisplay.Select((z, i) => $"{z:000}, {(i != 0 && i % 10 == 9 ? Environment.NewLine : "")}")); + File.WriteAllText(Path.Combine(outPath, "tm_display.txt"), asDisplay); + + var remap = GetRemap(tms); + var asRemap = string.Concat(remap.Select((z, i) => $"{z}, {(i != 0 && i % 10 == 9 ? Environment.NewLine : "")}")); + File.WriteAllText(Path.Combine(outPath, "tm_remap.txt"), asRemap); + static string[] GetRemap(IReadOnlyList items) + { + // Gets a bias value to convert an old-gen TM index text to the new-gen TM index. + // Relies on the TM's internal name (consistent with old games). + + static int GetOldIndex(ItemData item) => int.Parse(item.InternalName.AsSpan("WAZAMASIN".Length)); + var maxIndex = items.Max(GetOldIndex) + 1; + var result = new string[maxIndex]; + result.AsSpan().Fill(" 0"); + foreach (var item in items) + { + var shift = GetRemap(item, out var oldIndex); + result[oldIndex] = shift; + } + return result; + + static string GetRemap(ItemData item, out int oldIndex) + { + oldIndex = GetOldIndex(item); + var newIndex = item.MachineIndex + 1; + + var delta = newIndex - oldIndex; + // return a 3-char string + return GetFormatted(delta); + } + + static string GetFormatted(int delta) + { + if (delta is 0) + return " 0"; + return delta < 0 ? $"{delta:00}" : $"+{delta:00}"; + } + } + } + + public void DumpConfig() + { + const string playerDamage = "world/ik_data/battle/battle_player_damage/battle_player_damage.bfbs"; + DumpJson(playerDamage); + DumpSel(playerDamage, z => z.Move, "move"); + DumpSel(playerDamage, z => z.PokemonRatio, "poke"); + DumpSel(playerDamage, z => z.MegaPokemon, "mega"); + + DumpJson("world/ik_data/field/playables/field_player/data.bfbs"); + + DumpJson("world/ik_data/battle/lockon_desc/player.bfbs"); + DumpJson("world/ik_data/battle/battle_setting/battle_setting.bfbs"); + DumpJson("world/ik_data/field/oyabun/oyabun_setting/oyabun_setting.bfbs"); + DumpJson("world/ik_data/field/config/field_config/field_config_data.bfbs"); + DumpJson("world/ik_data/field/area/area_config/area_config_data.bfbs"); + + Dump("world/ik_data/field/data/field_data_config/field_data_config_array.bfbs", z => z.Table); + DumpSel("world/ik_data/field/data/field_data_config/field_data_config_array.bfbs", z => z.Table.Select(x => x.Info)); + } + + public void DumpPokemonData() + { + const string pmd = "world/ik_data/field/pokemon/pokemon_data/pokemon_data/pokemon_data_array.bfbs"; + var pokemon = Dump(pmd, z => z.Table); + + DumpPokemonPretty(pokemon); + DumpPokemonPKHeX(pokemon); + } + + private void DumpPokemonPretty(PokemonDataDBArray pokemon) + { + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + List result = []; + + var names = GetCommonText("monsname", lang, cfg); + var forms = GetCommonText("zkn_form", lang, cfg); + var abilities = GetCommonText("tokusei", lang, cfg); + var natures = GetCommonText("seikaku", lang, cfg); + var moves = GetCommonText("wazaname", lang, cfg); + var items = GetCommonText("itemname", lang, cfg); + + var ahtbForms = rom.GetPackedFile($"ik_message/dat/{lang}/common/zkn_form.tbl"); + var personal = rom.GetPackedFile("avalon/data/personal_array.bin"); + var personalTable = Get(personal); + + var helper = new DumpHelper9a + { + SpeciesNames = names, + AbilityNames = abilities, + MoveNames = moves, + NatureNames = natures, + FormNames = forms, + Personal = personalTable, + Forms = new(ahtbForms), + }; + + int index = 0; + foreach (var enc in pokemon.Table) + { + result.Add($"Table: {index++}"); + foreach (var t in enc.Table) + { + result.Add("==="); + result.Add($"{t.Id}"); + result.Add("==="); + + var name = names[(int)t.DevNo]; + var form = helper.GetFormName((ushort)t.DevNo, (short)t.FormNo); + var formDisplay = PrettyDumpUtil.GetFormDisplay((short)t.FormNo, form); + result.Add($"{name}{formDisplay}"); + + var fixedLevel = t.MinLevel == t.MaxLevel; + if (fixedLevel) + { + result.Add($"Level: {t.MinLevel}"); + } + else + { + result.Add($"Min Level: {t.MinLevel}"); + result.Add($"Max Level: {t.MaxLevel}"); + } + + if (t.Sex is not (-1 or 2)) + result.Add($"Gender: {PrettyDumpUtil.GetGender(t.Sex)}"); + + result.Add($"Shiny: {PrettyDumpUtil.GetShiny(t.Rare)}"); + + if ((sbyte)t.Tokusei is not -1) + result.Add($"Ability: {PrettyDumpUtil.GetAbilityName(t.DevNo, (short)t.FormNo, abilities, personalTable, (TokuseiType)t.Tokusei)}"); + + result.Add($"Nature: {PrettyDumpUtil.GetNature(natures, t.Seikaku)}"); + + if (t.TalentScale is not -1) + result.Add($"Scale: {t.TalentScale}"); + + var ivs = t.TalentValue; + if (ivs is { HP: -1, ATK: -1, DEF: -1, SPA: -1, SPD: -1, SPE: -1 }) + result.Add(t.TalentVNum < 1 ? "IVs: Random" : $"IVs: {t.TalentVNum} Flawless"); + else + result.Add($"IVs: {ivs.HP}/{ivs.ATK}/{ivs.DEF}/{ivs.SPA}/{ivs.SPD}/{ivs.SPE}"); + + if (t.OyabunProbability is not 0) + result.Add($"Alpha Probability: {t.OyabunProbability}%"); + + if (t.OyabunAdditionalLevel is not 0) + result.Add($"Alpha Additional Level: +{t.OyabunAdditionalLevel}"); + + if (t.Item is { } item) + result.Add($"Held Item: {items[item.ItemId]}"); + + // not a generic wild zone encounter + if (fixedLevel && t.OyabunAdditionalLevel is 0 && t.Moves is { } wl && (int)wl.Waza1 is not (0 or 65535)) + { + result.Add("Moves:"); + result.Add($"- {moves[(int)wl.Waza1]}"); + if ((int)wl.Waza2 is not (0 or 65535)) result.Add($"- {moves[(int)wl.Waza2]}"); + if ((int)wl.Waza3 is not (0 or 65535)) result.Add($"- {moves[(int)wl.Waza3]}"); + if ((int)wl.Waza4 is not (0 or 65535)) result.Add($"- {moves[(int)wl.Waza4]}"); + } + + if (t.ActivationConditionArray is { } a) + { + foreach (var cond in a) + { + if (cond.Element is not { Count: not 0 } elemList) + continue; // never true + + foreach (var elem in elemList) + { + if (elem.Param is not { Count: not 0 } pl) + continue; // never true + + for (var i = 0; i < pl.Count; i++) + { + var param = pl[i]; + var set = param.Param is null ? "NO PARAM" : string.Join(", ", param.Param); + result.Add($"Param[{i}] {param.Condition} - {param.Op} - {set}"); + } + } + } + } + + result.Add(""); + } + } + + File.WriteAllLines(GetPath("pretty", "pokemon_data_pretty.txt"), result); + } + + private void DumpPokemonPKHeX(PokemonDataDBArray pokemon) + { + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + List result = []; + + var names = GetCommonText("monsname", lang, cfg); + var natures = GetCommonText("seikaku", lang, cfg); + ReadOnlySpan Trades = ["sub_addpoke_araichu", "sub_tradepoke_riolu", "sub_addpoke_gyadon", "sub_tradepoke_heracros"]; + + foreach (var enc in pokemon.Table) + { + foreach (var t in enc.Table) + { + var name = names[(int)t.DevNo]; + var national = SpeciesConverterZA.GetNational9((ushort)t.DevNo); + var formDisplay = t.FormNo is 0 ? string.Empty : $"-{t.FormNo}"; + var shiny = t.Rare switch + { + 0x3FFFFFFF => ", Shiny = Random", + 0x2FFFFFFF => ", Shiny = Always", + _ => string.Empty, + }; + var gender = t.Sex is -1 or 2 ? string.Empty : $", Gender = {t.Sex}"; + var nature = t.Seikaku is -1 ? string.Empty : $", Nature = Nature.{natures[t.Seikaku]}"; + + var ivs = t.TalentValue; + string iv = ivs switch + { + { HP: 31, ATK: 31, DEF: 31, SPA: 31, SPD: 31, SPE: 31 } => ", FlawlessIVCount = 6", + { HP: -1, ATK: -1, DEF: -1, SPA: -1, SPD: -1, SPE: -1 } + => t.TalentVNum is 0 ? string.Empty : $", FlawlessIVCount = {t.TalentVNum}", + _ => $", IVs = new({ivs.HP:00},{ivs.ATK:00},{ivs.DEF:00},{ivs.SPE:00},{ivs.SPA:00},{ivs.SPD:00})", + }; + + var moves = ""; + if (t.OyabunAdditionalLevel is 0 && t.Moves is { } m && (int)m.Waza1 is not (0 or 65535)) + { + Span moveset = [(int)m.Waza1, (int)m.Waza2, (int)m.Waza3, (int)m.Waza4]; + moveset.Replace(65535, 0); + moves = $", Moves = new({moveset[0]:000},{moveset[1]:000},{moveset[2]:000},{moveset[3]:000})"; + } + + var alpha = t.OyabunProbability is 0 ? string.Empty : ", IsAlpha = true"; + var level = t.OyabunProbability is 0 ? t.MinLevel : (t.MinLevel + t.OyabunAdditionalLevel); + var scale = t.TalentScale is -1 ? 0 : t.TalentScale; + var line = $" new({national:0000},{t.FormNo},{level:00},{scale:000}) {{ Location = 000{shiny}{gender}{nature}{iv}{moves}{alpha} }}, // {name}{formDisplay} ({t.Id})"; + + // annoying that these are lumped together with gift encounters + if (Trades.Contains(t.Id)) + { + var index = Trades.IndexOf(t.Id); + line = $" new(TradeNames,{index},{national:0000},{t.FormNo},{level:00}) {{ ID32 = 000000, OTGender = 0{gender}{nature}{iv}{moves}{alpha} }}, // {name}{formDisplay} ({t.Id})"; + } + + result.Add(line); + + // is not fixed alpha, but can still be alpha OR non-alpha + if (t.OyabunProbability is >= 1 and <= 99) + { + line = line.Remove(19, 2).Insert(19, $"{t.MinLevel:00}").Replace(", IsAlpha = true", ""); + result.Add(line); + } + } + } + + File.WriteAllLines(GetPath("pkhex", "pokemon_data_pkhex.txt"), result); + DumpTradeNames(); + } + + public void DumpEncountData() + { + const string emd = "world/ik_data/field/pokemon/encount_data/encount_data/encount_data_array.bfbs"; + const string dro = "world/ik_data/field/pokemon/pokemon_drop_item_table/pokemon_drop_item_table_data/pokemon_drop_item_table_data_array.bfbs"; + var pokemon = Dump(emd, z => z.Table); + DumpSel(emd, z => z.Table.SelectMany(x => x.Table)); + var drops = Dump(dro, z => z.Table); + + for (var i = 0; i < pokemon.Table.Count; i++) + { + var table = pokemon.Table[i]; + var lines = TableUtil.GetTable(table.Table); + var path = GetRawPath(emd); + var fileName = Path.ChangeExtension(path, $".{i:00}.txt"); + File.WriteAllText(fileName, lines); + } + + const string psp = "world/ik_data/field/pokemon_spawner/pokemon_spawner_data/pokemon_spawner_data_array.bfbs"; + var spawners = Dump(psp, z => z.Table); + for (var i = 0; i < spawners.Table.Count; i++) + { + var table = spawners.Table[i]; + var lines = TableUtil.GetTable(table.Table); + var path = GetRawPath(psp); + var fileName = Path.ChangeExtension(path, $".{i:00}.txt"); + File.WriteAllText(fileName, lines); + } + + const string pst = "world/ik_data/field/spawner_transform_data/pokemon_spawner_transform/pokemon_spawner_transform/pokemon_spawner_transform_array.bfbs"; + var spawnerT = Dump(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); + } + + DumpEncountPretty(pokemon, drops); + DumpEncountPKHeX(pokemon); + + Dump("world/ik_data/field/area/field_main_area/field_main_area_array.bin", z => z.Table); + DumpSel("world/ik_data/field/area/field_main_area/field_main_area_array.bin", z => z.Table.Select(x => x.AreaInfo)); + + Dump("world/ik_data/field/area/field_sub_area/field_sub_area_array.bin", z => z.Table); + DumpSel("world/ik_data/field/area/field_sub_area/field_sub_area_array.bin", z => z.Table.Select(x => x.AreaInfo)); + + Dump("world/ik_data/field/area/field_battle_zone/field_battle_zone_array.bin", z => z.Table); + DumpSel("world/ik_data/field/area/field_battle_zone/field_battle_zone_array.bin", z => z.Table.Select(x => x.AreaInfo)); + + Dump("world/ik_data/field/area/field_wild_zone/field_wild_zone_array.bin", z => z.Table); + DumpSel("world/ik_data/field/area/field_wild_zone/field_wild_zone_array.bin", z => z.Table.Select(x => x.AreaInfo)); + + Dump("world/ik_data/field/area/field_scene_area/field_scene_area_array.bin", z => z.Table); + DumpSel("world/ik_data/field/area/field_scene_area/field_scene_area_array.bin", z => z.Table.Select(x => x.AreaInfo)); + + Dump("world/ik_data/field/area/field_location/field_location_array.bin", z => z.Table); + DumpSel("world/ik_data/field/area/field_location/field_location_array.bin", z => z.Table.Select(x => x.AreaInfo)); + + var outPath = GetPath("spawner"); + var dumper = new SpawnRipper9a(rom, "English", outPath); + dumper.ExportRippedMaps(); + } + + private void DumpEncountPretty(EncountDataDBArray pokemon, PokemonDropItemTableDataDBArray drops) + { + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + List result = []; + + var names = GetCommonText("monsname", lang, cfg); + var forms = GetCommonText("zkn_form", lang, cfg); + var abilities = GetCommonText("tokusei", lang, cfg); + var natures = GetCommonText("seikaku", lang, cfg); + var moves = GetCommonText("wazaname", lang, cfg); + var items = GetCommonText("itemname", lang, cfg); + + var ahtbForms = rom.GetPackedFile($"ik_message/dat/{lang}/common/zkn_form.tbl"); + var personal = rom.GetPackedFile("avalon/data/personal_array.bin"); + var personalTable = Get(personal); + + var helper = new DumpHelper9a + { + SpeciesNames = names, + AbilityNames = abilities, + MoveNames = moves, + NatureNames = natures, + FormNames = forms, + Personal = personalTable, + Forms = new(ahtbForms), + }; + + int index = 0; + foreach (var enc in pokemon.Table) + { + result.Add($"Table: {index++}"); + foreach (var t in enc.Table) + { + result.Add("==="); + result.Add($"{t.Id}"); + result.Add("==="); + + var name = names[(int)t.DevNo]; + var form = helper.GetFormName((ushort)t.DevNo, (short)t.FormNo); + var formDisplay = PrettyDumpUtil.GetFormDisplay((short)t.FormNo, form); + result.Add($"{name}{formDisplay}"); + + var fixedLevel = t.MinLevel == t.MaxLevel; + if (fixedLevel) + { + result.Add($"Level: {t.MinLevel}"); + } + else + { + result.Add($"Min Level: {t.MinLevel}"); + result.Add($"Max Level: {t.MaxLevel}"); + } + + if (t.Sex is not (-1 or 2)) + result.Add($"Gender: {PrettyDumpUtil.GetGender(t.Sex)}"); + + result.Add($"Shiny: {PrettyDumpUtil.GetShiny(t.Rare)}"); + + if ((sbyte)t.Tokusei is not -1) + result.Add($"Ability: {PrettyDumpUtil.GetAbilityName(t.DevNo, (short)t.FormNo, abilities, personalTable, (TokuseiType)t.Tokusei)}"); + + result.Add($"Nature: {PrettyDumpUtil.GetNature(natures, t.Seikaku)}"); + + if (t.TalentScale is not -1) + result.Add($"Scale: {t.TalentScale}"); + + var ivs = t.TalentValue; + if (ivs is { HP: -1, ATK: -1, DEF: -1, SPA: -1, SPD: -1, SPE: -1 }) + result.Add(t.TalentVNum < 1 ? "IVs: Random" : $"IVs: {t.TalentVNum} Flawless"); + else + result.Add($"IVs: {ivs.HP}/{ivs.ATK}/{ivs.DEF}/{ivs.SPA}/{ivs.SPD}/{ivs.SPE}"); + + if (t.StrengthenValue is { } s) + { + ReadOnlySpan evs = [s.HP, s.ATK, s.DEF, s.SPA, s.SPD, s.SPE]; + if (evs.ContainsAnyInRange(1, 252)) + result.Add($"EVs: {PrettyDumpUtil.GetEVSpread(evs)}"); + } + + if (t.OyabunProbability is not 0) + result.Add($"Alpha Probability: {t.OyabunProbability}%"); + + if (t.OyabunAdditionalLevel is not 0) + result.Add($"Alpha Additional Level: +{t.OyabunAdditionalLevel}"); + + if (t.Item is { } item) + result.Add($"Held Item: {items[item.ItemId]}"); + + // not a generic wild zone encounter + if (fixedLevel && t.OyabunAdditionalLevel is 0 && t.Moves is { } wl && (int)wl.Waza1 is not (0 or 65535)) + { + result.Add("Moves:"); + result.Add($"- {moves[(int)wl.Waza1]}"); + if ((int)wl.Waza2 is not (0 or 65535)) result.Add($"- {moves[(int)wl.Waza2]}"); + if ((int)wl.Waza3 is not (0 or 65535)) result.Add($"- {moves[(int)wl.Waza3]}"); + if ((int)wl.Waza4 is not (0 or 65535)) result.Add($"- {moves[(int)wl.Waza4]}"); + } + + if (t.ActivationConditionArray is { } a) + { + foreach (var cond in a) + { + if (cond.Element is not { Count: not 0 } elemList) + continue; // never true + + foreach (var elem in elemList) + { + if (elem.Param is not { Count: not 0 } pl) + continue; // never true + + for (var i = 0; i < pl.Count; i++) + { + var param = pl[i]; + var set = param.Param is null ? "NO PARAM" : string.Join(", ", param.Param); + result.Add($"Param[{i}] {param.Condition} - {param.Op} - {set}"); + } + } + } + } + + if (t.ItemDropInfoList is { } encDropData && t.OyabunProbability > 0) + { + result.Add("Alpha Item Drops:"); + + var dropData = drops.Table; + foreach (var entry in dropData) + { + var dropItems = entry.Data; + foreach (var i in dropItems) + { + foreach (var slot in encDropData.Where(z => z.ItemTableId == i.Id)) + { + 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})"); + } + } + } + } + } + + result.Add(""); + } + } + + File.WriteAllLines(GetPath("pretty", "encount_data_pretty.txt"), result); + } + + private void DumpEncountPKHeX(EncountDataDBArray pokemon) + { + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + List result = []; + + var names = GetCommonText("monsname", lang, cfg); + var natures = GetCommonText("seikaku", lang, cfg); + ReadOnlySpan Trades = ["sub_addpoke_araichu", "sub_tradepoke_riolu", "sub_addpoke_gyadon", "sub_tradepoke_heracros"]; + + foreach (var enc in pokemon.Table) + { + foreach (var t in enc.Table) + { + var name = names[(int)t.DevNo]; + var national = SpeciesConverterZA.GetNational9((ushort)t.DevNo); + var formDisplay = t.FormNo is 0 ? string.Empty : $"-{t.FormNo}"; + var shiny = t.Rare switch + { + 0x3FFFFFFF => ", Shiny = Random", + 0x2FFFFFFF => ", Shiny = Always", + _ => string.Empty, + }; + var gender = t.Sex is -1 or 2 ? string.Empty : $", Gender = {t.Sex}"; + var nature = t.Seikaku is -1 ? string.Empty : $", Nature = Nature.{natures[t.Seikaku]}"; + + var ivs = t.TalentValue; + string iv = ivs switch + { + { HP: 31, ATK: 31, DEF: 31, SPA: 31, SPD: 31, SPE: 31 } => ", FlawlessIVCount = 6", + { HP: -1, ATK: -1, DEF: -1, SPA: -1, SPD: -1, SPE: -1 } + => t.TalentVNum is 0 ? string.Empty : $", FlawlessIVCount = {t.TalentVNum}", + _ => $", IVs = new({ivs.HP:00},{ivs.ATK:00},{ivs.DEF:00},{ivs.SPE:00},{ivs.SPA:00},{ivs.SPD:00})", + }; + + var moves = ""; + if (t.OyabunAdditionalLevel is 0 && t.Moves is { } m && (int)m.Waza1 is not (0 or 65535)) + { + Span moveset = [(int)m.Waza1, (int)m.Waza2, (int)m.Waza3, (int)m.Waza4]; + moveset.Replace(65535, 0); + moves = $", Moves = new({moveset[0]:000},{moveset[1]:000},{moveset[2]:000},{moveset[3]:000})"; + } + + var alpha = t.OyabunProbability is 0 ? string.Empty : ", IsAlpha = true"; + var level = t.OyabunProbability is 0 ? t.MinLevel : (t.MinLevel + t.OyabunAdditionalLevel); + var scale = t.TalentScale is -1 ? 0 : t.TalentScale; + var line = $" new({national:0000},{t.FormNo},{level:00},{scale:000}) {{ Location = 000{shiny}{gender}{nature}{iv}{moves}{alpha} }}, // {name}{formDisplay} ({t.Id})"; + + // annoying that these are lumped together with gift encounters + if (Trades.Contains(t.Id)) + { + var index = Trades.IndexOf(t.Id); + line = $" new(TradeNames,{index},{national:0000},{t.FormNo},{level:00}) {{ ID32 = 000000, OTGender = 0{gender}{nature}{iv}{moves}{alpha} }}, // {name}{formDisplay} ({t.Id})"; + } + + result.Add(line); + + // is not fixed alpha, but can still be alpha OR non-alpha + if (t.OyabunProbability is >= 1 and <= 99) + { + line = line.Remove(19, 2).Insert(19, $"{t.MinLevel:00}").Replace(", IsAlpha = true", ""); + result.Add(line); + } + } + } + + File.WriteAllLines(GetPath("pkhex", "encount_data_pkhex.txt"), result); + } + + private void DumpTradeNames() + { + var cfg = new TextConfig(GameVersion.ZA); + foreach (var lang in LanguageEnglishNames) + { + var names = GetCommonText("namelist", lang, cfg); + var l = GetLanguageCode(lang); + List result = []; + + result.Add(names[414]); // Bois (Heracross) + result.Add(names[415]); // Riolouie (Riolu) + result.Add(names[416]); // Spicy (Slowpoke) + result.Add(names[417]); // Floffy (Raichu) + result.Add(names[293]); // Tracie + result.Add(names[306]); // Bond + result.Add(names[310]); // Quille + result.Add(names[362]); // Griddella + + File.WriteAllLines(GetPath("pkhex", "trades", $"text_tradeza_{l}.txt"), result); + } + } + + public void DumpScrubbedPokedexEntries() + { + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + List result = []; + + var comments = GetCommonText("zukan_comment_A", lang, cfg); + var names = GetCommonText("monsname", lang, cfg); + var ahtb = rom.GetPackedFile("ik_message/dat/English/common/zukan_comment_A.tbl"); + var table = new AHTB(ahtb).Entries; + + for (int i = 0; i < table.Count - 1; i++) + { + var entry = table[i]; + var line = comments[i]; + var name = entry.Name; + + if (!name.StartsWith("msg_") || line.StartsWith("[~ ")) + continue; + + for (int s = 1; s <= 1025; s++) + { + var national = SpeciesConverterZA.GetNational9((ushort)s); + for (int f = 0; f <= 28; f++) + { + var target = $"ZKN_COMMENT_A_{s:000}_{f:000}"; + var input = Encoding.ASCII.GetBytes(target); + var bytes = MD5.HashData(input); + var hash = Convert.ToHexString(bytes).ToLower(); + if (name == $"msg_{hash}") + result.Add($"{national:0000}\t{target}\t{names[s]}-{f}"); + } + } + } + + result.Sort(); + File.WriteAllLines(GetPath("scrubbed", "pokedex_entries.txt"), result); + } + + public void DumpScrubbedItemInfo() + { + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + List result = []; + + var infos = GetCommonText("iteminfo", lang, cfg); + var names = GetCommonText("itemname", lang, cfg); + var ahtb = rom.GetPackedFile("ik_message/dat/English/common/iteminfo.tbl"); + var table = new AHTB(ahtb).Entries; + + for (int i = 0; i < table.Count - 1; i++) + { + var entry = table[i]; + var line = infos[i]; + var name = entry.Name; + + if (!name.StartsWith("msg_")) + continue; + + var target = $"ITEMINFO_{i:000}"; + var input = Encoding.ASCII.GetBytes(target); + var bytes = MD5.HashData(input); + var hash = Convert.ToHexString(bytes).ToLower(); + if (name == $"msg_{hash}") + result.Add($"{i:0000}\tITEMINFO_{i:000}\t{names[i]}"); + } + + File.WriteAllLines(GetPath("scrubbed", "item_infos.txt"), result); + } + + public void DumpScrubbedMoveInfo() + { + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + List result = []; + + var infos = GetCommonText("wazainfo", lang, cfg); + var names = GetCommonText("wazaname", lang, cfg); + var ahtb = rom.GetPackedFile("ik_message/dat/English/common/wazainfo.tbl"); + var table = new AHTB(ahtb).Entries; + + for (int i = 0; i < table.Count - 1; i++) + { + var entry = table[i]; + var line = infos[i]; + var name = entry.Name; + + if (!name.StartsWith("msg_") || line.StartsWith("[~ ")) + continue; + + var target = $"WAZAINFO_{i:000}"; + var input = Encoding.ASCII.GetBytes(target); + var bytes = MD5.HashData(input); + var hash = Convert.ToHexString(bytes).ToLower(); + if (name == $"msg_{hash}") + result.Add($"{i:0000}\tWAZAINFO_{i:000}\t{names[i]}"); + } + + File.WriteAllLines(GetPath("scrubbed", "waza_infos.txt"), result); + } + + public void DumpScrubbedPokedexCategories() + { + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + List result = []; + + var comments = GetCommonText("zkn_type", lang, cfg); + var names = GetCommonText("monsname", lang, cfg); + var ahtb = rom.GetPackedFile("ik_message/dat/English/common/zkn_type.tbl"); + var table = new AHTB(ahtb).Entries; + + for (int i = 0; i < table.Count - 1; i++) + { + var entry = table[i]; + var line = comments[i]; + var name = entry.Name; + + if (!name.StartsWith("msg_") || line.StartsWith("[~ ")) + continue; + + for (int s = 1; s <= 1025; s++) + { + var national = SpeciesConverterZA.GetNational9((ushort)s); + for (int f = 0; f <= 28; f++) + { + var target = $"ZKN_TYPE_{s:000}_{f:000}"; + var input = Encoding.ASCII.GetBytes(target); + var bytes = MD5.HashData(input); + var hash = Convert.ToHexString(bytes).ToLower(); + if (name == $"msg_{hash}") + result.Add($"{national:0000}\t{target}\t{names[s]}-{f}"); + } + } + } + + result.Sort(); + File.WriteAllLines(GetPath("scrubbed", "pokedex_categories.txt"), result); + } + + public void DumpScrubbedDressupItemNames() + { + var names = new[] + { + "dressup_item_bangs_{0:00}", + "dressup_item_color_{0:000}", + "dressup_item_darkcircles_{0:00}", + "dressup_item_eye_{0:00}", + "dressup_item_eyebrow_{0:00}", + "dressup_item_eyecolor_tex_{0:00}", + "dressup_item_eyecolor_{0:00}", + "dressup_item_eyelash_{0:00}", + "dressup_item_freckles_{0:00}", + "dressup_item_group_{0:000}", + "dressup_item_hair_{0:00}", + "dressup_item_haircolor_{0:00}", + "dressup_item_lip_{0:00}", + "dressup_item_mole_{0:00}", + }; + + var cfg = new TextConfig(GameVersion.ZA); + const string lang = "English"; + List result = []; + + var dressup = GetCommonText("dressup_item_name", lang, cfg); + var ahtb = rom.GetPackedFile("ik_message/dat/English/common/dressup_item_name.tbl"); + var table = new AHTB(ahtb).Entries; + + foreach (var t in names) + { + for (int i = 0; i < dressup.Length; i++) + { + var entry = table[i]; + var line = dressup[i]; + var name = entry.Name; + + if (!name.StartsWith("msg_")) + continue; + + for (int d = 0; d <= 999; d++) + { + var target = string.Format(t, d); + var input = Encoding.ASCII.GetBytes(target); + var bytes = MD5.HashData(input); + var hash = Convert.ToHexString(bytes).ToLower(); + if (name == $"msg_{hash}") + result.Add(target); + } + } + } + + File.WriteAllLines(GetPath("scrubbed", "dressup_item_names.txt"), result); + } + + public void DumpEventTriggers() + { + var eventTriggerFiles = GetTriggerFileList(); + + const string outFolder = "event_trigger"; + Directory.CreateDirectory(GetPath(outFolder)); + + //var unknownTriggers = new List(); + //var unknownConditions = new List(); + //var unknownCommands = new List(); + + var allLines = new List(); + + foreach (var f in eventTriggerFiles) + { + var data = rom.GetPackedFile(f); + var table = FlatBufferConverter.DeserializeFrom(data); + + var curLines = new List { $"File: {Path.GetFileName(f)}" }; + + foreach (var line in TriggerUtil.GetTriggerTableSummary(table)) + curLines.Add($"\t{line}"); + + var outFile = GetPath(outFolder, $"trigger_{Path.GetFileNameWithoutExtension(f).Replace("trigger_", string.Empty)}"); + + DumpJson(table, $"{outFile}.json"); + File.WriteAllLines($"{outFile}.txt", curLines); + + allLines.AddRange(curLines); + allLines.Add(string.Empty); + } + + File.WriteAllLines(GetPath(outFolder, "triggerAll.txt"), allLines); + + //File.WriteAllLines(GetPath(outFolder, "triggerUnknownTypes.txt"), unknownTriggers.Order().Select(x => $"0x{x:X16},")); + //File.WriteAllLines(GetPath(outFolder, "triggerUnknownConditions.txt"), unknownConditions.Order().Select(x => $"0x{x:X16},")); + //File.WriteAllLines(GetPath(outFolder, "triggerUnknownCommands.txt"), unknownCommands.Order().Select(x => $"0x{x:X16},")); + } + + private IEnumerable GetTriggerFileList() + { + for (int i = 0; i <= 9; i++) + { + const string main = "ik_event/bin/trigger/main/trigger_main_{0:00}.bin"; + var file = string.Format(main, i); + if (rom.HasFile(file)) + yield return file; + } + for (int i = 0; i <= 300; i++) + { + const string sub = "ik_event/bin/trigger/sub/trigger_sub_{0:0000}.bin"; + var file = string.Format(sub, i); + if (rom.HasFile(file)) + yield return file; + } + } +} + +public static class PrettyDumpUtil +{ + private static readonly string[] StatNames = ["HP", "Atk", "Def", "SpA", "SpD", "Spe"]; + + public static string GetAbilityName(DevID species, short form, ReadOnlySpan abilities, PersonalTable personal, TokuseiType type) + { + if (type is TokuseiType.RANDOM_123) + return "Any (1/2/H)"; + if (type is TokuseiType.RANDOM_12) + return "Any (1/2)"; + + var target = personal.Table.FirstOrDefault(z => z.Info.SpeciesInternal == (ushort)species && z.Info.Form == form)!; + var value = GetAbility(target, type); + var text = GetAbilitySuffix(type); + return $"{abilities[value]} ({text})"; + } + + private static ushort GetAbility(PersonalInfo target, TokuseiType type) => type switch + { + TokuseiType.SET_1 => target.Ability1, + TokuseiType.SET_2 => target.Ability2, + TokuseiType.SET_3 => target.AbilityH, + (TokuseiType)0xFF => 0, + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null), + }; + + private static string GetAbilitySuffix(TokuseiType type) => type switch + { + TokuseiType.SET_1 => "1", + TokuseiType.SET_2 => "2", + TokuseiType.SET_3 => "H", + (TokuseiType)0xFF => "-", + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null), + }; + + public static string GetMoveText(WazaSetBattle waza, ReadOnlySpan moves) => GetMoveText(waza.WazaId, moves, waza.IsPlusWaza); + public static string GetMoveText(WazaSet waza, ReadOnlySpan moves) => GetMoveText(waza.WazaId, moves, waza.IsPlusWaza); + + public static string GetMoveText(WazaID id, ReadOnlySpan moves, bool plus) + { + if (id == 0) + return string.Empty; + var name = $"{moves[(int)id]}"; + if (plus) + name += " (+)"; + return name; + } + + public static List GetCurrentMoves(DevID species, short form, byte level, PersonalTable personal) + { + var target = personal.Table + .First(z => z.Info.SpeciesInternal == (ushort)species && z.Info.Form == form); + List Moves = target.Learnset.Where(z => z.Level <= level) + .Distinct().TakeLast(4).Select(z => z.Move).ToList(); + + // always return 4 moves + while (Moves.Count < 4) + Moves.Add(0); + + return Moves; + } + + public static string GetEVSpread(ReadOnlySpan evs) + { + StringBuilder sb = new(); + for (int i = 0; i < evs.Length; i++) + { + if (evs[i] <= 0) + continue; + if (sb.Length != 0) + sb.Append(" / "); + sb.Append($"{evs[i]} {StatNames[i]}"); + } + return sb.ToString(); + } + + public static string GetFormString(ushort species, short form, ReadOnlySpan forms, AHTB formNames) + { + var hash = FnvHash.HashFnv1a_64($"ZKN_FORM_{species:000}_{form:000}"); + var index = formNames.GetIndex(hash); + return forms[index]; + } + + public static string GetFormDisplay(short form, string name) => name switch + { + not "" when form is 0 => $" ({name})", + not "" => $"-{form} ({name})", + _ => string.Empty, + }; + + public static string GetGender(int gender) => gender switch + { + 0 => "Male", + 1 => "Female", + _ => "Random", + }; + + public static string GetNature(ReadOnlySpan natures, int nature) => nature is -1 ? "Random" : $"{natures[nature]}"; + + public static string GetShiny(int rare) => rare switch + { + 0x1FFFFFFF => "Never", + 0x2FFFFFFF => "Always", + _ => "Random", + }; +} + +public static class TriggerUtil +{ + public static IEnumerable GetTriggerTableSummary(TriggerTable tab) + { + foreach (var trg in tab.Table!) + { + yield return "Trigger:"; + foreach (var line in GetTriggerSummary(trg)) + yield return $"\t{line}"; + } + } + + public static IEnumerable GetTriggerSummary(Trigger trigger) + { + if (trigger.Start is not { } start) + { + yield return "No Start Condition!"; + yield break; + } + yield return "Start:"; + yield return $"Condition: {start.Condition}"; + if (start.Param is { Count: not 0 } p) + { + yield return "Params:"; + foreach (var param in p) + yield return $"\t{string.Join(", ", param)}"; + } + + if (start.Activators is { Count: not 0 } act) + { + yield return "Activators:"; + foreach (var a in act) + { + if (a.Triggers is { Count: not 0 } t) + { + yield return $"(Triggers: {t.Count})"; + foreach (var trg in t) + yield return $"\t- {string.Join(Environment.NewLine, trg.Summarize())}"; + } + else + { + yield return "(No Triggers)"; + } + + if (a.Element is { Count: not 0 } elem) + { + yield return $"Elements: {elem.Count}"; + foreach (var e in elem) + yield return $"\t- {string.Join(Environment.NewLine, e.Summarize())}"; + } + else + { + yield return "No Elements"; + } + } + } + } + + public static IEnumerable Summarize(this TriggerCommand cmd) + { + if (cmd.Element is not { Count: not 0 } x) + { + yield return "Command: (No Elements)"; + yield break; + } + + foreach (var elem in x) + { + var args = elem.Param is { Count: not 0 } p ? GetTriggerArgsSummary(p) : "No Args"; + yield return $"Command: {elem.Command} - {args}"; + } + } + + public static IEnumerable Summarize(this ActivationConditionElement act) + { + if (act.Param is not { Count: not 0 } p) + { + yield return "Condition: (No Params)"; + yield break; + } + + foreach (var elem in p) + { + var args = elem.Param is { Count: not 0 } pp ? GetTriggerArgsSummary(pp) : "No Args"; + yield return $"Condition: {elem.Condition} - {elem.Op} - {args}"; + } + } + + public static string GetTriggerArgsSummary(IList args) + { + var firstEmpty = -1; + for (var i = 0; i < args.Count; i++) + { + if (firstEmpty >= 0 && !string.IsNullOrEmpty(args[i])) + throw new ArgumentException($"Invalid TriggerArg at index {i}!"); + if (firstEmpty < 0 && string.IsNullOrEmpty(args[i])) + firstEmpty = i; + } + + return string.Join(", ", args.Select(s => $"\"{s}\"").Take(firstEmpty >= 0 ? firstEmpty : args.Count)); + } +} + diff --git a/pkNX.WinForms/Dumping/TextInput.cs b/pkNX.WinForms/Dumping/TextInput.cs index 134e7c20..0e911ffa 100644 --- a/pkNX.WinForms/Dumping/TextInput.cs +++ b/pkNX.WinForms/Dumping/TextInput.cs @@ -15,14 +15,14 @@ public TextInput(Func? validator = null) InitializeComponent(); } - private void Input_TextChanged(object sender, System.EventArgs e) + private void Input_TextChanged(object sender, EventArgs e) { Result = Input.Text; if (Validator != null) B_Export.ForeColor = Validator(Result) ? Color.Green : Color.Red; } - private void B_Export_Click(object sender, System.EventArgs e) + private void B_Export_Click(object sender, EventArgs e) { DialogResult = DialogResult.OK; Close(); diff --git a/pkNX.WinForms/Main.cs b/pkNX.WinForms/Main.cs index 65b5f4cc..2f0e6eb8 100644 --- a/pkNX.WinForms/Main.cs +++ b/pkNX.WinForms/Main.cs @@ -6,7 +6,6 @@ using System.IO; using System.Windows; using System.Windows.Forms; -using Application = System.Windows.Forms.Application; using Clipboard = System.Windows.Forms.Clipboard; using DataFormats = System.Windows.Forms.DataFormats; using DragDropEffects = System.Windows.Forms.DragDropEffects; @@ -17,8 +16,7 @@ namespace pkNX.WinForms; public partial class Main : Form { - public static readonly string ProgramSettingsPath = Path.Combine(Application.StartupPath, "settings.json"); - public ProgramSettings Settings { get; } + public static ProgramSettings Settings => Program.Settings; private int Language { @@ -36,10 +34,9 @@ public Main() FLP_Controls.Controls.Clear(); - Settings = SettingsSerializer.GetSettings(ProgramSettingsPath).Result; CB_Lang.SelectedIndex = Settings.Language; if (!string.IsNullOrWhiteSpace(Settings.GamePath) && Directory.Exists(Settings.GamePath)) - OpenPath(Settings.GamePath, Settings.GameOverride); + OpenPath(Settings.GamePath); DragDrop += (s, e) => { @@ -87,8 +84,7 @@ private async void Main_FormClosing(object sender, FormClosingEventArgs e) EditUtil.SaveSettings(Editor.Game); Settings.Language = CB_Lang.SelectedIndex; Settings.GamePath = TB_Path.Text; - Settings.GameOverride = Editor.Game; - await SettingsSerializer.SaveSettings(Settings, ProgramSettingsPath); + await ProgramSettings.SaveSettings(Program.Settings); } private void Menu_Exit_Click(object sender, EventArgs e) diff --git a/pkNX.WinForms/MainEditor/EditUtil.cs b/pkNX.WinForms/MainEditor/EditUtil.cs index b4616aee..9b803358 100644 --- a/pkNX.WinForms/MainEditor/EditUtil.cs +++ b/pkNX.WinForms/MainEditor/EditUtil.cs @@ -65,8 +65,7 @@ public static void SaveSettings(GameVersion game) private static string GetSettingsFileName(GameVersion game) { var path = Path.GetDirectoryName(Application.StartupPath); - if (path is null) - throw new ArgumentNullException(nameof(path)); + ArgumentNullException.ThrowIfNull(path); return Path.Combine(path, $"randsetting{game}.xml"); } } diff --git a/pkNX.WinForms/MainEditor/Editor9a.cs b/pkNX.WinForms/MainEditor/Editor9a.cs new file mode 100644 index 00000000..07b4344d --- /dev/null +++ b/pkNX.WinForms/MainEditor/Editor9a.cs @@ -0,0 +1,66 @@ +using pkNX.Containers; +using pkNX.Game; +using pkNX.Structures; +using pkNX.WinForms.Subforms; +using System.IO; +using System.Windows.Forms; + +namespace pkNX.WinForms.Controls; + +internal class Editor9a : EditorBase +{ + protected override GameManager9a ROM { get; } + private GameData Data => ROM.Data; + + protected internal Editor9a(GameManager9a rom) + { + ROM = rom; + CheckOodleDllPresence(); + } + + private static void CheckOodleDllPresence() + { + const string file = $"{Oodle.OodleLibraryPath}.dll"; + var dir = Application.StartupPath; + var path = Path.Combine(dir, file); + if (!File.Exists(path)) + WinFormsUtil.Alert($"{file} not found in the executable folder", "Some decompression functions may cause errors."); + } + + [EditorCallable(EditorCategory.Dialog)] + public void EditCommon() + { + var text = ROM.GetFilteredFolder(GameFile.GameText, z => Path.GetExtension(z) == ".dat"); + var config = new TextConfig(ROM.Game); + var tc = new TextContainer(text, config); + using var form = new TextEditor(tc, TextEditor.TextEditorMode.Common); + form.ShowDialog(); + if (!form.Modified) + text.CancelEdits(); + } + + [EditorCallable(EditorCategory.Dialog)] + public void EditScript() + { + var text = ROM.GetFilteredFolder(GameFile.StoryText, z => Path.GetExtension(z) == ".dat"); + var config = new TextConfig(ROM.Game); + var tc = new TextContainer(text, config); + using var form = new TextEditor(tc, TextEditor.TextEditorMode.Script); + form.ShowDialog(); + if (!form.Modified) + text.CancelEdits(); + } + + [EditorCallable(EditorCategory.Field)] + public void EditMapViewer() + { + using var form = new MapViewer9a(ROM, "English"); + form.ShowDialog(); + } + + public void EditMasterDump() + { + using var md = new Dumper9a(ROM); + md.ShowDialog(); + } +} diff --git a/pkNX.WinForms/MainEditor/EditorGG.cs b/pkNX.WinForms/MainEditor/EditorGG.cs index b7a09a40..4ca3aa72 100644 --- a/pkNX.WinForms/MainEditor/EditorGG.cs +++ b/pkNX.WinForms/MainEditor/EditorGG.cs @@ -317,7 +317,7 @@ public void EditTypeChart() if (!editor.Modified) return; - chart.Data.CopyTo(nso.DecompressedRO, ofs); + chart.Data.CopyTo(nso.DecompressedRO.AsSpan(ofs)); data = nso.Write(); FileMitm.WriteAllBytes(path, data); } @@ -336,7 +336,7 @@ private void EditShop(bool shop2) { var table = shop.Single; var names = table.Select((z, _) => $"{(SingleShop.LGPE.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); - var cache = new DirectCache(table); + var cache = new DirectCache(table!); using var form = new GenericEditor(cache, names, $"{nameof(SingleShop)} Editor", Randomize); form.ShowDialog(); if (!form.Modified) diff --git a/pkNX.WinForms/MainEditor/EditorProvider.cs b/pkNX.WinForms/MainEditor/EditorProvider.cs index f2b39bf3..a60ade07 100644 --- a/pkNX.WinForms/MainEditor/EditorProvider.cs +++ b/pkNX.WinForms/MainEditor/EditorProvider.cs @@ -96,6 +96,7 @@ public void Close() GameManagerSWSH swsh => new EditorSWSH(swsh), GameManagerPLA pla => new EditorPLA(pla), GameManagerSV sv => new EditorSV(sv), + GameManager9a za => new Editor9a(za), _ => null, }; diff --git a/pkNX.WinForms/MainEditor/EditorSWSH.cs b/pkNX.WinForms/MainEditor/EditorSWSH.cs index 77cc2969..69a5c586 100644 --- a/pkNX.WinForms/MainEditor/EditorSWSH.cs +++ b/pkNX.WinForms/MainEditor/EditorSWSH.cs @@ -194,7 +194,7 @@ public void NotWorking_EditTypeChart() if (!editor.Modified) return; - chart.Data.CopyTo(nso.DecompressedRO, ofs); + chart.Data.CopyTo(nso.DecompressedRO.AsSpan(ofs)); data = nso.Write(); FileMitm.WriteAllBytes(path, data); } @@ -249,7 +249,7 @@ public void EditRaids() var nest_encounts = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName(nest)); var arr = nest_encounts.Table; - var cache = new DataCache(arr); + var cache = new DataCache(arr!); var games = new[] { "Sword", "Shield" }; var names = arr.Select((z, i) => $"{games[z.GameVersion - 1]} - {i / 2}").ToArray(); @@ -295,7 +295,7 @@ public void EditRaidRewards() var nest_drops = FlatBufferConverter.DeserializeFrom(originalData); var arr = nest_drops.Table; - var cache = new DataCache(arr); + var cache = new DataCache(arr!); var names = arr.Select(z => $"{z.TableID}").ToArray(); void Randomize() @@ -325,7 +325,7 @@ public void EditRBonusRewards() var nest_bonus = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName(nest)); var arr = nest_bonus.Table; - var cache = new DataCache(arr); + var cache = new DataCache(arr!); var names = arr.Select(z => $"{z.TableID}").ToArray(); void Randomize() @@ -408,7 +408,7 @@ private void EditShop(bool shop2) { var table = shop.Single; var names = table.Select((z, _) => $"{(SingleShop.SWSH.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); - var cache = new DirectCache(table); + var cache = new DirectCache(table!); using var form = new GenericEditor(cache, names, $"{nameof(SingleShop)} Editor", Randomize); form.ShowDialog(); if (!form.Modified) @@ -435,7 +435,7 @@ void Randomize() { var table = shop.Multi; var names = table.Select((z, _) => $"{(SingleShop.SWSH.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); - var cache = new DirectCache(table); + var cache = new DirectCache(table!); using var form = new GenericEditor(cache, names, $"{nameof(MultiShop)} Editor", Randomize); form.ShowDialog(); if (!form.Modified) @@ -485,7 +485,7 @@ public void EditRental() var obj = ROM[GameFile.Rentals]; var data = obj[0]; var rentals = FlatBufferConverter.DeserializeFrom(data); - var cache = new DataCache(rentals.Table); + var cache = new DataCache(rentals.Table!); var names = rentals.Table.Select((z, i) => $"{i:000} {z.Hash1:X16}").ToArray(); using var form = new GenericEditor(cache, names, "Rental Editor"); form.ShowDialog(); @@ -536,7 +536,7 @@ public void EditGift() var gifts = objs.Table; var names = Enumerable.Range(0, gifts.Count).Select(z => $"{z:000}").ToArray(); - var cache = new DirectCache(gifts); + var cache = new DirectCache(gifts!); void Randomize() { @@ -729,7 +729,7 @@ public void EditDynamaxAdv() var table = objs.Table; var names = Enumerable.Range(0, table.Count).Select(z => $"{z:000}").ToArray(); - var cache = new DirectCache(table); + var cache = new DirectCache(table!); void Randomize() { @@ -766,7 +766,7 @@ public void EditSymbolBehave() var obj = ROM.GetFile(GameFile.SymbolBehave); var data = obj[0]; var root = FlatBufferConverter.DeserializeFrom(data); - var cache = new DataCache(root.Table); + var cache = new DataCache(root.Table!); var names = root.Table.Select(z => $"{z.Species}{(z.Form != 0 ? $"-{z.Form}" : "")}").ToArray(); using var form = new GenericEditor(cache, names, "Symbol Behavior Editor", Randomize); form.ShowDialog(); diff --git a/pkNX.WinForms/Program.cs b/pkNX.WinForms/Program.cs index bd23f4a5..1cb8d2f3 100644 --- a/pkNX.WinForms/Program.cs +++ b/pkNX.WinForms/Program.cs @@ -7,6 +7,10 @@ namespace pkNX.WinForms; internal static class Program { + public static ProgramSettings Settings { get; } + + static Program() => Settings = ProgramSettings.LoadSettings(); + /// /// The main entry point for the application. /// diff --git a/pkNX.WinForms/ProgramSettings.cs b/pkNX.WinForms/ProgramSettings.cs index 21b8739d..0b6435fa 100644 --- a/pkNX.WinForms/ProgramSettings.cs +++ b/pkNX.WinForms/ProgramSettings.cs @@ -13,6 +13,5 @@ public class ProgramSettings public int Language { get; set; } = 2; public string GamePath { get; set; } = string.Empty; - public GameVersion GameOverride { get; set; } = GameVersion.Any; public bool DisplayAdvanced { get; set; } = false; } diff --git a/pkNX.WinForms/Subforms/BTTE.cs b/pkNX.WinForms/Subforms/Gen7b/BTTE.cs similarity index 100% rename from pkNX.WinForms/Subforms/BTTE.cs rename to pkNX.WinForms/Subforms/Gen7b/BTTE.cs diff --git a/pkNX.WinForms/Subforms/BTTE.designer.cs b/pkNX.WinForms/Subforms/Gen7b/BTTE.designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/BTTE.designer.cs rename to pkNX.WinForms/Subforms/Gen7b/BTTE.designer.cs diff --git a/pkNX.WinForms/Subforms/BTTE.resx b/pkNX.WinForms/Subforms/Gen7b/BTTE.resx similarity index 100% rename from pkNX.WinForms/Subforms/BTTE.resx rename to pkNX.WinForms/Subforms/Gen7b/BTTE.resx diff --git a/pkNX.WinForms/Subforms/GGWE.Designer.cs b/pkNX.WinForms/Subforms/Gen7b/GGWE.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/GGWE.Designer.cs rename to pkNX.WinForms/Subforms/Gen7b/GGWE.Designer.cs diff --git a/pkNX.WinForms/Subforms/GGWE.cs b/pkNX.WinForms/Subforms/Gen7b/GGWE.cs similarity index 100% rename from pkNX.WinForms/Subforms/GGWE.cs rename to pkNX.WinForms/Subforms/Gen7b/GGWE.cs diff --git a/pkNX.WinForms/Subforms/GGWE.resx b/pkNX.WinForms/Subforms/Gen7b/GGWE.resx similarity index 100% rename from pkNX.WinForms/Subforms/GGWE.resx rename to pkNX.WinForms/Subforms/Gen7b/GGWE.resx diff --git a/pkNX.WinForms/Subforms/PokeDataUI.Designer.cs b/pkNX.WinForms/Subforms/Gen7b/PokeDataUI.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/PokeDataUI.Designer.cs rename to pkNX.WinForms/Subforms/Gen7b/PokeDataUI.Designer.cs diff --git a/pkNX.WinForms/Subforms/PokeDataUI.cs b/pkNX.WinForms/Subforms/Gen7b/PokeDataUI.cs similarity index 100% rename from pkNX.WinForms/Subforms/PokeDataUI.cs rename to pkNX.WinForms/Subforms/Gen7b/PokeDataUI.cs diff --git a/pkNX.WinForms/Subforms/PokeDataUI.resx b/pkNX.WinForms/Subforms/Gen7b/PokeDataUI.resx similarity index 100% rename from pkNX.WinForms/Subforms/PokeDataUI.resx rename to pkNX.WinForms/Subforms/Gen7b/PokeDataUI.resx diff --git a/pkNX.WinForms/Subforms/ShinyRate.Designer.cs b/pkNX.WinForms/Subforms/Gen7b/ShinyRate.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/ShinyRate.Designer.cs rename to pkNX.WinForms/Subforms/Gen7b/ShinyRate.Designer.cs diff --git a/pkNX.WinForms/Subforms/ShinyRate.cs b/pkNX.WinForms/Subforms/Gen7b/ShinyRate.cs similarity index 100% rename from pkNX.WinForms/Subforms/ShinyRate.cs rename to pkNX.WinForms/Subforms/Gen7b/ShinyRate.cs diff --git a/pkNX.WinForms/Subforms/ShinyRate.resx b/pkNX.WinForms/Subforms/Gen7b/ShinyRate.resx similarity index 100% rename from pkNX.WinForms/Subforms/ShinyRate.resx rename to pkNX.WinForms/Subforms/Gen7b/ShinyRate.resx diff --git a/pkNX.WinForms/Subforms/TMList.Designer.cs b/pkNX.WinForms/Subforms/Gen7b/TMList.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/TMList.Designer.cs rename to pkNX.WinForms/Subforms/Gen7b/TMList.Designer.cs diff --git a/pkNX.WinForms/Subforms/TMList.cs b/pkNX.WinForms/Subforms/Gen7b/TMList.cs similarity index 100% rename from pkNX.WinForms/Subforms/TMList.cs rename to pkNX.WinForms/Subforms/Gen7b/TMList.cs diff --git a/pkNX.WinForms/Subforms/TMList.resx b/pkNX.WinForms/Subforms/Gen7b/TMList.resx similarity index 100% rename from pkNX.WinForms/Subforms/TMList.resx rename to pkNX.WinForms/Subforms/Gen7b/TMList.resx diff --git a/pkNX.WinForms/Subforms/TypeChart.Designer.cs b/pkNX.WinForms/Subforms/Gen7b/TypeChart.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/TypeChart.Designer.cs rename to pkNX.WinForms/Subforms/Gen7b/TypeChart.Designer.cs diff --git a/pkNX.WinForms/Subforms/TypeChart.cs b/pkNX.WinForms/Subforms/Gen7b/TypeChart.cs similarity index 84% rename from pkNX.WinForms/Subforms/TypeChart.cs rename to pkNX.WinForms/Subforms/Gen7b/TypeChart.cs index 13597f56..4a0edd17 100644 --- a/pkNX.WinForms/Subforms/TypeChart.cs +++ b/pkNX.WinForms/Subforms/Gen7b/TypeChart.cs @@ -8,37 +8,33 @@ namespace pkNX.WinForms; public sealed partial class TypeChart : Form { - private readonly string[] types; + private readonly string[] TypeNames; private readonly TypeChartEditor Editor; - public byte[] Chart; + public Span Chart => Editor.Data; public bool Modified { get; set; } private const int TypeWidth = 32; // px - private int TypeCount => types.Length; + private int TypeCount => TypeNames.Length; - public TypeChart(TypeChartEditor editor, string[] types) + public TypeChart(TypeChartEditor editor, string[] typeNames) { - Editor = editor; InitializeComponent(); - this.types = types; - Chart = editor.Data; + + Editor = editor; + TypeNames = typeNames; LoadChart(); } private void B_Save_Click(object sender, EventArgs e) { Modified = true; - SaveChart(); Close(); } - private void SaveChart() => Chart = Editor.Data; - private void B_RTM_Click(object sender, EventArgs e) { Editor.Randomize(); - Chart = Editor.Data; LoadChart(); System.Media.SystemSounds.Asterisk.Play(); } @@ -71,9 +67,9 @@ private void ClickMouse(object sender, MouseEventArgs e) private void UpdateLabel(int X, int Y, int value) { - if (value >= effects.Length || X >= types.Length || Y >= types.Length) + if (value >= effects.Length || X >= TypeNames.Length || Y >= TypeNames.Length) return; // clicking and moving outside the box has invalid values - L_Hover.Text = $"[{X:00}x{Y:00}: {value:00}] {types[Y]} attacking {types[X]} {effects[value]}"; + L_Hover.Text = $"[{X:00}x{Y:00}: {value:00}] {TypeNames[Y]} attacking {TypeNames[X]} {effects[value]}"; } private readonly string[] effects = @@ -111,7 +107,7 @@ public static byte ToggleEffectiveness(byte currentValue, bool increase) return vals[newIndex]; } - public static Bitmap GetGrid(byte[] vals, int itemsize, int itemsPerRow) + public static Bitmap GetGrid(ReadOnlySpan vals, int itemsize, int itemsPerRow) { // set up image var bmpData = TypeChartEditor.GetTypeChartImageData(itemsize, itemsPerRow, vals, out int width, out int height); diff --git a/pkNX.WinForms/Subforms/TypeChart.resx b/pkNX.WinForms/Subforms/Gen7b/TypeChart.resx similarity index 100% rename from pkNX.WinForms/Subforms/TypeChart.resx rename to pkNX.WinForms/Subforms/Gen7b/TypeChart.resx diff --git a/pkNX.WinForms/Subforms/SSWE.Designer.cs b/pkNX.WinForms/Subforms/Gen8/SSWE.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/SSWE.Designer.cs rename to pkNX.WinForms/Subforms/Gen8/SSWE.Designer.cs diff --git a/pkNX.WinForms/Subforms/SSWE.cs b/pkNX.WinForms/Subforms/Gen8/SSWE.cs similarity index 100% rename from pkNX.WinForms/Subforms/SSWE.cs rename to pkNX.WinForms/Subforms/Gen8/SSWE.cs diff --git a/pkNX.WinForms/Subforms/SSWE.resx b/pkNX.WinForms/Subforms/Gen8/SSWE.resx similarity index 100% rename from pkNX.WinForms/Subforms/SSWE.resx rename to pkNX.WinForms/Subforms/Gen8/SSWE.resx diff --git a/pkNX.WinForms/Subforms/AreaEditor8a.Designer.cs b/pkNX.WinForms/Subforms/Gen8a/AreaEditor8a.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/AreaEditor8a.Designer.cs rename to pkNX.WinForms/Subforms/Gen8a/AreaEditor8a.Designer.cs diff --git a/pkNX.WinForms/Subforms/AreaEditor8a.cs b/pkNX.WinForms/Subforms/Gen8a/AreaEditor8a.cs similarity index 100% rename from pkNX.WinForms/Subforms/AreaEditor8a.cs rename to pkNX.WinForms/Subforms/Gen8a/AreaEditor8a.cs diff --git a/pkNX.WinForms/Subforms/AreaEditor8a.resx b/pkNX.WinForms/Subforms/Gen8a/AreaEditor8a.resx similarity index 100% rename from pkNX.WinForms/Subforms/AreaEditor8a.resx rename to pkNX.WinForms/Subforms/Gen8a/AreaEditor8a.resx diff --git a/pkNX.WinForms/Subforms/MapViewer8a.Designer.cs b/pkNX.WinForms/Subforms/Gen8a/MapViewer8a.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/MapViewer8a.Designer.cs rename to pkNX.WinForms/Subforms/Gen8a/MapViewer8a.Designer.cs diff --git a/pkNX.WinForms/Subforms/MapViewer8a.cs b/pkNX.WinForms/Subforms/Gen8a/MapViewer8a.cs similarity index 100% rename from pkNX.WinForms/Subforms/MapViewer8a.cs rename to pkNX.WinForms/Subforms/Gen8a/MapViewer8a.cs diff --git a/pkNX.WinForms/Subforms/MapViewer8a.resx b/pkNX.WinForms/Subforms/Gen8a/MapViewer8a.resx similarity index 100% rename from pkNX.WinForms/Subforms/MapViewer8a.resx rename to pkNX.WinForms/Subforms/Gen8a/MapViewer8a.resx diff --git a/pkNX.WinForms/Subforms/PokeDataUI8a.Designer.cs b/pkNX.WinForms/Subforms/Gen8a/PokeDataUI8a.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/PokeDataUI8a.Designer.cs rename to pkNX.WinForms/Subforms/Gen8a/PokeDataUI8a.Designer.cs diff --git a/pkNX.WinForms/Subforms/PokeDataUI8a.cs b/pkNX.WinForms/Subforms/Gen8a/PokeDataUI8a.cs similarity index 100% rename from pkNX.WinForms/Subforms/PokeDataUI8a.cs rename to pkNX.WinForms/Subforms/Gen8a/PokeDataUI8a.cs diff --git a/pkNX.WinForms/Subforms/PokeDataUI8a.resx b/pkNX.WinForms/Subforms/Gen8a/PokeDataUI8a.resx similarity index 100% rename from pkNX.WinForms/Subforms/PokeDataUI8a.resx rename to pkNX.WinForms/Subforms/Gen8a/PokeDataUI8a.resx diff --git a/pkNX.WinForms/Subforms/MapViewer9.Designer.cs b/pkNX.WinForms/Subforms/Gen9/MapViewer9.Designer.cs similarity index 100% rename from pkNX.WinForms/Subforms/MapViewer9.Designer.cs rename to pkNX.WinForms/Subforms/Gen9/MapViewer9.Designer.cs diff --git a/pkNX.WinForms/Subforms/MapViewer9.cs b/pkNX.WinForms/Subforms/Gen9/MapViewer9.cs similarity index 98% rename from pkNX.WinForms/Subforms/MapViewer9.cs rename to pkNX.WinForms/Subforms/Gen9/MapViewer9.cs index 6640bcbd..9c9af3c8 100644 --- a/pkNX.WinForms/Subforms/MapViewer9.cs +++ b/pkNX.WinForms/Subforms/Gen9/MapViewer9.cs @@ -20,7 +20,7 @@ public MapViewer9(GameManagerSV rom) InitializeComponent(); Loading = true; - CB_Field.Items.AddRange(new[] { "Paldea", "Kitakami", "Terarium" }); + CB_Field.Items.AddRange("Paldea", "Kitakami", "Terarium"); Loading = false; CB_Field.SelectedIndex = 0; } diff --git a/pkNX.WinForms/Subforms/MapViewer9.resx b/pkNX.WinForms/Subforms/Gen9/MapViewer9.resx similarity index 100% rename from pkNX.WinForms/Subforms/MapViewer9.resx rename to pkNX.WinForms/Subforms/Gen9/MapViewer9.resx diff --git a/pkNX.WinForms/Subforms/PaldeaMap.cs b/pkNX.WinForms/Subforms/Gen9/PaldeaMap.cs similarity index 100% rename from pkNX.WinForms/Subforms/PaldeaMap.cs rename to pkNX.WinForms/Subforms/Gen9/PaldeaMap.cs diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/ActivationConditionUtil9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/ActivationConditionUtil9a.cs new file mode 100644 index 00000000..1d891252 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/ActivationConditionUtil9a.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Text; +using pkNX.Structures.FlatBuffers.ZA; + +namespace pkNX.WinForms; + +public static class ActivationConditionUtil9a +{ + public static string GetSummary(this IList? list) + { + if (list == null) + return ""; + var sb = new StringBuilder(); + foreach (var cond in list) + { + if (cond.Element is null) + continue; + sb.Append(GetSummary(cond.Element)); + } + return sb.ToString(); + } + + private static string GetSummary(this IList list) + { + var sb = new StringBuilder(); + foreach (var cond in list) + sb.AppendJoin("&&", cond.Summarize()); + return sb.ToString(); + } + + public static string GetSummary(this IEnumerable?> list) + { + var sb = new StringBuilder(); + foreach (var element in list) + { + if (element == null) + continue; + sb.Append(GetSummary(element)); + } + return sb.ToString(); + } +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/FlatBufferSource.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/FlatBufferSource.cs new file mode 100644 index 00000000..e913a525 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/FlatBufferSource.cs @@ -0,0 +1,14 @@ +using FlatSharp; +using pkNX.Containers; +using pkNX.Structures.FlatBuffers; +using System; + +namespace pkNX.WinForms; + +public sealed class FlatBufferSource(IFileInternal rom) +{ + public T Get(string path) where T : class, IFlatBufferSerializable + => Get(rom.GetPackedFile(path)); + public T Get(Memory data) where T : class, IFlatBufferSerializable + => FlatBufferConverter.DeserializeFrom(data); +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SceneSpawner.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SceneSpawner.cs new file mode 100644 index 00000000..fcfef5e3 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SceneSpawner.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using pkNX.Structures.FlatBuffers; + +namespace pkNX.WinForms; + +public sealed record SceneSpawner( + PackedVec3f Scale, + PackedVec3f Rotation, + PackedVec3f Position, + string Type, + string Name) +{ + public List Inner { get; set; } = []; +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnGlobalInfo.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnGlobalInfo.cs new file mode 100644 index 00000000..f74e0001 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnGlobalInfo.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using System.Linq; +using FlatSharp; +using pkNX.Game; +using pkNX.Structures.FlatBuffers; +using pkNX.Structures.FlatBuffers.ZA; + +namespace pkNX.WinForms; + +public sealed class SpawnGlobalInfo +{ + private readonly GameManager9a _rom; + + public readonly Dictionary Encounters; + public readonly Dictionary SpawnerTransforms; + + public readonly PokemonSpawnerDataDBArray SpawnerDatabase; + + public SpawnGlobalInfo(GameManager9a rom) + { + _rom = rom; + + const string emd = "world/ik_data/field/pokemon/encount_data/encount_data/encount_data_array.bin"; + var encT = Get(emd); + Encounters = encT.Table.SelectMany(z => z.Table).ToDictionary(z => z.Id, z => z); + + const string pst = "world/ik_data/field/spawner_transform_data/pokemon_spawner_transform/pokemon_spawner_transform/pokemon_spawner_transform_array.bin"; + var spawnerT = Get(pst); + SpawnerTransforms = spawnerT.Table.SelectMany(z => z.Table).ToDictionary(z => z.Name ?? "", z => z); + + const string psp = "world/ik_data/field/pokemon_spawner/pokemon_spawner_data/pokemon_spawner_data_array.bin"; + SpawnerDatabase = Get(psp); + } + + private T Get(string path) where T : class, IFlatBufferSerializable + => FlatBufferConverter.DeserializeFrom(_rom.GetPackedFile(path)); +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnNameResolver.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnNameResolver.cs new file mode 100644 index 00000000..6b94d660 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnNameResolver.cs @@ -0,0 +1,44 @@ +using System; +using System.Linq; +using pkNX.Containers; +using pkNX.Game; +using pkNX.Structures; + +namespace pkNX.WinForms; + +public sealed class SpawnNameResolver +{ + private readonly GameManager9a _rom; + + // From Text File + public readonly string[] PlaceNames; // internal + public readonly string[] LocationNames; // display + public readonly AHTB Lookup; + + public SpawnNameResolver(GameManager9a rom, string language) + { + _rom = rom; + var cfg = new TextConfig(rom.Game); + LocationNames = GetCommonText("place_name", language, cfg); + Lookup = GetCommonAHTB("place_name", language); + PlaceNames = Lookup.Entries.Select(z => z.Name).ToArray(); + } + + public int GetLocationIndex(string place) => Array.IndexOf(PlaceNames, place); + + private const string message = "ik_message"; + + private string[] GetCommonText(string name, string lang, TextConfig cfg) + { + var path = $"{message}/dat/{lang}/common/{name}.dat"; + var data = _rom.GetPackedFile(path); + return new TextFile(data, cfg).Lines; + } + + private AHTB GetCommonAHTB(string name, string lang) + { + var path = $"{message}/dat/{lang}/common/{name}.tbl"; + var data = _rom.GetPackedFile(path); + return new AHTB(data); + } +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnSceneSimulation.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnSceneSimulation.cs new file mode 100644 index 00000000..574656bc --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Dumping/SpawnSceneSimulation.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using pkNX.Structures.FlatBuffers; +using pkNX.Structures.FlatBuffers.ZA.Trinity; + +namespace pkNX.WinForms; + +public sealed class SpawnSceneSimulation +{ + public required string Name { get; init; } + public required string[] Paths { get; init; } + public required Func LocationNameFetch { get; init; } + public required FlatBufferSource Game { get; init; } + + public readonly Dictionary SpawnerPositions = []; // scraped from Scene + + public void ScrapePoints() + { + // For every scene, scrape out every v3f point we can find that is of a valid spawner object shape. + for (var i = 0; i < Paths.Length; i++) + { + Debug.WriteLine($"Processing Scene {i + 1}/{Paths.Length}: {Paths[i]}"); + var file = Paths[i]; + var scene = Game.Get(file); + RipScenePoints(scene); + } + } + + private void RipScenePoints(TrinitySceneObjectTemplate scene) + { + Debug.WriteLine($"Dumping {scene.Objects.Count} from {scene.ObjectTemplateName}"); + foreach (var obj in scene.Objects) + { + var name = obj.Type; + if (name is not ObjectTemplate) + continue; + + var so = Game.Get(obj.Data); + if (!RipScenePoints(so, out var point)) + continue; + + SpawnerPositions.Add(point.Name, point); + for (var i = 0; i < obj.SubObjects.Count; i++) + { + var sub = obj.SubObjects[i]; + name = sub.Type; + if (name is not SceneObject) + continue; + var s = Game.Get(sub.Data); + if (RipScenePoints(s, $"subObject[{i}]", out var result)) + point.Inner.Add(result); + } + } + } + + private bool RipScenePoints(TrinitySceneObjectTemplateData obj, [NotNullWhen(true)] out SceneSpawner? result) + { + result = null; + var name = obj.Type; + if (name is not SceneObject) + return false; + + var objName = obj.ObjectTemplateName; + + var so = Game.Get(obj.Data); + return RipScenePoints(so, objName, out result); + } + + private static bool RipScenePoints(TrinitySceneObject so, string objName, [NotNullWhen(true)] out SceneSpawner? result) + { + result = null; + var type = so.Name; + if (!IsValidSpawnerShape(type)) + return false; + + var scale = so.Position.Scale; + var rotation = so.Position.Rotation; + var position = so.Position.Translation; + result = new SceneSpawner(scale, rotation, position, type, objName); + return true; + } + + private const string SceneObject = "trinity_SceneObject"; + private const string ObjectTemplate = "trinity_ObjectTemplate"; + + private const string SpawnerSphere = "pokemon_spawner_sphere_object"; + private const string SpawnerBox = "pokemon_spawner_box_object"; + private const string SpawnerPoint = "pokemon_spawner_point_object"; + + private static bool IsValidSpawnerShape(string name) => name is SpawnerSphere or SpawnerBox or SpawnerPoint; +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Exports/DetailedSpawn9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/DetailedSpawn9a.cs new file mode 100644 index 00000000..1d42f316 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/DetailedSpawn9a.cs @@ -0,0 +1,57 @@ +using pkNX.Structures.FlatBuffers.ZA; + +namespace pkNX.WinForms; + +public sealed record DetailedSpawn9a +{ + public required string Id { get; init; } + public required ushort Species { get; init; } + public required byte Form { get; init; } + public required int Gender { get; init; } + public required int Nature { get; init; } + + public required float AlphaProbability { get; init; } + + public required byte LevelMin { get; init; } + public required byte LevelMax { get; init; } + public required int LevelBoostFromArea { get; init; } + public required byte LevelBoostIfAlpha { get; init; } + + public required string Tags { get; init; } + public required string Condition { get; init; } + + public required int RepopProbabilityAfterCapture { get; init; } + public required int RepopProbabilityAfterDefeat { get; init; } + public required int ConditionTime { get; init; } + public required int ConditionWeather { get; init; } + public required int RandomWeight { get; init; } + public required int TotalWeight { get; init; } + public required int Quantity { get; init; } + + public static DetailedSpawn9a Create(EncountDataInfo enc, EncountData slot, int totalWeight) => new() + { + Id = slot.Id, + Species = SpeciesConverterZA.GetNational9((ushort)slot.DevNo), + Form = (byte)slot.FormNo, + LevelMin = (byte)slot.MinLevel, + LevelMax = (byte)slot.MaxLevel, + AlphaProbability = slot.OyabunProbability, + LevelBoostIfAlpha = (byte)slot.OyabunAdditionalLevel, + Gender = slot.Sex, + Nature = slot.Seikaku, + Condition = slot.ActivationConditionArray.GetSummary(), + + LevelBoostFromArea = enc.AdditionalLevel, // unused, future DLC level boost like Kitakami + Tags = enc.TagList is { } tl ? string.Join("&&", tl) : "", + + RepopProbabilityAfterCapture = enc.Repop?.AfterCaptured ?? -1, + RepopProbabilityAfterDefeat = enc.Repop?.AfterDefeated ?? -1, + + ConditionTime = enc.AppearedTimeCondition, + ConditionWeather = enc.AppearedWeatherCondition, + + RandomWeight = enc.Weight, + TotalWeight = totalWeight, + Quantity = enc.MaxCount, + }; +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Exports/EncounterArea9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/EncounterArea9a.cs new file mode 100644 index 00000000..6c19419a --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/EncounterArea9a.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace pkNX.WinForms; + +public sealed record EncounterArea9a +{ + public required List Slots { get; init; } + public required int Location { get; init; } + + public void CondenseList() + { + // If level range overlaps, and Species-Form-Gender-Alpha merge the overlap + // Level (and Alpha) check is before the crypto-secure 64-bit seed generates, so merging level ranges is OK to deduplicate some templates. + Slots.Sort((a, b) => a.Species.CompareTo(b.Species)); + for (int i = 0; i < Slots.Count - 1; i++) + { + var a = Slots[i]; + for (int j = i + 1; j < Slots.Count; j++) + { + var b = Slots[j]; + if (!a.IsSame(b)) + continue; + if (!a.LevelOverlap(b)) + continue; + Slots[i] = a = a.MergeWith(b); + Slots.RemoveAt(j); + j--; + } + } + } +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Exports/EncounterSlot9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/EncounterSlot9a.cs new file mode 100644 index 00000000..0fb0f772 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/EncounterSlot9a.cs @@ -0,0 +1,108 @@ +using pkNX.Containers; +using pkNX.Structures; +using pkNX.Structures.FlatBuffers.ZA; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace pkNX.WinForms; + +public sealed record EncounterSlot9a(ushort Species, byte Form, byte LevelMin, byte LevelMax, sbyte Gender, sbyte Nature, bool IsAlpha, Shiny Shiny) +{ + public bool IsSame(EncounterSlot9a b) => Species == b.Species && Form == b.Form && Gender == b.Gender && IsAlpha == b.IsAlpha && Shiny == b.Shiny; + public bool LevelOverlap(EncounterSlot9a b) => !(LevelMax < b.LevelMin || b.LevelMax < LevelMin); + + public EncounterSlot9a MergeWith(EncounterSlot9a b) + { + var newMin = Math.Min(LevelMin, b.LevelMin); + var newMax = Math.Max(LevelMax, b.LevelMax); + return this with { LevelMin = newMin, LevelMax = newMax }; + } + + /// + /// Creates a copy of the slot as an Alpha spawn, with an applied level boost to both min and max levels. + /// + /// Amount to increase each level component by. + public EncounterSlot9a WithAlpha(int boost) => this with { IsAlpha = true, LevelMax = (byte)(LevelMax + boost), LevelMin = (byte)(LevelMin + boost) }; + + public void Write(BinaryWriter bw) + { + bw.Write(Species); + bw.Write(Form); + bw.Write(Gender); // Required; gender is used in generator. Can't generalize to "random gender" via slot compression. + + bw.Write(LevelMin); + bw.Write(LevelMax); + + bw.Write(IsAlpha ? (byte)1 : (byte)0); + bw.Write((byte)(Shiny switch + { + Shiny.Never => 1, + Shiny.Always => 2, + _ => 0, // Random + })); // can be packed into IsAlpha if we get sizeof(slot) down to 6 + + // Assert that none have fixed natures. We have already used 8 bytes of a structure for the above fields. + // bw.Write(slot.Nature); // seems to always be FF, can be omitted if so + if (Nature is not unchecked((sbyte)0xFF)) + throw new ArgumentOutOfRangeException(nameof(Nature), Nature, null); + } + + public static void WritePickleWithoutLocations(IEnumerable slots, string path) + { + var ms = new MemoryStream(); + var bw = new BinaryWriter(ms); + foreach (var slot in slots) + slot.Write(bw); + File.WriteAllBytes(Path.ChangeExtension(path, ".bin"), ms.ToArray()); + } + + public static void WritePickle(IReadOnlyList slotSets, string path) + { + var result = new byte[slotSets.Count][]; + var i = 0; + foreach (var area in slotSets.OrderBy(z => z.Location)) + { + var ms = new MemoryStream(); + var bw = new BinaryWriter(ms); + + // keep location header 4 bytes for future-proofing and better aligned slot reads (rather than 2 bytes) + bw.Write((ushort)area.Location); + bw.Write((ushort)0); // reserved (slot type) -- location IDs are already pretty high (235) and DLC will undoubtedly overflow above 255. + foreach (var slot in area.Slots) + slot.Write(bw); + + result[i++] = ms.ToArray(); + } + + var mini = BinLinkerWriter.Write16(result, "za"u8); + File.WriteAllBytes(path, mini); + } + + public static void AddSlots(List list, EncountData slot, EncountDataInfo enc) + { + 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. + var minLevel = (byte)(slot.MinLevel + boost); + var maxLevel = (byte)(slot.MaxLevel + boost); + var gender = (sbyte)slot.Sex; + var nature = (sbyte)slot.Seikaku; + var shiny = GetShiny(slot.Rare); + + var template = new EncounterSlot9a(species, form, minLevel, maxLevel, gender, nature, false, shiny); + if (slot.OyabunProbability < 100) + list.Add(template); + if (slot.OyabunProbability > 0) + list.Add(template.WithAlpha(slot.OyabunAdditionalLevel)); + } + + private static Shiny GetShiny(int valueRare) => valueRare switch + { + 0x1FFFFFFF => Shiny.Never, + 0x2FFFFFFF => Shiny.Always, + 0x3FFFFFFF => Shiny.Random, + _ => throw new ArgumentOutOfRangeException(nameof(valueRare), valueRare, null), + }; +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Exports/FakeSpawner9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/FakeSpawner9a.cs new file mode 100644 index 00000000..a052d370 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/FakeSpawner9a.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace pkNX.WinForms; + +/// +/// Wrapper for concise exports for viewing/importing Json data of spawners in Gen 9a maps. +/// +public sealed record FakeSpawner9a +{ + public required SceneSpawner Link { private get; init; } + + public string Name => Link.Name; + public string Type => Link.Type; + public string Scale => $"{Link.Scale.X:F2}, {Link.Scale.Y:F2}, {Link.Scale.Z:F2}"; + public string Rotation => $"{Link.Rotation.X:F2}, {Link.Rotation.Y:F2}, {Link.Rotation.Z:F2}"; + public string Position => $"{Link.Position.X:F2}, {Link.Position.Y:F2}, {Link.Position.Z:F2}"; + + public required int SpawnCountMin { get; init; } + public required int SpawnCountMax { get; init; } + public required string Location { get; init; } + public required float Cooldown { get; init; } + public required int CooldownCondition { get; init; } + public required string Conditions { get; init; } + public List Spawns { get; } = []; +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Exports/SimulatedAreaSet.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/SimulatedAreaSet.cs new file mode 100644 index 00000000..f623b4e0 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/SimulatedAreaSet.cs @@ -0,0 +1,104 @@ +using pkNX.Structures.FlatBuffers.ZA; +using System.Collections.Generic; +using System.Linq; + +namespace pkNX.WinForms; + +public sealed class SimulatedAreaSet(SpawnRipper9a self) +{ + // Synthetic data to aggregate results in an easier to handle format. + public readonly Dictionary> Simple = []; // pkl for PKHeX + public readonly Dictionary> Detailed = []; // json for detailed import elsewhere + + public void Populate(SpawnSceneSimulation simulation) + { + var spawnerPositions = simulation.SpawnerPositions; + foreach (var (name, pos) in spawnerPositions) + { + if (!self.TryGetSpawner(name, out var spawnerData)) + continue; + + var locationIndex = simulation.LocationNameFetch(pos.Position); + foreach (var appearInfo in spawnerData.AppearanceSpawnerObjectInfoList) + { + var count = appearInfo.Appearance; + if (count.MaxCount == 0) + continue; // shouldn't ever be true + + var encounters = spawnerData.EncountDataInfoList; + if (encounters.Count == 0) + continue; // no encounters? + + AddSpawnsToLocation(locationIndex, encounters); + AddSpawnsToMap(locationIndex, encounters, pos, spawnerData, count); + } + } + } + + private void AddSpawnsToLocation(int locationIndex, IEnumerable encounters) + { + if (!Simple.TryGetValue(locationIndex, out var list)) + Simple[locationIndex] = list = []; + + foreach (var enc in encounters) + { + if (enc.EncountDataId is not { } id) + continue; + if (!self.TryGetEncounter(id, out var slot)) + continue; + + EncounterSlot9a.AddSlots(list, slot, enc); + } + } + + private void AddSpawnsToMap(int locationIndex, IList encounters, SceneSpawner link, PokemonSpawnerData spawnerData, AppearanceInfo count) + { + if (!Detailed.TryGetValue(locationIndex, out var list)) + Detailed[locationIndex] = list = []; + + var point = new FakeSpawner9a + { + Link = link, + Location = self.GetLocationName(locationIndex), + SpawnCountMin = count.MinCount, + SpawnCountMax = count.MaxCount, + Cooldown = spawnerData.CoolTime.Time, + CooldownCondition = spawnerData.CoolTime.Condition, + + Conditions = spawnerData.ActivationConditionList.Select(z => z.Element).GetSummary(), + }; + + // not a perfect approximate (time of day Pumpkaboo, weather) but close enough for rough rips. + var totalWeight = encounters.Sum(z => z.Weight); + + foreach (var enc in encounters) + { + if (enc.EncountDataId is not { } id) + continue; + if (!self.TryGetEncounter(id, out var slot)) + continue; + + var detailed = DetailedSpawn9a.Create(enc, slot, totalWeight); + point.Spawns.Add(detailed); + } + + if (point.Spawns.Count == 0) + { + + } + + list.Add(point); + } + + public IEnumerable ToAreas() + { + foreach (var (loc, slots) in Simple) + { + yield return new EncounterArea9a + { + Location = loc, + Slots = slots, + }; + } + } +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Exports/SpawnExporter.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/SpawnExporter.cs new file mode 100644 index 00000000..89165fd9 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Exports/SpawnExporter.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Json.Serialization; +using pkNX.Containers; +using pkNX.Structures.FlatBuffers; + +namespace pkNX.WinForms; + +public sealed class SpawnExporter(string folder) +{ + /// + /// Allows location ID to name mapping to be provided by the caller. + /// + public required Func GetLocationName { get; init; } + + + public static readonly JsonSerializerOptions Options = new() + { + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, // japanese text in some Encounter tags; don't bother escaping for safety + Converters = { new PackedVec3fConverter(true) }, + }; + + public void ExportJson(T obj, string name, string map) + { + var json = JsonSerializer.Serialize(obj, Options); + File.WriteAllText(Path.Combine(folder, $"{map}_{name}.json"), json); + } + + public void ExportJson(Dictionary> pointSpawners, string map) + { + var array = pointSpawners.SelectMany(x => x.Value); + ExportJson(array, "point_spawners_a", map); + } + + public void ExportJson(IEnumerable slotSets, string map) + { + var dict = slotSets.ToDictionary(z => $"{GetLocationName(z.Location)} ({z.Location})", z => z.Slots); + ExportJson(dict, "slot_sets", map); + } + + public void ExportJson(IEnumerable maps) + { + foreach (var result in maps) + { + // Export info for inspection/loading into downstream tools + ExportJson(result.SpawnerPositions, nameof(result.SpawnerPositions), result.Name); + + // Flatten the spawner positions to a string, as passing in a FlatBuffer object doesn't serialize nicely. + var transform = result.SpawnerPositions + .OrderBy(z => GetLocationName(result.LocationNameFetch(z.Value.Position))) + .ThenBy(z => z.Key); + var points = transform.Select(z => GetPositionString(result, z.Key, z.Value)).Order(); + ExportJson(points, "point_spawners", result.Name); + } + } + + public void ExportAll(SpawnRipper9a all) + { + ExportJson(all.RipInfo.SpawnerInfo, nameof(MapSpawnerSet.SpawnerInfo), "all"); + ExportJson(all.RippedMaps.SelectMany(z => z.SpawnerPositions).ToArray(), "point_spawners", "all"); + } + + private string GetPositionString(SpawnSceneSimulation result, string internalName, SceneSpawner point) + { + var location = result.LocationNameFetch(point.Position); + var name = GetLocationName(location); + var hash = FnvHash.HashFnv1a_64(internalName); + return $"{name} - {hash:X16} - {internalName} @ {point.Position}"; + } + + // Custom converter so PackedVec3f serializes to a string via ToString(). + private sealed class PackedVec3fConverter(bool concise) : JsonConverter + { + public override PackedVec3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + // Deserialization is not required for current usage; avoid lossy parsing. + throw new NotSupportedException("Deserializing PackedVec3f from JSON is not supported."); + } + + public override void Write(Utf8JsonWriter writer, PackedVec3f value, JsonSerializerOptions options) + { + if (concise) + writer.WriteStringValue(value.ToShortString()); + else + writer.WriteStringValue(value.ToString()); + } + } +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Info/AreaDef9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Info/AreaDef9a.cs new file mode 100644 index 00000000..3cd0a60f --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Info/AreaDef9a.cs @@ -0,0 +1,11 @@ +using pkNX.Structures.FlatBuffers.ZA; +using pkNX.Structures.FlatBuffers.ZA.Trinity; + +namespace pkNX.WinForms; + +public class AreaDef9a +{ + public required TrinitySceneObject SceneObject; + public required CollisionComponent CollisionComponent; + public required FieldAreaInfo Info; +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Info/LumioseFieldIndex.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Info/LumioseFieldIndex.cs new file mode 100644 index 00000000..fb1f1475 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Info/LumioseFieldIndex.cs @@ -0,0 +1,9 @@ +namespace pkNX.WinForms; + +public enum LumioseFieldIndex +{ + Overworld = 0, + LysandreLabs = 1, + SewersCh5 = 2, + SewersCh6 = 3, +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Info/LumioseMap.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Info/LumioseMap.cs new file mode 100644 index 00000000..e15a624a --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Info/LumioseMap.cs @@ -0,0 +1,428 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using pkNX.Game; +using pkNX.Structures; +using pkNX.Structures.FlatBuffers; +using pkNX.Structures.FlatBuffers.ZA; +using pkNX.Structures.FlatBuffers.ZA.Trinity; + +namespace pkNX.WinForms; + +public sealed class LumioseMap +{ + // Public surface for consumers of a single map + public List AreaNames { get; } = []; + public OrderedDictionary AreaCollisionTrees { get; } = []; + public OrderedDictionary AreaCollisionBoxes { get; } = []; + + private readonly IList MainAreas; + private readonly IList SubAreas; + private readonly IList BattleZoneAreas; + private readonly IList WildZoneAreas; + private readonly IList SceneAreas; + private readonly IList FieldLocations; + + public LumioseMap( + IList main, + IList sub, + IList battle, + IList wild, + IList scene, + IList locations) + { + MainAreas = main; + SubAreas = sub; + BattleZoneAreas = battle; + WildZoneAreas = wild; + SceneAreas = scene; + FieldLocations = locations; + } + + public void LoadScenes(GameManager9a ROM, IEnumerable scenePaths) + { + foreach (var scene in scenePaths) + { + var data = ROM.GetPackedFile(scene); + LoadScene(ROM, data, scene); + } + } + + private void LoadScene(GameManager9a rom, Memory rootData, string fileName) + { + var root = FlatBufferConverter.DeserializeFrom(rootData); + var subScenes = root.Field05; + + // Recurse for sub-scenes. + foreach (var sub in subScenes) + { + // Convert from relative path to actual romfs path. + // Ensure it actually is configured as a relative path + System.Diagnostics.Debug.Assert(sub.StartsWith("../area_collision")); + + // Find parent directory, as we only load fully qualified file paths + var start = fileName.AsSpan().IndexOf(sub.AsSpan(2, "/area_collision".Length)); + System.Diagnostics.Debug.Assert(start != -1); + + // Get actual file name (with _0 appended -- why? dunno!) + var subFileName = $"{fileName[..start]}{sub[2..].Replace(".trscn", "_0.trscn")}"; + var file = rom.GetPackedFile(subFileName); + + LoadScene(rom, file, subFileName); + } + + foreach (var obj in root.Objects) + { + // "SubScene" are already handled at start. We only care about collision components at this point. + + // Main map immediately has trinity Scene objects. + if (obj is { Type: "trinity_SceneObject", SubObjects: { Count: not 0 } so }) + { + var inner = so[0]; + if (inner.Type is not "trinity_CollisionComponent") + continue; + + var scene = FlatBufferConverter.DeserializeFrom(obj.Data); + var name = scene.Name; + var trc = FlatBufferConverter.DeserializeFrom(inner.Data); + var coll = trc.Component.CollisionComponent; + LoadSceneCollision(rom, name, scene, coll); + } + + // Zone scene containers store them in nested object templates. + if (obj is { Type: "trinity_ObjectTemplate", SubObjects: { Count: not 0 } ot }) + { + var inner = ot[0]; + if (inner.Type is not "trinity_CollisionComponent") + continue; + + var sObj = FlatBufferConverter.DeserializeFrom(obj.Data); + if (sObj.Type is not "trinity_SceneObject") + continue; + + var scene = FlatBufferConverter.DeserializeFrom(sObj.Data); + var name = sObj.ObjectTemplateName; + var trc = FlatBufferConverter.DeserializeFrom(inner.Data); + var coll = trc.Component.CollisionComponent; + LoadSceneCollision(rom, name, scene, coll); + } + } + } + + private void LoadSceneCollision(GameManager9a rom, string name, TrinitySceneObject sceneObject, CollisionComponent collisionComponent) + { + AreaNames.Add(name); + + // Verified unused booleans + // if (sceneObject.Field02 || sceneObject.Field05) + + var shape = collisionComponent.Shape; + if (shape.TryGet(out Box? box)) + { + // Box collision, obj.ObjectPosition.Transform is pos, box.Size is size of box + // Box rotation/transform is unused in this game + // if (!box.Transform.IsZero() || !box.Rotation.IsZero()) + var value = new BoxCollision9 + { + Position = sceneObject.Position.Translation, + Size = box.Size, + }; + AreaCollisionBoxes.Add(name, value); + } + else if (shape.TryGet(out Havok? havok)) + { + var havokData = rom.GetPackedFile(havok.TrcolFilePath); + var tree = HavokCollision.ParseAABBTree(havokData); + + // if (sceneObject.ApplySRT) -- no idea? + { + var srt = sceneObject.Position; + var s = srt.Scale; + var r = srt.Rotation; + var t = srt.Translation; + + // Havok shape SRT is unused in this game + // if (!havok.Transform.IsZero() || !havok.Scale.IsOne() || !havok.Rotation.IsZero()) + + if (!s.IsOne()) + tree.Scale(s.X, s.Y, s.Z); + if (!r.IsZero()) + tree.Rotate(r.X, r.Y, r.Z); + if (!t.IsZero()) + tree.Translate(t.X, t.Y, t.Z); + } + if (AreaCollisionTrees.TryGetValue(name, out var exist)) + exist.Add(tree); + else + AreaCollisionTrees.Add(name, new MultiAABBTree(name, tree)); + } + else + { + System.Diagnostics.Debug.Fail("Unhandled shape."); + } + } + + public IAreaLayer FindAreaInfo(string name) + { + foreach (var area in MainAreas) + { + if (IsAreaName(area, name)) + return area; + } + foreach (var area in SubAreas) + { + if (IsAreaName(area, name)) + return area; + } + foreach (var area in SceneAreas) + { + if (IsAreaName(area, name)) + return area; + } + foreach (var area in BattleZoneAreas) + { + if (IsAreaName(area, name)) + return area; + } + foreach (var area in WildZoneAreas) + { + if (IsAreaName(area, name)) + return area; + } + foreach (var area in FieldLocations) + { + if (IsAreaName(area, name)) + return area; + } + throw new ArgumentException($"Unknown area {name}"); + } + + private static bool IsAreaName(T area, string name) where T : IAreaLayer => area.AreaInfo.AreaName == name; + + public IEnumerable GetCollisions(float x, float z, SpawnNameResolver resolver) => GetCollisions(x, 100, z, true, resolver); + public IEnumerable GetCollisions(float x, float y, float z, SpawnNameResolver resolver) => GetCollisions(x, y, z, false, resolver); + public string GetPlaceName(float x, float z, out string areaKey) => GetPlaceName(x, 100, z, true, out areaKey); + public string GetPlaceName(float x, float y, float z, out string areaKey) => GetPlaceName(x, y, z, false, out areaKey); + + private IEnumerable GetCollisions(float x, float y, float z, bool noY, SpawnNameResolver resolver) + { + foreach (var area in AreaCollisionTrees) + { + var coll = area.Value; + if (noY ? !coll.ContainsPoint(x, z) : !coll.ContainsPoint(x, y, z)) + continue; + + var key = area.Key; + var info = FindAreaInfo(key); + + var layer = info.Layer; + var type = info.AreaInfo.AreaType; + var valid = IsValidLocation(info.AreaInfo); + var placeName = GetPlaceName(info); + var locationID = resolver.GetLocationIndex(placeName); + var locationName = locationID == -1 ? "Out of Bounds" : resolver.LocationNames[locationID]; + yield return new IntersectingTree + { + Layer = layer, + Name = key, + Valid = valid, + Type = type, + AreaInfo = info.AreaInfo, + Collision = coll, + PlaceName = placeName, + LocationID = locationID, + LocationName = locationName, + }; + } + } + + private string GetPlaceName(float x, float y, float z, bool noY, out string areaKey) + { + areaKey = string.Empty; + IAreaLayer? result = null; + var best = (AreaLayer.Scene, AreaType.Default); + float bestFloorDistance = float.PositiveInfinity; + // The highest value of tuple is preferred. + // Prefer better Layer first, then AreaType second. + + foreach (var area in AreaCollisionBoxes) + { + var coll = area.Value; + if (!coll.ContainsPoint(x, y, z)) + continue; + + var key = area.Key; + var info = FindAreaInfo(key); + + var layer = info.Layer; + var type = info.AreaInfo.AreaType; + var candidate = (layer, type); + if (!IsZoneBetter(candidate, best) || !IsValidLocation(info.AreaInfo)) + continue; + + areaKey = key; + result = info; + best = candidate; + bestFloorDistance = 0f; // boxes don't provide floor; treat as perfect fit if they win layer/type + } + foreach (var area in AreaCollisionTrees) + { + var coll = area.Value; + if (noY ? !coll.ContainsPoint(x, z) : !coll.ContainsPoint(x, y, z)) + continue; + + var key = area.Key; + var info = FindAreaInfo(key); + + var layer = info.Layer; + var type = info.AreaInfo.AreaType; + var candidate = (layer, type); + if (!IsValidLocation(info.AreaInfo)) + continue; + + if (IsZoneBetter(candidate, best)) + { + result = info; + best = candidate; + bestFloorDistance = coll.DistanceToFloor(x, y, z); + continue; + } + + // Final tie-breaker: same priority, prefer closest floor under (x,y,z) + if (candidate != best) // only check if same layer + continue; + + var dist = coll.DistanceToFloor(x, y, z); + if ((dist > bestFloorDistance)) + continue; + + areaKey = key; + result = info; + bestFloorDistance = dist; + } + + if (result is null) + { + System.Diagnostics.Debug.WriteLine($"Unable to place {x:R},{z:R}"); + return string.Empty; + } + + return GetPlaceName(result); + } + + private static string GetPlaceName(IAreaLayer result) + { + var ai = result.AreaInfo; + if (!string.IsNullOrWhiteSpace(ai.SubAreaName)) + return ai.SubAreaName; + if (!string.IsNullOrWhiteSpace(ai.MainAreaName)) + return ai.MainAreaName; + return ai.AreaName; // should never hit, filtered via quality check below + } + + private static bool IsValidLocation(FieldAreaInfo info) => + !string.IsNullOrWhiteSpace(info.SubAreaName) || !string.IsNullOrWhiteSpace(info.MainAreaName); + + private static bool IsZoneBetter((AreaLayer Layer, AreaType Type) candidate, (AreaLayer Layer, AreaType Type) best) + { + if (candidate.Layer is AreaLayer.BattleZone) + return false; // No wild encounters; don't care. + if (candidate.Type is AreaType.Room) + return false; // No wild encounters; don't care. + + if (candidate.Layer < best.Layer) + return false; + + if (candidate.Layer > best.Layer) + return true; + return candidate.Type > best.Type; + } +} + +public sealed record MultiAABBTree(string Name, HavokCollision.AABBTree Tree1) : IEnumerable +{ + public MultiAABBTree? Next { get; set; } + + public void Add(HavokCollision.AABBTree tree) + { + if (Next is null) + Next = new MultiAABBTree(Name, tree); + else + Next.Add(tree); + } + + public bool ContainsPoint(float x, float z) + { + if (Tree1.ContainsPoint(x, 100, z)) // drop floor of Y axis + return true; + if (Next is not null) + return Next.ContainsPoint(x, z); + return false; + } + + public bool ContainsPoint(float x, float y, float z) + { + if (Tree1.ContainsPointDirect(x, y + 1, z)) // don't drop floor of Y axis + return true; + if (Next is not null) + return Next.ContainsPoint(x, y, z); + return false; + } + + /// + /// Attempts to find the highest floor (LoY) beneath the given point across all chained trees. + /// + public bool TryGetFloorY(float x, float y, float z, out float floorY) + { + var found = Tree1.TryGetFloorY(x, y, z, out floorY); + + // check if any Next set found a better floor + if (Next is null) + return found; + if (!Next.TryGetFloorY(x, y, z, out var ny)) + return found; + if (found && !(ny > floorY)) + return found; + + // next found a better floor + floorY = ny; + found = true; + return found; + } + + /// + /// Returns the distance from y to the closest floor below (y - floorY). Returns PositiveInfinity if none found. + /// + public float DistanceToFloor(float x, float y, float z) + { + return TryGetFloorY(x, y, z, out var fy) ? (y - fy) : float.PositiveInfinity; + } + + public IEnumerator GetEnumerator() + { + yield return Tree1; + if (Next is null) + yield break; + foreach (var tree in Next) + yield return tree; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} + +public sealed record IntersectingTree +{ + // Displayed via Json reflection + public required AreaLayer Layer { get; init; } + public required string Name { get; init; } + public required bool Valid { get; init; } + public required AreaType Type { get; init; } + public required string PlaceName { get; init; } + public required int LocationID { get; init; } + public required string LocationName { get; init; } + + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public FieldAreaInfo AreaInfo { get; init; } = null!; + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public MultiAABBTree Collision { get; init; } = null!; + public string GetAreaInternal() => AreaInfo.AreaName; +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Info/MapTransform.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Info/MapTransform.cs new file mode 100644 index 00000000..c74261b9 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Info/MapTransform.cs @@ -0,0 +1,23 @@ +namespace pkNX.WinForms; + +public sealed record MapTransform(TransformScale Texture, TransformScale Range, TransformScale Scale, TransformScale Dir, TransformScale Offset) +{ + public double ConvertWidth(double s) => (Range.X / Scale.X) * s; + public double ConvertHeight(double s) => (Range.Z / Scale.Z) * s; + public double ConvertX(double x) => (Texture.X / 2) + (Dir.X * ((Range.X / Scale.X) * (x + Offset.X))); + public double ConvertZ(double z) => (Texture.Z / 2) + (Dir.Z * ((Range.Z / Scale.Z) * (z + Offset.Z))); + + public (float X, float Z) ScreenToWorld(double px, double pz, double controlWidth, double controlHeight) + { + var xTex = (px / controlWidth) * Texture.X; + var zTex = (pz / controlHeight) * Texture.Z; + var x = (((Texture.X / 2.0f) - xTex) * -Dir.X * (Scale.X / Range.X)) - Offset.X; + var z = (((Texture.Z / 2.0f) - zTex) * -Dir.Z * (Scale.Z / Range.Z)) - Offset.Z; + return ((float)x, (float)z); + } +} + +public readonly record struct TransformScale(double X, double Z) +{ + public static implicit operator TransformScale((double X, double Z) value) => new(value.X, value.Z); +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Info/SceneInfo9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Info/SceneInfo9a.cs new file mode 100644 index 00000000..2b4a002f --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Info/SceneInfo9a.cs @@ -0,0 +1,47 @@ +namespace pkNX.WinForms; + +public static class SceneInfo9a +{ + public static readonly string[] ScenePathsT1 = // Overworld Lumiose (e.g. Wild Areas and the canals/surface streets/building tops) + [ + "world/ik_scene/field/area/t1/sub_scene/t1_gimmick/t1_pokemon_spawner_/t1_pokemon_spawner_0.trscn", + + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0101_w01/t1_wild_a0101_w01_pokemon_spawner_/t1_wild_a0101_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0102_w01/t1_wild_a0102_w01_pokemon_spawner_/t1_wild_a0102_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0103_w01/t1_wild_a0103_w01_pokemon_spawner_/t1_wild_a0103_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0201_w01/t1_wild_a0201_w01_pokemon_spawner_/t1_wild_a0201_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0202_w01/t1_wild_a0202_w01_pokemon_spawner_/t1_wild_a0202_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0202_w02/t1_wild_a0202_w02_pokemon_spawner_/t1_wild_a0202_w02_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0203_w01/t1_wild_a0203_w01_pokemon_spawner_/t1_wild_a0203_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0301_w01/t1_wild_a0301_w01_pokemon_spawner_/t1_wild_a0301_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0301_w02/t1_wild_a0301_w02_pokemon_spawner_/t1_wild_a0301_w02_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0302_w01/t1_wild_a0302_w01_pokemon_spawner_/t1_wild_a0302_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0303_w01/t1_wild_a0303_w01_pokemon_spawner_/t1_wild_a0303_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0401_w01/t1_wild_a0401_w01_pokemon_spawner_/t1_wild_a0401_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0402_w01/t1_wild_a0402_w01_pokemon_spawner_/t1_wild_a0402_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0403_w01/t1_wild_a0403_w01_pokemon_spawner_/t1_wild_a0403_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0501_w01/t1_wild_a0501_w01_pokemon_spawner_/t1_wild_a0501_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0501_w02/t1_wild_a0501_w02_pokemon_spawner_/t1_wild_a0501_w02_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0502_w01/t1_wild_a0502_w01_pokemon_spawner_/t1_wild_a0502_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0502_w02/t1_wild_a0502_w02_pokemon_spawner_/t1_wild_a0502_w02_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0503_w01/t1_wild_a0503_w01_pokemon_spawner_/t1_wild_a0503_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0601_w01/t1_wild_a0601_w01_pokemon_spawner_/t1_wild_a0601_w01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0601_w01_v01/t1_wild_a0601_w01_v01_pokemon_spawner_/t1_wild_a0601_w01_v01_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0601_w01_v02/t1_wild_a0601_w01_v02_pokemon_spawner_/t1_wild_a0601_w01_v02_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t1/sub_scene/t1_zone/t1_wild_a0601_w01_v03/t1_wild_a0601_w01_v03_pokemon_spawner_/t1_wild_a0601_w01_v03_pokemon_spawner_0.trscn", + + "world/ik_scene/field/area/t1_i007a/sub_scene/t1_i007a_gimmick/t1_i007a_pokemon_spawner_/t1_i007a_pokemon_spawner_0.trscn", + ]; + + public static readonly string[] ScenePathsT2 = // Labs + [ + "world/ik_scene/field/area/t2/sub_scene/t2_gimmick/t2_pokemon_spawner_/t2_pokemon_spawner_0.trscn", + ]; + + + public static readonly string[] ScenePathsT3 = // Sewer + [ + "world/ik_scene/field/area/t3/sub_scene/t3_gimmick/t3_pokemon_spawner_/t3_pokemon_spawner_0.trscn", + "world/ik_scene/field/area/t3_2/sub_scene/t3_2_gimmick/t3_2_pokemon_spawner_/t3_2_pokemon_spawner_0.trscn", + ]; +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/Info/TransformUI9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/Info/TransformUI9a.cs new file mode 100644 index 00000000..2c433603 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/Info/TransformUI9a.cs @@ -0,0 +1,49 @@ +using System; + +namespace pkNX.WinForms; + +public static class TransformUI9a +{ + public static MapTransform GetMapTransform(LumioseFieldIndex index) => index switch + { + LumioseFieldIndex.Overworld => TransformLumiose, + LumioseFieldIndex.LysandreLabs => TransformLysandreLabs, + LumioseFieldIndex.SewersCh5 => TransformSewersCh5, + LumioseFieldIndex.SewersCh6 => TransformSewersCh6, + _ => throw new ArgumentOutOfRangeException(nameof(index)), + }; + + // Named transforms for each map index + // Instantiate transforms for each map index + public static readonly MapTransform TransformLumiose = new( + Texture: new(4096.0, 4096.0), + Range: new(3940.0, 3940.0), + Scale: new(1000.0, 1000.0), + Dir: new(-1.0, -1.0), + Offset: new(500.0, 500.0) + ); + + public static readonly MapTransform TransformLysandreLabs = new( + Texture: new(2160.0, 2160.0), + Range: new(1662.0, 2041.0), + Scale: new(1662.0 / 10.291021, 2041.0 / 10.291021), + Dir: new(-1.0, -1.0), + Offset: new(-3.0, -80.0) + ); + + public static readonly MapTransform TransformSewersCh5 = new( + Texture: new(2160.0, 2160.0), + Range: new(1364.0, 1975.0), + Scale: new(1364.0 / 6.2, 1975.0 / 6.2), + Dir: new(1.0, 1.0), + Offset: new(1.0, 146.0) + ); + + public static readonly MapTransform TransformSewersCh6 = new( + Texture: new(2160.0, 2160.0), + Range: new(1521.0, 1966.0), + Scale: new(1521.0 / 16.714285, 1966.0 / 16.714285), + Dir: new(1.0, 1.0), + Offset: new(39.0, 45.0) + ); +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/MapSpawnerSet.cs b/pkNX.WinForms/Subforms/Gen9a/Map/MapSpawnerSet.cs new file mode 100644 index 00000000..e89b1e00 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/MapSpawnerSet.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; +using pkNX.Structures.FlatBuffers.ZA; + +namespace pkNX.WinForms; + +public sealed class MapSpawnerSet +{ + public required Dictionary SpawnerInfo { get; init; } +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/SpawnRipper9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/SpawnRipper9a.cs new file mode 100644 index 00000000..f506ddb3 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/SpawnRipper9a.cs @@ -0,0 +1,1395 @@ +using pkNX.Game; +using pkNX.Structures.FlatBuffers; +using pkNX.Structures.FlatBuffers.ZA; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; + +namespace pkNX.WinForms; + +public sealed class SpawnRipper9a +{ + private readonly FlatBufferSource Game; + private readonly string _outDir; + + // Spawner Information + public readonly World9a AllMaps; + public readonly LumioseMap Overworld; + public const byte LocationLabs = 234; + public const byte LocationSewer = 235; + + public readonly SpawnNameResolver Resolver; + public readonly SpawnGlobalInfo Shared; + public readonly MapSpawnerSet RipInfo; + private readonly SpawnExporter Exporter; + + public List RippedMaps = []; + + public SpawnRipper9a(GameManager9a rom, string language, string outDir, World9a world) + { + AllMaps = world; + _outDir = outDir; + if (!Directory.Exists(_outDir) && Path.IsPathRooted(_outDir)) + Directory.CreateDirectory(_outDir); + + Game = new(rom); + Resolver = new(rom, language); + Shared = new(rom); + + Overworld = AllMaps.Overworld; + Exporter = new(_outDir) + { + GetLocationName = z => Resolver.LocationNames[z], + }; + RipInfo = new MapSpawnerSet + { + SpawnerInfo = GetLinkedSpawnerNames(Shared.SpawnerDatabase.Table), + }; + + FindAllPointsOnMaps(); + } + + public SpawnRipper9a(GameManager9a rom, string language, string outDir) : this(rom, language, outDir, new(rom)) { } + + private void FindAllPointsOnMaps() + { + RippedMaps.Add(SimulateScene(SceneInfo9a.ScenePathsT1, "t1", ManualPositionRip.GetLocation)); + RippedMaps.Add(SimulateScene(SceneInfo9a.ScenePathsT2, "t2", _ => LocationLabs)); + RippedMaps.Add(SimulateScene(SceneInfo9a.ScenePathsT3, "t3", _ => LocationSewer)); + } + + + public void DumpSceneToPickle(List rip) + { + var sets = rip.SelectMany(z => z.ToAreas()).ToArray(); + foreach (var set in sets) + set.CondenseList(); + + var path = Path.Combine(_outDir, "encounter_za.pkl"); + EncounterSlot9a.WritePickle(sets, path); + + // Write a concatenated array of slots for visual pattern inspection. + EncounterSlot9a.WritePickleWithoutLocations(sets.SelectMany(z => z.Slots), path); + } + + public void ExportRippedMaps() + { + List rip = []; + foreach (var map in RippedMaps) + { + // Iterate all points and populate our fake spawners with every result encounter. + var spawnIn = new SimulatedAreaSet(this); + spawnIn.Populate(map); + rip.Add(spawnIn); + + Exporter.ExportJson(spawnIn.Detailed, map.Name); + Exporter.ExportJson(spawnIn.ToAreas(), map.Name); + + var sp = map.SpawnerPositions; + var pt = sp.Select(z => PointDump.FromSpawner(z.Value, map.LocationNameFetch)).ToList(); + var text = string.Join(Environment.NewLine, ManualPositionRip.Export(pt)); + var path = Path.Combine(_outDir, $"{map.Name}_pt.txt"); + File.WriteAllText(path, text); + } + DumpSceneToPickle(rip); + Exporter.ExportJson(RippedMaps); + Exporter.ExportAll(this); + } + + private static Dictionary GetLinkedSpawnerNames(IEnumerable spawnerI) + { + var result = new Dictionary(); + foreach (var spawn in spawnerI) + { + foreach (var obj in spawn.Table) + { + foreach (var sub in obj.AppearanceSpawnerObjectInfoList) + result.Add(sub.ObjectName, obj); + } + } + return result; + } + + private int GetLocationFromOverworldMap(PackedVec3f arg) + { + var placeName = Overworld.GetPlaceName(arg.X, arg.Y, arg.Z, out _); + if (placeName is "") + return 0; + return Resolver.GetLocationIndex(placeName); + } + + private SpawnSceneSimulation SimulateScene(string[] scenePaths, string map, Func location) + { + var result = new SpawnSceneSimulation + { + Name = map, + Paths = scenePaths, + LocationNameFetch = location, + Game = Game, + }; + result.ScrapePoints(); + return result; + } + + 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 record PointDump +{ + public static PointDump FromSpawner(SceneSpawner sp, Func resolver) => new() + { + X = sp.Position.X, + Y = sp.Position.Y, + Z = sp.Position.Z, + Guess = resolver(sp.Position), + Name = sp.Name, + Type = sp.Type, + }; + + public required float X { get; init; } + public required float Y { get; init; } + public required float Z { get; init; } + public required int Guess { get; init; } + public required string Name { get; init; } + public required string Type { get; init; } + + public float DistanceTo(PackedVec3f other) => new PackedVec3f(X, Y, Z).DistanceTo(other); + public float DistanceTo(PointDump other) => new PackedVec3f(X, Y, Z).DistanceTo(new PackedVec3f(other.X, other.Y, other.Z)); +} + +public record ManualPosition(PackedVec3f Position, int Actual, int Guess); + +public static class ManualPositionRip +{ + public static List Manual = GetCoordinates(Import); + + private static List GetCoordinates(string import) + { + var result = new List(); + var lines = import.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); + foreach (var line in lines) + { + var parts = line.Split(',', StringSplitOptions.TrimEntries); + if (parts.Length != 5) + throw new FormatException($"Invalid line: {line}"); + var actual = int.Parse(parts[0]); + var guess = int.Parse(parts[1]); + var x = float.Parse(parts[2]); + var y = float.Parse(parts[3]); + var z = float.Parse(parts[4]); + var pos = new PackedVec3f(x, y, z); + result.Add(new ManualPosition(pos, actual, guess)); + } + + return result; + } + + public static IEnumerable Export(List points) + { + points.RemoveAll(z => z.X > -5f); + var ordered = OrderPoints(points); + ordered = TwoOpt(ordered); // refine + foreach (var pt in ordered) + yield return $"({pt.X:R}f, {pt.Y:R}f, {pt.Z}f, {pt.Guess:000}, \"{pt.Name}\", \"{pt.Type}\"),"; + } + + // Nearest Neighbor heuristic + public static List OrderPoints(List points) + { + var ordered = new List(); + var remaining = new HashSet(points); + + // Start at the first point + var current = points[0]; + ordered.Add(current); + remaining.Remove(current); + + while (remaining.Count > 0) + { + // Pick nearest neighbor + var next = remaining + .OrderBy(p => current.DistanceTo(p)) + .First(); + + ordered.Add(next); + remaining.Remove(next); + current = next; + } + + return ordered; + } + + // Optional: 2-opt refinement for better path + public static List TwoOpt(List path) + { + bool improved = true; + while (improved) + { + improved = false; + for (int i = 1; i < path.Count - 2; i++) + { + for (int j = i + 1; j < path.Count - 1; j++) + { + double d1 = path[i - 1].DistanceTo(path[i]) + path[j].DistanceTo(path[j + 1]); + double d2 = path[i - 1].DistanceTo(path[j]) + path[i].DistanceTo(path[j + 1]); + + if (d2 < d1) + { + path.Reverse(i, j - i + 1); + improved = true; + } + } + } + } + return path; + } + + public static int GetLocation(PackedVec3f pos) => Manual.MinBy(z => z.Position.DistanceTo(pos))!.Actual; + + private const string Import = """ +198, 198, -436.49307, 0.053550035, -573.49695 +198, 198, -415.6467, -3.291191, -563.68854 +198, 198, -418.441, 19.2004, -576.9063 +198, 198, -424.4425, 0.113318324, -592.0836 +198, 198, -437.45175, 0.14151679, -603.6813 +198, 198, -450.7321, 12.88028, -598.6775 +198, 198, -469.2205, 15.43618, -593.7524 +198, 198, -460.24335, -4.571766, -609.0784 +198, 198, -460.0753, -6.579818, -630.5808 +198, 198, -450.65567, -6.932743, -630.4142 +198, 198, -433.1807, -5.080095, -648.0021 +198, 198, -421.5417, 1.487759, -654.51807 +198, 198, -415.6606, 13.59257, -656.8047 +199, 199, -382.0111, 0.2324152, -663.26086 +199, 199, -365.4998, 0.24981685, -656.5547 +199, 199, -377.95786, -1.446644, -681.5765 +199, 199, -377.95786, -1.446644, -681.5765 +199, 199, -395.01993, 0.2227406, -680.2921 +199, 199, -387.3936, -1.4983622, -696.9576 +199, 199, -374.37375, -1.3242222, -718.8202 +199, 199, -357.1133, -1.324223, -724.2719 +199, 199, -332.53278, -1.324223, -706.23944 +199, 199, -359.35193, 2.4851353, -694.81464 +199, 199, -366.33582, -1.3225124, -673.00226 +199, 199, -366.33582, -1.3225124, -673.00226 +199, 199, -338.72903, -1.3242209, -674.252 +199, 199, -330.70242, -1.3242196, -689.0014 +043, 43, -286.03595, 19.23623, -697.3953 +043, 43, -262.8521, 29.15431, -662.0996 +043, 43, -262.8313, 29.08139, -662.0577 +043, 43, -273.01562, 32.27869, -654.5244 +043, 43, -299.56488, 18.59794, -646.0943 +043, 43, -289.40637, 2.7817826, -609.336 +043, 43, -309.00385, 27.808655, -589.90857 +043, 43, -309.08438, 27.808655, -589.90857 +043, 43, -309.38437, 27.808655, -589.90857 +043, 43, -314.73636, 5.1561203, -576.2222 +054, 54, -322.17972, 25.76465, -533.6763 +054, 54, -310.9538, 23.44651, -515.6079 +055, 55, -267.1104, 15.478579, -545.76404 +055, 55, -255.01208, 15.464759, -555.6548 +013, 13, -258.4067, 1.5, -588.963 +043, 43, -262.9566, 30.317593, -599.77423 +043, 43, -253.12706, 30.618273, -614.0333 +043, 43, -246.95174, 25.916769, -633.3873 +043, 43, -252.4176, 11.5, -644.8788 +043, 43, -230.66103, 16.921091, -670.10596 +043, 43, -225.95222, 16.93439, -671.6836 +044, 44, -213.9913, 5.635887, -652.0436 +043, 43, -212.7453, 23.44562, -626.937 +013, 13, -179.68794, 7.427531, -614.4534 +055, 55, -168.85136, 3.983619, -595.446 +201, 201, -144.43121, 21.783031, -584.7592 +201, 201, -136.02135, 21.783148, -585.1529 +201, 201, -123.79133, 21.836004, -566.0702 +201, 201, -137.05963, 1.4055421, -574.61896 +201, 201, -142.1108, 1.539107, -559.1307 +201, 201, -117.09781, 1.5645028, -552.7548 +201, 201, -96.745674, 17.911325, -565.23846 +201, 201, -96.745674, 17.911325, -565.23846 +201, 201, -88.51922, 15.602076, -551.16327 +201, 201, -87.74617, 15.59945, -551.2334 +201, 201, -73.78605, 15.59529, -558.60736 +201, 201, -73.06181, 15.59946, -558.88043 +201, 201, -75.89025, 15.60141, -576.5163 +201, 201, -75.928085, 15.596442, -577.1364 +201, 201, -53.006775, 24.00073, -581.54584 +201, 201, -68.630226, 1.403285, -595.5384 +201, 201, -79.97242, 23.999947, -612.77356 +201, 201, -68.96969, 23.999702, -608.5915 +201, 201, -69.492905, 24.013645, -612.3185 +201, 201, -59.669765, 23.999388, -618.91534 +036, 36, -47.593925, 7.4054236, -662.8398 +197, 197, -79.4974, 21.6021, -662.90405 +197, 197, -94.93474, 21.603077, -661.28076 +197, 197, -85.61398, 0.10283974, -674.1013 +197, 197, -94.66832, 0.110854425, -689.664 +197, 197, -97.482666, 0.110854425, -698.74493 +197, 197, -104.676895, 0.10601022, -704.6736 +197, 197, -113.69867, -1.8931999, -682.6562 +197, 197, -112.18329, 0.11575771, -660.57355 +197, 197, -131.14087, 23.92463, -668.85236 +197, 197, -153.4682, -1.890476, -679.49774 +197, 197, -158.98831, -1.890674, -669.51434 +197, 197, -186.73047, -1.473637, -660.4167 +197, 197, -169.98872, 5.833132, -663.7622 +197, 197, -140.95566, 1.521814, -652.3074 +197, 197, -145.01138, 19.284943, -638.22144 +197, 197, -150.67287, 19.295383, -633.0518 +197, 197, -167.8551, 5.65449, -645.79834 +197, 197, -183.03488, 21.84042, -649.48267 +197, 197, -182.98357, 21.844702, -657.51227 +197, 197, -187.2512, 21.851557, -663.2342 +045, 45, -204.186, 14.761297, -701.946 +045, 45, -193.655, 14.701405, -716.0358 +045, 45, -222.1099, 3.2242508, -712.8588 +045, 45, -242.33818, 19.32423, -721.08203 +045, 45, -257.49823, 5.7596736, -706.96545 +045, 45, -273.2931, 2.0183332, -739.9211 +045, 45, -272.28873, 1.9724181, -746.7478 +045, 45, -272.4066, 4.900545, -740.751 +045, 45, -288.5841, 19.440556, -731.02637 +045, 45, -291.95776, 21.758017, -759.22723 +034, 34, -321.9037, 5.7995796, -757.718 +040, 40, -349.9188, 20.14602, -771.527 +040, 40, -373.2985, 2.174772, -762.35016 +038, 38, -396.08856, 1.5294743, -767.8075 +196, 196, -415.3627, -0.45683333, -809.04266 +196, 196, -415.72647, -0.4568562, -814.86383 +196, 196, -410.28482, -0.4568692, -812.2233 +196, 196, -396.90494, -1.2660723, -828.78827 +196, 196, -406.9212, -1.2605963, -831.6445 +196, 196, -414.81195, -1.1460401, -840.3881 +196, 196, -431.9289, -1.2777712, -843.7723 +196, 196, -439.35876, -1.2630782, -838.4637 +196, 196, -437.29178, -0.8089979, -830.1864 +196, 196, -437.37286, -1.2661624, -822.0677 +196, 196, -450.9785, -1.1083586, -840.1668 +196, 196, -445.0118, -1.2577716, -860.46234 +196, 196, -454.92078, -1.3357357, -879.4537 +196, 196, -421.56033, -5.0200224, -863.9032 +196, 196, -415.408, -2.6339045, -873.99786 +039, 39, -427.82925, 17.222433, -900.3797 +039, 39, -441.5045, 19.221716, -910.4636 +041, 41, -436.1177, 17.506962, -925.7897 +041, 41, -414.53958, 3.782926, -911.1146 +196, 196, -375.3143, -5.0174413, -882.8643 +196, 196, -371.2664, -5.0096345, -873.3173 +196, 196, -383.8684, -5.0320616, -866.8816 +040, 40, -352.8605, 0, -854.8809 +040, 40, -328.8833, -5.0216074, -852.6286 +040, 40, -317.35086, 3.5201254, -879.5751 +041, 41, -306.88818, 21.30065, -882.81323 +040, 40, -304.5779, 0.15614605, -860.6346 +040, 40, -300.4652, -4.8248377, -840.2083 +040, 40, -305.12274, 2.8936915, -821.20734 +040, 40, -306.0247, 3.030923, -819.9156 +040, 40, -324.68143, 12.498132, -812.4358 +040, 40, -337.0234, 1.4675332, -818.96606 +039, 39, -382.86798, 20.685165, -811.4866 +039, 39, -375.18225, 15.14987, -805.355 +039, 39, -375.18225, 15.14987, -805.355 +040, 40, -353.15796, 14.825506, -798.42 +040, 40, -344.12943, -5.0265155, -786.7111 +040, 40, -342.332, -5.027344, -787.8901 +040, 40, -342.22058, -4.834983, -788.9366 +040, 40, -340.6502, -5.0273438, -790.24963 +040, 40, -338.26886, -5.024852, -791.1737 +040, 40, -302.69543, 15.383945, -802.1677 +040, 40, -288.04202, 17.667131, -828.1217 +046, 46, -265.3379, 3.1813624, -805.36316 +046, 46, -245.7228, 15.641821, -808.7034 +046, 46, -252.65393, 2.833399, -792.68 +046, 46, -249.24556, 2.8332875, -793.0565 +046, 46, -235.68622, 15.597906, -785.0089 +045, 45, -236.27742, 14.43672, -758.8571 +046, 46, -208.33267, 17.21393, -752.84454 +046, 46, -200.7536, 2.8362963, -763.3757 +047, 47, -170.22421, 19.377611, -750.4393 +047, 47, -161.47589, 19.376198, -760.65814 +047, 47, -142.34052, 0.32581767, -746.1937 +047, 47, -144.02429, 0.336877, -746.2578 +047, 47, -146.01962, 0.4686557, -743.4532 +197, 197, -124.35263, 21.607708, -699.3221 +197, 197, -105.584145, 19.282307, -717.94073 +197, 197, -96.51411, 19.281727, -715.9309 +036, 36, -78.08053, 7.419309, -730.6168 +047, 47, -115.5731, 16.99921, -747.95685 +047, 47, -153.37952, 19.37568, -770.70447 +046, 46, -168.23592, 2.8416293, -794.4768 +046, 46, -208.93173, 7.6089644, -805.0601 +046, 46, -227.9088, 15.362843, -831.446 +046, 46, -221.10522, 15.362827, -842.3767 +046, 46, -220.95786, 17.693401, -862.1948 +036, 36, -202.303, 4.3614736, -898.62213 +041, 41, -247.65225, 17.117393, -885.2769 +041, 41, -258.8069, 15.648184, -884.96967 +035, 35, -281.09177, 7.422904, -925.6754 +041, 41, -292.906, 15.006688, -908.1622 +041, 41, -298.7453, -4.9460864, -894.75885 +041, 41, -304.5671, -4.932153, -900.29175 +041, 41, -318.3035, -1.519055, -904.0894 +041, 41, -321.55054, 17.141912, -923.966 +041, 41, -323.49667, 17.136015, -917.9264 +041, 41, -334.64508, 20.563654, -912.4587 +041, 41, -348.54086, 20.023268, -908.47955 +040, 40, -345.94778, 3.745554, -895.8925 +040, 40, -345.94778, 3.745554, -895.8925 +041, 41, -342.61334, 1.238483, -915.6075 +041, 41, -342.17328, 17.13539, -928.4568 +041, 41, -381.88977, 1.4882333, -928.6873 +041, 41, -393.007, 1.6, -929.8372 +041, 41, -386.31903, 12.7161045, -942.0782 +041, 41, -393.36966, 12.715927, -944.0611 +041, 41, -424.09955, 1.6, -937.1403 +041, 41, -450.7644, 16.719864, -951.2682 +041, 41, -462.3969, 1.6, -941.3291 +041, 41, -478.51086, 17.48342, -927.06696 +012, 12, -492.53888, 7.559636, -951.6976 +012, 12, -503.86832, 7.622027, -959.8831 +194, 194, -518.1671, 13.362688, -951.6115 +194, 194, -534.24286, 0.312, -952.3106 +194, 194, -541.03375, 13.391792, -936.3197 +031, 31, -541.0495, 18.26497, -916.4832 +031, 31, -545.1324, 18.31736, -916.0195 +031, 31, -546.8103, 0.3, -904.3467 +031, 31, -568.26556, 16.35868, -914.4067 +194, 194, -575.0439, 22.341629, -934.6345 +194, 194, -585.6353, 22.07217, -935.9479 +194, 194, -586.84735, 22.09378, -938.1483 +194, 194, -575.6059, 0.2, -959.94684 +194, 194, -581.627, 0.2, -956.702 +194, 194, -597.33704, 0.452636, -946.2914 +194, 194, -610.404, 0.2, -959.5748 +194, 194, -618.855, 0.241, -955.253 +194, 194, -621.673, -0.123, -946.262 +194, 194, -602.9927, 0.20430177, -939.5055 +194, 194, -602.78986, 2.4400458E-06, -931.37036 +031, 31, -593.2308, 16.235691, -912.3518 +031, 31, -592.04974, 16.22654, -896.6685 +031, 31, -580.1772, 0.9901935, -899.87744 +031, 31, -578.8307, 0.1935585, -898.80896 +031, 31, -570.4394, -4.1, -895.2193 +031, 31, -563.2971, -4.248385, -880.93146 +031, 31, -560.1993, -4.6687903, -856.2932 +031, 31, -546.265, -3.6968865, -855.64404 +031, 31, -534.48, 12.79127, -875.76514 +031, 31, -533.5247, 12.79127, -874.7391 +031, 31, -513.753, 0.3, -885.10583 +031, 31, -525.2515, 0.30089298, -900.14435 +031, 31, -525.1657, 0.30150518, -901.0148 +031, 31, -525.99963, 0.30171886, -901.6119 +031, 31, -526.74915, 0.30100137, -900.9702 +031, 31, -526.64557, 0.30137748, -900.2346 +031, 31, -516.8685, 16.209, -895.4986 +039, 39, -480.3366, 17.38358, -901.9344 +039, 39, -480.6365, 17.48225, -887.5674 +039, 39, -480.24258, 17.48225, -882.768 +039, 39, -480.4549, 17.26929, -877.42816 +039, 39, -480.1531, 17.38358, -868.7341 +039, 39, -480.789, 17.38358, -864.285 +039, 39, -480.66843, 17.38358, -855.6935 +031, 31, -515.02625, 16.57381, -841.0704 +031, 31, -519.105, 16.52411, -834.5059 +031, 31, -524.2077, 16.57393, -833.7924 +031, 31, -523.8612, 16.574083, -831.9415 +012, 12, -507.4835, 7.713086, -814.6774 +039, 39, -478.04504, 14.90571, -804.159 +196, 196, -450.54874, -1.3365003, -809.57587 +039, 39, -440.8488, 10.288585, -788.73975 +039, 39, -442.22397, 10.287881, -788.74677 +038, 38, -450.0652, 3.9440875, -782.539 +038, 38, -465.0541, 16.123226, -764.76056 +028, 28, -513.5421, 14.43305, -754.00476 +028, 28, -518.98517, 14.43305, -755.4226 +028, 28, -518.961, 14.580638, -743.0317 +028, 28, -513.432, 14.580638, -738.099 +028, 28, -522.8078, 14.580638, -735.6502 +028, 28, -538.08545, 20.52162, -730.0595 +028, 28, -549.463, 20.371521, -724.90546 +028, 28, -542.3692, 0.15584096, -739.3582 +028, 28, -546.6448, 0.1580935, -752.11957 +028, 28, -552.194, 0.15751025, -756.0387 +028, 28, -546.3313, 0.16481161, -759.2451 +028, 28, -540.717, 0.164109, -755.3888 +028, 28, -541.5185, 16.98347, -783.6002 +028, 28, -547.15063, 0.3, -787.5279 +028, 28, -552.5117, 0.3, -791.0126 +028, 28, -566.4843, 12.3606415, -797.4114 +028, 28, -566.3632, 12.376762, -807.6714 +028, 28, -583.75665, 4.041861, -791.4021 +029, 29, -596.1716, 13.458905, -779.3648 +029, 29, -606.17804, 0.1618239, -796.4077 +029, 29, -595.849, 0.978, -801.84 +029, 29, -596.88995, 0.1496122, -813.9021 +031, 31, -566.24896, 18.322136, -824.8412 +031, 31, -575.8083, 18.39812, -859.8461 +030, 30, -598.33234, 16.11472, -872.75934 +029, 29, -599.3008, 14.527241, -842.9815 +029, 29, -613.86676, 22.321651, -812.6485 +029, 29, -628.67926, 16.070604, -817.0898 +029, 29, -633.56586, 16.07161, -809.1702 +029, 29, -630.5372, 13.930426, -806.4757 +029, 29, -634.066, 3.030468, -778.50116 +029, 29, -642.2288, 13.92397, -757.6052 +029, 29, -611.03174, 18.134396, -746.1614 +028, 28, -593.8663, 8.211622, -735.6991 +028, 28, -576.6349, 18.51936, -721.1066 +028, 28, -572.6117, 18.680927, -715.4457 +028, 27, -549.8323, 0.3, -706.6898 +027, 27, -539.9563, 14.477622, -690.2589 +027, 27, -514.8118, 18.918724, -659.25934 +027, 27, -513.31396, 16.645702, -674.7025 +027, 27, -517.073, 16.645222, -676.9202 +028, 28, -540.5354, -0.0006413531, -701.4871 +028, 28, -533.3722, 0.3, -711.804 +012, 12, -506.45557, 7.577606, -703.4408 +012, 12, -489.6219, 7.714674, -685.8691 +037, 37, -464.73264, -6.200384, -676.862 +038, 38, -461.23212, 1.66903, -703.2106 +038, 38, -455.54108, 4.835745, -701.652 +038, 38, -468.2832, 20.774448, -707.69495 +038, 38, -471.77985, 18.61173, -737.4282 +038, 38, -472.02777, 21.89691, -741.8488 +038, 38, -476.9239, 18.61173, -742.27 +038, 38, -462.6201, 2.6194277, -754.47705 +038, 38, -461.51163, 2.6194277, -755.80035 +038, 38, -418.30338, 15.355397, -763.9573 +038, 38, -413.77713, 15.34032, -758.4497 +038, 38, -436.35, 4.3599977, -727.4808 +038, 38, -426.7861, 16.706629, -707.1496 +198, 198, -442.0581, 15.905443, -664.6455 +198, 198, -429.8964, 11.471686, -635.4598 +198, 198, -420.4837, 4, -612.379 +198, 198, -402.70807, 0.25645322, -610.684 +198, 198, -371.569, 1.969228, -615.0104 +198, 198, -371.28918, 2.37213, -610.0234 +198, 198, -369.6849, 2.1733701, -602.2526 +198, 198, -385.8152, 20, -573.1413 +198, 198, -377.134, 19.75823, -557.72437 +054, 54, -367.0882, 0.3, -531.5695 +054, 54, -372.506, 26.937597, -520.6188 +054, 54, -391.81274, 15.923169, -502.4209 +212, 212, -457.78177, 0.15, -515.3074 +212, 212, -457.78177, 0.15, -515.3074 +212, 212, -457.78177, 0.15, -515.3074 +212, 212, -457.78177, 0.15, -515.3074 +212, 212, -479.9531, 1.47, -539.7094 +212, 212, -479.9531, 1.47, -539.7094 +212, 212, -479.9531, 1.47, -539.7094 +212, 212, -479.9531, 1.47, -539.7094 +212, 212, -505.23108, -1.0198169, -499.9066 +212, 212, -500.0511, -1.0198169, -499.9066 +212, 212, -500.0511, -1.0198169, -499.9066 +212, 212, -500.0511, -1.0198169, -499.9066 +212, 212, -492.44614, -1.0198169, -499.9066 +212, 212, -461.802, 0.15, -481.5595 +212, 212, -461.802, 0.15, -481.5595 +212, 212, -461.802, 0.15, -481.5595 +212, 212, -461.802, 0.4320028, -481.5595 +212, 212, -474.63855, 0.44309872, -463.2214 +212, 212, -474.63855, 0.15, -463.2214 +212, 212, -474.63855, 0.15, -463.2214 +212, 212, -474.63855, 0.15, -463.2214 +212, 212, -509.1811, 0.5, -459.6664 +212, 212, -509.1811, 0.5, -459.6664 +212, 212, -509.1811, 0.5, -459.6664 +212, 212, -509.1811, 0.5, -459.6664 +212, 212, -541.3076, 0.5, -478.8282 +212, 212, -541.3076, 0.5, -478.8282 +212, 212, -541.3076, 0.5, -478.8282 +212, 212, -541.3076, 0.5, -478.8282 +212, 212, -558.713, 0.155, -467.225 +085, 85, -590.7906, 0.2674167, -431.83374 +085, 85, -616.2855, 3.9192736, -423.95947 +085, 85, -616.53174, 6.991074, -415.4471 +086, 86, -645.7379, 25.956345, -422.1317 +086, 86, -656.7048, 6.123087, -407.4549 +086, 86, -636.1718, 28.320766, -376.09818 +086, 86, -623.1806, 28.461264, -378.82553 +086, 86, -622.29333, 28.327168, -359.07916 +087, 87, -648.2416, 28.91756, -343.70294 +087, 87, -657.1884, 28.915632, -341.563 +087, 87, -653.5164, 25.398283, -334.63596 +087, 87, -644.8152, 27.239635, -328.9497 +015, 15, -599.8794, 0.1493426, -363.0221 +015, 15, -564.5529, 0.1568958, -411.415 +015, 15, -542.4196, 7.594155, -421.41458 +075, 75, -545.7656, 19.291525, -404.67953 +075, 216, -545.0929, 10.265976, -387.96783 +075, 216, -545.0929, 10.265976, -387.96783 +075, 75, -536.6177, 11.433445, -387.31625 +075, 75, -536.8106, 10.265976, -380.45944 +075, 216, -528.4611, 10.265976, -372.8261 +075, 216, -528.4611, 10.265976, -372.8261 +075, 75, -519.41254, 17.260221, -354.12537 +075, 75, -546.53, 19.454334, -353.7949 +075, 75, -575.7995, 10.265976, -344.6486 +075, 75, -586.6599, 15.668894, -345.7225 +076, 76, -586.5218, 9, -331.4405 +076, 76, -568.1168, 4.5408463, -316.34317 +075, 75, -537.1566, 20.047688, -322.7141 +206, 206, -515.30597, 0.1632412, -293.8569 +206, 206, -527.1445, 0.1632412, -290.2637 +206, 206, -526.13074, 0.1677322, -277.3595 +206, 206, -530.8832, 0.14424342, -262.4771 +206, 206, -521.7371, 0.14424342, -262.4132 +206, 206, -505.85327, 0.16744648, -266.632 +206, 206, -493.9106, 0.14424342, -266.3078 +206, 206, -494.6988, 0.14424342, -257.7809 +206, 206, -499.8032, 0.23609853, -262.4771 +206, 206, -500.01, 0.14262128, -262.24753 +206, 206, -505.88354, 0.15518348, -257.89584 +206, 206, -510.0297, 0.17103006, -236.96147 +206, 206, -523.0755, 0.16337536, -232.86401 +080, 80, -529.8306, 7.607343, -209.55168 +077, 77, -531.29425, 0.1440723, -185.7334 +205, 205, -523.8661, 0.142, -150.83893 +205, 205, -523.8661, 0.142, -147.0758 +205, 205, -541.2463, 0.14199452, -146.5025 +205, 205, -554.559, 0.14200231, -141.6722 +205, 78, -559.9139, 0.14091028, -152.09644 +205, 205, -567.8556, 0.12387186, -147.0291 +205, 205, -567.8556, 0.12387186, -147.0291 +205, 205, -567.8556, 0.12387186, -145.58325 +205, 205, -568.5355, 0.14691785, -128.87785 +205, 205, -564.3571, 0.13848421, -111.58162 +205, 205, -561.5171, 0.10754927, -108.4962 +205, 205, -567.22, 0.14200258, -105.2099 +205, 205, -575.8585, 0.1382617, -105.8719 +205, 205, -582.65027, 0.57921624, -108.96786 +205, 205, -587.3942, 0.14200252, -101.22609 +205, 205, -599.068, 0.47945476, -133.675 +205, 205, -601.5515, 0.11085006, -142.12375 +205, 205, -592.1047, 0.14201003, -149.1526 +205, 205, -592.1047, 0.14201003, -149.1526 +077, 77, -596.46814, 1.6839098, -167.73439 +077, 77, -577.5175, 5.957127, -169.6367 +077, 77, -551.6217, 16.5, -175.3818 +077, 77, -559.993, 18.217672, -200.51765 +077, 77, -567.4041, 18.67152, -228.43907 +076, 76, -601.8332, 17.073677, -245.40312 +077, 77, -587.86334, 16.195156, -222.16956 +077, 77, -575.059, 0.16432494, -205.23328 +077, 77, -579.6168, 27.556925, -182.573 +077, 77, -593.56647, 27.472813, -187.7275 +077, 77, -611.0755, 21.334948, -185.40422 +077, 77, -628.716, 0.1631956, -169.9681 +077, 77, -629.18243, 0.2728719, -169.6451 +205, 205, -628.3925, 0.14199452, -151.5657 +205, 205, -617.3007, 0.1420032, -142.034 +079, 79, -657.6277, 25.886225, -120.90715 +077, 77, -646.89777, 5.733079, -169.44861 +077, 77, -658.6438, 0.15672731, -206.32254 +077, 77, -687.8489, 18.6, -205.1035 +079, 79, -680.5945, 23.754808, -152.5749 +079, 79, -715.0624, 22.94313, -156.07428 +079, 79, -710.92957, 25.21151, -129.65807 +079, 79, -712.6678, 25.210556, -124.462364 +079, 79, -732.4718, 0.14085966, -121.342804 +079, 79, -727.19867, 0.14963374, -131.97162 +079, 79, -739.5284, 25.21163, -141.71436 +015, 15, -754.721, 0.15341204, -149.0981 +015, 15, -727.6874, 0.15341204, -185.9972 +089, 89, -740.8385, 19.76089, -197.48796 +089, 89, -727.12695, 3.182387, -214.8762 +089, 89, -730.988, 11.95226, -252.35518 +089, 89, -732.94, 0.15278628, -250.11478 +089, 89, -750.1995, 2.3111343, -252.5769 +089, 89, -749.148, 0.1566269, -237.97946 +089, 89, -762.32916, 19.74044, -244.73715 +089, 89, -762.3802, 19.740337, -249.569 +089, 89, -767.665, 23.262754, -251.8608 +089, 89, -773.3959, 19.693659, -250.41814 +089, 89, -764.3059, 19.741135, -229.9284 +089, 89, -782.2358, 0.15146606, -234.3884 +089, 89, -781.9814, 1.219401, -237.56502 +089, 89, -784.50226, 0.16111504, -243.55847 +090, 90, -790.7302, 4.882915, -253.9093 +208, 208, -803.0239, 5.5125113, -276.0806 +208, 208, -816.3831, 5.8877044, -273.2349 +208, 208, -835.1235, 5.851436, -269.22977 +208, 208, -841.97504, 8.065287, -284.3202 +208, 208, -827.7217, 10.345472, -290.301 +208, 208, -816.23346, 8.482858, -294.2021 +208, 208, -812.8249, 8.850368, -312.0203 +208, 208, -837.5829, 12.005853, -311.3865 +208, 208, -837.5829, 12.005853, -311.3865 +208, 208, -836.889, 12.024765, -309.62125 +208, 208, -837.168, 11.40024, -309.2614 +208, 208, -849.4729, 9.677533, -302.9281 +208, 208, -861.7444, 8.514413, -315.00934 +208, 208, -866.03784, 8.754953, -330.78192 +208, 208, -852.5195, 10.331965, -328.9032 +208, 208, -839.28766, 10.35757, -338.0364 +082, 82, -819.9581, 27.887213, -356.84714 +082, 82, -795.6435, 30.261, -352.0465 +082, 82, -800.95416, 19.597, -379.3563 +082, 82, -800.446, 19.597, -379.484 +088, 88, -783.51105, 12.121502, -367.50458 +088, 88, -775.5274, 12.12041, -371.27213 +088, 88, -779.1544, 12.152735, -346.70193 +088, 88, -767.77795, 6.1217656, -339.6477 +088, 88, -768.412, 6.1229177, -329.60242 +090, 90, -791.2985, 26.137222, -317.49857 +090, 90, -785.1301, 26.289682, -319.3395 +090, 90, -779.94025, 26.137917, -321.37204 +088, 88, -771.6627, 28.008255, -331.8364 +088, 88, -759.48785, 25.680737, -343.89227 +088, 88, -750.8709, 18.807873, -312.7223 +088, 88, -745.27277, 18.807941, -314.7243 +088, 88, -740.2382, 22.22573, -303.1267 +089, 89, -727.506, 3.984026, -284.3506 +087, 87, -692.2868, 19.010803, -277.8099 +087, 87, -692.0522, 18.969803, -277.8187 +087, 87, -679.3676, 20.747192, -280.342 +087, 87, -688.2274, 1, -303.44235 +087, 87, -686.7252, 0, -303.91254 +087, 87, -673.7761, 3.9863324, -308.3199 +087, 87, -674.0831, 1, -317.0174 +087, 87, -672.4958, 0.005060276, -328.07785 +087, 87, -686.2793, 0, -326.5136 +087, 87, -688.8361, 1, -321.53452 +087, 87, -712.9109, 21.193321, -318.28732 +088, 88, -730.3009, 0.30291483, -310.5963 +088, 88, -734.3098, 6.1242704, -340.60797 +088, 88, -707.67706, 6.122446, -349.8023 +088, 88, -715.7577, 25.090124, -359.68338 +088, 88, -720.2447, 25.08413, -357.89075 +088, 88, -719.32294, 25.084757, -354.23166 +088, 88, -724.9837, 25.089954, -357.18066 +211, 211, -734.3048, 12.3, -403.72568 +211, 211, -742.31665, 12.3, -430.7365 +211, 211, -730.3349, 12.02, -418.9196 +211, 211, -730.3349, 12.02, -418.9196 +211, 211, -730.3349, 12.02, -418.9196 +211, 211, -730.3349, 12.02, -418.9196 +211, 211, -730.3349, 12.02, -418.9196 +211, 211, -729.08, 12.3, -420.0334 +211, 211, -715.2521, 12.3, -422.8596 +211, 211, -712.3095, 12.018108, -422.8596 +086, 86, -671.39276, 25.953423, -401.1714 +086, 86, -667.20337, 25.952608, -417.4868 +081, 81, -665.086, 13.26179, -433.84744 +081, 81, -658.3753, 6.950434, -443.36517 +081, 81, -669.3402, 13.25892, -446.03973 +081, 81, -666.88916, 14.899103, -447.03745 +091, 91, -666.63153, 28.222538, -456.6295 +091, 91, -671.953, 24.688967, -459.6098 +091, 91, -675.0998, 11.92948, -478.43274 +091, 91, -661.7796, 22.677177, -494.01447 +091, 91, -645.4558, 2.8859348, -488.44113 +091, 91, -642.775, 3.0065424, -481.77493 +091, 91, -635.97565, 2.8859348, -484.20413 +091, 91, -624.2281, 16.864815, -484.39865 +091, 91, -622.3832, 17.15964, -482.7892 +091, 91, -616.8134, 16.863642, -488.89777 +092, 92, -626.3987, 2.88672, -503.0465 +011, 11, -585.316, 0.004, -502.934 +212, 212, -541.7012, 0.019755347, -509.2261 +212, 212, -542.393, 0.5, -514.9189 +212, 212, -542.393, 0.5, -514.9189 +212, 212, -542.393, 0.5, -514.9189 +212, 212, -532.10785, 1.154498, -535.7166 +212, 212, -529.30194, 1.154498, -539.8976 +212, 212, -529.30194, 1.154498, -539.8976 +212, 212, -529.30194, 1.154498, -539.8976 +212, 212, -515.07404, 1.154498, -542.9277 +212, 212, -515.07404, 1.154498, -542.9277 +212, 212, -515.07404, 1.154498, -542.9277 +212, 212, -515.07404, 1.154498, -542.9277 +027, 27, -511.28906, 16.002882, -594.3894 +027, 27, -516.65643, 16.00318, -596.95135 +027, 27, -524.67236, 4.5383153, -607.94965 +027, 27, -560.66876, 15.692097, -631.07056 +017, 17, -586.12726, 0.003152345, -621.32227 +017, 17, -577.0205, 0.0033238872, -606.4584 +017, 17, -572.6253, 0.003199535, -598.6294 +017, 17, -572.2136, 0.0012577148, -598.6326 +017, 17, -562.1136, -0.008685261, -585.0804 +021, 21, -594.0128, 16.599257, -573.15344 +021, 21, -584.2496, 14.22143, -570.12445 +021, 21, -577.2863, 16.597609, -558.66046 +021, 21, -584.57715, 16.591858, -548.3049 +021, 21, -604.7284, 16.591812, -558.92993 +021, 21, -625.1262, 1.4676656, -553.3824 +021, 21, -627.02936, 19.938726, -563.0725 +021, 21, -628.5096, 19.9354, -567.0581 +021, 21, -628.2071, 0.3960507, -584.0901 +021, 21, -613.4425, 0.27635238, -593.2502 +021, 21, -610.2355, 0.2563012, -591.9881 +021, 21, -615.5666, 15.150184, -601.4503 +021, 21, -622.8188, 15.100024, -607.02374 +195, 195, -638.739, -0.063578986, -628.54706 +195, 195, -631.80426, -1.7434797, -638.9217 +195, 195, -631.80426, -1.7434797, -638.9217 +195, 195, -610.1002, -1.7743438, -646.897 +195, 195, -610.1002, -1.7743438, -646.897 +195, 195, -595.675, 0.09715712, -646.989 +195, 195, -579.3757, -0.06343725, -669.10223 +195, 195, -595.9076, -1.773599, -679.4624 +195, 195, -595.9076, -1.773599, -679.4624 +195, 195, -587.92584, 0.07, -699.8498 +195, 195, -602.5127, -1.7714028, -699.3604 +195, 195, -602.5127, -1.7714028, -699.3604 +195, 195, -613.39667, 0.02768034, -719.6455 +195, 195, -627.81134, -1.0417038, -706.164 +195, 195, -618.918, -1.0417038, -702.52045 +195, 195, -626.4797, 2.7996366, -676.73694 +195, 195, -641.7521, 0, -683.147 +195, 195, -659.21216, -1.773453, -702.5976 +195, 195, -659.21216, -1.773453, -702.5976 +195, 195, -667.4258, -0.06430818, -705.60046 +195, 195, -667.4258, -0.06430818, -705.60046 +195, 195, -665.60815, -1.772849, -680.9472 +195, 195, -665.60815, -1.772849, -680.9472 +195, 195, -644.9461, -1.0417038, -653.58 +195, 195, -654.0212, -1.0417038, -656.607 +195, 195, -676.3301, -0.06530342, -659.0754 +022, 22, -691.6953, 14.866914, -633.3018 +022, 22, -717.95105, 27.327301, -621.34503 +022, 22, -714.2216, 27.39702, -619.8514 +021, 21, -682.8949, 17.889954, -580.91425 +021, 21, -681.8032, 17.887444, -576.3238 +021, 21, -671.038, 19.93876, -577.549 +021, 21, -646.2761, 0.15079094, -594.88245 +021, 21, -645.6793, 0.25283328, -585.7482 +021, 21, -653.8427, 0.15031837, -585.45123 +016, 16, -670.0173, -5.696914, -542.8859 +016, 16, -686.6589, -5.697324, -549.9587 +092, 92, -689.1364, 5.929931, -526.3904 +091, 91, -702.52844, 21.570019, -518.3827 +091, 91, -706.73114, 21.508717, -524.867 +093, 93, -718.4135, 6.361183, -508.7051 +091, 91, -714.9724, 31.699179, -488.65567 +091, 91, -711.74, 31.336477, -485.857 +091, 91, -708.2646, 31.337908, -486.73593 +091, 91, -710.8749, 31.333448, -478.6988 +091, 91, -716.5649, 31.333559, -480.92612 +093, 93, -732.47125, 25.172935, -485.42462 +093, 93, -742.736, 25.1672, -489.47452 +093, 93, -735.2956, 25.200922, -477.51624 +093, 93, -745.0691, 25.171377, -475.37228 +093, 93, -774.5265, 31.053297, -464.88425 +093, 93, -777.69305, 27.51251, -462.12732 +093, 93, -767.4598, 27.579422, -457.01944 +094, 94, -781.8815, 31.856993, -415.2969 +094, 94, -829.4607, 32.383034, -408.2471 +094, 94, -833.81805, 32.392643, -421.98685 +094, 94, -857.4337, 18.121439, -407.69672 +094, 94, -863.2777, 32.38866, -394.5474 +082, 82, -848.6132, 20.961817, -375.20044 +082, 82, -852.9417, 27.081102, -357.01505 +082, 82, -864.4035, 12.118988, -346.05975 +082, 86, -868.7935, 12.120337, -353.3589 +082, 82, -869.124, 12.119233, -359.06863 +082, 82, -884.7262, 12.206078, -366.8624 +082, 82, -893.2098, 9.819473, -363.4224 +082, 82, -907.4021, 6.0092955, -358.93112 +096, 96, -904.8656, 38, -390.446 +096, 96, -884.80426, 29.622557, -394.4732 +094, 94, -874.2686, 18.12112, -397.89038 +094, 94, -879.66565, 18.12051, -413.27097 +096, 96, -895.7682, 31.40954, -421.09488 +094, 94, -867.7713, 26.5, -443.4597 +094, 94, -865.69684, 32.38216, -452.58752 +094, 94, -861.6298, 26.39159, -460.48633 +094, 94, -879.2234, 31.812384, -472.08337 +094, 94, -871.9806, 31.821466, -478.0746 +094, 94, -877.3857, 29.544146, -487.48456 +094, 94, -868.7082, 29.5441, -494.3016 +094, 94, -863.18805, 34.95951, -517.0504 +094, 94, -866.09, 34.95969, -523.45905 +094, 94, -860.8417, 17.997496, -545.1214 +094, 94, -841.77893, 17.952782, -527.8831 +094, 94, -833.1746, 18.4, -513.7616 +094, 94, -826.81445, 23.899055, -507.39795 +094, 94, -833.5892, 29.845745, -489.45026 +093, 93, -792.7494, 23, -501.4701 +093, 93, -785.00073, 22.733442, -499.17902 +093, 93, -790.94904, 22.73121, -513.0743 +093, 93, -743.0754, 22.443913, -538.38617 +092, 92, -713.18176, -4.077637, -548.6959 +022, 22, -720.3919, 5.780088, -585.3254 +022, 22, -755.49164, 5.2177286, -606.0858 +022, 22, -766.31287, 5.2176065, -610.00806 +022, 22, -767.3057, 3.1783953, -597.0926 +016, 16, -777.3508, -5.6860056, -574.31946 +016, 16, -783.5877, -5.6860056, -550.50275 +092, 92, -783.0193, -2.624262, -536.11774 +093, 93, -796.77856, 9.971833, -531.9439 +095, 95, -803.5598, 20.455849, -551.97906 +095, 95, -801, 19.781363, -558 +210, 210, -810.4279, -5.69997, -576.22797 +210, 210, -807.8695, -5.698603, -593.2402 +210, 16, -815.0799, -5.694185, -601.0153 +210, 210, -820.8909, -5.691393, -605.13416 +210, 210, -830.17847, -5.4948626, -593.0994 +210, 210, -831.26697, -0.8346319, -579.7957 +210, 210, -832.8592, 0.6682889, -565.9009 +210, 210, -837.876, 0.100099236, -569.5969 +210, 210, -850.8661, -0.7040277, -575.3474 +210, 210, -863.046, 0, -580.133 +097, 93, -894.79333, 7.2787156, -596.89215 +209, 209, -914.8885, 1.5041946, -589.72174 +209, 209, -916.13983, 1.5080476, -578.5286 +209, 97, -930.5046, -5.695506, -581.3396 +209, 209, -926.4533, -5.695489, -594.2373 +016, 16, -920.2338, -5.2, -621.0335 +024, 24, -909.39307, -2.8542004, -639.968 +210, 210, -882.7686, -5.4948626, -608.4708 +210, 16, -882.781, -5.699441, -621.03534 +210, 210, -879.99347, -5.6937604, -621.1793 +210, 210, -874.91974, -5.520567, -632.8537 +024, 24, -895.6987, 1.4650941, -654.1455 +024, 24, -917.9216, 1.4675726, -660.29785 +024, 24, -880.0562, 6.276864, -685.24 +024, 24, -856.0948, 1.5781132, -657.4748 +024, 24, -846.2874, 1.9061773, -654.7769 +210, 210, -840.09143, -2.9160156, -641.83 +210, 210, -851.0163, -5.348221, -628.2429 +210, 210, -859.952, -5.6937604, -617.8118 +210, 210, -858.03174, -5.4948626, -605.1479 +210, 16, -843.05255, -5.697912, -614.244 +210, 210, -839.6779, -5.6947794, -613.804 +210, 210, -832.86255, -5.5496325, -622.99976 +210, 210, -805.02026, -5.6990976, -621.2947 +210, 210, -793.1719, -2.7514179, -625.8112 +024, 24, -813.9235, 11.705788, -652.5524 +024, 24, -830.077, 6.277, -671.976 +024, 24, -845.624, 6.3781147, -690.79706 +024, 24, -811.18463, 6.278435, -690.8233 +024, 24, -804.2697, 16.56101, -714.0974 +025, 25, -792.0646, 17.1026, -735.5884 +025, 25, -785.2017, 17.102959, -740.3717 +024, 24, -797.368, 5.36348, -714.1707 +023, 6, -771.58795, -5.527122, -692.50793 +022, 22, -750.29865, 5.218656, -658.40295 +022, 22, -737.54364, 5.218141, -658.70483 +022, 22, -731.68256, 25.008175, -654.3761 +022, 22, -721.9812, 25.180319, -657.9936 +022, 22, -719.1521, 34.73738, -667.091 +022, 22, -717.00824, 34.139088, -674.26685 +022, 22, -725.8054, 23.206276, -672.7771 +022, 22, -729.0921, 23.206139, -681.7978 +022, 22, -725.9532, 5.365872, -685.0275 +022, 22, -724.8764, 5.365872, -688.0071 +022, 22, -692.23883, 20.33208, -728.31903 +022, 22, -704.80927, 20.325857, -742.7174 +023, 6, -736.82715, -5.692833, -756.3341 +025, 25, -762.0114, 0.0029645334, -783.55145 +025, 25, -755.568, 0.0029144476, -789.54205 +025, 25, -748.12305, 17.93558, -778.5645 +025, 25, -749.1003, 18.483934, -804.93604 +025, 25, -740.0003, 18.3079, -810.57275 +030, 30, -711.81274, 14.150298, -813.8167 +030, 30, -704.3329, 12.152962, -797.15985 +030, 30, -700.0967, 12.153003, -800.5082 +030, 30, -697.6376, 0.02418779, -813.7903 +029, 29, -685.5467, 0.31856066, -801.878 +029, 29, -663.5179, -5.0053673, -793.69763 +029, 29, -657.84595, 5.779393, -810.82886 +030, 30, -680.1064, 15.615301, -820.6064 +030, 30, -688.2699, 17.564873, -823.0538 +030, 30, -705.43665, 27.8116, -842.4502 +030, 30, -709.79443, 27.810848, -848.924 +030, 30, -694.5104, 17.400644, -852.0669 +030, 30, -629.65497, 0.94771415, -882.50964 +030, 30, -614.1562, 0.15725297, -875.39026 +031, 31, -590.2987, 0.3, -884.1716 +030, 30, -616.48834, 0.1569412, -890.3148 +030, 30, -637.05884, 16.615112, -891.8674 +030, 30, -638.3157, 16.617275, -895.2673 +030, 30, -656.22876, 18.93855, -932.3254 +194, 194, -659.20807, 0.1484837, -947.3228 +194, 194, -659.2081, 0.1484837, -947.3228 +194, 194, -673.964, 0.13, -941.4958 +194, 194, -673.964, 0.13, -941.4958 +030, 30, -700.00446, 13.91225, -914.9721 +030, 30, -693.0479, 0.1675936, -888.8876 +030, 30, -693.0479, 0.1675936, -888.8876 +030, 30, -717.4949, 0.0030184875, -881.2986 +030, 30, -739.3459, 18.06275, -854.16644 +030, 30, -754.52026, 20.14939, -868.7883 +030, 30, -761.1849, 15.342972, -878.9799 +025, 25, -781.39923, 10.452387, -866.5173 +025, 25, -779.0406, 14.953762, -858.4279 +193, 193, -774.44257, 0.182375, -832.19135 +193, 193, -760.7057, 0.18041055, -826.3315 +193, 193, -772.7378, 0.18178345, -822.2657 +193, 193, -779.3051, 19.497458, -789.1444 +193, 193, -775.64014, 19.495327, -776.6087 +193, 193, -774.7549, 19.501358, -776.7604 +193, 193, -764.0951, 17.22518, -773.59283 +193, 193, -764.14154, 17.22963, -773.57166 +193, 193, -794.7666, 5.236941, -772.72406 +193, 193, -794.7666, 5.236941, -772.72406 +193, 193, -794.7666, 5.236941, -772.72406 +193, 193, -794.7666, 5.236941, -772.72406 +193, 193, -796.2637, 5.2181187, -773.12994 +025, 25, -822.0745, 17.558718, -789.62054 +025, 25, -803.9559, 17.72604, -829.8746 +025, 25, -796.4446, 17.727577, -835.9146 +025, 25, -793.74603, 18.55919, -847.1246 +025, 25, -826.1276, 17.714558, -823.10596 +025, 25, -845.0035, 20.866041, -806.5674 +006, 6, -889.6226, 5.9285755, -822.66736 +024, 24, -865.1313, 16.005865, -766.7104 +024, 24, -869.95074, 16.071, -761.56036 +024, 24, -874.77795, 0.15096436, -753.1709 +024, 24, -879.26556, 0.15093887, -748.6891 +024, 24, -868.8728, 18.656128, -709.7323 +024, 24, -873.38916, 16.654087, -714.45483 +024, 24, -891.8268, 5.365208, -723.29626 +019, 19, -913.9525, 7.580545, -716.7966 +024, 24, -919.0105, 13.518816, -689.61053 +024, 24, -925.0036, 13.516235, -678.6399 +024, 24, -927.0975, 15.838404, -666.8224 +016, 16, -953.6292, 0.85, -637.8823 +016, 16, -956.1894, 0.85, -629.7689 +097, 97, -943.0605, 24, -598.2548 +097, 97, -944.08167, 23, -595.3843 +209, 209, -915.5142, 30.880136, -564.5125 +209, 209, -903.6403, 30.878426, -574.1333 +209, 209, -895.6614, 30.880726, -571.08075 +209, 209, -905.03564, 30.880379, -560.1855 +095, 95, -906.2317, 11.61139, -552.3723 +094, 94, -901.2362, 19.74388, -540.325 +094, 94, -898.4361, 19.527565, -532.45557 +209, 209, -919.79144, 23.754793, -543.7757 +209, 209, -939.68835, 23.88732, -531.56256 +209, 209, -922.27924, 1.5003066, -566.4279 +209, 209, -929.6727, -4.843723, -559.57416 +209, 209, -939.36633, -4.8410134, -553.6292 +209, 209, -943.99536, -4.8482046, -563.6221 +209, 209, -965.5322, 0.15260212, -559.1427 +209, 209, -978.12646, 0.152195, -538.63696 +209, 209, -979.33344, 0.1517358, -513.8006 +209, 209, -976.9339, 0.15181814, -500.61636 +209, 209, -950.567, 0.24161567, -506.16254 +096, 96, -923.1203, 5.829481, -499.0733 +094, 94, -900.7894, 17.899908, -492.06064 +096, 96, -924.2882, 6.469924, -476.2327 +209, 209, -953.7761, 15.584611, -472.6889 +097, 97, -946.9294, 0.4240656, -454.91486 +084, 84, -947.3641, 0.24184048, -444.46426 +096, 96, -951.27783, 22.48262, -438.56558 +096, 96, -933.55133, 22.622375, -439.83713 +096, 96, -917.57745, 31.946898, -465.45477 +096, 96, -912.7172, 8.12677, -445.5099 +096, 96, -921.50757, 9.955005, -399.17242 +084, 84, -948.2054, 0.49383944, -399.2482 +082, 82, -958.6201, 7.574949, -359.8804 +082, 82, -935.4478, 0.15179925, -370.5106 +082, 82, -926.4124, 11.92317, -368.56732 +082, 82, -924.8113, 18.75929, -327.43893 +090, 90, -892.2092, 17.40808, -261.4777 +090, 90, -873.50366, 17.461021, -262.40833 +090, 90, -879.49677, 17.459463, -257.08234 +090, 90, -886.40454, 17.574276, -252.4251 +083, 83, -880.3366, 7.617012, -221.05223 +207, 207, -850.8886, 0.15656346, -187.21323 +207, 207, -858.269, 0.16273677, -180.2777 +207, 207, -837.8342, 0.15228097, -169.5926 +207, 207, -837.50525, 0.15153126, -163.1532 +207, 207, -828.74786, 0.17731091, -159.0954 +207, 207, -825.1478, 0.2198727, -151.11942 +207, 207, -820.38, -0.00033742285, -154.50359 +207, 207, -816.06, 0.1558229, -165.28944 +207, 207, -814.0015, 0.29999778, -168.09056 +207, 207, -815.6548, 0.30000025, -169.36922 +207, 207, -810.1938, 0.2164208, -172.47299 +207, 207, -809.4201, 0.3, -174.37953 +207, 207, -817.2682, 0.2999983, -172.86127 +207, 207, -820.961, 0.15351415, -177.6828 +207, 207, -825.3735, 0.3, -179.98013 +207, 207, -829.3954, 0.15249212, -181.24846 +207, 207, -819.4222, 0.151758, -189.07097 +207, 207, -819.61847, 0.16635543, -191.6509 +089, 89, -832.4525, 20.291985, -200.0325 +089, 89, -821.277, 5.460296, -220.6952 +089, 89, -811.0948, 19.742384, -230.41899 +089, 89, -801.0445, 21.382334, -204.80865 +089, 89, -784.9748, 21.38863, -200.0103 +089, 89, -794.137, 24.905819, -194.8226 +207, 207, -798.9529, 21.376942, -163.6489 +207, 207, -814.249, -0.00033742285, -135.8096 +079, 79, -723.71875, 25.294285, -99.30398 +079, 79, -705.5965, 26.02024, -92.52155 +079, 79, -697.6579, 26.056562, -99.14774 +069, 69, -682.05615, 7.570192, -67.49576 +079, 79, -661.15796, 12.930454, -70.404 +069, 69, -619.72766, 1.1098356, -27.83598 +069, 69, -603.9368, 0.7028214, -24.739925 +079, 79, -614.59985, 25.24528, -56.20018 +079, 79, -615.1914, 25.587854, -56.42654 +079, 79, -613.2792, 6.002089, -78.3779 +079, 79, -594.7126, 16, -74.031685 +079, 79, -590.72205, 15.24834, -61.429646 +079, 79, -594.93384, 15.068696, -61.36564 +079, 79, -594.9091, 15.370276, -49.30568 +079, 79, -568.40564, 17.732733, -47.60769 +069, 69, -565.1521, 7.5136104, -35.49284 +079, 79, -546.7414, 19.93981, -43.202164 +079, 79, -543.7692, 17.732733, -71.87796 +079, 79, -516.8872, 15.352933, -60.70821 +067, 67, -507.0906, 4.646632, -19.354397 +074, 74, -471.5195, 19.876156, -44.38076 +204, 204, -424.59018, 0.15044932, -25.163519 +204, 204, -401.57257, 0.15022741, -28.548365 +204, 204, -399.41248, 0.1377164, -30.137867 +204, 204, -399.34543, 0.14565878, -30.38186 +204, 204, -410.15353, 0.1520518, -46.964825 +204, 204, -410.15353, 0.1520518, -46.964825 +074, 74, -400.18552, 3.3323627, -80.93609 +074, 74, -375.9288, 1.601451, -80.32025 +074, 74, -374.06924, 19.924631, -71.41057 +204, 204, -369.2654, 0.13948321, -57.13841 +204, 204, -369.2654, 0.13948321, -57.13841 +204, 204, -386.09613, 0.14273863, -55.83812 +204, 204, -386.09613, 0.14273863, -55.83812 +204, 203, -391.81467, 0.14243536, -52.640133 +204, 204, -379.77557, 0.15034258, -33.871014 +204, 204, -363.18442, 0.21175456, -39.601685 +074, 74, -342.33002, 0.14278811, -96.53931 +072, 72, -325.8758, 15.396044, -111.876785 +072, 72, -347.44363, 15.620305, -122.574135 +072, 72, -348.61407, 15.626485, -123.08553 +072, 72, -335.17587, 15.5544, -145.4002 +071, 71, -334.88873, 0.1418888, -163.94585 +072, 72, -362.0172, 15.399015, -162.05847 +072, 72, -395.3647, 15.58198, -183.9022 +072, 72, -388.4815, 15.655398, -222.3199 +071, 71, -370.46304, 20.298492, -246.60608 +071, 71, -345.1197, 20.115467, -256.53146 +071, 71, -385.28186, 4.2387843, -290.1911 +070, 70, -394.2613, 20.785946, -314.5132 +014, 14, -354.9741, 0.1520214, -300.21957 +060, 60, -323.48877, 20.835709, -294.7906 +060, 60, -310.62326, 15.993875, -277.9254 +071, 71, -340.2679, 20.29506, -224.6862 +071, 71, -320.9247, 23.502699, -217.5881 +071, 71, -314.01166, 26.931, -164.2464 +071, 71, -300.7006, 23.227232, -156.37125 +071, 71, -288.54886, 18.838245, -165.55748 +071, 71, -292.70853, 0.14030388, -160.1178 +071, 71, -292.70853, 0.14030388, -160.1178 +071, 71, -292.70853, 0.14030388, -160.1178 +071, 71, -278.28265, 0.3244393, -117.8852 +071, 71, -277.9027, 0.2687649, -117.358925 +071, 71, -287.3369, 18.903158, -103.7773 +071, 71, -293.242, 18.901825, -100.073685 +071, 71, -314.8927, 27.358282, -80.47659 +068, 68, -263.45898, 7.569899, -84.01389 +014, 14, -234.4748, 7.604145, -114.4589 +071, 71, -248.07744, 22.227428, -120.17594 +014, 14, -247.6977, 0.11488077, -151.5825 +064, 64, -244.99347, 25.528978, -194.11197 +202, 202, -208.12854, 0.0017473609, -184.6323 +202, 202, -181.6602, 0.2547056, -167.7859 +202, 202, -181.57814, 0.14896901, -167.3247 +202, 202, -174.808, 0.248, -160.47136 +202, 202, -194.56255, 26.260014, -156.0447 +202, 202, -191.2787, 19.629929, -177.67651 +202, 202, -191.2787, 19.629929, -177.67651 +202, 202, -190.4805, 19.630203, -177.8194 +202, 202, -190.47792, 19.632042, -177.90501 +064, 64, -193.29741, 1.0380695, -216.84688 +064, 64, -165.53282, 0.14441578, -221.9648 +064, 64, -162.3003, 0.16749397, -219.67871 +064, 64, -149.78125, 0.14441578, -224.8443 +053, 53, -133.39455, 7.5605283, -209.56184 +064, 64, -134.273, 19.208395, -226.8111 +064, 64, -159.43561, 24.180727, -235.306 +063, 63, -124.0236, 27.807608, -252.13661 +063, 63, -146.1064, 24.325747, -274.72003 +063, 63, -154.953, 1.9691647, -281.2485 +063, 63, -166.84769, 24.535372, -282.0737 +064, 64, -175.3716, 17.20533, -260.02463 +064, 64, -172.33109, 0.14441578, -239.1807 +061, 61, -206.81491, 25.376139, -242.8257 +061, 61, -220.57794, 25.374874, -262.73996 +061, 61, -208.91174, 0.13540918, -273.51752 +061, 61, -223.2453, 0.13540918, -295.30826 +061, 61, -213.83678, 0.3936885, -294.79553 +061, 61, -191.5719, 19.854132, -297.82077 +061, 61, -224.74617, 19.840775, -315.9101 +061, 61, -195.28375, 32.725777, -333.5652 +063, 63, -138.35593, 17.500801, -338.5747 +061, 61, -192.4491, 4.526347, -350.7723 +061, 61, -202.66805, 0.60650384, -351.57803 +061, 61, -202.69191, 0.60650384, -351.5955 +060, 60, -234.62, 23.360697, -357.27652 +060, 60, -241.244, 23.64608, -351.0685 +060, 60, -236.03595, 23.233398, -336.7746 +060, 60, -256.3966, 23.984869, -330.7697 +060, 60, -267.4983, 0.27190694, -318.1724 +060, 60, -274.7993, 27.806908, -334.46564 +060, 60, -291.57114, 27.890318, -321.2972 +060, 60, -294.2001, 27.042387, -340.31943 +060, 60, -283.70563, 23.231638, -353.84372 +060, 60, -268.0961, 23.507078, -353.8988 +060, 60, -279.9686, 0.0023109699, -346.57254 +203, 203, -268.61996, 0.3007334, -395.972 +203, 203, -278.27786, 0.27225703, -404.13083 +203, 203, -277.9549, 0.15198354, -427.6336 +203, 203, -277.9549, 0.35, -427.6336 +203, 203, -277.9549, 0.35, -427.6336 +203, 203, -277.9549, 0.35, -427.6336 +203, 203, -276.13315, 0.28941756, -427.8864 +203, 203, -277.88242, 9.392027, -427.8508 +203, 203, -277.88528, 9.457367, -427.8015 +203, 203, -252.02153, 0.29245293, -448.2534 +055, 55, -209.55019, 18.91692, -438.188 +057, 57, -194.47598, 5.992203, -429.32068 +051, 51, -198.796, 1.1829, -383.05002 +061, 61, -185.39072, 17.738716, -363.469 +051, 51, -173.09227, 4.567314, -372.40927 +051, 51, -169.88837, -4.6930904, -377.93643 +051, 51, -170.83531, -5.4709253, -393.7728 +057, 57, -148.5403, 17.015362, -418.53134 +057, 57, -142.8562, 3.2015371, -441.99295 +057, 57, -132.6152, 0.007900189, -483.68118 +057, 57, -135.12225, 0.007900189, -486.37 +057, 57, -121.91718, 3.0727391, -488.3461 +057, 57, -140.32143, 19.44675, -463.7196 +057, 57, -140.32143, 19.44675, -463.7196 +057, 57, -123.74199, 19.341864, -429.5226 +057, 57, -118.6141, 19.52497, -437.9413 +057, 57, -105.103676, 31.73022, -462.5752 +057, 57, -84.39295, 31.978224, -483.7872 +200, 200, -84.532715, 0.16, -452.3264 +200, 200, -67.47989, 5, -439.8151 +200, 200, -78.66753, 5, -413.19724 +200, 200, -82.17556, 0.1411619, -413.62097 +200, 200, -92.874596, 0.16, -419.34564 +200, 200, -95.932175, 0.13486712, -420.7799 +200, 200, -101.7485, 0.16, -422.0644 +051, 51, -123.91185, 1.131965, -388.4311 +051, 51, -134.60263, -5.197735, -380.27008 +051, 51, -122.948, 1.2698841, -358.3963 +051, 51, -99.38546, -4.953873, -370.4685 +063, 63, -103.95356, 19.660477, -337.09882 +063, 63, -104.75575, 19.659382, -327.9457 +063, 63, -90.260895, 17.32649, -334.6056 +063, 63, -97.72606, 0.5327309, -319.77774 +063, 63, -103.296295, 27.828733, -305.76382 +063, 63, -105.71426, 27.839386, -296.9996 +063, 63, -96.194466, 27.990164, -293.7842 +063, 63, -93.50706, 27.828459, -301.96436 +053, 53, -69.14683, 7.562212, -286.6352 +053, 53, -44.17, 0.1500177, -322.313 +200, 200, -57.13415, 0.16, -388.0632 +200, 200, -56.483067, 0.19181605, -390.84793 +200, 200, -67.6063, 0.16, -407.5764 +200, 200, -64.0925, 0.14133641, -409.0656 +052, 52, -34.15146, 7.405001, -430.9276 +200, 200, -43.78214, 0.16, -438.73184 +200, 200, -67.47989, -2.2079873, -439.8151 +200, 200, -64.47137, 0.16, -442.83295 +200, 200, -64.47137, 0.16, -442.83447 +200, 200, -64.38969, 0.14189515, -443.8342 +200, 200, -53.07425, 0.16, -470.16483 +057, 57, -47.12625, 19.56764, -489.58423 +057, 57, -46.39899, 19.56764, -489.7047 +057, 57, -46.318268, 19.56764, -489.58423 +052, 52, -20.39056, 7.55375, -529.7445 +201, 201, -49.614555, 26.32112, -544.24 +201, 201, -62.819042, 1.3998259, -560.5039 +201, 201, -65.46984, 0.1469257, -523.6021 +057, 57, -87.73488, 26.32303, -513.6406 +057, 57, -107.7692, 31.74181, -500.3733 +057, 57, -107.8893, 31.754894, -500.319 +057, 57, -107.93051, 31.754894, -500.4292 +201, 201, -149.27042, 25.782537, -546.5008 +055, 55, -191.68, 0.14057958, -530.7417 +055, 55, -197.27367, 15.656371, -523.05054 +055, 55, -189.51021, 0.1403522, -508.3274 +055, 55, -201.59918, 21.262573, -492.7771 +057, 57, -179.26216, 24.802517, -483.90692 +055, 55, -205.46573, 16.587423, -454.14902 +055, 57, -213.7282, 0.16169524, -468.23373 +055, 55, -238.9872, 5.6095624, -478.2424 +055, 55, -231.73695, 3.9713006, -497.98236 +055, 55, -241.99399, 15.467599, -509.92206 +055, 55, -242.81895, 15.462746, -515.45715 +055, 55, -253.4855, 15.46291, -509.317 +055, 55, -273.644, 13.385, -503.55246 +055, 55, -274.3744, 8.743682, -485.00003 +065, 65, -294.24817, 5.9184976, -474.98782 +054, 54, -315.1442, 21.24025, -482.73572 +054, 54, -334.2291, 0.13550541, -500.50507 +054, 54, -334.1401, 0.13550541, -501.44473 +054, 54, -375.9615, 5.4594865, -488.6362 +054, 54, -347.0353, 18.80028, -482.7866 +054, 54, -320.86423, 16.530159, -469.51715 +203, 203, -296.31888, 0.27225703, -447.2837 +059, 59, -343.32538, 15.44828, -417.29327 +059, 59, -341.1888, 15.403247, -406.77252 +059, 59, -333.47537, 15.449966, -399.3898 +060, 60, -313.97437, 26.06629, -371.09015 +060, 60, -310.3512, 26.066282, -370.81876 +060, 60, -343.87613, 26.080667, -332.506 +059, 59, -387.6381, 23.45343, -386.1327 +059, 59, -376.76627, 17.85066, -413.15125 +059, 59, -359.6174, 5.752217, -433.6925 +050, 50, -365.42108, -5.3281765, -456.5827 +059, 59, -398.30353, 24.98, -409.49942 +014, 14, -427.1138, 0.06205024, -399.54007 +066, 66, -490.7718, 7.628335, -372.1721 +070, 70, -479.084, 20.109472, -356.7551 +070, 70, -484.4857, 17.78315, -335.5543 +070, 70, -470.982, 17.781294, -325.7623 +070, 70, -461.9635, 15.461093, -321.0924 +080, 80, -452.79037, 7.575359, -300.8072 +206, 206, -469.11316, 0.1492374, -285.5858 +206, 206, -489.8163, 0.17606416, -295.24954 +206, 206, -484.6586, 0.2325921, -285.2422 +206, 206, -472.88644, 1.4575319, -262.3028 +206, 206, -484.5136, 0.14755927, -239.74991 +206, 206, -489.65347, 0.17230487, -229.1426 +206, 206, -468.9759, 0.14755927, -238.90694 +206, 206, -470.49692, 28.323246, -262.2668 +070, 70, -437.1663, 18.481367, -291.9483 +070, 70, -422.26794, 18.481197, -303.09598 +070, 70, -413.11017, 1.701935, -288.1963 +070, 70, -412.0199, 0.14801389, -288.6267 +070, 70, -405.062, 23.500029, -264.7225 +070, 70, -405.8543, 2.6341317, -257.28476 +070, 70, -409.8231, 0.4254148, -259.73395 +070, 70, -421.7305, 4.172991, -261.5267 +070, 70, -429.9722, 18.432514, -235.8708 +070, 70, -430.91046, 18.436342, -234.4223 +070, 70, -432.0375, 18.432514, -231.5954 +070, 70, -425.3025, 5.907047, -213.2134 +073, 73, -437.9457, 24, -193.94487 +073, 73, -468.62744, 24.630943, -197.002 +073, 73, -460.79666, 26.60265, -167.3956 +073, 73, -424.89017, 18.68194, -148.4062 +073, 73, -409.0955, 17.62059, -144.59929 +073, 73, -414.01083, 17.61835, -142.2771 +073, 73, -436.18973, 19.356428, -141.76978 +073, 73, -450.0574, 19.35643, -141.75517 +074, 74, -463.4695, 5.279024, -133.78212 +073, 73, -478.6617, 24.806454, -142.68454 +074, 74, -474.3518, 19.87578, -116.6822 +074, 74, -480.0169, 19.876781, -116.5886 +074, 74, -480.4805, 19.87578, -115.796524 +067, 67, -499.892, 0.44626266, -98.27879 +067, 9, -500.0229, 0.4017878, -98.33713 +205, 205, -517.9244, 0.110404626, -95.05955 +205, 205, -521.11707, 0.108854204, -104.1026 +205, 205, -532.5488, 0.14200252, -116.12237 +205, 205, -531.9558, 0.14200272, -135.252 +205, 205, -542.0148, 0.10868632, -131.8714 +205, 205, -541.4237, 0.142, -126.173 +205, 205, -549.4777, 0.14200306, -119.2947 +205, 205, -536.0783, 0.1422626, -111.27025 +205, 205, -535.15924, 0.10868632, -111.1376 +205, 205, -536.0783, 0.1422626, -96.3953 +"""; +} diff --git a/pkNX.WinForms/Subforms/Gen9a/Map/World9a.cs b/pkNX.WinForms/Subforms/Gen9a/Map/World9a.cs new file mode 100644 index 00000000..79ef6577 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/Map/World9a.cs @@ -0,0 +1,63 @@ +using System; +using FlatSharp; +using pkNX.Game; +using pkNX.Structures.FlatBuffers; +using pkNX.Structures.FlatBuffers.ZA; + +namespace pkNX.WinForms; + +public class World9a +{ + // New: explicit map instances for 4 maps (0..3) + public readonly LumioseMap Overworld; + public readonly LumioseMap Labs; + public readonly LumioseMap Sewer1; + public readonly LumioseMap Sewer2; + + public World9a(GameManager9a rom) + { + // Map 0: load data + Overworld = new LumioseMap( + Get(rom, "world/ik_data/field/area/field_main_area/field_main_area_array.bin").Table, + Get(rom, "world/ik_data/field/area/field_sub_area/field_sub_area_array.bin").Table, + Get(rom, "world/ik_data/field/area/field_battle_zone/field_battle_zone_array.bin").Table, + Get(rom, "world/ik_data/field/area/field_wild_zone/field_wild_zone_array.bin").Table, + Get(rom, "world/ik_data/field/area/field_scene_area/field_scene_area_array.bin").Table, + Get(rom, "world/ik_data/field/area/field_location/field_location_array.bin").Table + ); + Overworld.LoadScenes(rom, ScenesT1); + + Labs = new LumioseMap([], [], [], [], [], []); + Sewer1 = new LumioseMap([], [], [], [], [], []); + Sewer2 = new LumioseMap([], [], [], [], [], []); + } + + public LumioseMap GetMap(int index) => index switch + { + 0 => Overworld, + 1 => Labs, + 2 => Sewer1, + 3 => Sewer2, + _ => throw new ArgumentOutOfRangeException(nameof(index)), + }; + + private static T Get(GameManager9a rom, string path) where T : class, IFlatBufferSerializable + => FlatBufferConverter.DeserializeFrom(rom.GetPackedFile(path)); + + private static readonly string[] ScenesT1 = + [ + // Order scenes so that the collision check finds the inner ones first -- might have some overlaps in main map? + "world/ik_scene/field/area/t1/sub_scene/t1_zone/area_collision_/area_collision_0.trscn", // zones (wild, battle) + "world/ik_scene/field/area/t1/sub_scene/t1_field_area_/t1_field_area_0.trscn", // general map + + // Others, implicitly visited via recursion from the main scene. + // "world/ik_scene/field/area/t1/sub_scene/t1_zone/area_collision/area_col_a0102_b01_/area_col_a0102_b01_0.trscn", + // "world/ik_scene/field/area/t1/sub_scene/t1_zone/area_collision/area_col_a0102_b02_/area_col_a0102_b02_0.trscn", + // "world/ik_scene/field/area/t1/sub_scene/t1_zone/area_collision/area_col_a0202_w01_01_/area_col_a0202_w01_01_0.trscn", + // "world/ik_scene/field/area/t1/sub_scene/t1_zone/area_collision/area_col_a0202_w01_02_/area_col_a0202_w01_02_0.trscn", + // "world/ik_scene/field/area/t1/sub_scene/t1_zone/area_collision/area_col_a0502_w01_01_/area_col_a0502_w01_01_0.trscn", + // "world/ik_scene/field/area/t1/sub_scene/t1_zone/area_collision/area_col_a0502_w01_02_/area_col_a0502_w01_02_0.trscn", + ]; +} + +// Concrete implementation for current ZA map handling diff --git a/pkNX.WinForms/Subforms/Gen9a/MapViewer9a.Designer.cs b/pkNX.WinForms/Subforms/Gen9a/MapViewer9a.Designer.cs new file mode 100644 index 00000000..7227bb40 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/MapViewer9a.Designer.cs @@ -0,0 +1,261 @@ +namespace pkNX.WinForms.Subforms +{ + partial class MapViewer9a + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + PB_Map = new System.Windows.Forms.PictureBox(); + CB_AreaIndex = new System.Windows.Forms.ComboBox(); + CB_Map = new System.Windows.Forms.ComboBox(); + CB_Species = new System.Windows.Forms.ComboBox(); + L_SpeciesFilter = new System.Windows.Forms.Label(); + B_ExportSpawnsToClipboard = new System.Windows.Forms.Button(); + TB_ObjectName = new System.Windows.Forms.TextBox(); + L_FilterName = new System.Windows.Forms.Label(); + L_PointName = new System.Windows.Forms.Label(); + TB_PointName = new System.Windows.Forms.TextBox(); + CHK_ExportImages = new System.Windows.Forms.CheckBox(); + B_ExportImage = new System.Windows.Forms.Button(); + NUD_CollisionTransparency = new System.Windows.Forms.NumericUpDown(); + label1 = new System.Windows.Forms.Label(); + RTB_Analysis = new System.Windows.Forms.RichTextBox(); + ((System.ComponentModel.ISupportInitialize)PB_Map).BeginInit(); + ((System.ComponentModel.ISupportInitialize)NUD_CollisionTransparency).BeginInit(); + SuspendLayout(); + // + // PB_Map + // + PB_Map.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; + PB_Map.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + PB_Map.Location = new System.Drawing.Point(0, 0); + PB_Map.Margin = new System.Windows.Forms.Padding(0); + PB_Map.Name = "PB_Map"; + PB_Map.Size = new System.Drawing.Size(512, 512); + PB_Map.TabIndex = 0; + PB_Map.TabStop = false; + PB_Map.MouseMove += Map_MouseMove; + // + // CB_AreaIndex + // + CB_AreaIndex.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + CB_AreaIndex.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; + CB_AreaIndex.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + CB_AreaIndex.DropDownWidth = 300; + CB_AreaIndex.FormattingEnabled = true; + CB_AreaIndex.Location = new System.Drawing.Point(516, 33); + CB_AreaIndex.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_AreaIndex.Name = "CB_AreaIndex"; + CB_AreaIndex.Size = new System.Drawing.Size(296, 25); + CB_AreaIndex.TabIndex = 1; + CB_AreaIndex.SelectedIndexChanged += ChangeAreaIndex; + // + // CB_Map + // + CB_Map.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + CB_Map.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + CB_Map.FormattingEnabled = true; + CB_Map.Location = new System.Drawing.Point(516, 0); + CB_Map.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_Map.Name = "CB_Map"; + CB_Map.Size = new System.Drawing.Size(140, 25); + CB_Map.TabIndex = 2; + CB_Map.SelectedIndexChanged += ChangeMap; + // + // CB_Species + // + CB_Species.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + CB_Species.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; + CB_Species.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + CB_Species.DropDownWidth = 300; + CB_Species.FormattingEnabled = true; + CB_Species.Location = new System.Drawing.Point(517, 109); + CB_Species.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_Species.Name = "CB_Species"; + CB_Species.Size = new System.Drawing.Size(295, 25); + CB_Species.TabIndex = 3; + CB_Species.SelectedValueChanged += ChangeSpawnFilter; + // + // L_SpeciesFilter + // + L_SpeciesFilter.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + L_SpeciesFilter.AutoSize = true; + L_SpeciesFilter.Location = new System.Drawing.Point(517, 89); + L_SpeciesFilter.Name = "L_SpeciesFilter"; + L_SpeciesFilter.Size = new System.Drawing.Size(55, 17); + L_SpeciesFilter.TabIndex = 4; + L_SpeciesFilter.Text = "Species:"; + // + // B_ExportSpawnsToClipboard + // + B_ExportSpawnsToClipboard.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; + B_ExportSpawnsToClipboard.Location = new System.Drawing.Point(664, 437); + B_ExportSpawnsToClipboard.Name = "B_ExportSpawnsToClipboard"; + B_ExportSpawnsToClipboard.Size = new System.Drawing.Size(148, 75); + B_ExportSpawnsToClipboard.TabIndex = 5; + B_ExportSpawnsToClipboard.Text = "Export Spawners To Clipboard"; + B_ExportSpawnsToClipboard.UseVisualStyleBackColor = true; + B_ExportSpawnsToClipboard.Click += B_ExportSpawnsToClipboard_Click; + // + // TB_ObjectName + // + TB_ObjectName.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + TB_ObjectName.Location = new System.Drawing.Point(516, 157); + TB_ObjectName.Name = "TB_ObjectName"; + TB_ObjectName.Size = new System.Drawing.Size(296, 25); + TB_ObjectName.TabIndex = 6; + TB_ObjectName.TextChanged += ChangeSpawnFilter; + // + // L_FilterName + // + L_FilterName.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + L_FilterName.AutoSize = true; + L_FilterName.Location = new System.Drawing.Point(516, 137); + L_FilterName.Name = "L_FilterName"; + L_FilterName.Size = new System.Drawing.Size(88, 17); + L_FilterName.TabIndex = 7; + L_FilterName.Text = "Object Name:"; + // + // L_PointName + // + L_PointName.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + L_PointName.AutoSize = true; + L_PointName.Location = new System.Drawing.Point(516, 185); + L_PointName.Name = "L_PointName"; + L_PointName.Size = new System.Drawing.Size(79, 17); + L_PointName.TabIndex = 9; + L_PointName.Text = "Point Name:"; + // + // TB_PointName + // + TB_PointName.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + TB_PointName.Location = new System.Drawing.Point(516, 205); + TB_PointName.Name = "TB_PointName"; + TB_PointName.Size = new System.Drawing.Size(296, 25); + TB_PointName.TabIndex = 8; + TB_PointName.TextChanged += ChangeSpawnFilter; + // + // CHK_ExportImages + // + CHK_ExportImages.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; + CHK_ExportImages.AutoSize = true; + CHK_ExportImages.Location = new System.Drawing.Point(518, 418); + CHK_ExportImages.Name = "CHK_ExportImages"; + CHK_ExportImages.Size = new System.Drawing.Size(54, 21); + CHK_ExportImages.TabIndex = 10; + CHK_ExportImages.Text = "Auto"; + CHK_ExportImages.UseVisualStyleBackColor = true; + // + // B_ExportImage + // + B_ExportImage.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; + B_ExportImage.Location = new System.Drawing.Point(516, 437); + B_ExportImage.Name = "B_ExportImage"; + B_ExportImage.Size = new System.Drawing.Size(148, 75); + B_ExportImage.TabIndex = 11; + B_ExportImage.Text = "Export Current Image"; + B_ExportImage.UseVisualStyleBackColor = true; + B_ExportImage.Click += B_ExportImage_Click; + // + // NUD_CollisionTransparency + // + NUD_CollisionTransparency.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + NUD_CollisionTransparency.Location = new System.Drawing.Point(761, 64); + NUD_CollisionTransparency.Maximum = new decimal(new int[] { 255, 0, 0, 0 }); + NUD_CollisionTransparency.Name = "NUD_CollisionTransparency"; + NUD_CollisionTransparency.Size = new System.Drawing.Size(51, 25); + NUD_CollisionTransparency.TabIndex = 12; + NUD_CollisionTransparency.Value = new decimal(new int[] { 34, 0, 0, 0 }); + // + // label1 + // + label1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; + label1.Location = new System.Drawing.Point(618, 64); + label1.Name = "label1"; + label1.Size = new System.Drawing.Size(139, 25); + label1.TabIndex = 13; + label1.Text = "Transparency:"; + label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // RTB_Analysis + // + RTB_Analysis.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; + RTB_Analysis.Location = new System.Drawing.Point(517, 236); + RTB_Analysis.Name = "RTB_Analysis"; + RTB_Analysis.ReadOnly = true; + RTB_Analysis.Size = new System.Drawing.Size(295, 176); + RTB_Analysis.TabIndex = 15; + RTB_Analysis.Text = ""; + // + // MapViewer9a + // + AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + ClientSize = new System.Drawing.Size(816, 512); + Controls.Add(RTB_Analysis); + Controls.Add(label1); + Controls.Add(NUD_CollisionTransparency); + Controls.Add(B_ExportImage); + Controls.Add(CHK_ExportImages); + Controls.Add(L_PointName); + Controls.Add(TB_PointName); + Controls.Add(L_FilterName); + Controls.Add(TB_ObjectName); + Controls.Add(B_ExportSpawnsToClipboard); + Controls.Add(L_SpeciesFilter); + Controls.Add(CB_Species); + Controls.Add(CB_Map); + Controls.Add(CB_AreaIndex); + Controls.Add(PB_Map); + Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + Name = "MapViewer9a"; + StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + Text = "Pokémon Legends: Z-A Map Viewer (2D)"; + ((System.ComponentModel.ISupportInitialize)PB_Map).EndInit(); + ((System.ComponentModel.ISupportInitialize)NUD_CollisionTransparency).EndInit(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private System.Windows.Forms.PictureBox PB_Map; + private System.Windows.Forms.ComboBox CB_AreaIndex; + private System.Windows.Forms.ComboBox CB_Map; + private System.Windows.Forms.ComboBox CB_Species; + private System.Windows.Forms.Label L_SpeciesFilter; + private System.Windows.Forms.Button B_ExportSpawnsToClipboard; + private System.Windows.Forms.TextBox TB_ObjectName; + private System.Windows.Forms.Label L_FilterName; + private System.Windows.Forms.Label L_PointName; + private System.Windows.Forms.TextBox TB_PointName; + private System.Windows.Forms.CheckBox CHK_ExportImages; + private System.Windows.Forms.Button B_ExportImage; + private System.Windows.Forms.NumericUpDown NUD_CollisionTransparency; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.RichTextBox RTB_Analysis; + } +} diff --git a/pkNX.WinForms/Subforms/Gen9a/MapViewer9a.cs b/pkNX.WinForms/Subforms/Gen9a/MapViewer9a.cs new file mode 100644 index 00000000..fe031fca --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/MapViewer9a.cs @@ -0,0 +1,445 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Linq; +using System.Numerics; +using System.Text.Json; +using System.Windows.Forms; +using pkNX.Game; +using pkNX.Structures; +using pkNX.Structures.FlatBuffers; +using static pkNX.WinForms.LumioseFieldIndex; +using Point = pkNX.WinForms.TransformScale; + +namespace pkNX.WinForms.Subforms; + +public partial class MapViewer9a : Form +{ + private readonly GameManager9a ROM; + private readonly LumioseMap Map; + private readonly World9a Maps; + private readonly SpawnRipper9a Spawners; + private bool Loading; + + private bool HasWarnedUserNoFilesFound; + + private readonly List RenderedSpawns = []; + private CoordinateInfo9a? Current; + + private LumioseFieldIndex MapIndex => CB_Map.SelectedIndex != -1 ? (LumioseFieldIndex)CB_Map.SelectedIndex : 0; + + private MapTransform CurrentTransform => TransformUI9a.GetMapTransform(MapIndex); + + public MapViewer9a(GameManager9a rom, string language) + { + ROM = rom; + Maps = new(rom); + Spawners = new(rom, language, "", Maps); + Map = Maps.Overworld; + + InitializeComponent(); + + var species = GetSpeciesList(rom, language); + + Loading = true; + CB_Species.DisplayMember = nameof(ComboItem.Text); + CB_Species.ValueMember = nameof(ComboItem.Value); + CB_Species.DataSource = new BindingSource(species, string.Empty); + CB_Map.Items.AddRange("Lumiose", "Lysandre Labs", "The Sewers Ch5", "The Sewers Ch6"); + ReloadAreaIndexes(CB_Map.SelectedIndex = 0); + CB_Species.SelectedValue = -1; // None + Loading = false; + + PB_Map.Click += ClickMap; + + LoadMap(); + } + + private List GetSpeciesList(GameManager9a rom, string language) + { + var cfg = new TextConfig(rom.Game); + var speciesNames = GetCommonText("monsname", language, cfg); + var species = speciesNames.Select((z, i) => new ComboItem(z, i)).ToList(); + + var valid = new HashSet(Spawners.Shared.Encounters.Select(z => (int)z.Value.DevNo)); + species.RemoveAll(z => !valid.Contains(z.Value)); + + species.Insert(0, new ComboItem("(All)", 0)); + species.Insert(0, new ComboItem("(None)", -1)); + return species; + } + + private sealed record ComboItem(string Text, int Value); + + private string[] GetCommonText(string name, string lang, TextConfig cfg) + { + var data = ROM.GetPackedFile($"ik_message/dat/{lang}/common/{name}.dat"); + return new TextFile(data, cfg).Lines; + } + + private void ChangeMap(object sender, EventArgs e) + { + if (Loading) + return; + Loading = true; + ReloadAreaIndexes(CB_Map.SelectedIndex); + Loading = false; + } + + private void ReloadAreaIndexes(int map) + { + CB_AreaIndex.Items.Clear(); + if (map == 0) + CB_AreaIndex.Items.AddRange(Map.AreaNames.Select(z => z).ToArray()); + else + CB_AreaIndex.Items.Add("Dungeon"); + CB_AreaIndex.SelectedIndex = 0; + } + + private void ChangeAreaIndex(object sender, EventArgs e) + { + if (Loading) + return; + LoadMap(); + } + + private const string mapFolderName = "map_za"; // folder we expect the user to place map png's in + + private static string GetMapImagePath(LumioseFieldIndex field) => field switch + { + Overworld => $@"{mapFolderName}\lumiose.png", + LysandreLabs => $@"{mapFolderName}\lysandre_labs.png", + SewersCh5 => $@"{mapFolderName}\the_sewers_ch5.png", + SewersCh6 => $@"{mapFolderName}\the_sewers_ch6.png", + _ => throw new ArgumentException($"Unknown field {field}"), + }; + + private void B_ExportImage_Click(object sender, EventArgs e) + { + if (ModifierKeys == Keys.Alt) + { + // Open folder + var path = System.IO.Path.GetFullPath(GetMapImagePath(MapIndex)); + var folder = System.IO.Path.GetDirectoryName(path); + if (folder != null && System.IO.Directory.Exists(folder)) + System.Diagnostics.Process.Start("explorer.exe", folder); + return; + } + + var index = CB_AreaIndex.SelectedIndex; + var suffix = MapIndex switch + { + Overworld => Map.AreaNames[index], + _ => "Dungeon", + }; + if (CHK_ExportImages.Checked) + ExportImage(suffix); + } + + private void ExportImage(string suffix) + { + var img = PB_Map.BackgroundImage; + var path = GetMapImagePath(MapIndex); + var fileName = $"{path.Replace(".png", "")}_{suffix}.png"; + img?.Save(fileName); + } + + private int AreaIndex => CB_AreaIndex.SelectedIndex; + + private void LoadMap() + { + var tr = CurrentTransform; + var mapImagePath = System.IO.Path.GetFullPath(GetMapImagePath(MapIndex)); + var img = GetBackground(mapImagePath, tr); + PB_Map.BackgroundImage = img; + + using var gr = Graphics.FromImage(img); + string fileSuffix; + + var coords = GetCoordinatesToRender(MapIndex); + RenderPoints(gr, tr, Brushes.Red, coords); + + var areaIndex = AreaIndex; + if (areaIndex < 0) + areaIndex = 0; + + if (MapIndex == 0) // Overworld + { + var areaName = Map.AreaNames[areaIndex]; + if (Map.AreaCollisionTrees.TryGetValue(areaName, out var colTree)) + RenderTree(tr, gr, colTree); + else if (Map.AreaCollisionBoxes.TryGetValue(areaName, out var colBox)) + RenderBox(tr, gr, colBox); + + fileSuffix = areaName; + if (CHK_ExportImages.Checked) + ExportImage(areaName); + } + else + { + // Nothing rendered at this point. + fileSuffix = "Dungeon"; + } + + RenderSpawns(gr, tr); + + if (CHK_ExportImages.Checked) + ExportImage(fileSuffix); + } + + private Image GetBackground(string mapImagePath, MapTransform tr) + { + if (System.IO.File.Exists(mapImagePath)) + return Image.FromFile(mapImagePath); + + if (!HasWarnedUserNoFilesFound) + { + WinFormsUtil.Error($"Unable to find map image at path: {mapImagePath}", "Automatic extraction of map image is not yet supported.\nYou will have to extract it manually and place them at the location above."); + HasWarnedUserNoFilesFound = true; + } + return new Bitmap((int)tr.Texture.X, (int)tr.Texture.Z); + } + + private void RenderBox(MapTransform tr, Graphics gr, BoxCollision9 colBox) + { + var center_x = colBox.Position.X; + var center_z = colBox.Position.Z; + var size_x = colBox.Size.X; + var size_z = colBox.Size.Z; + + using var brush = new SolidBrush(Color.FromArgb((int)NUD_CollisionTransparency.Value, Color.Cyan)); + var x = (float)tr.ConvertX(center_x - (tr.Dir.X * (size_x / 2.0f))); + var z = (float)tr.ConvertZ(center_z - (tr.Dir.Z * (size_z / 2.0f))); + var w = (float)tr.ConvertWidth(size_x); + var d = (float)tr.ConvertHeight(size_z); + gr.FillRectangle(brush, new RectangleF(x, z, w, d)); + } + + private void RenderTree(MapTransform tr, Graphics gr, MultiAABBTree colTree) + { + foreach (var tree in colTree) + { + foreach (var node in tree.Nodes) + { + if (!node.IsLeaf) + continue; + + for (var i = 0; i < HavokCollision.hkcdSimdTreeNode.NodeCount; i++) + { + if (!node.IsBound(i)) + continue; + var lo = new Vector3(node.LoX[i], node.LoY[i], node.LoZ[i]); + var hi = new Vector3(node.HiX[i], node.HiY[i], node.HiZ[i]); + + var yh = node.HiY[i] + 6; + var y = node.LoY[i] + 6; + var color1 = Color.FromArgb((int)NUD_CollisionTransparency.Value, 0, Math.Clamp((int)(y / 30.0f * 255), 0, 255), Math.Clamp(255 - (int)(y / 30.0f * 255), 0, 255)); + var color2 = Color.FromArgb((int)NUD_CollisionTransparency.Value, 0, Math.Clamp((int)(yh / 01.0f * 255), 0, 255), Math.Clamp(255 - (int)(yh / 1.0f * 255), 0, 255)); + + using var brush = new HatchBrush(HatchStyle.BackwardDiagonal, color1, color2); + var rect = new HavokCollision.Rectangle3D(lo, hi); + var x = (float)tr.ConvertX(rect.X + rect.Width); + var z = (float)tr.ConvertZ(rect.Z + rect.Depth); + var w = (float)tr.ConvertWidth(rect.Width); + var d = (float)tr.ConvertHeight(rect.Depth); + + gr.FillRectangle(brush, new RectangleF(x, z, w, d)); + } + } + + for (var i = 0; i < tree.BoundingBoxRectangles.Length; i++) + { + var rect = tree.BoundingBoxRectangles[i]; + } + } + } + + public static Color GetSpeciesColor(int species) + { + var mash = (0x41C64E6D * (uint)species) + 0x00006073; + var r = (byte)((mash >> 16) & 0xFF); + var g = (byte)((mash >> 8) & 0xFF); + var b = (byte)(mash & 0xFF); + return Color.FromArgb(r, g, b); + } + + private void RenderSpawns(Graphics gr, MapTransform tr) + { + RenderedSpawns.Clear(); + var speciesFilter = WinFormsUtil.GetIndex(CB_Species); + if (speciesFilter == -1) + return; + + var nameFilter = TB_ObjectName.Text.Trim(); + var pointFilter = TB_PointName.Text.Trim(); + + var areaIndex = AreaIndex; + var mapIndex = (int)MapIndex; + + var map = Spawners.RippedMaps[mapIndex]; + foreach (var (name, point) in map.SpawnerPositions) + { + if (pointFilter.Length != 0 && !name.Contains(pointFilter)) + continue; + + if (!Spawners.TryGetSpawner(name, out var spawn)) + continue; + + bool rendered = false; + var position = point.Position; + foreach (var edi in spawn.EncountDataInfoList) + { + if (edi.EncountDataId is not { } id) + continue; + if (!Spawners.TryGetEncounter(id, out var slot)) + continue; + + var species = slot.DevNo; + if (speciesFilter != 0 && speciesFilter != (int)species) + continue; + + var color = GetSpeciesColor((int)species); + using var brush = new SolidBrush(color); + RenderPoints(gr, tr, brush, (position.X, position.Z)); + rendered = true; + } + if (rendered) + RenderedSpawns.Add(point); + } + } + + private static void RenderPoints(Graphics gr, MapTransform tr, Brush brush, params ReadOnlySpan coords) + { + foreach (var pt in coords) + { + const int length = (10 * 2) + 1; // Diameter of the circle + var x = (float)tr.ConvertX(pt.X) - (length / 2.0f); + var y = (float)tr.ConvertZ(pt.Z) - (length / 2.0f); + gr.FillEllipse(brush, x, y, length, length); + } + } + + private static Point[] GetCoordinatesToRender(LumioseFieldIndex mapIndex) => mapIndex switch + { + LysandreLabs => [(-11.009529, 92.041016), (21.560417, 94.00054), (-67.99764, 52.998158)], + SewersCh5 => [(-94.78022, -129.65295), (89.97959, -49.889454), (76.90937, -149.78218)], + SewersCh6 => [(-74.71503, -17.543823), (-65.31848, -42.548283), (-83.20368, -90.00267)], + _ => [new(420, 420)], + }; + + private void Map_MouseMove(object sender, MouseEventArgs e) + { + var snap = false; + if (ModifierKeys == Keys.Alt) + snap = true; + else if (ModifierKeys != Keys.None) + return; + + var tr = CurrentTransform; + var (x, z) = tr.ScreenToWorld(e.X, e.Y, PB_Map.Width, PB_Map.Height); + + var info = GetCoordinateInfo(x, z); + var title = $"{info.LocationName} X: {x:F2}, Z: {z:F2}"; + if (info.Spawner is { } spawner) + title += $" - Spawner: {spawner.Name} ({spawner.Type})"; + Text = title; + + RTB_Analysis.Text = JsonSerializer.Serialize(info, SpawnExporter.Options); + + Current = info; + if (snap) + SnapAreaToCurrent(); + } + + private CoordinateInfo9a GetCoordinateInfo(float x, float z) + { + var info = new CoordinateInfo9a + { + X = x, + Z = z, + }; + info.PlaceName = Spawners.Overworld.GetPlaceName(x, z, out var areaName); + info.AreaName = areaName; + info.LocationIndex = Spawners.Resolver.GetLocationIndex(info.PlaceName); + info.LocationName = info.LocationIndex == -1 ? "Out of Bounds" : Spawners.GetLocationName(info.LocationIndex); + info.Collisions = Map.GetCollisions(x, z, Spawners.Resolver) + .OrderByDescending(a => a.Valid) + .ThenByDescending(tree => tree.Layer) + .ToArray(); + + if (TryGetSceneSpawner((x, z), out var spawner)) + info.Spawner = spawner; + return info; + } + + public record CoordinateInfo9a + { + public required float X { get; init; } + public required float Z { get; init; } + + public string AreaName { get; set; } = ""; + public string PlaceName { get; set; } = ""; + public string LocationName { get; set; } = ""; + public SceneSpawner? Spawner { get; set; } + public int LocationIndex { get; set; } + public IntersectingTree[] Collisions { get; set; } = []; + + public string? GetArea() + { + if (Collisions.Length == 0) + return null; + var info = Collisions[0].GetAreaInternal(); + return info; + } + } + + private void B_ExportSpawnsToClipboard_Click(object sender, EventArgs e) => WinFormsUtil.Alert("Not implemented."); + + private void ChangeSpawnFilter(object sender, EventArgs e) + { + if (Loading) + return; + LoadMap(); + } + + private bool TryGetSceneSpawner(Point position, [NotNullWhen(true)] out SceneSpawner? result) + { + const float minResult = 5.0f; + result = null; + var minDistance = float.MaxValue; + foreach (var spawner in RenderedSpawns) + { + var sp = spawner.Position; + var distance = sp.DistanceTo((float)position.X, (float)position.Z); + if (distance > minResult) + continue; + if (distance >= minDistance) + continue; + minDistance = distance; + result = spawner; + } + return result != null; + } + + private void ClickMap(object? sender, EventArgs e) => SnapAreaToCurrent(); + + private void SnapAreaToCurrent() + { + if (MapIndex != 0) + return; + + if (Current is not { } c) + return; + + // Set the current area to the clicked location's area + var areaInfo = c.GetArea(); + if (areaInfo is null) + return; + + var index = Math.Max(0, Map.AreaNames.IndexOf(areaInfo)); + if (index != CB_AreaIndex.SelectedIndex) + CB_AreaIndex.SelectedIndex = index; + } +} diff --git a/pkNX.WinForms/Subforms/Gen9a/MapViewer9a.resx b/pkNX.WinForms/Subforms/Gen9a/MapViewer9a.resx new file mode 100644 index 00000000..4edf53f8 --- /dev/null +++ b/pkNX.WinForms/Subforms/Gen9a/MapViewer9a.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/pkNX.WinForms/Subforms/GenericEditor/GenericEditor.cs b/pkNX.WinForms/Subforms/GenericEditor/GenericEditor.cs index 924bfc67..1c634e14 100644 --- a/pkNX.WinForms/Subforms/GenericEditor/GenericEditor.cs +++ b/pkNX.WinForms/Subforms/GenericEditor/GenericEditor.cs @@ -13,7 +13,6 @@ public sealed partial class GenericEditor : Form where T : class private DataCache Cache; public bool Modified { get; set; } - [Obsolete("Use the constructor overload with callbacks instead")] public GenericEditor(DataCache Cache, string[] names, string title, Action? randomizeCallback = null, Action? addEntryCallback = null, bool canSave = true) : this(_ => Cache, (_, i) => names[i], title, _ => randomizeCallback?.Invoke(), addEntryCallback, canSave) { } diff --git a/pkNX.WinForms/Subforms/GenericEditor.resx b/pkNX.WinForms/Subforms/GenericEditor/GenericEditor.resx similarity index 100% rename from pkNX.WinForms/Subforms/GenericEditor.resx rename to pkNX.WinForms/Subforms/GenericEditor/GenericEditor.resx diff --git a/pkNX.WinForms/Subforms/ModelConverter.cs b/pkNX.WinForms/Subforms/ModelConverter.cs index f3805558..364f50c0 100644 --- a/pkNX.WinForms/Subforms/ModelConverter.cs +++ b/pkNX.WinForms/Subforms/ModelConverter.cs @@ -160,7 +160,7 @@ private void UpdatePLAModel() BasePath = $"bin/pokemon/pm{SpeciesId:0000}/{FileName}/"; - var pack = new GFPack(PokemonModelDir.GetFileData(selectedFile) ?? []); + var pack = new GFPack(PokemonModelDir.GetFileData(selectedFile)); PLAModel.Config = FlatBufferConverter.DeserializeFrom(pack.GetDataFullPath(BasePath + $"{FileName}.trpokecfg")); Debug.Assert((int)PLAModel.Config.SizeIndex <= 3, "Here's one!"); @@ -177,7 +177,7 @@ private void UpdateSWSHModel() BasePath = $"bin/pokemon/{FileName}/"; - var pack = new GFPack(SWSHPokemonModelDir.GetFileData($"{FileName}.gfpak") ?? []); + var pack = new GFPack(SWSHPokemonModelDir.GetFileData($"{FileName}.gfpak")); SWSHModel.Config = FlatBufferConverter.DeserializeFrom(pack.GetDataFullPath(BasePath + $"{FileName}.gfbpokecfg")); diff --git a/pkNX.WinForms/UI/MainWindow.xaml.cs b/pkNX.WinForms/UI/MainWindow.xaml.cs index cfd77afe..e641c8c9 100644 --- a/pkNX.WinForms/UI/MainWindow.xaml.cs +++ b/pkNX.WinForms/UI/MainWindow.xaml.cs @@ -62,8 +62,6 @@ public EditorButtonData[] Categories set => SetValue(CategoriesProperty, value); } - public ProgramSettings Settings { get; } - private new int Language { get => CB_Lang.SelectedIndex; @@ -72,6 +70,8 @@ private new int Language private EditorBase? Editor; + private static ProgramSettings Settings => Program.Settings; + public MainWindow() { InitializeComponent(); @@ -82,12 +82,11 @@ public MainWindow() SpriteName.AllowShinySprite = true; SpriteBuilderUtil.SpriterPreference = SpriteBuilderPreference.ForceSprites; - Settings = ProgramSettings.LoadSettings(); CB_Lang.SelectedIndex = Settings.Language; Menu_DisplayAdvanced.IsChecked = Settings.DisplayAdvanced; if (!string.IsNullOrWhiteSpace(Settings.GamePath) && Directory.Exists(Settings.GamePath)) - OpenPath(Settings.GamePath, Settings.GameOverride); + OpenPath(Settings.GamePath); Drop += (s, e) => { @@ -307,7 +306,6 @@ private async void Window_Closing(object sender, CancelEventArgs e) EditUtil.SaveSettings(Editor.Game); Settings.Language = CB_Lang.SelectedIndex; Settings.GamePath = (string)L_Path.Content; - Settings.GameOverride = Editor.Game; await ProgramSettings.SaveSettings(Settings); } diff --git a/pkNX.WinForms/UI/UIStaticSources.cs b/pkNX.WinForms/UI/UIStaticSources.cs index c435eccc..70685bda 100644 --- a/pkNX.WinForms/UI/UIStaticSources.cs +++ b/pkNX.WinForms/UI/UIStaticSources.cs @@ -20,7 +20,7 @@ public static class UIStaticSources public static void SetupForGame(GameManager ROM) { - if (ROM.Game == GameVersion.SV) + if (ROM.Game is GameVersion.SV or GameVersion.SL or GameVersion.VL or GameVersion.ZA) return; // SV doesn't support these file mappings yet SpeciesList = ROM.GetStrings(TextName.SpeciesNames); diff --git a/pkNX.WinForms/UI/WPFTextEditor.xaml.cs b/pkNX.WinForms/UI/WPFTextEditor.xaml.cs index b51f59aa..d32f3fdf 100644 --- a/pkNX.WinForms/UI/WPFTextEditor.xaml.cs +++ b/pkNX.WinForms/UI/WPFTextEditor.xaml.cs @@ -115,7 +115,7 @@ public WPFTextEditor(TextEditorMode mode, TextConfig? config = null) TextFiles = textFiles; InitializeComponent(); - var settings = ProgramSettings.LoadSettings(); + var settings = Program.Settings; CHK_ShowHashes.IsChecked = settings.DisplayAdvanced; CB_Entry.SelectedIndex = 0; @@ -294,7 +294,7 @@ public void LoadSelectedFile() var tbl = new AHTB(tblFile.Open()); // The table has 1 more entry than the dat to show when the table ends - if (tbl.Entries.Length != lines.Length + 1) + if (tbl.Entries.Count != lines.Length + 1) { var result = WinFormsUtil.Warn(MessageBoxButton.YesNo, "Data corruption detected!", "The number of labels in the table does not match the number of lines in the text file.", "Do you wish to restore the original file?"); if (result != MessageBoxResult.Yes) @@ -308,7 +308,7 @@ public void LoadSelectedFile() flags = file.Flags; tbl = new AHTB(tblFile.Open()); // Reopen the original file - Debug.Assert(tbl.Entries.Length == lines.Length + 1); + Debug.Assert(tbl.Entries.Count == lines.Length + 1); } for (int i = 0; i < tbl.Count; ++i) diff --git a/pkNX.WinForms/Utils/FormsIconHelper.cs b/pkNX.WinForms/Utils/FormsIconHelper.cs index 0036a76e..b19bae53 100644 --- a/pkNX.WinForms/Utils/FormsIconHelper.cs +++ b/pkNX.WinForms/Utils/FormsIconHelper.cs @@ -23,26 +23,30 @@ private static int UniCode(this TEnum icon) ]; private static readonly Typeface[] Typefaces = typeof(IconHelper).Assembly.LoadTypefaces("fonts", FontTitles); + private static readonly Dictionary FontForStyle = []; internal static FontFamily? FontFor(IconChar iconChar) { - if (IconHelper.Orphans.Contains(iconChar)) return null; + if (IconHelper.Orphans.Contains(iconChar)) + return null; var typeFace = Typefaces.Find(iconChar.UniCode(), out _, out _); return typeFace?.FontFamily; } internal static FontFamily? FontFamilyFor(this IconChar iconChar, IconFont iconFont) { - if (iconFont == IconFont.Auto) return FontFor(iconChar); - var key = (int)iconFont; - if (FontForStyle.TryGetValue(key, out var fontFamily)) return fontFamily; + if (iconFont == IconFont.Auto) + return FontFor(iconChar); - int id = Array.FindIndex(FontTitles, f => - f.IndexOf(iconFont.ToString(), StringComparison.InvariantCultureIgnoreCase) >= 0); + var key = (int)iconFont; + if (FontForStyle.TryGetValue(key, out var fontFamily)) + return fontFamily; + + var name = iconFont.ToString(); + int id = Array.FindIndex(FontTitles, f => f.Contains(name, StringComparison.InvariantCultureIgnoreCase)); fontFamily = Typefaces[id].FontFamily; FontForStyle.Add(key, fontFamily); return fontFamily; } - private static readonly Dictionary FontForStyle = []; } diff --git a/pkNX.WinForms/WinFormsUtil.cs b/pkNX.WinForms/WinFormsUtil.cs index f6ed4827..b8df5204 100644 --- a/pkNX.WinForms/WinFormsUtil.cs +++ b/pkNX.WinForms/WinFormsUtil.cs @@ -11,28 +11,28 @@ public static class WinFormsUtil /// /// User-friendly message about the error. /// The associated with the dialog. - internal static MessageBoxResult Error(params string[] lines) + internal static MessageBoxResult Error(params ReadOnlySpan lines) { SystemSounds.Hand.Play(); string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); return MessageBox.Show(msg, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } - internal static MessageBoxResult Alert(params string[] lines) + internal static MessageBoxResult Alert(params ReadOnlySpan lines) { SystemSounds.Asterisk.Play(); string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); return MessageBox.Show(msg, "Alert", MessageBoxButton.OK, MessageBoxImage.Information); } - internal static MessageBoxResult Warn(MessageBoxButton btn, params string[] lines) + internal static MessageBoxResult Warn(MessageBoxButton btn, params ReadOnlySpan lines) { SystemSounds.Hand.Play(); string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); return MessageBox.Show(msg, "Warning", btn, MessageBoxImage.Warning); } - internal static MessageBoxResult Prompt(MessageBoxButton btn, params string[] lines) + internal static MessageBoxResult Prompt(MessageBoxButton btn, params ReadOnlySpan lines) { SystemSounds.Question.Play(); string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); diff --git a/pkNX.WinForms/pkNX.WinForms.csproj b/pkNX.WinForms/pkNX.WinForms.csproj index 3459f320..7a1e2beb 100644 --- a/pkNX.WinForms/pkNX.WinForms.csproj +++ b/pkNX.WinForms/pkNX.WinForms.csproj @@ -18,6 +18,16 @@ + + + + + + + + + + @@ -48,7 +58,7 @@ - + @@ -61,11 +71,15 @@ + + Form + True True Resources.resx + diff --git a/pkNX.sln b/pkNX.sln index af3722fd..25dfbb79 100644 --- a/pkNX.sln +++ b/pkNX.sln @@ -1,97 +1,119 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.4.33110.190 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.11205.157 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Randomization", "pkNX.Randomization\pkNX.Randomization.csproj", "{77E3FEBB-9C86-4F8D-B4E0-66B7504080D5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Containers", "pkNX.Containers\pkNX.Containers.csproj", "{EA4D9D71-BD02-8C4F-FD88-36B7DFD0A152}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Game", "pkNX.Game\pkNX.Game.csproj", "{01FA36D2-C032-EF99-2FA7-5845FCB1742F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Randomization", "pkNX.Randomization\pkNX.Randomization.csproj", "{4D22F40E-E79E-9426-76C8-CB6F83BEE4E0}" ProjectSection(ProjectDependencies) = postProject - {01447516-8382-4E9B-8B6C-92FF0A2D0CBF} = {01447516-8382-4E9B-8B6C-92FF0A2D0CBF} - {2A909229-C9C0-42CE-88E0-72D9AF84AFE3} = {2A909229-C9C0-42CE-88E0-72D9AF84AFE3} + {EA4D9D71-BD02-8C4F-FD88-36B7DFD0A152} = {EA4D9D71-BD02-8C4F-FD88-36B7DFD0A152} + {024FA0B1-3AFD-B8A4-186F-C7BA0FB3E602} = {024FA0B1-3AFD-B8A4-186F-C7BA0FB3E602} EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures", "pkNX.Structures\pkNX.Structures.csproj", "{01447516-8382-4E9B-8B6C-92FF0A2D0CBF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures", "pkNX.Structures\pkNX.Structures.csproj", "{024FA0B1-3AFD-B8A4-186F-C7BA0FB3E602}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Containers", "pkNX.Containers\pkNX.Containers.csproj", "{2A909229-C9C0-42CE-88E0-72D9AF84AFE3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.WinForms", "pkNX.WinForms\pkNX.WinForms.csproj", "{3CF3FA3E-B38E-4774-BA77-924A391DDC9D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.WinForms", "pkNX.WinForms\pkNX.WinForms.csproj", "{BA836714-B406-0EA7-0CE8-F552464582D8}" ProjectSection(ProjectDependencies) = postProject - {01447516-8382-4E9B-8B6C-92FF0A2D0CBF} = {01447516-8382-4E9B-8B6C-92FF0A2D0CBF} - {2A909229-C9C0-42CE-88E0-72D9AF84AFE3} = {2A909229-C9C0-42CE-88E0-72D9AF84AFE3} - {77E3FEBB-9C86-4F8D-B4E0-66B7504080D5} = {77E3FEBB-9C86-4F8D-B4E0-66B7504080D5} + {EA4D9D71-BD02-8C4F-FD88-36B7DFD0A152} = {EA4D9D71-BD02-8C4F-FD88-36B7DFD0A152} + {4D22F40E-E79E-9426-76C8-CB6F83BEE4E0} = {4D22F40E-E79E-9426-76C8-CB6F83BEE4E0} + {024FA0B1-3AFD-B8A4-186F-C7BA0FB3E602} = {024FA0B1-3AFD-B8A4-186F-C7BA0FB3E602} EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Game", "pkNX.Game\pkNX.Game.csproj", "{3C4AF1ED-7C81-4AF8-A6DB-1D397650DA0A}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FlatBuffers", "FlatBuffers", "{B496CD4E-1553-0358-8ACB-EB4772637246}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BC933AB9-8BF5-4E94-BC26-7EDE48BFD300}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.Reflection", "FlatBuffers\pkNX.Structures.FlatBuffers.Reflection\pkNX.Structures.FlatBuffers.Reflection.csproj", "{A3F553E3-4887-5C77-26A8-BB17B41443BF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SourceGen", "FlatBuffers\pkNX.Structures.FlatBuffers.SourceGen\pkNX.Structures.FlatBuffers.SourceGen.csproj", "{50D4478B-E025-016E-9030-B8C09CED0904}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers", "FlatBuffers\pkNX.Structures.FlatBuffers\pkNX.Structures.FlatBuffers.csproj", "{925042AA-DA65-5A0F-9528-064734CD71F4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Arceus", "Arceus", "{B76D1E2C-C828-74EF-79CE-A0825BB44C5F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.Arceus", "FlatBuffers\Arceus\pkNX.Structures.FlatBuffers.Arceus.csproj", "{104B9964-7C55-A2DD-F328-73D2921DA3E7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LGPE", "LGPE", "{8110BE20-E7DC-CB45-1121-BBC4A82BFF56}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.LGPE", "FlatBuffers\LGPE\pkNX.Structures.FlatBuffers.LGPE.csproj", "{44D6D911-CD52-6385-1132-76DDE72B4554}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SV", "SV", "{027910FB-8394-ECE8-F6FA-0C922121209B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Audio", "FlatBuffers\SV\Audio\pkNX.Structures.FlatBuffers.SV.Audio.csproj", "{245C570D-DF69-7B89-A420-B6846F8CAB38}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Balloon", "FlatBuffers\SV\Balloon\pkNX.Structures.FlatBuffers.SV.Balloon.csproj", "{5D98DDF1-1545-93BD-F473-EFFA579485F3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Battle", "FlatBuffers\SV\Battle\pkNX.Structures.FlatBuffers.SV.Battle.csproj", "{DE59A07A-79D0-FB18-90E5-16BEF3F6BA7D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Cooking", "FlatBuffers\SV\Cooking\pkNX.Structures.FlatBuffers.SV.Cooking.csproj", "{E5894DC8-4742-A80C-2772-C7DABC741E4F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Event", "FlatBuffers\SV\Event\pkNX.Structures.FlatBuffers.SV.Event.csproj", "{BE89F4E7-7977-FE39-8482-ECE14B9DAF65}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Gym", "FlatBuffers\SV\Gym\pkNX.Structures.FlatBuffers.SV.Gym.csproj", "{CB7249E4-F6A4-4D41-2B7C-320FE941F114}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Item", "FlatBuffers\SV\Item\pkNX.Structures.FlatBuffers.SV.Item.csproj", "{3BCAD297-67E5-07AF-E589-B7FEF1E4723E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Misc", "FlatBuffers\SV\Misc\pkNX.Structures.FlatBuffers.SV.Misc.csproj", "{6F9DA4E9-EC79-5DC0-EBE8-22464FDB5930}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Personal", "FlatBuffers\SV\Personal\pkNX.Structures.FlatBuffers.SV.Personal.csproj", "{B626557A-D1BF-9536-45A1-12439877E9D0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Picnic", "FlatBuffers\SV\Picnic\pkNX.Structures.FlatBuffers.SV.Picnic.csproj", "{63AA714F-D705-9DDB-1D1B-5151A3521753}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Raid", "FlatBuffers\SV\Raid\pkNX.Structures.FlatBuffers.SV.Raid.csproj", "{BFA5F955-DB3B-2C0B-F43E-95B82048DF8B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Shared", "FlatBuffers\SV\Shared\pkNX.Structures.FlatBuffers.SV.Shared.csproj", "{B37A8369-E61D-1EB7-3B5A-10A76ED57337}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Trainers", "FlatBuffers\SV\Trainers\pkNX.Structures.FlatBuffers.SV.Trainers.csproj", "{0CDC74AD-8F98-F35D-95D1-C8849BEAE349}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Trinity", "FlatBuffers\SV\Trinity\pkNX.Structures.FlatBuffers.SV.Trinity.csproj", "{2E0EACA0-F786-FE8A-7AA9-6B2850985183}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.UI", "FlatBuffers\SV\UI\pkNX.Structures.FlatBuffers.SV.UI.csproj", "{32463A30-7994-3478-8FD1-9BE6ED5AE507}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Waza", "FlatBuffers\SV\Waza\pkNX.Structures.FlatBuffers.SV.Waza.csproj", "{1660F86E-5067-02FE-3587-80EC59DCC385}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.World", "FlatBuffers\SV\World\pkNX.Structures.FlatBuffers.SV.World.csproj", "{A069DCDE-83A0-D308-3888-678C429C0157}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SV.Zukan", "FlatBuffers\SV\Zukan\pkNX.Structures.FlatBuffers.SV.Zukan.csproj", "{7BA4B09C-DF73-ED2D-45AA-225C7466A62E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SWSH", "SWSH", "{663E6D2B-C3CC-08FB-2C9D-8847075391BF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SWSH", "FlatBuffers\SWSH\pkNX.Structures.FlatBuffers.SWSH.csproj", "{0664464F-E7A6-C62E-C439-EA3CC15B46F5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ZA", "ZA", "{456C6151-853F-9D7E-B457-981E0CE410B1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.Battle", "FlatBuffers\ZA\Battle\pkNX.Structures.FlatBuffers.ZA.Battle.csproj", "{B560BEF2-1429-53EF-4985-E0C4A3AF8383}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.Item", "FlatBuffers\ZA\Item\pkNX.Structures.FlatBuffers.ZA.Item.csproj", "{4C022EFD-DEE7-260B-1451-96E6731FC0BC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.Misc", "FlatBuffers\ZA\Misc\pkNX.Structures.FlatBuffers.ZA.Misc.csproj", "{1465AD51-9152-BC1D-81A3-FBAE3538DE6A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.Personal", "FlatBuffers\ZA\Personal\pkNX.Structures.FlatBuffers.ZA.Personal.csproj", "{83BD125C-4BB5-8215-1433-D1753E30AD61}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.Shared", "FlatBuffers\ZA\Shared\pkNX.Structures.FlatBuffers.ZA.Shared.csproj", "{E5945CCA-4C13-2A81-BFB7-FDF97838C4EB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.Trainers", "FlatBuffers\ZA\Trainers\pkNX.Structures.FlatBuffers.ZA.Trainers.csproj", "{CD161F0B-265C-5E71-1C8B-BED4056195A2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.Trinity", "FlatBuffers\ZA\Trinity\pkNX.Structures.FlatBuffers.ZA.Trinity.csproj", "{D9031880-0813-C74E-500F-E25D17C0F938}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.Waza", "FlatBuffers\ZA\Waza\pkNX.Structures.FlatBuffers.ZA.Waza.csproj", "{843C1360-D467-407D-A234-EE155C12786C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.World", "FlatBuffers\ZA\World\pkNX.Structures.FlatBuffers.ZA.World.csproj", "{8B8ED8FC-F32F-4FA9-3E6B-623B5532FFAF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.ZA.Zukan", "FlatBuffers\ZA\Zukan\pkNX.Structures.FlatBuffers.ZA.Zukan.csproj", "{F885AE24-191E-9F26-57B1-5AC287EA8EF7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{089100B1-113F-4E66-888A-E83F3999EAFD}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FlatBuffers", "FlatBuffers", "{8ED95003-D481-4E81-95E9-E44499E1A847}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers", "FlatBuffers\pkNX.Structures.FlatBuffers\pkNX.Structures.FlatBuffers.csproj", "{7E843D65-0A79-4E6F-A770-A8612096AFEC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Tests.FileSystem", "pkNX.Tests\pkNX.Tests.FileSystem\pkNX.Tests.FileSystem.csproj", "{E3B433FE-B3E6-1CC8-D084-CA475C79226D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Structures.FlatBuffers.SourceGen", "FlatBuffers\pkNX.Structures.FlatBuffers.SourceGen\pkNX.Structures.FlatBuffers.SourceGen.csproj", "{56C9DC36-06E6-400D-B58E-1CCF1D934AD3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Tests.SourceGen", "pkNX.Tests\pkNX.Tests.SourceGen\pkNX.Tests.SourceGen.csproj", "{3916C23C-0AAD-2F57-4B3C-7FCD79A46089}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.Reflection", "FlatBuffers\pkNX.Structures.FlatBuffers.Reflection\pkNX.Structures.FlatBuffers.Reflection.csproj", "{ECC93A01-CD80-4AF2-AB9F-FE46277571FF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.LGPE", "FlatBuffers\LGPE\pkNX.Structures.FlatBuffers.LGPE.csproj", "{F9EAEF82-BBB2-4520-B59E-3EB74A4C7487}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SWSH", "FlatBuffers\SWSH\pkNX.Structures.FlatBuffers.SWSH.csproj", "{F8916261-B21C-4CFC-B6D8-4179E1CBB730}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.Arceus", "FlatBuffers\Arceus\pkNX.Structures.FlatBuffers.Arceus.csproj", "{0ECF2003-0E48-4C6D-B11E-EA6199FFA8D4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Shared", "FlatBuffers\SV\Shared\pkNX.Structures.FlatBuffers.SV.Shared.csproj", "{96017CC2-78B1-4A1A-B543-2219F692A0FC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Zukan", "FlatBuffers\SV\Zukan\pkNX.Structures.FlatBuffers.SV.Zukan.csproj", "{7D7FCAB8-B748-4512-8DF9-28C0B27AE0F1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Balloon", "FlatBuffers\SV\Balloon\pkNX.Structures.FlatBuffers.SV.Balloon.csproj", "{AB3B2BB3-BE88-47EB-9299-14E2243BC564}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Battle", "FlatBuffers\SV\Battle\pkNX.Structures.FlatBuffers.SV.Battle.csproj", "{DF90D20A-1F2E-49D1-AD88-78FCC3D9B000}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Cooking", "FlatBuffers\SV\Cooking\pkNX.Structures.FlatBuffers.SV.Cooking.csproj", "{BB7D10EB-6685-42D5-AA0D-C6C5DB8D1F54}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Event", "FlatBuffers\SV\Event\pkNX.Structures.FlatBuffers.SV.Event.csproj", "{404CD793-A214-47AD-9C65-067FD6F55DDE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Gym", "FlatBuffers\SV\Gym\pkNX.Structures.FlatBuffers.SV.Gym.csproj", "{73135648-B72F-40CA-AB2E-74BEEF7B4084}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Item", "FlatBuffers\SV\Item\pkNX.Structures.FlatBuffers.SV.Item.csproj", "{C518975C-2E23-456F-8548-748605FB575D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Misc", "FlatBuffers\SV\Misc\pkNX.Structures.FlatBuffers.SV.Misc.csproj", "{25DE5B0B-5A35-4003-A4AD-36E783DCBFFC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Personal", "FlatBuffers\SV\Personal\pkNX.Structures.FlatBuffers.SV.Personal.csproj", "{DA78EBE9-394D-45F8-A9A2-8EB6036C109E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Picnic", "FlatBuffers\SV\Picnic\pkNX.Structures.FlatBuffers.SV.Picnic.csproj", "{073247D9-342E-4C76-9D35-A2BA2701AABA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Raid", "FlatBuffers\SV\Raid\pkNX.Structures.FlatBuffers.SV.Raid.csproj", "{6D1E1751-E941-46F2-B703-E8EDF29565E6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Trainers", "FlatBuffers\SV\Trainers\pkNX.Structures.FlatBuffers.SV.Trainers.csproj", "{E21AB1FD-B4B8-4973-AB91-38C348C28E02}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Trinity", "FlatBuffers\SV\Trinity\pkNX.Structures.FlatBuffers.SV.Trinity.csproj", "{989E1CDE-4A35-44D0-A142-B9DF7C3401CF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.UI", "FlatBuffers\SV\UI\pkNX.Structures.FlatBuffers.SV.UI.csproj", "{8338BBC7-8F59-4C51-BEF0-665F53403A8C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Waza", "FlatBuffers\SV\Waza\pkNX.Structures.FlatBuffers.SV.Waza.csproj", "{BB73E54A-20F9-44BA-B6E2-7C7E2C22CA77}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.World", "FlatBuffers\SV\World\pkNX.Structures.FlatBuffers.SV.World.csproj", "{1B561015-5A83-422D-A75F-A1A2FC756C8D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Structures.FlatBuffers.SV.Audio", "FlatBuffers\SV\Audio\pkNX.Structures.FlatBuffers.SV.Audio.csproj", "{97BC69AF-3CE9-48BC-A2AC-197D43184821}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D571A50B-59B6-4DA6-9184-0C1A546D7137}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Tests.Trinity", "pkNX.Tests\pkNX.Tests.Trinity\pkNX.Tests.Trinity.csproj", "{7530A87C-4D49-41C4-8526-AAC6CBCCBA0B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pkNX.Tests.FileSystem", "pkNX.Tests\pkNX.Tests.FileSystem\pkNX.Tests.FileSystem.csproj", "{E83E7B1A-1E56-4C2D-A704-A20003CDCAAF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SV", "SV", "{F82C6DE0-48A5-45C5-AC50-3D0352ED2242}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Arceus", "Arceus", "{BD736B77-78CD-4E96-A31C-FA157E9D1B11}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LGPE", "LGPE", "{79B294E4-9990-46D6-9014-788BE234792B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SWSH", "SWSH", "{AF239399-CBF9-4EB3-8B18-F10ACC9C4E1D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Tests.SourceGen", "pkNX.Tests\pkNX.Tests.SourceGen\pkNX.Tests.SourceGen.csproj", "{A3BF4AE5-59B0-44DB-A5D9-30C51BBEC5A1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pkNX.Tests.Trinity", "pkNX.Tests\pkNX.Tests.Trinity\pkNX.Tests.Trinity.csproj", "{535104C9-1DE5-1F16-64B1-9B761E76B3EE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -99,172 +121,220 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {77E3FEBB-9C86-4F8D-B4E0-66B7504080D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {77E3FEBB-9C86-4F8D-B4E0-66B7504080D5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {77E3FEBB-9C86-4F8D-B4E0-66B7504080D5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {77E3FEBB-9C86-4F8D-B4E0-66B7504080D5}.Release|Any CPU.Build.0 = Release|Any CPU - {01447516-8382-4E9B-8B6C-92FF0A2D0CBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {01447516-8382-4E9B-8B6C-92FF0A2D0CBF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {01447516-8382-4E9B-8B6C-92FF0A2D0CBF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {01447516-8382-4E9B-8B6C-92FF0A2D0CBF}.Release|Any CPU.Build.0 = Release|Any CPU - {2A909229-C9C0-42CE-88E0-72D9AF84AFE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A909229-C9C0-42CE-88E0-72D9AF84AFE3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A909229-C9C0-42CE-88E0-72D9AF84AFE3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A909229-C9C0-42CE-88E0-72D9AF84AFE3}.Release|Any CPU.Build.0 = Release|Any CPU - {3CF3FA3E-B38E-4774-BA77-924A391DDC9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3CF3FA3E-B38E-4774-BA77-924A391DDC9D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3CF3FA3E-B38E-4774-BA77-924A391DDC9D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3CF3FA3E-B38E-4774-BA77-924A391DDC9D}.Release|Any CPU.Build.0 = Release|Any CPU - {3C4AF1ED-7C81-4AF8-A6DB-1D397650DA0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C4AF1ED-7C81-4AF8-A6DB-1D397650DA0A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C4AF1ED-7C81-4AF8-A6DB-1D397650DA0A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C4AF1ED-7C81-4AF8-A6DB-1D397650DA0A}.Release|Any CPU.Build.0 = Release|Any CPU - {7E843D65-0A79-4E6F-A770-A8612096AFEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7E843D65-0A79-4E6F-A770-A8612096AFEC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7E843D65-0A79-4E6F-A770-A8612096AFEC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7E843D65-0A79-4E6F-A770-A8612096AFEC}.Release|Any CPU.Build.0 = Release|Any CPU - {56C9DC36-06E6-400D-B58E-1CCF1D934AD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {56C9DC36-06E6-400D-B58E-1CCF1D934AD3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {56C9DC36-06E6-400D-B58E-1CCF1D934AD3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {56C9DC36-06E6-400D-B58E-1CCF1D934AD3}.Release|Any CPU.Build.0 = Release|Any CPU - {ECC93A01-CD80-4AF2-AB9F-FE46277571FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ECC93A01-CD80-4AF2-AB9F-FE46277571FF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ECC93A01-CD80-4AF2-AB9F-FE46277571FF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ECC93A01-CD80-4AF2-AB9F-FE46277571FF}.Release|Any CPU.Build.0 = Release|Any CPU - {F9EAEF82-BBB2-4520-B59E-3EB74A4C7487}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F9EAEF82-BBB2-4520-B59E-3EB74A4C7487}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F9EAEF82-BBB2-4520-B59E-3EB74A4C7487}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F9EAEF82-BBB2-4520-B59E-3EB74A4C7487}.Release|Any CPU.Build.0 = Release|Any CPU - {F8916261-B21C-4CFC-B6D8-4179E1CBB730}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F8916261-B21C-4CFC-B6D8-4179E1CBB730}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F8916261-B21C-4CFC-B6D8-4179E1CBB730}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F8916261-B21C-4CFC-B6D8-4179E1CBB730}.Release|Any CPU.Build.0 = Release|Any CPU - {0ECF2003-0E48-4C6D-B11E-EA6199FFA8D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0ECF2003-0E48-4C6D-B11E-EA6199FFA8D4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0ECF2003-0E48-4C6D-B11E-EA6199FFA8D4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0ECF2003-0E48-4C6D-B11E-EA6199FFA8D4}.Release|Any CPU.Build.0 = Release|Any CPU - {96017CC2-78B1-4A1A-B543-2219F692A0FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {96017CC2-78B1-4A1A-B543-2219F692A0FC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {96017CC2-78B1-4A1A-B543-2219F692A0FC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {96017CC2-78B1-4A1A-B543-2219F692A0FC}.Release|Any CPU.Build.0 = Release|Any CPU - {7D7FCAB8-B748-4512-8DF9-28C0B27AE0F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7D7FCAB8-B748-4512-8DF9-28C0B27AE0F1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7D7FCAB8-B748-4512-8DF9-28C0B27AE0F1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7D7FCAB8-B748-4512-8DF9-28C0B27AE0F1}.Release|Any CPU.Build.0 = Release|Any CPU - {AB3B2BB3-BE88-47EB-9299-14E2243BC564}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB3B2BB3-BE88-47EB-9299-14E2243BC564}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB3B2BB3-BE88-47EB-9299-14E2243BC564}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB3B2BB3-BE88-47EB-9299-14E2243BC564}.Release|Any CPU.Build.0 = Release|Any CPU - {DF90D20A-1F2E-49D1-AD88-78FCC3D9B000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DF90D20A-1F2E-49D1-AD88-78FCC3D9B000}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DF90D20A-1F2E-49D1-AD88-78FCC3D9B000}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DF90D20A-1F2E-49D1-AD88-78FCC3D9B000}.Release|Any CPU.Build.0 = Release|Any CPU - {BB7D10EB-6685-42D5-AA0D-C6C5DB8D1F54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BB7D10EB-6685-42D5-AA0D-C6C5DB8D1F54}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BB7D10EB-6685-42D5-AA0D-C6C5DB8D1F54}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BB7D10EB-6685-42D5-AA0D-C6C5DB8D1F54}.Release|Any CPU.Build.0 = Release|Any CPU - {404CD793-A214-47AD-9C65-067FD6F55DDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {404CD793-A214-47AD-9C65-067FD6F55DDE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {404CD793-A214-47AD-9C65-067FD6F55DDE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {404CD793-A214-47AD-9C65-067FD6F55DDE}.Release|Any CPU.Build.0 = Release|Any CPU - {73135648-B72F-40CA-AB2E-74BEEF7B4084}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {73135648-B72F-40CA-AB2E-74BEEF7B4084}.Debug|Any CPU.Build.0 = Debug|Any CPU - {73135648-B72F-40CA-AB2E-74BEEF7B4084}.Release|Any CPU.ActiveCfg = Release|Any CPU - {73135648-B72F-40CA-AB2E-74BEEF7B4084}.Release|Any CPU.Build.0 = Release|Any CPU - {C518975C-2E23-456F-8548-748605FB575D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C518975C-2E23-456F-8548-748605FB575D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C518975C-2E23-456F-8548-748605FB575D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C518975C-2E23-456F-8548-748605FB575D}.Release|Any CPU.Build.0 = Release|Any CPU - {25DE5B0B-5A35-4003-A4AD-36E783DCBFFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {25DE5B0B-5A35-4003-A4AD-36E783DCBFFC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {25DE5B0B-5A35-4003-A4AD-36E783DCBFFC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {25DE5B0B-5A35-4003-A4AD-36E783DCBFFC}.Release|Any CPU.Build.0 = Release|Any CPU - {DA78EBE9-394D-45F8-A9A2-8EB6036C109E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA78EBE9-394D-45F8-A9A2-8EB6036C109E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DA78EBE9-394D-45F8-A9A2-8EB6036C109E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DA78EBE9-394D-45F8-A9A2-8EB6036C109E}.Release|Any CPU.Build.0 = Release|Any CPU - {073247D9-342E-4C76-9D35-A2BA2701AABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {073247D9-342E-4C76-9D35-A2BA2701AABA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {073247D9-342E-4C76-9D35-A2BA2701AABA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {073247D9-342E-4C76-9D35-A2BA2701AABA}.Release|Any CPU.Build.0 = Release|Any CPU - {6D1E1751-E941-46F2-B703-E8EDF29565E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6D1E1751-E941-46F2-B703-E8EDF29565E6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6D1E1751-E941-46F2-B703-E8EDF29565E6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6D1E1751-E941-46F2-B703-E8EDF29565E6}.Release|Any CPU.Build.0 = Release|Any CPU - {E21AB1FD-B4B8-4973-AB91-38C348C28E02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E21AB1FD-B4B8-4973-AB91-38C348C28E02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E21AB1FD-B4B8-4973-AB91-38C348C28E02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E21AB1FD-B4B8-4973-AB91-38C348C28E02}.Release|Any CPU.Build.0 = Release|Any CPU - {989E1CDE-4A35-44D0-A142-B9DF7C3401CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {989E1CDE-4A35-44D0-A142-B9DF7C3401CF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {989E1CDE-4A35-44D0-A142-B9DF7C3401CF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {989E1CDE-4A35-44D0-A142-B9DF7C3401CF}.Release|Any CPU.Build.0 = Release|Any CPU - {8338BBC7-8F59-4C51-BEF0-665F53403A8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8338BBC7-8F59-4C51-BEF0-665F53403A8C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8338BBC7-8F59-4C51-BEF0-665F53403A8C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8338BBC7-8F59-4C51-BEF0-665F53403A8C}.Release|Any CPU.Build.0 = Release|Any CPU - {BB73E54A-20F9-44BA-B6E2-7C7E2C22CA77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BB73E54A-20F9-44BA-B6E2-7C7E2C22CA77}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BB73E54A-20F9-44BA-B6E2-7C7E2C22CA77}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BB73E54A-20F9-44BA-B6E2-7C7E2C22CA77}.Release|Any CPU.Build.0 = Release|Any CPU - {1B561015-5A83-422D-A75F-A1A2FC756C8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1B561015-5A83-422D-A75F-A1A2FC756C8D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B561015-5A83-422D-A75F-A1A2FC756C8D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1B561015-5A83-422D-A75F-A1A2FC756C8D}.Release|Any CPU.Build.0 = Release|Any CPU - {97BC69AF-3CE9-48BC-A2AC-197D43184821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {97BC69AF-3CE9-48BC-A2AC-197D43184821}.Debug|Any CPU.Build.0 = Debug|Any CPU - {97BC69AF-3CE9-48BC-A2AC-197D43184821}.Release|Any CPU.ActiveCfg = Release|Any CPU - {97BC69AF-3CE9-48BC-A2AC-197D43184821}.Release|Any CPU.Build.0 = Release|Any CPU - {7530A87C-4D49-41C4-8526-AAC6CBCCBA0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7530A87C-4D49-41C4-8526-AAC6CBCCBA0B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7530A87C-4D49-41C4-8526-AAC6CBCCBA0B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7530A87C-4D49-41C4-8526-AAC6CBCCBA0B}.Release|Any CPU.Build.0 = Release|Any CPU - {E83E7B1A-1E56-4C2D-A704-A20003CDCAAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E83E7B1A-1E56-4C2D-A704-A20003CDCAAF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E83E7B1A-1E56-4C2D-A704-A20003CDCAAF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E83E7B1A-1E56-4C2D-A704-A20003CDCAAF}.Release|Any CPU.Build.0 = Release|Any CPU - {A3BF4AE5-59B0-44DB-A5D9-30C51BBEC5A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A3BF4AE5-59B0-44DB-A5D9-30C51BBEC5A1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A3BF4AE5-59B0-44DB-A5D9-30C51BBEC5A1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A3BF4AE5-59B0-44DB-A5D9-30C51BBEC5A1}.Release|Any CPU.Build.0 = Release|Any CPU + {EA4D9D71-BD02-8C4F-FD88-36B7DFD0A152}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA4D9D71-BD02-8C4F-FD88-36B7DFD0A152}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA4D9D71-BD02-8C4F-FD88-36B7DFD0A152}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA4D9D71-BD02-8C4F-FD88-36B7DFD0A152}.Release|Any CPU.Build.0 = Release|Any CPU + {01FA36D2-C032-EF99-2FA7-5845FCB1742F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01FA36D2-C032-EF99-2FA7-5845FCB1742F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01FA36D2-C032-EF99-2FA7-5845FCB1742F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01FA36D2-C032-EF99-2FA7-5845FCB1742F}.Release|Any CPU.Build.0 = Release|Any CPU + {4D22F40E-E79E-9426-76C8-CB6F83BEE4E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D22F40E-E79E-9426-76C8-CB6F83BEE4E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D22F40E-E79E-9426-76C8-CB6F83BEE4E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D22F40E-E79E-9426-76C8-CB6F83BEE4E0}.Release|Any CPU.Build.0 = Release|Any CPU + {024FA0B1-3AFD-B8A4-186F-C7BA0FB3E602}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {024FA0B1-3AFD-B8A4-186F-C7BA0FB3E602}.Debug|Any CPU.Build.0 = Debug|Any CPU + {024FA0B1-3AFD-B8A4-186F-C7BA0FB3E602}.Release|Any CPU.ActiveCfg = Release|Any CPU + {024FA0B1-3AFD-B8A4-186F-C7BA0FB3E602}.Release|Any CPU.Build.0 = Release|Any CPU + {BA836714-B406-0EA7-0CE8-F552464582D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA836714-B406-0EA7-0CE8-F552464582D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA836714-B406-0EA7-0CE8-F552464582D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA836714-B406-0EA7-0CE8-F552464582D8}.Release|Any CPU.Build.0 = Release|Any CPU + {A3F553E3-4887-5C77-26A8-BB17B41443BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3F553E3-4887-5C77-26A8-BB17B41443BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3F553E3-4887-5C77-26A8-BB17B41443BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3F553E3-4887-5C77-26A8-BB17B41443BF}.Release|Any CPU.Build.0 = Release|Any CPU + {50D4478B-E025-016E-9030-B8C09CED0904}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50D4478B-E025-016E-9030-B8C09CED0904}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50D4478B-E025-016E-9030-B8C09CED0904}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50D4478B-E025-016E-9030-B8C09CED0904}.Release|Any CPU.Build.0 = Release|Any CPU + {925042AA-DA65-5A0F-9528-064734CD71F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {925042AA-DA65-5A0F-9528-064734CD71F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {925042AA-DA65-5A0F-9528-064734CD71F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {925042AA-DA65-5A0F-9528-064734CD71F4}.Release|Any CPU.Build.0 = Release|Any CPU + {104B9964-7C55-A2DD-F328-73D2921DA3E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {104B9964-7C55-A2DD-F328-73D2921DA3E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {104B9964-7C55-A2DD-F328-73D2921DA3E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {104B9964-7C55-A2DD-F328-73D2921DA3E7}.Release|Any CPU.Build.0 = Release|Any CPU + {44D6D911-CD52-6385-1132-76DDE72B4554}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44D6D911-CD52-6385-1132-76DDE72B4554}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44D6D911-CD52-6385-1132-76DDE72B4554}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44D6D911-CD52-6385-1132-76DDE72B4554}.Release|Any CPU.Build.0 = Release|Any CPU + {245C570D-DF69-7B89-A420-B6846F8CAB38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {245C570D-DF69-7B89-A420-B6846F8CAB38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {245C570D-DF69-7B89-A420-B6846F8CAB38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {245C570D-DF69-7B89-A420-B6846F8CAB38}.Release|Any CPU.Build.0 = Release|Any CPU + {5D98DDF1-1545-93BD-F473-EFFA579485F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D98DDF1-1545-93BD-F473-EFFA579485F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D98DDF1-1545-93BD-F473-EFFA579485F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D98DDF1-1545-93BD-F473-EFFA579485F3}.Release|Any CPU.Build.0 = Release|Any CPU + {DE59A07A-79D0-FB18-90E5-16BEF3F6BA7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE59A07A-79D0-FB18-90E5-16BEF3F6BA7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE59A07A-79D0-FB18-90E5-16BEF3F6BA7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE59A07A-79D0-FB18-90E5-16BEF3F6BA7D}.Release|Any CPU.Build.0 = Release|Any CPU + {E5894DC8-4742-A80C-2772-C7DABC741E4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5894DC8-4742-A80C-2772-C7DABC741E4F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5894DC8-4742-A80C-2772-C7DABC741E4F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5894DC8-4742-A80C-2772-C7DABC741E4F}.Release|Any CPU.Build.0 = Release|Any CPU + {BE89F4E7-7977-FE39-8482-ECE14B9DAF65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE89F4E7-7977-FE39-8482-ECE14B9DAF65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE89F4E7-7977-FE39-8482-ECE14B9DAF65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE89F4E7-7977-FE39-8482-ECE14B9DAF65}.Release|Any CPU.Build.0 = Release|Any CPU + {CB7249E4-F6A4-4D41-2B7C-320FE941F114}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB7249E4-F6A4-4D41-2B7C-320FE941F114}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB7249E4-F6A4-4D41-2B7C-320FE941F114}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB7249E4-F6A4-4D41-2B7C-320FE941F114}.Release|Any CPU.Build.0 = Release|Any CPU + {3BCAD297-67E5-07AF-E589-B7FEF1E4723E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BCAD297-67E5-07AF-E589-B7FEF1E4723E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BCAD297-67E5-07AF-E589-B7FEF1E4723E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BCAD297-67E5-07AF-E589-B7FEF1E4723E}.Release|Any CPU.Build.0 = Release|Any CPU + {6F9DA4E9-EC79-5DC0-EBE8-22464FDB5930}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6F9DA4E9-EC79-5DC0-EBE8-22464FDB5930}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F9DA4E9-EC79-5DC0-EBE8-22464FDB5930}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6F9DA4E9-EC79-5DC0-EBE8-22464FDB5930}.Release|Any CPU.Build.0 = Release|Any CPU + {B626557A-D1BF-9536-45A1-12439877E9D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B626557A-D1BF-9536-45A1-12439877E9D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B626557A-D1BF-9536-45A1-12439877E9D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B626557A-D1BF-9536-45A1-12439877E9D0}.Release|Any CPU.Build.0 = Release|Any CPU + {63AA714F-D705-9DDB-1D1B-5151A3521753}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63AA714F-D705-9DDB-1D1B-5151A3521753}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63AA714F-D705-9DDB-1D1B-5151A3521753}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63AA714F-D705-9DDB-1D1B-5151A3521753}.Release|Any CPU.Build.0 = Release|Any CPU + {BFA5F955-DB3B-2C0B-F43E-95B82048DF8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFA5F955-DB3B-2C0B-F43E-95B82048DF8B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFA5F955-DB3B-2C0B-F43E-95B82048DF8B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFA5F955-DB3B-2C0B-F43E-95B82048DF8B}.Release|Any CPU.Build.0 = Release|Any CPU + {B37A8369-E61D-1EB7-3B5A-10A76ED57337}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B37A8369-E61D-1EB7-3B5A-10A76ED57337}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B37A8369-E61D-1EB7-3B5A-10A76ED57337}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B37A8369-E61D-1EB7-3B5A-10A76ED57337}.Release|Any CPU.Build.0 = Release|Any CPU + {0CDC74AD-8F98-F35D-95D1-C8849BEAE349}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CDC74AD-8F98-F35D-95D1-C8849BEAE349}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CDC74AD-8F98-F35D-95D1-C8849BEAE349}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CDC74AD-8F98-F35D-95D1-C8849BEAE349}.Release|Any CPU.Build.0 = Release|Any CPU + {2E0EACA0-F786-FE8A-7AA9-6B2850985183}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E0EACA0-F786-FE8A-7AA9-6B2850985183}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E0EACA0-F786-FE8A-7AA9-6B2850985183}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E0EACA0-F786-FE8A-7AA9-6B2850985183}.Release|Any CPU.Build.0 = Release|Any CPU + {32463A30-7994-3478-8FD1-9BE6ED5AE507}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32463A30-7994-3478-8FD1-9BE6ED5AE507}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32463A30-7994-3478-8FD1-9BE6ED5AE507}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32463A30-7994-3478-8FD1-9BE6ED5AE507}.Release|Any CPU.Build.0 = Release|Any CPU + {1660F86E-5067-02FE-3587-80EC59DCC385}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1660F86E-5067-02FE-3587-80EC59DCC385}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1660F86E-5067-02FE-3587-80EC59DCC385}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1660F86E-5067-02FE-3587-80EC59DCC385}.Release|Any CPU.Build.0 = Release|Any CPU + {A069DCDE-83A0-D308-3888-678C429C0157}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A069DCDE-83A0-D308-3888-678C429C0157}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A069DCDE-83A0-D308-3888-678C429C0157}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A069DCDE-83A0-D308-3888-678C429C0157}.Release|Any CPU.Build.0 = Release|Any CPU + {7BA4B09C-DF73-ED2D-45AA-225C7466A62E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7BA4B09C-DF73-ED2D-45AA-225C7466A62E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7BA4B09C-DF73-ED2D-45AA-225C7466A62E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7BA4B09C-DF73-ED2D-45AA-225C7466A62E}.Release|Any CPU.Build.0 = Release|Any CPU + {0664464F-E7A6-C62E-C439-EA3CC15B46F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0664464F-E7A6-C62E-C439-EA3CC15B46F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0664464F-E7A6-C62E-C439-EA3CC15B46F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0664464F-E7A6-C62E-C439-EA3CC15B46F5}.Release|Any CPU.Build.0 = Release|Any CPU + {B560BEF2-1429-53EF-4985-E0C4A3AF8383}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B560BEF2-1429-53EF-4985-E0C4A3AF8383}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B560BEF2-1429-53EF-4985-E0C4A3AF8383}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B560BEF2-1429-53EF-4985-E0C4A3AF8383}.Release|Any CPU.Build.0 = Release|Any CPU + {4C022EFD-DEE7-260B-1451-96E6731FC0BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C022EFD-DEE7-260B-1451-96E6731FC0BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C022EFD-DEE7-260B-1451-96E6731FC0BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C022EFD-DEE7-260B-1451-96E6731FC0BC}.Release|Any CPU.Build.0 = Release|Any CPU + {1465AD51-9152-BC1D-81A3-FBAE3538DE6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1465AD51-9152-BC1D-81A3-FBAE3538DE6A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1465AD51-9152-BC1D-81A3-FBAE3538DE6A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1465AD51-9152-BC1D-81A3-FBAE3538DE6A}.Release|Any CPU.Build.0 = Release|Any CPU + {83BD125C-4BB5-8215-1433-D1753E30AD61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83BD125C-4BB5-8215-1433-D1753E30AD61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83BD125C-4BB5-8215-1433-D1753E30AD61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83BD125C-4BB5-8215-1433-D1753E30AD61}.Release|Any CPU.Build.0 = Release|Any CPU + {E5945CCA-4C13-2A81-BFB7-FDF97838C4EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5945CCA-4C13-2A81-BFB7-FDF97838C4EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5945CCA-4C13-2A81-BFB7-FDF97838C4EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5945CCA-4C13-2A81-BFB7-FDF97838C4EB}.Release|Any CPU.Build.0 = Release|Any CPU + {CD161F0B-265C-5E71-1C8B-BED4056195A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD161F0B-265C-5E71-1C8B-BED4056195A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD161F0B-265C-5E71-1C8B-BED4056195A2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD161F0B-265C-5E71-1C8B-BED4056195A2}.Release|Any CPU.Build.0 = Release|Any CPU + {D9031880-0813-C74E-500F-E25D17C0F938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9031880-0813-C74E-500F-E25D17C0F938}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9031880-0813-C74E-500F-E25D17C0F938}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9031880-0813-C74E-500F-E25D17C0F938}.Release|Any CPU.Build.0 = Release|Any CPU + {843C1360-D467-407D-A234-EE155C12786C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {843C1360-D467-407D-A234-EE155C12786C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {843C1360-D467-407D-A234-EE155C12786C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {843C1360-D467-407D-A234-EE155C12786C}.Release|Any CPU.Build.0 = Release|Any CPU + {8B8ED8FC-F32F-4FA9-3E6B-623B5532FFAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B8ED8FC-F32F-4FA9-3E6B-623B5532FFAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B8ED8FC-F32F-4FA9-3E6B-623B5532FFAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B8ED8FC-F32F-4FA9-3E6B-623B5532FFAF}.Release|Any CPU.Build.0 = Release|Any CPU + {F885AE24-191E-9F26-57B1-5AC287EA8EF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F885AE24-191E-9F26-57B1-5AC287EA8EF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F885AE24-191E-9F26-57B1-5AC287EA8EF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F885AE24-191E-9F26-57B1-5AC287EA8EF7}.Release|Any CPU.Build.0 = Release|Any CPU + {E3B433FE-B3E6-1CC8-D084-CA475C79226D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3B433FE-B3E6-1CC8-D084-CA475C79226D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3B433FE-B3E6-1CC8-D084-CA475C79226D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3B433FE-B3E6-1CC8-D084-CA475C79226D}.Release|Any CPU.Build.0 = Release|Any CPU + {3916C23C-0AAD-2F57-4B3C-7FCD79A46089}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3916C23C-0AAD-2F57-4B3C-7FCD79A46089}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3916C23C-0AAD-2F57-4B3C-7FCD79A46089}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3916C23C-0AAD-2F57-4B3C-7FCD79A46089}.Release|Any CPU.Build.0 = Release|Any CPU + {535104C9-1DE5-1F16-64B1-9B761E76B3EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {535104C9-1DE5-1F16-64B1-9B761E76B3EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {535104C9-1DE5-1F16-64B1-9B761E76B3EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {535104C9-1DE5-1F16-64B1-9B761E76B3EE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {7E843D65-0A79-4E6F-A770-A8612096AFEC} = {8ED95003-D481-4E81-95E9-E44499E1A847} - {56C9DC36-06E6-400D-B58E-1CCF1D934AD3} = {8ED95003-D481-4E81-95E9-E44499E1A847} - {ECC93A01-CD80-4AF2-AB9F-FE46277571FF} = {8ED95003-D481-4E81-95E9-E44499E1A847} - {F9EAEF82-BBB2-4520-B59E-3EB74A4C7487} = {79B294E4-9990-46D6-9014-788BE234792B} - {F8916261-B21C-4CFC-B6D8-4179E1CBB730} = {AF239399-CBF9-4EB3-8B18-F10ACC9C4E1D} - {0ECF2003-0E48-4C6D-B11E-EA6199FFA8D4} = {BD736B77-78CD-4E96-A31C-FA157E9D1B11} - {96017CC2-78B1-4A1A-B543-2219F692A0FC} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {7D7FCAB8-B748-4512-8DF9-28C0B27AE0F1} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {AB3B2BB3-BE88-47EB-9299-14E2243BC564} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {DF90D20A-1F2E-49D1-AD88-78FCC3D9B000} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {BB7D10EB-6685-42D5-AA0D-C6C5DB8D1F54} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {404CD793-A214-47AD-9C65-067FD6F55DDE} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {73135648-B72F-40CA-AB2E-74BEEF7B4084} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {C518975C-2E23-456F-8548-748605FB575D} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {25DE5B0B-5A35-4003-A4AD-36E783DCBFFC} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {DA78EBE9-394D-45F8-A9A2-8EB6036C109E} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {073247D9-342E-4C76-9D35-A2BA2701AABA} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {6D1E1751-E941-46F2-B703-E8EDF29565E6} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {E21AB1FD-B4B8-4973-AB91-38C348C28E02} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {989E1CDE-4A35-44D0-A142-B9DF7C3401CF} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {8338BBC7-8F59-4C51-BEF0-665F53403A8C} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {BB73E54A-20F9-44BA-B6E2-7C7E2C22CA77} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {1B561015-5A83-422D-A75F-A1A2FC756C8D} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {97BC69AF-3CE9-48BC-A2AC-197D43184821} = {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} - {7530A87C-4D49-41C4-8526-AAC6CBCCBA0B} = {D571A50B-59B6-4DA6-9184-0C1A546D7137} - {E83E7B1A-1E56-4C2D-A704-A20003CDCAAF} = {D571A50B-59B6-4DA6-9184-0C1A546D7137} - {F82C6DE0-48A5-45C5-AC50-3D0352ED2242} = {8ED95003-D481-4E81-95E9-E44499E1A847} - {BD736B77-78CD-4E96-A31C-FA157E9D1B11} = {8ED95003-D481-4E81-95E9-E44499E1A847} - {79B294E4-9990-46D6-9014-788BE234792B} = {8ED95003-D481-4E81-95E9-E44499E1A847} - {AF239399-CBF9-4EB3-8B18-F10ACC9C4E1D} = {8ED95003-D481-4E81-95E9-E44499E1A847} - {A3BF4AE5-59B0-44DB-A5D9-30C51BBEC5A1} = {D571A50B-59B6-4DA6-9184-0C1A546D7137} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {3EB083E9-2376-4061-91EB-BA8DC7F2712F} + {A3F553E3-4887-5C77-26A8-BB17B41443BF} = {B496CD4E-1553-0358-8ACB-EB4772637246} + {50D4478B-E025-016E-9030-B8C09CED0904} = {B496CD4E-1553-0358-8ACB-EB4772637246} + {925042AA-DA65-5A0F-9528-064734CD71F4} = {B496CD4E-1553-0358-8ACB-EB4772637246} + {B76D1E2C-C828-74EF-79CE-A0825BB44C5F} = {B496CD4E-1553-0358-8ACB-EB4772637246} + {104B9964-7C55-A2DD-F328-73D2921DA3E7} = {B76D1E2C-C828-74EF-79CE-A0825BB44C5F} + {8110BE20-E7DC-CB45-1121-BBC4A82BFF56} = {B496CD4E-1553-0358-8ACB-EB4772637246} + {44D6D911-CD52-6385-1132-76DDE72B4554} = {8110BE20-E7DC-CB45-1121-BBC4A82BFF56} + {027910FB-8394-ECE8-F6FA-0C922121209B} = {B496CD4E-1553-0358-8ACB-EB4772637246} + {245C570D-DF69-7B89-A420-B6846F8CAB38} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {5D98DDF1-1545-93BD-F473-EFFA579485F3} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {DE59A07A-79D0-FB18-90E5-16BEF3F6BA7D} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {E5894DC8-4742-A80C-2772-C7DABC741E4F} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {BE89F4E7-7977-FE39-8482-ECE14B9DAF65} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {CB7249E4-F6A4-4D41-2B7C-320FE941F114} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {3BCAD297-67E5-07AF-E589-B7FEF1E4723E} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {6F9DA4E9-EC79-5DC0-EBE8-22464FDB5930} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {B626557A-D1BF-9536-45A1-12439877E9D0} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {63AA714F-D705-9DDB-1D1B-5151A3521753} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {BFA5F955-DB3B-2C0B-F43E-95B82048DF8B} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {B37A8369-E61D-1EB7-3B5A-10A76ED57337} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {0CDC74AD-8F98-F35D-95D1-C8849BEAE349} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {2E0EACA0-F786-FE8A-7AA9-6B2850985183} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {32463A30-7994-3478-8FD1-9BE6ED5AE507} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {1660F86E-5067-02FE-3587-80EC59DCC385} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {A069DCDE-83A0-D308-3888-678C429C0157} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {7BA4B09C-DF73-ED2D-45AA-225C7466A62E} = {027910FB-8394-ECE8-F6FA-0C922121209B} + {663E6D2B-C3CC-08FB-2C9D-8847075391BF} = {B496CD4E-1553-0358-8ACB-EB4772637246} + {0664464F-E7A6-C62E-C439-EA3CC15B46F5} = {663E6D2B-C3CC-08FB-2C9D-8847075391BF} + {456C6151-853F-9D7E-B457-981E0CE410B1} = {B496CD4E-1553-0358-8ACB-EB4772637246} + {B560BEF2-1429-53EF-4985-E0C4A3AF8383} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {4C022EFD-DEE7-260B-1451-96E6731FC0BC} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {1465AD51-9152-BC1D-81A3-FBAE3538DE6A} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {83BD125C-4BB5-8215-1433-D1753E30AD61} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {E5945CCA-4C13-2A81-BFB7-FDF97838C4EB} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {CD161F0B-265C-5E71-1C8B-BED4056195A2} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {D9031880-0813-C74E-500F-E25D17C0F938} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {843C1360-D467-407D-A234-EE155C12786C} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {8B8ED8FC-F32F-4FA9-3E6B-623B5532FFAF} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {F885AE24-191E-9F26-57B1-5AC287EA8EF7} = {456C6151-853F-9D7E-B457-981E0CE410B1} + {E3B433FE-B3E6-1CC8-D084-CA475C79226D} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {3916C23C-0AAD-2F57-4B3C-7FCD79A46089} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {535104C9-1DE5-1F16-64B1-9B761E76B3EE} = {0AB3BF05-4346-4AA6-1389-037BE0695223} EndGlobalSection EndGlobal