From fa3f0e3cc81119d72bb4827d1bbf942fd026a61e Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 13 Jan 2026 16:02:58 -0600 Subject: [PATCH] Update to .NET 10 (#683) --- .editorconfig | 115 + .github/README-es.md | 5 - .github/README-fr.md | 5 - .github/README-it.md | 5 - .github/README-jp.md | 5 - .github/README-zh-CN.md | 4 - Directory.Build.props | 4 +- NHSE.Core/Drawing/AcreTileColor.cs | 31 +- NHSE.Core/Drawing/ColorUtil.cs | 93 +- NHSE.Core/Drawing/FieldItemColor.cs | 147 +- NHSE.Core/Drawing/ItemColor.cs | 45 +- NHSE.Core/Drawing/TerrainTileColor.cs | 463 ++- NHSE.Core/Editing/Batch/BatchMutator.cs | 15 +- NHSE.Core/Editing/Batch/BatchProcessor.cs | 142 +- NHSE.Core/Editing/Batch/ItemMutator.cs | 373 +- NHSE.Core/Editing/Batch/ItemProcessor.cs | 84 +- NHSE.Core/Editing/Batch/ItemReflection.cs | 118 +- NHSE.Core/Editing/Batch/ModifyResult.cs | 43 +- NHSE.Core/Editing/Batch/StringInstruction.cs | 442 ++- .../Editing/Batch/StringInstructionSet.cs | 169 +- .../Editing/FieldItem/FieldItemColumn.cs | 41 +- .../Editing/FieldItem/FieldItemDropper.cs | 242 +- NHSE.Core/Editing/Inventory/PlayerItemSet.cs | 252 +- NHSE.Core/Editing/ItemRequest/IConfigItem.cs | 35 +- NHSE.Core/Editing/ItemRequest/ItemParser.cs | 734 ++-- .../ItemRequest/LevenshteinDistance.cs | 79 +- NHSE.Core/Encryption/Aes128Ctr.cs | 228 +- NHSE.Core/Encryption/CryptoFile.cs | 17 +- NHSE.Core/Encryption/EncryptedInt32.cs | 152 +- NHSE.Core/Encryption/EncryptedSaveFile.cs | 35 +- NHSE.Core/Encryption/Encryption.cs | 147 +- NHSE.Core/Hashing/FileHashDetails.cs | 47 +- NHSE.Core/Hashing/FileHashInfo.cs | 37 +- NHSE.Core/Hashing/FileHashRegion.cs | 64 +- NHSE.Core/Hashing/FileHashRevision.cs | 1080 +++-- NHSE.Core/Hashing/Murmur3.cs | 152 +- NHSE.Core/NHSE.Core.csproj | 4 - NHSE.Core/Save/Files/MainSave.cs | 516 ++- NHSE.Core/Save/Files/Personal.cs | 335 +- NHSE.Core/Save/Files/PhotoStudioIsland.cs | 15 +- NHSE.Core/Save/Files/PostBox.cs | 15 +- NHSE.Core/Save/Files/Profile.cs | 19 +- NHSE.Core/Save/Files/WhereAreN.cs | 29 +- NHSE.Core/Save/Meta/EncryptedFilePair.cs | 169 +- NHSE.Core/Save/Meta/FileHeaderInfo.cs | 33 +- NHSE.Core/Save/Meta/HorizonSave.cs | 184 +- NHSE.Core/Save/Meta/Player.cs | 109 +- NHSE.Core/Save/Meta/RevisionChecker.cs | 262 +- NHSE.Core/Save/Meta/SaveFileSizes.cs | 45 +- NHSE.Core/Save/Offsets/MainSaveOffsets.cs | 405 +- NHSE.Core/Save/Offsets/MainSaveOffsets10.cs | 103 +- NHSE.Core/Save/Offsets/MainSaveOffsets11.cs | 103 +- NHSE.Core/Save/Offsets/MainSaveOffsets110.cs | 105 +- NHSE.Core/Save/Offsets/MainSaveOffsets111.cs | 107 +- NHSE.Core/Save/Offsets/MainSaveOffsets12.cs | 103 +- NHSE.Core/Save/Offsets/MainSaveOffsets13.cs | 103 +- NHSE.Core/Save/Offsets/MainSaveOffsets14.cs | 103 +- NHSE.Core/Save/Offsets/MainSaveOffsets15.cs | 103 +- NHSE.Core/Save/Offsets/MainSaveOffsets16.cs | 103 +- NHSE.Core/Save/Offsets/MainSaveOffsets17.cs | 103 +- NHSE.Core/Save/Offsets/MainSaveOffsets18.cs | 105 +- NHSE.Core/Save/Offsets/MainSaveOffsets19.cs | 105 +- NHSE.Core/Save/Offsets/MainSaveOffsets20.cs | 107 +- NHSE.Core/Save/Offsets/PersonalOffsets.cs | 155 +- NHSE.Core/Save/Offsets/PersonalOffsets10.cs | 75 +- NHSE.Core/Save/Offsets/PersonalOffsets11.cs | 75 +- NHSE.Core/Save/Offsets/PersonalOffsets110.cs | 77 +- NHSE.Core/Save/Offsets/PersonalOffsets111.cs | 75 +- NHSE.Core/Save/Offsets/PersonalOffsets12.cs | 75 +- NHSE.Core/Save/Offsets/PersonalOffsets13.cs | 75 +- NHSE.Core/Save/Offsets/PersonalOffsets14.cs | 75 +- NHSE.Core/Save/Offsets/PersonalOffsets15.cs | 75 +- NHSE.Core/Save/Offsets/PersonalOffsets16.cs | 75 +- NHSE.Core/Save/Offsets/PersonalOffsets17.cs | 75 +- NHSE.Core/Save/Offsets/PersonalOffsets18.cs | 77 +- NHSE.Core/Save/Offsets/PersonalOffsets19.cs | 77 +- NHSE.Core/Save/Offsets/PersonalOffsets20.cs | 75 +- NHSE.Core/Save/Offsets/WhereAreNOffsets.cs | 47 +- NHSE.Core/Save/Offsets/WhereAreNOffsets20.cs | 17 +- NHSE.Core/Strings/GameInfo.cs | 61 +- NHSE.Core/Strings/GameLanguage.cs | 53 +- NHSE.Core/Strings/GameStrings.cs | 483 ++- .../Structures/Building/BridgeMaterial.cs | 33 +- NHSE.Core/Structures/Building/BridgeType.cs | 123 +- NHSE.Core/Structures/Building/Building.cs | 98 +- NHSE.Core/Structures/Building/BuildingType.cs | 75 +- NHSE.Core/Structures/Building/DoorKind.cs | 521 ++- NHSE.Core/Structures/Building/RoofType.cs | 347 +- NHSE.Core/Structures/Building/SlopeType.cs | 33 +- .../Structures/Building/SoundAmbientKind.cs | 63 +- .../Structures/Building/StructureUtil.cs | 37 +- NHSE.Core/Structures/Building/WallType.cs | 313 +- NHSE.Core/Structures/Designs/DesignPattern.cs | 280 +- .../Structures/Designs/DesignPatternPRO.cs | 286 +- NHSE.Core/Structures/GameFileDumper.cs | 537 ++- NHSE.Core/Structures/GameFileLoader.cs | 108 +- NHSE.Core/Structures/GameLists.cs | 862 ++-- .../Item/FieldItem/FieldItemDefinition.cs | 99 +- .../Item/FieldItem/FieldItemKind.cs | 192 +- .../Item/FieldItem/FieldItemList.cs | 1119 +++--- NHSE.Core/Structures/Item/FlowerGene.cs | 35 +- NHSE.Core/Structures/Item/ICopyableItem.cs | 13 +- NHSE.Core/Structures/Item/IGridItem.cs | 11 +- NHSE.Core/Structures/Item/Item.cs | 497 ++- NHSE.Core/Structures/Item/ItemArrayEditor.cs | 108 +- NHSE.Core/Structures/Item/ItemCheatCode.cs | 123 +- NHSE.Core/Structures/Item/ItemInfo.cs | 720 ++-- NHSE.Core/Structures/Item/ItemKind.cs | 476 +-- NHSE.Core/Structures/Item/ItemMenuIconType.cs | 1239 +++--- NHSE.Core/Structures/Item/ItemSize.cs | 91 +- NHSE.Core/Structures/Item/ItemSizeType.cs | 73 +- NHSE.Core/Structures/Item/ItemWrapping.cs | 29 +- .../Structures/Item/ItemWrappingPaper.cs | 45 +- .../Structures/Item/Remake/ItemCustomColor.cs | 45 +- .../Item/Remake/ItemRemakeCommonPattern.cs | 439 ++- .../Remake/ItemRemakeCommonPatternCategory.cs | 37 +- .../Item/Remake/ItemRemakeDesignSource.cs | 25 +- .../Structures/Item/Remake/ItemRemakeInfo.cs | 269 +- .../Item/Remake/ItemRemakeInfoData.cs | 2525 ++++++------ .../Structures/Item/Remake/ItemRemakeUtil.cs | 3495 ++++++++--------- NHSE.Core/Structures/Item/VillagerItem.cs | 76 +- .../Structures/Map/Layers/FieldItemLayer.cs | 221 +- NHSE.Core/Structures/Map/Layers/ItemLayer.cs | 391 +- .../Structures/Map/Layers/RoomItemLayer.cs | 54 +- .../Structures/Map/Layers/TerrainLayer.cs | 306 +- .../Map/Managers/FieldItemManager.cs | 183 +- .../Map/Managers/RoomItemManager.cs | 97 +- .../Map/Managers/RoomLayerSurface.cs | 25 +- NHSE.Core/Structures/Map/MapGrid.cs | 77 +- NHSE.Core/Structures/Map/OutsideAcre.cs | 465 ++- .../Structures/Map/Terrain/AcreCoordinate.cs | 89 +- .../Map/Terrain/PlacedItemPermission.cs | 35 +- .../Structures/Map/Terrain/TerrainTile.cs | 184 +- .../Map/Terrain/TerrainUnitModel.cs | 557 +-- NHSE.Core/Structures/Map/TileGrid.cs | 143 +- NHSE.Core/Structures/Misc/AchievementList.cs | 193 +- NHSE.Core/Structures/Misc/AirportColor.cs | 23 +- NHSE.Core/Structures/Misc/GSaveAudioInfo.cs | 23 +- NHSE.Core/Structures/Misc/GSaveBBS.cs | 141 +- NHSE.Core/Structures/Misc/GSaveDate.cs | 45 +- NHSE.Core/Structures/Misc/GSaveDateMD.cs | 47 +- NHSE.Core/Structures/Misc/GSaveFg.cs | 33 +- NHSE.Core/Structures/Misc/GSaveItemName.cs | 43 +- NHSE.Core/Structures/Misc/GSaveLandId.cs | 25 +- .../Structures/Misc/GSavePlayerBaseId.cs | 25 +- NHSE.Core/Structures/Misc/GSavePlayerId.cs | 23 +- NHSE.Core/Structures/Misc/GSavePlayerManpu.cs | 217 +- .../Structures/Misc/GSaveRoomFloorWall.cs | 35 +- NHSE.Core/Structures/Misc/GSaveTime.cs | 43 +- NHSE.Core/Structures/Misc/GSaveVisitorNpc.cs | 103 +- NHSE.Core/Structures/Misc/Gender.cs | 19 +- NHSE.Core/Structures/Misc/Hemisphere.cs | 13 +- NHSE.Core/Structures/Misc/MapManager.cs | 94 +- NHSE.Core/Structures/Misc/MapView.cs | 205 +- NHSE.Core/Structures/Misc/Museum.cs | 49 +- NHSE.Core/Structures/Misc/MuseumEditor.cs | 214 +- NHSE.Core/Structures/Misc/Reaction.cs | 179 +- NHSE.Core/Structures/Misc/RecipeBook.cs | 123 +- .../Structures/Misc/ValueTypeTypeConverter.cs | 38 +- NHSE.Core/Structures/RecipeList.cs | 1869 +++++---- .../Structures/Records/EventFlagHouse.cs | 95 +- NHSE.Core/Structures/Records/EventFlagLand.cs | 1031 +++-- .../Structures/Records/EventFlagPlayer.cs | 3095 ++++++++------- .../Structures/Records/EventFlagVillager.cs | 207 +- .../Records/EventFlagVillagerMemoryPlayer.cs | 415 +- NHSE.Core/Structures/Records/INamedValue.cs | 13 +- .../Records/LifeSupportAchievement.cs | 416 +- NHSE.Core/Structures/TurnipStonk.cs | 67 +- NHSE.Core/Structures/Villager/GSaveMemory.cs | 127 +- NHSE.Core/Structures/Villager/IHouseInfo.cs | 53 +- NHSE.Core/Structures/Villager/IPlayerHouse.cs | 30 +- NHSE.Core/Structures/Villager/IPlayerRoom.cs | 21 +- NHSE.Core/Structures/Villager/IVillager.cs | 74 +- .../Structures/Villager/IVillagerHouse.cs | 23 +- .../Structures/Villager/IVillagerOrigin.cs | 91 +- NHSE.Core/Structures/Villager/PlayerHouse1.cs | 187 +- NHSE.Core/Structures/Villager/PlayerHouse2.cs | 120 +- .../Villager/PlayerHouseConverter.cs | 137 +- NHSE.Core/Structures/Villager/PlayerRoom1.cs | 90 +- NHSE.Core/Structures/Villager/PlayerRoom2.cs | 141 +- .../Villager/PlayerRoomConverter.cs | 135 +- NHSE.Core/Structures/Villager/Villager1.cs | 253 +- NHSE.Core/Structures/Villager/Villager2.cs | 253 +- .../Structures/Villager/VillagerConverter.cs | 227 +- .../Structures/Villager/VillagerHouse1.cs | 85 +- .../Structures/Villager/VillagerHouse2.cs | 250 +- .../Villager/VillagerHouseConverter.cs | 137 +- .../Structures/Villager/VillagerHouseItem.cs | 47 +- .../Villager/VillagerPersonality.cs | 25 +- NHSE.Core/Structures/Villager/VillagerUtil.cs | 89 +- NHSE.Core/Structures/XorShift128.cs | 65 +- NHSE.Core/Util/ArrayUtil.cs | 226 +- NHSE.Core/Util/ComboItem.cs | 140 +- NHSE.Core/Util/EnumUtil.cs | 48 +- NHSE.Core/Util/FlagUtil.cs | 41 +- NHSE.Core/Util/FrameworkUtil.cs | 36 - NHSE.Core/Util/RandUtil.cs | 64 +- NHSE.Core/Util/ReflectUtil.cs | 323 +- NHSE.Core/Util/ResourceUtil.cs | 151 +- NHSE.Core/Util/StringUtil.cs | 131 +- NHSE.Core/Util/StructConverter.cs | 130 +- NHSE.Injection/Injector/AutoInjector.cs | 111 +- NHSE.Injection/Injector/IDataInjector.cs | 27 +- NHSE.Injection/Injector/IRAMReadWriter.cs | 13 +- NHSE.Injection/Injector/InjectionResult.cs | 21 +- NHSE.Injection/NHSE.Injection.csproj | 4 - NHSE.Injection/PocketInjector.cs | 153 +- NHSE.Injection/SysBot/Decoder.cs | 79 +- NHSE.Injection/SysBot/SwitchButton.cs | 49 +- NHSE.Injection/SysBot/SwitchCommand.cs | 139 +- NHSE.Injection/SysBot/SwitchStick.cs | 17 +- NHSE.Injection/SysBot/SysBot.cs | 143 +- NHSE.Injection/SysBot/USBBot.cs | 278 +- NHSE.Parsing/BCSV/BCSV.cs | 223 +- NHSE.Parsing/BCSV/BCSVConverter.cs | 63 +- NHSE.Parsing/BCSV/BCSVEnumDictionary.cs | 127 +- NHSE.Parsing/BCSV/BCSVFieldParam.cs | 27 +- NHSE.Parsing/BCSV/CRC32.cs | 116 +- NHSE.Parsing/GameBCSVDumper.cs | 1640 ++++---- NHSE.Parsing/GameMSBTDumper.cs | 395 +- NHSE.Parsing/GameMSBTDumperNHSE.cs | 153 +- NHSE.Parsing/GamePBCDumper.cs | 47 +- NHSE.Parsing/MSBT/BinaryReaderX.cs | 76 +- NHSE.Parsing/MSBT/ByteOrder.cs | 11 +- NHSE.Parsing/MSBT/LBL1.cs | 22 +- NHSE.Parsing/MSBT/MSBT.cs | 257 +- NHSE.Parsing/MSBT/MSBTEncodingByte.cs | 11 +- NHSE.Parsing/MSBT/MSBTGroup.cs | 11 +- NHSE.Parsing/MSBT/MSBTHeader.cs | 69 +- NHSE.Parsing/MSBT/MSBTLabel.cs | 29 +- NHSE.Parsing/MSBT/MSBTSection.cs | 25 +- NHSE.Parsing/MSBT/MSBTTextString.cs | 70 +- NHSE.Parsing/MSBT/MSBTUtil.cs | 49 +- NHSE.Parsing/MSBT/TXT2.cs | 20 +- NHSE.Parsing/NHSE.Parsing.csproj | 4 - NHSE.Parsing/PBC/PBC.cs | 91 +- NHSE.Parsing/ParseConverter.cs | 67 +- NHSE.Sprites/Field/ItemLayerSprite.cs | 490 +-- NHSE.Sprites/Field/MapViewer.cs | 113 +- NHSE.Sprites/Field/TerrainSprite.cs | 370 +- NHSE.Sprites/Item/ItemSprite.cs | 219 +- NHSE.Sprites/NHSE.Sprites.csproj | 8 +- NHSE.Sprites/Util/ImageUtil.cs | 231 +- NHSE.Sprites/VillagerSprite.cs | 45 +- NHSE.Tests/BuildingTests.cs | 43 +- NHSE.Tests/DumpTests.cs | 49 +- NHSE.Tests/EncryptedIntTests.cs | 32 +- NHSE.Tests/EnumHashTests.cs | 23 +- NHSE.Tests/FancyMarshalTests.cs | 79 +- NHSE.Tests/InjectionTests.cs | 19 +- NHSE.Tests/ItemParsingTests.cs | 83 +- NHSE.Tests/MSBTTests.cs | 47 +- NHSE.Tests/MarshalTests.cs | 73 +- NHSE.Tests/NHSE.Tests.csproj | 7 +- NHSE.Villagers/NHSE.Villagers.csproj | 7 +- NHSE.Villagers/VillagerData.cs | 25 +- NHSE.Villagers/VillagerInfo.cs | 23 +- NHSE.Villagers/VillagerResources.cs | 59 +- NHSE.Villagers/VillagerSwap.cs | 55 +- NHSE.WinForms/Controls/AchievementRow.cs | 95 +- NHSE.WinForms/Controls/ItemEditor.cs | 723 ++-- NHSE.WinForms/Controls/ItemGrid.cs | 137 +- NHSE.WinForms/Controls/ItemGridEditor.cs | 607 ++- .../Controls/RestrictedItemSelect.cs | 83 +- NHSE.WinForms/Controls/VillagerEditor.cs | 620 ++- NHSE.WinForms/Editor.cs | 1011 +++-- NHSE.WinForms/FodyWeavers.xml | 4 - NHSE.WinForms/FodyWeavers.xsd | 111 - NHSE.WinForms/Main.cs | 340 +- NHSE.WinForms/NHSE.WinForms.csproj | 92 +- NHSE.WinForms/Program.cs | 34 +- NHSE.WinForms/Subforms/Map/BuildingHelp.cs | 44 +- NHSE.WinForms/Subforms/Map/BulkSpawn.cs | 321 +- NHSE.WinForms/Subforms/Map/FieldItemEditor.cs | 2091 +++++----- NHSE.WinForms/Subforms/Map/LandFlagEditor.cs | 115 +- NHSE.WinForms/Subforms/Map/MapDumpHelper.cs | 460 +-- NHSE.WinForms/Subforms/Map/MiscDumpHelper.cs | 486 ++- NHSE.WinForms/Subforms/Map/MuseumEditor.cs | 227 +- NHSE.WinForms/Subforms/Map/PatternEditor.cs | 340 +- .../Subforms/Map/PatternEditorPRO.cs | 350 +- .../Subforms/Map/PlayerHouseEditor.cs | 596 +-- .../Subforms/Map/PlayerHouseFlagEditor.cs | 115 +- .../Subforms/Map/TerrainBrushEditor.cs | 579 ++- .../Subforms/Map/VillagerHouseEditor.cs | 245 +- .../Subforms/Player/AchievementEditor.cs | 251 +- NHSE.WinForms/Subforms/Player/FlagEditor.cs | 137 +- .../Subforms/Player/ItemReceivedEditor.cs | 361 +- .../Subforms/Player/MiscPlayerEditor.cs | 103 +- .../Subforms/Player/ReactionEditor.cs | 61 +- .../Subforms/Player/RecipeListEditor.cs | 295 +- NHSE.WinForms/Subforms/PlayerItemEditor.cs | 293 +- .../Subforms/Program/ImageFetcher.cs | 231 +- .../Subforms/Program/SettingsEditor.cs | 43 +- NHSE.WinForms/Subforms/SingleItemEditor.cs | 45 +- NHSE.WinForms/Subforms/SingleObjectEditor.cs | 47 +- NHSE.WinForms/Subforms/SysBot/BatchEditor.cs | 277 +- .../Subforms/SysBot/SimpleHexEditor.cs | 39 +- .../Subforms/SysBot/SysBotController.cs | 177 +- .../Subforms/SysBot/SysBotRAMEdit.cs | 91 +- NHSE.WinForms/Subforms/SysBot/SysBotUI.cs | 391 +- .../Subforms/SysBot/USBBotController.cs | 81 +- .../Villager/SaveRoomFloorWallEditor.cs | 143 +- .../Villager/VillagerDIYTimerEditor.cs | 119 +- .../Subforms/Villager/VillagerFlagEditor.cs | 115 +- .../Subforms/Villager/VillagerMemoryEditor.cs | 307 +- NHSE.WinForms/Util/DevUtil.cs | 285 +- NHSE.WinForms/Util/FileUtil.cs | 37 +- NHSE.WinForms/Util/InterpolatingPictureBox.cs | 31 +- NHSE.WinForms/Util/MessageStrings.cs | 89 +- NHSE.WinForms/Util/TranslationUtil.cs | 208 +- NHSE.WinForms/Util/WinFormsTranslator.cs | 549 +-- NHSE.WinForms/Util/WinFormsUtil.cs | 145 +- NHSE.sln | 91 - NHSE.slnx | 15 + README.md | 5 - azure-pipelines.yml | 56 +- 316 files changed, 31897 insertions(+), 32159 deletions(-) create mode 100644 .editorconfig delete mode 100644 NHSE.Core/Util/FrameworkUtil.cs delete mode 100644 NHSE.WinForms/FodyWeavers.xml delete mode 100644 NHSE.WinForms/FodyWeavers.xsd delete mode 100644 NHSE.sln create mode 100644 NHSE.slnx diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..bf1bd73 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,115 @@ +root = true + +# All Files +[*] +charset = utf-8-bom +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +# XML Project Files +[*.{csproj,slnx,props}] +indent_style = space +indent_size = 2 + +# Code Files +[*.cs] +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 +tab_width = 4 +end_of_line = crlf +csharp_prefer_braces = when_multiline:warning +dotnet_diagnostic.IDE0047.severity = none +dotnet_diagnostic.IDE0048.severity = none +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggest +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggest +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggest +dotnet_style_parentheses_in_other_operators = always_for_clarity:suggest +csharp_indent_labels = one_less_than_current +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_prefer_system_threading_lock = true:suggestion +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +dotnet_diagnostic.WFO1000.severity = none + +[*.{cs,vb}] +#### Naming styles #### + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion + +# IDE0130: Namespace does not match folder structure +dotnet_diagnostic.IDE0130.severity = none diff --git a/.github/README-es.md b/.github/README-es.md index e756418..04bb50a 100644 --- a/.github/README-es.md +++ b/.github/README-es.md @@ -11,11 +11,6 @@ Editor de partidas guardadas para Animal Crossing: New Horizons Permite editar partidas guardadas extraídas del Nintendo Switch. * Debes extraer las partidas guardadas de la consola tu mismo, este programa no las extrae por ti. -## Véase también - -[MyHorizons](https://github.com/Cuyler36/MyHorizons) de [Cuyler36](https://github.com/Cuyler36/) -* Algunas partes del código fueron adaptadas del proyecto MyHorizons de Cuyler36 (arriba) - ## Otro Dirígete a la [Wiki](https://github.com/kwsch/NHSE/wiki) para más información. diff --git a/.github/README-fr.md b/.github/README-fr.md index 13f9423..1611c45 100644 --- a/.github/README-fr.md +++ b/.github/README-fr.md @@ -10,11 +10,6 @@ NHSE Modifiez les données de sauvegarde extraites de votre Nintendo Switch. * Veuillez préparer vos propres données de sauvegarde. Ce programme n'extrait pas les données de sauvegarde de la console. -## Voir également - -[MyHorizons](https://github.com/Cuyler36/MyHorizons) par [Cuyler36](https://github.com/Cuyler36/) -* Une partie du code est fortement adaptée du projet de Cuyler36 ci-dessus. - ## Autre Consultez le [Wiki](https://github.com/kwsch/NHSE/wiki) pour plus d'informations. diff --git a/.github/README-it.md b/.github/README-it.md index 0fb79c3..b84098a 100644 --- a/.github/README-it.md +++ b/.github/README-it.md @@ -11,11 +11,6 @@ Modificatore di salvataggi per Animal Crossing: New Horizons Puoi modificare i salvataggi esportati dalla tua Nintendo Switch. * Esporta i tuoi salvataggi; Questo programma non può esportare direttamente i salvataggi dalla tua console. -## Guarda Anche - -[MyHorizons](https://github.com/Cuyler36/MyHorizons) di [Cuyler36](https://github.com/Cuyler36/) -* Alcune porzioni del codice sono completamente adattate dal progetto di Cuyler36. - ## Altro Per ulteriori informazioni, consultare la nostra [Wiki](https://github.com/kwsch/NHSE/wiki) (in inglese). diff --git a/.github/README-jp.md b/.github/README-jp.md index 2659547..4c52b57 100644 --- a/.github/README-jp.md +++ b/.github/README-jp.md @@ -11,11 +11,6 @@ NHSE Nintendo Switch から抽出したセーブデータを編集します。 * 自分のセーブデータを用意してください。このプログラムはコンソールからセーブデータを抽出しません。 -## 参考 - -[MyHorizons](https://github.com/Cuyler36/MyHorizons) by [Cuyler36](https://github.com/Cuyler36/) -* コードの一部は上記の Cuyler36 のプロジェクトから大いに翻案されています。 - ## その他 詳しくは [Wiki](https://github.com/kwsch/NHSE/wiki) を参照してください。 diff --git a/.github/README-zh-CN.md b/.github/README-zh-CN.md index f9cc385..c610e74 100644 --- a/.github/README-zh-CN.md +++ b/.github/README-zh-CN.md @@ -10,10 +10,6 @@ NHSE 可以编辑你从Nintendo Switch中导出的存档。 * 请自行解决存档导出问题,本程序并不能直接从你的Switch中导出存档。 -## 参见 - -[MyHorizons](https://github.com/Cuyler36/MyHorizons) by [Cuyler36](https://github.com/Cuyler36/) -* 代码的某些部分完全改编自Cuyler36的项目。 ## 其他 diff --git a/Directory.Build.props b/Directory.Build.props index d33a2f3..081ad4a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,9 @@ - 10 + 14 + net10.0 enable NHSE + true diff --git a/NHSE.Core/Drawing/AcreTileColor.cs b/NHSE.Core/Drawing/AcreTileColor.cs index 2c0e10e..b422edb 100644 --- a/NHSE.Core/Drawing/AcreTileColor.cs +++ b/NHSE.Core/Drawing/AcreTileColor.cs @@ -1,22 +1,21 @@ using System.Drawing; -namespace NHSE.Core +namespace NHSE.Core; + +public static class AcreTileColor { - public static class AcreTileColor + public static readonly byte[] AcreTiles = ResourceUtil.GetBinaryResource("outside.bin"); + + public static int GetAcreTileColor(ushort acre, int x, int y) { - public static readonly byte[] AcreTiles = ResourceUtil.GetBinaryResource("outside.bin"); + if (acre > (ushort)OutsideAcre.FldOutNGardenRFront00) + return Color.Transparent.ToArgb(); + var baseOfs = acre * 32 * 32 * 4; - public static int GetAcreTileColor(ushort acre, int x, int y) - { - if (acre > (ushort)OutsideAcre.FldOutNGardenRFront00) - return Color.Transparent.ToArgb(); - var baseOfs = acre * 32 * 32 * 4; - - // 64x64 - var shift = (4 * ((y * 64) + x)); - var ofs = baseOfs + shift; - var tile = AcreTiles[ofs]; - return CollisionUtil.Dict[tile].ToArgb(); - } + // 64x64 + var shift = (4 * ((y * 64) + x)); + var ofs = baseOfs + shift; + var tile = AcreTiles[ofs]; + return CollisionUtil.Dict[tile].ToArgb(); } -} +} \ No newline at end of file diff --git a/NHSE.Core/Drawing/ColorUtil.cs b/NHSE.Core/Drawing/ColorUtil.cs index 9e16f86..ce0e1b3 100644 --- a/NHSE.Core/Drawing/ColorUtil.cs +++ b/NHSE.Core/Drawing/ColorUtil.cs @@ -1,54 +1,53 @@ using System.Drawing; using System.Linq; -namespace NHSE.Core +namespace NHSE.Core; + +public static class ColorUtil { - public static class ColorUtil + public static Color GetColor(int index) { - public static Color GetColor(int index) - { - var arr = Colors; - if ((uint) index < arr.Length) - return arr[index]; + var arr = Colors; + if ((uint) index < arr.Length) + return arr[index]; - // loop back and blend with something else - index %= arr.Length; - var c = arr[index]; - return Blend(Color.Red, c, 0.2f); - } - - private static readonly Color[] Colors = new[] - { - 0xD9D9D9, 0xCCD9E8, 0x7F7F7F, 0xD5D5D5, 0xF7F7F7, 0xCFCFCF, 0xB4B4B4, 0xF1F1F1, - 0xFFFFFF, 0x7F7F7F, 0x7F7F7F, 0xB6B6B6, 0x7FBBEB, 0xFFFFFF, 0x7FB2E5, 0xF9FBFD, - 0xDFE6ED, 0x7F7F7F, 0xFFFFF0, 0x7F7F7F, 0xF7F7F7, 0x7F7F7F, 0xE3E3E3, 0xFFFFFF, - 0xB1B1B1, 0x7F7F7F, 0xFFFFFF, 0xF7FBFF, 0xFCF5EB, 0x7FFFFF, 0xBFFFE9, 0xF7FFFF, - 0xFAFAED, 0xFFF1E1, 0x7F7F7F, 0xFFF5E6, 0x7F7FFF, 0xC495F0, 0xD29494, 0xEEDBC3, - 0xAFCECF, 0xBFFF7F, 0xE8B48E, 0xFFBFA7, 0xB1CAF6, 0xFFFBED, 0xED899D, 0x7FFFFF, - 0x7F7FC5, 0x7FC5C5, 0xDBC285, 0xD4D4D4, 0x7FB17F, 0xDEDBB5, 0xC57FC5, 0xAAB597, - 0xFFC57F, 0xCC98E5, 0xC57F7F, 0xF4CABC, 0xC7DDC5, 0xA39EC5, 0x97A7A7, 0x7FE6E8, - 0xC97FE9, 0xFF89C9, 0x7FDFFF, 0xB4B4B4, 0x8EC7FF, 0xD89090, 0xFFFCF7, 0x90C590, - 0xFF7FFF, 0xEDEDED, 0xFBFBFF, 0xFFEB7F, 0xECD28F, 0xBFBFBF, 0x7FBF7F, 0xD6FF97, - 0xF7FFF7, 0xFFB4D9, 0xE6ADAD, 0xA57FC0, 0xFFFFF7, 0xF7F2C5, 0xF2F2FC, 0xFFF7FA, - 0xBDFD7F, 0xFFFCE6, 0xD6EBF2, 0xF7BFBF, 0xEFFFFF, 0xFCFCE8, 0xE9E9E9, 0xC7F6C7, - 0xFFDAE0, 0xFFCFBC, 0x8FD8D4, 0xC3E6FC, 0xBBC3CC, 0xD7E1EE, 0xFFFFEF, 0x7FFF7F, - 0x98E698, 0xFCF7F2, 0xFF7FFF, 0xBF7F7F, 0xB2E6D4, 0x7F7FE6, 0xDCAAE9, 0xC9B7ED, - 0x9DD9B8, 0xBDB3F6, 0x7FFCCC, 0xA3E8E5, 0xE38AC2, 0x8C8CB7, 0xFAFFFC, 0xFFF1F0, - 0xFFF1DA, 0xFFEED6, 0x7F7FBF, 0xFEFAF2, 0xBFBF7F, 0xB5C691, 0xFFD27F, 0xFFA27F, - 0xECB7EA, 0xF6F3D4, 0xCBFDCB, 0xD7F6F6, 0xEDB7C9, 0xFFF7EA, 0xFFECDC, 0xE6C29F, - 0xFFDFE5, 0xEECFEE, 0xD7EFF2, 0xBF7FBF, 0xFF7F7F, 0xDDC7C7, 0xA0B4F0, 0xC5A289, - 0xFCBFB8, 0xF9D1AF, 0x96C5AB, 0xFFFAF6, 0xCFA896, 0xDFDFDF, 0xC3E6F5, 0xB4ACE6, - 0xB7BFC7, 0xFFFCFC, 0x7FFFBF, 0xA2C0D9, 0xE8D9C5, 0x7FBFBF, 0xEBDFEB, 0xFFB1A3, - 0x9FEFE7, 0xF6C0F6, 0xFAEED9, 0xFFFFFF, 0xFAFAFA, 0xFFFF7F, 0xCCE698, 0xF7F7F7, - 0xFFFFFF, 0xCFCFCF, 0xDCE8F4, 0xEBF1F8, 0xF7F7F7, 0x99CCFF, - }.Select(z => Color.FromArgb(z | -0x1000000)).ToArray(); - - public static Color Blend(Color color, Color backColor, double amount) - { - byte r = (byte)((color.R * amount) + (backColor.R * (1 - amount))); - byte g = (byte)((color.G * amount) + (backColor.G * (1 - amount))); - byte b = (byte)((color.B * amount) + (backColor.B * (1 - amount))); - return Color.FromArgb(r, g, b); - } + // loop back and blend with something else + index %= arr.Length; + var c = arr[index]; + return Blend(Color.Red, c, 0.2f); } -} + + private static readonly Color[] Colors = new[] + { + 0xD9D9D9, 0xCCD9E8, 0x7F7F7F, 0xD5D5D5, 0xF7F7F7, 0xCFCFCF, 0xB4B4B4, 0xF1F1F1, + 0xFFFFFF, 0x7F7F7F, 0x7F7F7F, 0xB6B6B6, 0x7FBBEB, 0xFFFFFF, 0x7FB2E5, 0xF9FBFD, + 0xDFE6ED, 0x7F7F7F, 0xFFFFF0, 0x7F7F7F, 0xF7F7F7, 0x7F7F7F, 0xE3E3E3, 0xFFFFFF, + 0xB1B1B1, 0x7F7F7F, 0xFFFFFF, 0xF7FBFF, 0xFCF5EB, 0x7FFFFF, 0xBFFFE9, 0xF7FFFF, + 0xFAFAED, 0xFFF1E1, 0x7F7F7F, 0xFFF5E6, 0x7F7FFF, 0xC495F0, 0xD29494, 0xEEDBC3, + 0xAFCECF, 0xBFFF7F, 0xE8B48E, 0xFFBFA7, 0xB1CAF6, 0xFFFBED, 0xED899D, 0x7FFFFF, + 0x7F7FC5, 0x7FC5C5, 0xDBC285, 0xD4D4D4, 0x7FB17F, 0xDEDBB5, 0xC57FC5, 0xAAB597, + 0xFFC57F, 0xCC98E5, 0xC57F7F, 0xF4CABC, 0xC7DDC5, 0xA39EC5, 0x97A7A7, 0x7FE6E8, + 0xC97FE9, 0xFF89C9, 0x7FDFFF, 0xB4B4B4, 0x8EC7FF, 0xD89090, 0xFFFCF7, 0x90C590, + 0xFF7FFF, 0xEDEDED, 0xFBFBFF, 0xFFEB7F, 0xECD28F, 0xBFBFBF, 0x7FBF7F, 0xD6FF97, + 0xF7FFF7, 0xFFB4D9, 0xE6ADAD, 0xA57FC0, 0xFFFFF7, 0xF7F2C5, 0xF2F2FC, 0xFFF7FA, + 0xBDFD7F, 0xFFFCE6, 0xD6EBF2, 0xF7BFBF, 0xEFFFFF, 0xFCFCE8, 0xE9E9E9, 0xC7F6C7, + 0xFFDAE0, 0xFFCFBC, 0x8FD8D4, 0xC3E6FC, 0xBBC3CC, 0xD7E1EE, 0xFFFFEF, 0x7FFF7F, + 0x98E698, 0xFCF7F2, 0xFF7FFF, 0xBF7F7F, 0xB2E6D4, 0x7F7FE6, 0xDCAAE9, 0xC9B7ED, + 0x9DD9B8, 0xBDB3F6, 0x7FFCCC, 0xA3E8E5, 0xE38AC2, 0x8C8CB7, 0xFAFFFC, 0xFFF1F0, + 0xFFF1DA, 0xFFEED6, 0x7F7FBF, 0xFEFAF2, 0xBFBF7F, 0xB5C691, 0xFFD27F, 0xFFA27F, + 0xECB7EA, 0xF6F3D4, 0xCBFDCB, 0xD7F6F6, 0xEDB7C9, 0xFFF7EA, 0xFFECDC, 0xE6C29F, + 0xFFDFE5, 0xEECFEE, 0xD7EFF2, 0xBF7FBF, 0xFF7F7F, 0xDDC7C7, 0xA0B4F0, 0xC5A289, + 0xFCBFB8, 0xF9D1AF, 0x96C5AB, 0xFFFAF6, 0xCFA896, 0xDFDFDF, 0xC3E6F5, 0xB4ACE6, + 0xB7BFC7, 0xFFFCFC, 0x7FFFBF, 0xA2C0D9, 0xE8D9C5, 0x7FBFBF, 0xEBDFEB, 0xFFB1A3, + 0x9FEFE7, 0xF6C0F6, 0xFAEED9, 0xFFFFFF, 0xFAFAFA, 0xFFFF7F, 0xCCE698, 0xF7F7F7, + 0xFFFFFF, 0xCFCFCF, 0xDCE8F4, 0xEBF1F8, 0xF7F7F7, 0x99CCFF, + }.Select(z => Color.FromArgb(z | -0x1000000)).ToArray(); + + public static Color Blend(Color color, Color backColor, double amount) + { + byte r = (byte)((color.R * amount) + (backColor.R * (1 - amount))); + byte g = (byte)((color.G * amount) + (backColor.G * (1 - amount))); + byte b = (byte)((color.B * amount) + (backColor.B * (1 - amount))); + return Color.FromArgb(r, g, b); + } +} \ No newline at end of file diff --git a/NHSE.Core/Drawing/FieldItemColor.cs b/NHSE.Core/Drawing/FieldItemColor.cs index 1633a2a..484a3f5 100644 --- a/NHSE.Core/Drawing/FieldItemColor.cs +++ b/NHSE.Core/Drawing/FieldItemColor.cs @@ -1,79 +1,78 @@ using System.Drawing; -namespace NHSE.Core +namespace NHSE.Core; + +public static class FieldItemColor { - public static class FieldItemColor + public static Color GetItemColor(Item item) { - public static Color GetItemColor(Item item) - { - if (item.DisplayItemId >= Item.FieldItemMin) - return GetItemColor60000(item); - var kind = ItemInfo.GetItemKind(item); - return ColorUtil.GetColor((int)kind); - } - - private static Color GetItemColor60000(Item item) - { - var id = item.DisplayItemId; - if (id == Item.NONE) - return Color.Transparent; - - if (!FieldItemList.Items.TryGetValue(id, out var def)) - return Color.DarkGreen; - - var kind = def.Kind; - if (kind.IsTree()) - return GetTreeColor(id); - if (kind.IsFlower()) - return Color.HotPink; - if (kind.IsWeed()) - return Color.DarkOliveGreen; - if (kind.IsFence()) - return Color.LightCoral; - if (kind == FieldItemKind.UnitIconHole) - return Color.Black; - if (kind.IsBush()) - return Color.LightGreen; - if (kind.IsStone()) - return Color.LightGray; - - return Color.DarkGreen; // shouldn't reach here, but ok - } - - private static Color GetTreeColor(ushort id) - { - if (0xEC9C <= id && id <= 0xECA0) // money tree - return Color.Gold; - - return id switch - { - // Fruit - 0xEA61 => Color.Red, // "PltTreeApple" - 0xEA62 => Color.Orange, // "PltTreeOrange" - 0xEAC8 => Color.Lime, // "PltTreePear" - 0xEAC9 => Color.DarkRed, // "PltTreeCherry" - 0xEACA => Color.PeachPuff, // "PltTreePeach" - - // Cedar - 0xEA69 => Color.SaddleBrown, // "PltTreeCedar4" - 0xEAB6 => Color.SaddleBrown, // "PltTreeCedar2" - 0xEAB7 => Color.SaddleBrown, // "PltTreeCedar1" - 0xEAB8 => Color.SaddleBrown, // "PltTreeCedar3" - - // Palm - 0xEA77 => Color.LightGoldenrodYellow, // "PltTreePalm4" - 0xEAC0 => Color.LightGoldenrodYellow, // "PltTreePalm2" - 0xEAC1 => Color.LightGoldenrodYellow, // "PltTreePalm1" - 0xEAC2 => Color.LightGoldenrodYellow, // "PltTreePalm3" - - 0xEA76 => Color.MediumSeaGreen, // "PltTreeBamboo4" - 0xEAC4 => Color.MediumSeaGreen, // "PltTreeBamboo0" - 0xEAC5 => Color.MediumSeaGreen, // "PltTreeBamboo2" - 0xEAC6 => Color.MediumSeaGreen, // "PltTreeBamboo1" - 0xEAC7 => Color.MediumSeaGreen, // "PltTreeBamboo3" - - _ => Color.SandyBrown, - }; - } + if (item.DisplayItemId >= Item.FieldItemMin) + return GetItemColor60000(item); + var kind = ItemInfo.GetItemKind(item); + return ColorUtil.GetColor((int)kind); } -} + + private static Color GetItemColor60000(Item item) + { + var id = item.DisplayItemId; + if (id == Item.NONE) + return Color.Transparent; + + if (!FieldItemList.Items.TryGetValue(id, out var def)) + return Color.DarkGreen; + + var kind = def.Kind; + if (kind.IsTree) + return GetTreeColor(id); + if (kind.IsFlower) + return Color.HotPink; + if (kind.IsWeed) + return Color.DarkOliveGreen; + if (kind.IsFence) + return Color.LightCoral; + if (kind == FieldItemKind.UnitIconHole) + return Color.Black; + if (kind.IsBush) + return Color.LightGreen; + if (kind.IsStone) + return Color.LightGray; + + return Color.DarkGreen; // shouldn't reach here, but ok + } + + private static Color GetTreeColor(ushort id) + { + if (id is >= 0xEC9C and <= 0xECA0) // money tree + return Color.Gold; + + return id switch + { + // Fruit + 0xEA61 => Color.Red, // "PltTreeApple" + 0xEA62 => Color.Orange, // "PltTreeOrange" + 0xEAC8 => Color.Lime, // "PltTreePear" + 0xEAC9 => Color.DarkRed, // "PltTreeCherry" + 0xEACA => Color.PeachPuff, // "PltTreePeach" + + // Cedar + 0xEA69 => Color.SaddleBrown, // "PltTreeCedar4" + 0xEAB6 => Color.SaddleBrown, // "PltTreeCedar2" + 0xEAB7 => Color.SaddleBrown, // "PltTreeCedar1" + 0xEAB8 => Color.SaddleBrown, // "PltTreeCedar3" + + // Palm + 0xEA77 => Color.LightGoldenrodYellow, // "PltTreePalm4" + 0xEAC0 => Color.LightGoldenrodYellow, // "PltTreePalm2" + 0xEAC1 => Color.LightGoldenrodYellow, // "PltTreePalm1" + 0xEAC2 => Color.LightGoldenrodYellow, // "PltTreePalm3" + + 0xEA76 => Color.MediumSeaGreen, // "PltTreeBamboo4" + 0xEAC4 => Color.MediumSeaGreen, // "PltTreeBamboo0" + 0xEAC5 => Color.MediumSeaGreen, // "PltTreeBamboo2" + 0xEAC6 => Color.MediumSeaGreen, // "PltTreeBamboo1" + 0xEAC7 => Color.MediumSeaGreen, // "PltTreeBamboo3" + + _ => Color.SandyBrown, + }; + } +} \ No newline at end of file diff --git a/NHSE.Core/Drawing/ItemColor.cs b/NHSE.Core/Drawing/ItemColor.cs index 031e1da..c4c07ab 100644 --- a/NHSE.Core/Drawing/ItemColor.cs +++ b/NHSE.Core/Drawing/ItemColor.cs @@ -1,27 +1,26 @@ using System.Drawing; -namespace NHSE.Core -{ - public static class ItemColor - { - public static Color GetItemColor(Item item) - { - if (item.ItemId == Item.NONE) - return Color.Transparent; - var kind = ItemInfo.GetItemKind(item); - if (kind == ItemKind.Unknown) - return Color.LimeGreen; - return ColorUtil.GetColor((int)kind); - } +namespace NHSE.Core; - public static Color GetItemColor(ushort item) - { - if (item == Item.NONE) - return Color.Transparent; - var kind = ItemInfo.GetItemKind(item); - if (kind == ItemKind.Unknown) - return Color.LimeGreen; - return ColorUtil.GetColor((int)kind); - } +public static class ItemColor +{ + public static Color GetItemColor(Item item) + { + if (item.ItemId == Item.NONE) + return Color.Transparent; + var kind = ItemInfo.GetItemKind(item); + if (kind == ItemKind.Unknown) + return Color.LimeGreen; + return ColorUtil.GetColor((int)kind); } -} + + public static Color GetItemColor(ushort item) + { + if (item == Item.NONE) + return Color.Transparent; + var kind = ItemInfo.GetItemKind(item); + if (kind == ItemKind.Unknown) + return Color.LimeGreen; + return ColorUtil.GetColor((int)kind); + } +} \ No newline at end of file diff --git a/NHSE.Core/Drawing/TerrainTileColor.cs b/NHSE.Core/Drawing/TerrainTileColor.cs index c4b0fec..78a2453 100644 --- a/NHSE.Core/Drawing/TerrainTileColor.cs +++ b/NHSE.Core/Drawing/TerrainTileColor.cs @@ -3,240 +3,237 @@ using static NHSE.Core.TerrainUnitModel; using static NHSE.Core.LandAngles; -namespace NHSE.Core +namespace NHSE.Core; + +public static class TerrainTileColor { - public static class TerrainTileColor + private static readonly Color River = Color.FromArgb(128, 215, 195); + private static readonly Color Grass = Color.ForestGreen; + + public static Color GetTileColor(TerrainTile tile, int relativeX, int relativeY) { - private static readonly Color River = Color.FromArgb(128, 215, 195); - private static readonly Color Grass = Color.ForestGreen; + if (tile.UnitModelRoad.IsRoad) + return GetRoadColor(tile.UnitModelRoad); + var baseColor = GetTileDefaultColor(tile.UnitModel, tile.LandMakingAngle, relativeX, relativeY); + if (tile.Elevation == 0) + return baseColor; - public static Color GetTileColor(TerrainTile tile, int relativeX, int relativeY) - { - if (tile.UnitModelRoad.IsRoad()) - return GetRoadColor(tile.UnitModelRoad); - var baseColor = GetTileDefaultColor(tile.UnitModel, tile.LandMakingAngle, relativeX, relativeY); - if (tile.Elevation == 0) - return baseColor; - - return ColorUtil.Blend(baseColor, Color.White, 1.4d / (tile.Elevation + 1)); - } - - private static Color GetRoadColor(TerrainUnitModel mdl) - { - if (mdl.IsRoadBrick()) - return Color.Firebrick; - if (mdl.IsRoadDarkSoil()) - return Color.SaddleBrown; - if (mdl.IsRoadSoil()) - return Color.Peru; - if (mdl.IsRoadStone()) - return Color.DarkGray; - if (mdl.IsRoadPattern()) - return Color.Ivory; - if (mdl.IsRoadTile()) - return Color.SteelBlue; - if (mdl.IsRoadSand()) - return Color.SandyBrown; - return Color.BurlyWood; - } - - /// Notes about rivers the number is how many sides / diagonals are water. - private static Color GetRiverColor(TerrainUnitModel mdl, LandAngles landAngle, int relativeX, int relativeY) - { - return mdl switch - { - // River0A single "hole" of water land all sides. Rotation does nothing - River0A when (relativeX < 4 || relativeX >= 12 || relativeY < 4 || relativeY >= 12) => - Grass, - // River1A narrow channel end opening on bottom, land on other sides - River1A => landAngle switch - { - Default when relativeX < 4 || relativeX >= 12 || relativeY < 4 => Grass, - Rotate90ClockAnverse when relativeX < 4 || relativeY < 4 || relativeY >= 12 => Grass, - Rotate180ClockAnverse when relativeX < 4 || relativeX >= 12 || relativeY >= 12 => Grass, - Rotate270ClockAnverse when relativeY < 4 || relativeY >= 12 || relativeX >= 12 => Grass, - _ => River - }, - // River2A narrow water channel opening on top and bottom, land left and right - River2A => landAngle switch - { - Default when relativeX is < 4 or >= 12 => Grass, - Rotate90ClockAnverse when relativeY is >= 12 or < 4 => Grass, - Rotate180ClockAnverse when relativeX is < 4 or >= 12 => Grass, - Rotate270ClockAnverse when relativeY is < 4 or >= 12 => Grass, - _ => River - }, - // River2B narrow 45 channel angled land top left with nub bottom right - River2B => landAngle switch - { - Default when IsPointInMultiTriangle(relativeX, relativeY, new(4, 15), new(0, 0), new(15, 4), new(0, 15), new(15, 0)) || IsNubOnBottomRight(relativeX, relativeY) || relativeX < 4 || relativeY < 4 => Grass, - Rotate90ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(4, 0), new(0, 15), new(15, 12), new(0, 0), new(15, 15)) || IsNubOnTopRight(relativeX, relativeY) || relativeX < 4 || relativeY >= 12 => Grass, - Rotate180ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 12), new(15, 15), new(12, 0), new(0, 15), new(15, 0)) || IsNubOnTopLeft(relativeX, relativeY) || relativeX >= 12 || relativeY >= 12 => Grass, - Rotate270ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 4), new(15, 0), new(12, 15), new(0, 0), new(15, 15)) || IsNubOnBottomLeft(relativeX, relativeY) || relativeX >= 12 || relativeY < 4 => Grass, - _ => River - }, - // River2C narrow 90 channel corner land top left with nub bottom right - River2C => landAngle switch - { - Default when relativeX < 4 || relativeY < 4 || IsNubOnBottomRight(relativeX, relativeY) => Grass, - Rotate90ClockAnverse when relativeX < 4 || relativeY >= 12 || IsNubOnTopRight(relativeX, relativeY) => Grass, - Rotate180ClockAnverse when relativeX >= 12 || relativeY >= 12 || IsNubOnTopLeft(relativeX, relativeY) => Grass, - Rotate270ClockAnverse when relativeX >= 12 || relativeY < 4 || IsNubOnBottomLeft(relativeX, relativeY) => Grass, - _ => River - }, - // River3A narrow 3 way land left side, nub top right and bottom right - River3A => landAngle switch - { - Default when relativeX < 4 || IsNubOnTopRight(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, - Rotate90ClockAnverse when relativeY >= 12 || IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, - Rotate180ClockAnverse when relativeX >= 12 || IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) => Grass, - Rotate270ClockAnverse when relativeY < 4 || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnBottomLeft(relativeX, relativeY) => Grass, - _ => River - }, - // River3B river 45 corner angled land top left, no nub - River3B => landAngle switch - { - Default when IsPointInMultiTriangle(relativeX, relativeY, new(4, 15), new(0, 0), new(15, 4), new(0, 15), new(15, 0)) => Grass, - Rotate90ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(4, 0), new(0, 15), new(15, 12), new(0, 0), new(15, 15)) => Grass, - Rotate180ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 12), new(15, 15), new(12, 0), new(0, 15), new(15, 0)) => Grass, - Rotate270ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 4), new(15, 0), new(12, 15), new(0, 0), new(15, 15)) => Grass, - _ => River - }, - // River3C river 90 corner corner land top left, no nub - River3C => landAngle switch - { - Default when relativeX < 4 || relativeY < 4 => Grass, - Rotate90ClockAnverse when relativeX < 4 || relativeY >= 12 => Grass, - Rotate180ClockAnverse when relativeX >= 12 || relativeY >= 12 => Grass, - Rotate270ClockAnverse when relativeX >= 12 || relativeY < 4 => Grass, - _ => River - }, - // River4A river side with nub top land left side with nub top right only - River4A => landAngle switch - { - Default when relativeX < 4 || IsNubOnTopRight(relativeX, relativeY) => Grass, - Rotate90ClockAnverse when relativeY >= 12 || IsNubOnTopLeft(relativeX, relativeY) => Grass, - Rotate180ClockAnverse when relativeX >= 12 || IsNubOnBottomLeft(relativeX, relativeY) => Grass, - Rotate270ClockAnverse when relativeY < 4 || IsNubOnBottomRight(relativeX, relativeY) => Grass, - _ => River - }, - // River4B river side with nub bottom land left side with nub bottom right only - River4B => landAngle switch - { - Default when relativeX < 4 || IsNubOnBottomRight(relativeX, relativeY) => Grass, - Rotate90ClockAnverse when relativeY >= 12 || IsNubOnTopRight(relativeX, relativeY) => Grass, - Rotate180ClockAnverse when relativeX >= 12 || IsNubOnTopLeft(relativeX, relativeY) => Grass, - Rotate270ClockAnverse when relativeY < 4 || IsNubOnBottomLeft(relativeX, relativeY) => Grass, - _ => River - }, - // River4C narrow 4 way nub on all 4 corners, 4 sides water. rotation does nothing - River4C when (IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY)) => Grass, - // River5A river corner to 2 narrow Nub on top left, top right, and bottom right. 2 narrows meet a river - River5A => landAngle switch - { - Default when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, - Rotate90ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, - Rotate180ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) => Grass, - Rotate270ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, - _ => River - }, - // River5B river side land on left side - River5B => landAngle switch - { - Default when relativeX < 4 => Grass, - Rotate90ClockAnverse when relativeY >= 12 => Grass, - Rotate180ClockAnverse when relativeX >= 12 => Grass, - Rotate270ClockAnverse when relativeY < 4 => Grass, - _ => River - }, - // River6A river 2 opposing nubs nub on top left and bottom right - River6A => landAngle switch - { - Default when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, - Rotate90ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, - Rotate180ClockAnverse when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, - Rotate270ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, - _ => River - }, - // River6B river 2 nubs same side nub on bottom left and bottom right corner, where 1 narrow meets river bottom side - River6B => landAngle switch - { - Default when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, - Rotate90ClockAnverse when IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, - Rotate180ClockAnverse when IsNubOnTopRight(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) => Grass, - Rotate270ClockAnverse when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnBottomLeft(relativeX, relativeY) => Grass, - _ => River - }, - // River7A river 1 nub nub on bottom left corner, fills gaps of diagonal bank - River7A => landAngle switch - { - Default when IsNubOnBottomLeft(relativeX, relativeY) => Grass, - Rotate90ClockAnverse when IsNubOnBottomRight(relativeX, relativeY) => Grass, - Rotate180ClockAnverse when IsNubOnTopRight(relativeX, relativeY) => Grass, - Rotate270ClockAnverse when IsNubOnTopLeft(relativeX, relativeY) => Grass, - _ => River - }, - // River8A river is no land, just water. Rotation doesn't matter - River8A => River, - _ => River - }; - } - - private static bool IsNubOnTopLeft(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(0, 4), new(0, 0), new(4, 0)); - private static bool IsNubOnTopRight(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(12, 0), new(15, 0), new(15, 4)); - private static bool IsNubOnBottomLeft(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(0, 12), new(0, 15), new(4, 15)); - private static bool IsNubOnBottomRight(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(12, 15), new(15, 15), new(15, 12)); - - private static bool IsPointInMultiTriangle(int px, int py, Coordinate a, Coordinate b, Coordinate c, Coordinate vortexA, Coordinate vortexB) - { - return IsPointInTriangle(px, py, a, vortexA, b) - || IsPointInTriangle(px, py, a, b, c) - || IsPointInTriangle(px, py, c, b, vortexB); - } - - private static bool IsPointInTriangle(int px, int py, Coordinate a, Coordinate b, Coordinate c) - { - Coordinate p = new(px, py); - float areaTotal = GetTriangleArea(a, b, c); - float area1 = GetTriangleArea(p, b, c); - float area2 = GetTriangleArea(a, p, c); - float area3 = GetTriangleArea(a, b, p); - - return Math.Abs(areaTotal - (area1 + area2 + area3)) < 0.0001f; - } - - private static float GetTriangleArea(Coordinate A, Coordinate B, Coordinate C) - { - return Math.Abs((A.X * (B.Y - C.Y) + - B.X * (C.Y - A.Y) + - C.X * (A.Y - B.Y)) / 2.0f); - } - - private readonly record struct Coordinate(int X, int Y); - - private static readonly Color CliffBase = ColorUtil.Blend(Grass, Color.Black, 0.6d); - - private static Color GetTileDefaultColor(TerrainUnitModel mdl, ushort landAngle, int relativeX, int relativeY) - { - var angle = (LandAngles)landAngle; - if (mdl.IsRiver()) - return GetRiverColor(mdl, angle, relativeX, relativeY); - if (mdl.IsFall()) - return Color.DeepSkyBlue; - if (mdl.IsCliff()) - return CliffBase; - return Grass; - } - - private static readonly char[] Numbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; - - public static string GetTileName(TerrainTile tile) - { - var name = tile.UnitModel.ToString(); - var num = name.IndexOfAny(Numbers); - if (num < 0) - return name; - return name.Substring(0, num) + Environment.NewLine + name.Substring(num); - } + return ColorUtil.Blend(baseColor, Color.White, 1.4d / (tile.Elevation + 1)); } -} + + private static Color GetRoadColor(TerrainUnitModel mdl) + { + if (mdl.IsRoadBrick) + return Color.Firebrick; + if (mdl.IsRoadDarkSoil) + return Color.SaddleBrown; + if (mdl.IsRoadSoil) + return Color.Peru; + if (mdl.IsRoadStone) + return Color.DarkGray; + if (mdl.IsRoadPattern) + return Color.Ivory; + if (mdl.IsRoadTile) + return Color.SteelBlue; + if (mdl.IsRoadSand) + return Color.SandyBrown; + return Color.BurlyWood; + } + + /// Notes about rivers the number is how many sides / diagonals are water. + private static Color GetRiverColor(TerrainUnitModel mdl, LandAngles landAngle, int relativeX, int relativeY) + { + return mdl switch + { + // River0A single "hole" of water land all sides. Rotation does nothing + River0A when (relativeX < 4 || relativeX >= 12 || relativeY < 4 || relativeY >= 12) => + Grass, + // River1A narrow channel end opening on bottom, land on other sides + River1A => landAngle switch + { + Default when relativeX < 4 || relativeX >= 12 || relativeY < 4 => Grass, + Rotate90ClockAnverse when relativeX < 4 || relativeY < 4 || relativeY >= 12 => Grass, + Rotate180ClockAnverse when relativeX < 4 || relativeX >= 12 || relativeY >= 12 => Grass, + Rotate270ClockAnverse when relativeY < 4 || relativeY >= 12 || relativeX >= 12 => Grass, + _ => River + }, + // River2A narrow water channel opening on top and bottom, land left and right + River2A => landAngle switch + { + Default when relativeX is < 4 or >= 12 => Grass, + Rotate90ClockAnverse when relativeY is >= 12 or < 4 => Grass, + Rotate180ClockAnverse when relativeX is < 4 or >= 12 => Grass, + Rotate270ClockAnverse when relativeY is < 4 or >= 12 => Grass, + _ => River + }, + // River2B narrow 45 channel angled land top left with nub bottom right + River2B => landAngle switch + { + Default when IsPointInMultiTriangle(relativeX, relativeY, new(4, 15), new(0, 0), new(15, 4), new(0, 15), new(15, 0)) || IsNubOnBottomRight(relativeX, relativeY) || relativeX < 4 || relativeY < 4 => Grass, + Rotate90ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(4, 0), new(0, 15), new(15, 12), new(0, 0), new(15, 15)) || IsNubOnTopRight(relativeX, relativeY) || relativeX < 4 || relativeY >= 12 => Grass, + Rotate180ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 12), new(15, 15), new(12, 0), new(0, 15), new(15, 0)) || IsNubOnTopLeft(relativeX, relativeY) || relativeX >= 12 || relativeY >= 12 => Grass, + Rotate270ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 4), new(15, 0), new(12, 15), new(0, 0), new(15, 15)) || IsNubOnBottomLeft(relativeX, relativeY) || relativeX >= 12 || relativeY < 4 => Grass, + _ => River + }, + // River2C narrow 90 channel corner land top left with nub bottom right + River2C => landAngle switch + { + Default when relativeX < 4 || relativeY < 4 || IsNubOnBottomRight(relativeX, relativeY) => Grass, + Rotate90ClockAnverse when relativeX < 4 || relativeY >= 12 || IsNubOnTopRight(relativeX, relativeY) => Grass, + Rotate180ClockAnverse when relativeX >= 12 || relativeY >= 12 || IsNubOnTopLeft(relativeX, relativeY) => Grass, + Rotate270ClockAnverse when relativeX >= 12 || relativeY < 4 || IsNubOnBottomLeft(relativeX, relativeY) => Grass, + _ => River + }, + // River3A narrow 3 way land left side, nub top right and bottom right + River3A => landAngle switch + { + Default when relativeX < 4 || IsNubOnTopRight(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, + Rotate90ClockAnverse when relativeY >= 12 || IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, + Rotate180ClockAnverse when relativeX >= 12 || IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) => Grass, + Rotate270ClockAnverse when relativeY < 4 || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnBottomLeft(relativeX, relativeY) => Grass, + _ => River + }, + // River3B river 45 corner angled land top left, no nub + River3B => landAngle switch + { + Default when IsPointInMultiTriangle(relativeX, relativeY, new(4, 15), new(0, 0), new(15, 4), new(0, 15), new(15, 0)) => Grass, + Rotate90ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(4, 0), new(0, 15), new(15, 12), new(0, 0), new(15, 15)) => Grass, + Rotate180ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 12), new(15, 15), new(12, 0), new(0, 15), new(15, 0)) => Grass, + Rotate270ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 4), new(15, 0), new(12, 15), new(0, 0), new(15, 15)) => Grass, + _ => River + }, + // River3C river 90 corner corner land top left, no nub + River3C => landAngle switch + { + Default when relativeX < 4 || relativeY < 4 => Grass, + Rotate90ClockAnverse when relativeX < 4 || relativeY >= 12 => Grass, + Rotate180ClockAnverse when relativeX >= 12 || relativeY >= 12 => Grass, + Rotate270ClockAnverse when relativeX >= 12 || relativeY < 4 => Grass, + _ => River + }, + // River4A river side with nub top land left side with nub top right only + River4A => landAngle switch + { + Default when relativeX < 4 || IsNubOnTopRight(relativeX, relativeY) => Grass, + Rotate90ClockAnverse when relativeY >= 12 || IsNubOnTopLeft(relativeX, relativeY) => Grass, + Rotate180ClockAnverse when relativeX >= 12 || IsNubOnBottomLeft(relativeX, relativeY) => Grass, + Rotate270ClockAnverse when relativeY < 4 || IsNubOnBottomRight(relativeX, relativeY) => Grass, + _ => River + }, + // River4B river side with nub bottom land left side with nub bottom right only + River4B => landAngle switch + { + Default when relativeX < 4 || IsNubOnBottomRight(relativeX, relativeY) => Grass, + Rotate90ClockAnverse when relativeY >= 12 || IsNubOnTopRight(relativeX, relativeY) => Grass, + Rotate180ClockAnverse when relativeX >= 12 || IsNubOnTopLeft(relativeX, relativeY) => Grass, + Rotate270ClockAnverse when relativeY < 4 || IsNubOnBottomLeft(relativeX, relativeY) => Grass, + _ => River + }, + // River4C narrow 4 way nub on all 4 corners, 4 sides water. rotation does nothing + River4C when (IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY)) => Grass, + // River5A river corner to 2 narrow Nub on top left, top right, and bottom right. 2 narrows meet a river + River5A => landAngle switch + { + Default when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, + Rotate90ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, + Rotate180ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) => Grass, + Rotate270ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, + _ => River + }, + // River5B river side land on left side + River5B => landAngle switch + { + Default when relativeX < 4 => Grass, + Rotate90ClockAnverse when relativeY >= 12 => Grass, + Rotate180ClockAnverse when relativeX >= 12 => Grass, + Rotate270ClockAnverse when relativeY < 4 => Grass, + _ => River + }, + // River6A river 2 opposing nubs nub on top left and bottom right + River6A => landAngle switch + { + Default when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, + Rotate90ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, + Rotate180ClockAnverse when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, + Rotate270ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, + _ => River + }, + // River6B river 2 nubs same side nub on bottom left and bottom right corner, where 1 narrow meets river bottom side + River6B => landAngle switch + { + Default when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass, + Rotate90ClockAnverse when IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass, + Rotate180ClockAnverse when IsNubOnTopRight(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) => Grass, + Rotate270ClockAnverse when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnBottomLeft(relativeX, relativeY) => Grass, + _ => River + }, + // River7A river 1 nub nub on bottom left corner, fills gaps of diagonal bank + River7A => landAngle switch + { + Default when IsNubOnBottomLeft(relativeX, relativeY) => Grass, + Rotate90ClockAnverse when IsNubOnBottomRight(relativeX, relativeY) => Grass, + Rotate180ClockAnverse when IsNubOnTopRight(relativeX, relativeY) => Grass, + Rotate270ClockAnverse when IsNubOnTopLeft(relativeX, relativeY) => Grass, + _ => River + }, + // River8A river is no land, just water. Rotation doesn't matter + River8A => River, + _ => River + }; + } + + private static bool IsNubOnTopLeft(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(0, 4), new(0, 0), new(4, 0)); + private static bool IsNubOnTopRight(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(12, 0), new(15, 0), new(15, 4)); + private static bool IsNubOnBottomLeft(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(0, 12), new(0, 15), new(4, 15)); + private static bool IsNubOnBottomRight(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(12, 15), new(15, 15), new(15, 12)); + + private static bool IsPointInMultiTriangle(int px, int py, Coordinate a, Coordinate b, Coordinate c, Coordinate vortexA, Coordinate vortexB) + { + return IsPointInTriangle(px, py, a, vortexA, b) + || IsPointInTriangle(px, py, a, b, c) + || IsPointInTriangle(px, py, c, b, vortexB); + } + + private static bool IsPointInTriangle(int px, int py, Coordinate a, Coordinate b, Coordinate c) + { + Coordinate p = new(px, py); + float areaTotal = GetTriangleArea(a, b, c); + float area1 = GetTriangleArea(p, b, c); + float area2 = GetTriangleArea(a, p, c); + float area3 = GetTriangleArea(a, b, p); + + return Math.Abs(areaTotal - (area1 + area2 + area3)) < 0.0001f; + } + + private static float GetTriangleArea(Coordinate a, Coordinate b, Coordinate c) + { + return Math.Abs(((a.X * (b.Y - c.Y)) + + (b.X * (c.Y - a.Y)) + + (c.X * (a.Y - b.Y))) / 2.0f); + } + + private readonly record struct Coordinate(int X, int Y); + + private static readonly Color CliffBase = ColorUtil.Blend(Grass, Color.Black, 0.6d); + + private static Color GetTileDefaultColor(TerrainUnitModel mdl, ushort landAngle, int relativeX, int relativeY) + { + var angle = (LandAngles)landAngle; + if (mdl.IsRiver) + return GetRiverColor(mdl, angle, relativeX, relativeY); + if (mdl.IsFall) + return Color.DeepSkyBlue; + if (mdl.IsCliff) + return CliffBase; + return Grass; + } + + public static string GetTileName(TerrainTile tile) + { + var name = tile.UnitModel.ToString(); + var num = name.IndexOfAnyInRange('0', '9'); + if (num < 0) + return name; + return name[..num] + Environment.NewLine + name[num..]; + } +} \ No newline at end of file diff --git a/NHSE.Core/Editing/Batch/BatchMutator.cs b/NHSE.Core/Editing/Batch/BatchMutator.cs index 9b47429..e6e3ef0 100644 --- a/NHSE.Core/Editing/Batch/BatchMutator.cs +++ b/NHSE.Core/Editing/Batch/BatchMutator.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -namespace NHSE.Core -{ - public abstract class BatchMutator where T : class - { - protected const string CONST_RAND = "$rand"; +namespace NHSE.Core; - public abstract ModifyResult Modify(T item, IEnumerable filters, IEnumerable modifications); - } -} +public abstract class BatchMutator where T : class +{ + protected const string CONST_RAND = "$rand"; + + public abstract ModifyResult Modify(T item, IEnumerable filters, IEnumerable modifications); +} \ No newline at end of file diff --git a/NHSE.Core/Editing/Batch/BatchProcessor.cs b/NHSE.Core/Editing/Batch/BatchProcessor.cs index a69d460..24168c4 100644 --- a/NHSE.Core/Editing/Batch/BatchProcessor.cs +++ b/NHSE.Core/Editing/Batch/BatchProcessor.cs @@ -2,86 +2,82 @@ using System.Collections.Generic; using System.Linq; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Carries out a batch edit and contains information summarizing the results. +/// +public abstract class BatchProcessor(BatchMutator Mutator) where T : class { + private int Modified { get; set; } + private int Iterated { get; set; } + private int Failed { get; set; } + + protected abstract bool CanModify(T item); + protected abstract bool Finalize(T item); + /// - /// Carries out a batch edit and contains information summarizing the results. + /// Tries to modify the . /// - public abstract class BatchProcessor where T : class + /// Object to modify. + /// Filters which must be satisfied prior to any modifications being made. + /// Modifications to perform on the item. + /// Result of the attempted modification. + public bool Process(T item, IEnumerable filters, IEnumerable modifications) { - private int Modified { get; set; } - private int Iterated { get; set; } - private int Failed { get; set; } + if (!CanModify(item)) + return false; - protected readonly BatchMutator Mutator; - protected BatchProcessor(BatchMutator mut) => Mutator = mut; + var result = Mutator.Modify(item, filters, modifications); + if (result != ModifyResult.Invalid) + Iterated++; + if (result == ModifyResult.Error) + Failed++; + if (result != ModifyResult.Modified) + return false; - protected abstract bool CanModify(T item); - protected abstract bool Finalize(T item); + Finalize(item); + Modified++; + return true; + } - /// - /// Tries to modify the . - /// - /// Object to modify. - /// Filters which must be satisfied prior to any modifications being made. - /// Modifications to perform on the item. - /// Result of the attempted modification. - public bool Process(T item, IEnumerable filters, IEnumerable modifications) + /// + /// Gets a message indicating the overall result of all modifications performed across multiple Batch Edit jobs. + /// + /// Collection of modifications. + /// Friendly (multi-line) string indicating the result of the batch edits. + public string GetEditorResults(ICollection sets) + { + if (sets.Count == 0) + return "No instructions present."; + int ctr = Modified / sets.Count; + int len = Iterated / sets.Count; + string maybe = sets.Count == 1 ? string.Empty : "~"; + string result = $"Success: {maybe}{ctr}/{len}"; + if (Failed > 0) + result += Environment.NewLine + maybe + $"Failed: {Failed} not processed."; + return result; + } + + public void Execute(ReadOnlySpan lines, IEnumerable data) + { + var sets = StringInstructionSet.GetBatchSets(lines).ToArray(); + foreach (var pk in data) { - if (!CanModify(item)) - return false; - - var result = Mutator.Modify(item, filters, modifications); - if (result != ModifyResult.Invalid) - Iterated++; - if (result == ModifyResult.Error) - Failed++; - if (result != ModifyResult.Modified) - return false; - - Finalize(item); - Modified++; - return true; - } - - /// - /// Gets a message indicating the overall result of all modifications performed across multiple Batch Edit jobs. - /// - /// Collection of modifications. - /// Friendly (multi-line) string indicating the result of the batch edits. - public string GetEditorResults(ICollection sets) - { - if (sets.Count == 0) - return "No instructions present."; - int ctr = Modified / sets.Count; - int len = Iterated / sets.Count; - string maybe = sets.Count == 1 ? string.Empty : "~"; - string result = $"Success: {maybe}{ctr}/{len}"; - if (Failed > 0) - result += Environment.NewLine + maybe + $"Failed: {Failed} not processed."; - return result; - } - - public void Execute(IList lines, IEnumerable data) - { - var sets = StringInstructionSet.GetBatchSets(lines).ToArray(); - foreach (var pk in data) - { - foreach (var set in sets) - Process(pk, set.Filters, set.Instructions); - } - } - - protected abstract void Initialize(StringInstructionSet[] sets); - - public void Process(StringInstructionSet[] sets, IReadOnlyList items) - { - Initialize(sets); - foreach (var s in sets) - { - foreach (var i in items) - Process(i, s.Filters, s.Instructions); - } + foreach (var set in sets) + Process(pk, set.Filters, set.Instructions); } } -} + + protected abstract void Initialize(ReadOnlySpan sets); + + public void Process(ReadOnlySpan sets, IReadOnlyList items) + { + Initialize(sets); + foreach (var s in sets) + { + foreach (var i in items) + Process(i, s.Filters, s.Instructions); + } + } +} \ No newline at end of file diff --git a/NHSE.Core/Editing/Batch/ItemMutator.cs b/NHSE.Core/Editing/Batch/ItemMutator.cs index 58a6c4b..bfa3c35 100644 --- a/NHSE.Core/Editing/Batch/ItemMutator.cs +++ b/NHSE.Core/Editing/Batch/ItemMutator.cs @@ -5,205 +5,214 @@ using System.Linq; using System.Reflection; -namespace NHSE.Core +namespace NHSE.Core; + +public class ItemMutator : BatchMutator { - public class ItemMutator : BatchMutator + public readonly ItemReflection Reflect = ItemReflection.Default; + private const char CONST_POINTER = '*'; + + public override ModifyResult Modify(Item item, IEnumerable filters, IEnumerable modifications) { - public readonly ItemReflection Reflect = ItemReflection.Default; - - public override ModifyResult Modify(Item item, IEnumerable filters, IEnumerable modifications) + var pi = Reflect.Props[Array.IndexOf(Reflect.Types, item.GetType())]; + foreach (var cmd in filters) { - var pi = Reflect.Props[Array.IndexOf(Reflect.Types, item.GetType())]; - foreach (var cmd in filters) + try { - try - { - if (!IsFilterMatch(cmd, item, pi)) - return ModifyResult.Filtered; - } - // Swallow any error because this can be malformed user input. - catch (Exception ex) - { - Debug.WriteLine($"Failed to compare: {ex.Message} - {cmd.PropertyName} {cmd.PropertyValue}"); - return ModifyResult.Error; - } + if (!IsFilterMatch(cmd, item, pi)) + return ModifyResult.Filtered; } - - ModifyResult result = ModifyResult.Modified; - foreach (var cmd in modifications) + // Swallow any error because this can be malformed user input. + catch (Exception ex) { - try - { - var tmp = SetProperty(cmd, item, pi); - if (tmp != ModifyResult.Modified) - result = tmp; - } - // Swallow any error because this can be malformed user input. - catch (Exception ex) - { - Debug.WriteLine($"Failed to modify: {ex.Message} - {cmd.PropertyName} {cmd.PropertyValue}"); - } + Debug.WriteLine($"Failed to compare: {ex.Message} - {cmd.PropertyName} {cmd.PropertyValue}"); + return ModifyResult.Error; } - return result; } - /// - /// Sets the if the should be filtered due to the provided. - /// - /// Command Filter - /// Pokémon to check. - /// PropertyInfo cache (optional) - /// True if filtered, else false. - private static ModifyResult SetProperty(StringInstruction cmd, Item item, IReadOnlyDictionary props) + ModifyResult result = ModifyResult.Modified; + foreach (var cmd in modifications) { - if (SetComplexProperty(item, cmd)) - return ModifyResult.Modified; + try + { + var tmp = SetProperty(cmd, item, pi); + if (tmp != ModifyResult.Modified) + result = tmp; + } + // Swallow any error because this can be malformed user input. + catch (Exception ex) + { + Debug.WriteLine($"Failed to modify: {ex.Message} - {cmd.PropertyName} {cmd.PropertyValue}"); + } + } + return result; + } - if (!props.TryGetValue(cmd.PropertyName, out var pi)) - return ModifyResult.Error; - - if (!pi.CanWrite) - return ModifyResult.Error; - - object val = cmd.Random ? (object)cmd.RandomValue : cmd.PropertyValue; - ReflectUtil.SetValue(pi, item, val); + /// + /// Sets if the should be filtered due to the provided. + /// + /// Command Filter + /// Pokémon to check. + /// PropertyInfo cache (optional) + /// True if filtered, else false. + private static ModifyResult SetProperty(StringInstruction cmd, Item item, Dictionary.AlternateLookup> props) + { + if (SetComplexProperty(item, cmd)) return ModifyResult.Modified; + + if (!props.TryGetValue(cmd.PropertyName, out var pi)) + return ModifyResult.Error; + + if (!pi.CanWrite) + return ModifyResult.Error; + + if (cmd.Random) + ReflectUtil.SetValue(pi, item, cmd.RandomValue); + else + ReflectUtil.SetValue(pi, item, cmd.PropertyValue); + return ModifyResult.Modified; + } + + private static bool SetComplexProperty(Item item, StringInstruction cmd) + { + // Zeroed out item? + if (cmd.PropertyName == nameof(Item.ItemId)) + { + if (!int.TryParse(cmd.PropertyValue, out var val)) + return false; + if (val is not (0 or 0xFFFE)) + return false; + item.Delete(); + return true; + } + return false; + } + + /// + /// Tries to fetch the property from the cache of available properties. + /// + /// Pokémon to check + /// Property Name to check + /// Property Info retrieved (if any). + /// True if has property, false if does not. + public bool TryGetHasProperty(Item item, string name, [NotNullWhen(true)] out PropertyInfo? pi) + { + var type = item.GetType(); + return TryGetHasProperty(type, name, out pi); + } + + /// + /// Tries to fetch the property from the cache of available properties. + /// + /// Type to check + /// Property Name to check + /// Property Info retrieved (if any). + /// True if has property, false if does not. + public bool TryGetHasProperty(Type type, string name, [NotNullWhen(true)] out PropertyInfo? pi) + { + var index = Array.IndexOf(Reflect.Types, type); + if (index < 0) + { + pi = null; + return false; + } + var props = Reflect.Props[index]; + return props.TryGetValue(name, out pi); + } + + /// + /// Gets the type of the property using the saved cache of properties. + /// + /// Property Name to fetch the type for + /// Type index. Leave empty (0) for a nonspecific format. + /// Short name of the property's type. + public string? GetPropertyType(string propertyName, int typeIndex = 0) + { + if (typeIndex == 0) // Any + { + foreach (var p in Reflect.Props) + { + if (p.TryGetValue(propertyName, out var pi)) + return pi.PropertyType.Name; + } + return null; } - private static bool SetComplexProperty(Item item, StringInstruction cmd) + int index = typeIndex - 1 >= Reflect.Props.Length ? 0 : typeIndex - 1; // All vs Specific + var pr = Reflect.Props[index]; + if (!pr.TryGetValue(propertyName, out var info)) + return null; + return info.PropertyType.Name; + } + + /// + /// Checks if the object is filtered by the provided . + /// + /// Filters which must be satisfied. + /// Object to check. + /// True if matches all filters. + public bool IsFilterMatch(IEnumerable filters, Item item) => filters.All(z => IsFilterMatch(z, item, Reflect.Props[Array.IndexOf(Reflect.Types, item.GetType())])); + + /// + /// Checks if the should be filtered due to the provided. + /// + /// Command Filter + /// Pokémon to check. + /// PropertyInfo cache (optional) + /// True if filter matches, else false. + private static bool IsFilterMatch(StringInstruction cmd, Item item, Dictionary.AlternateLookup> props) + { + return IsPropertyFiltered(cmd, item, props); + } + + /// + /// Checks if the should be filtered due to the provided. + /// + /// Command Filter + /// Pokémon to check. + /// PropertyInfo cache + /// True if filtered, else false. + private static bool IsPropertyFiltered(StringInstruction cmd, Item item, Dictionary.AlternateLookup> props) + { + if (!props.TryGetValue(cmd.PropertyName, out var pi)) + return false; + if (!pi.CanRead) + return false; + + var val = cmd.PropertyValue; + if (val.StartsWith(CONST_POINTER) && props.TryGetValue(val.AsSpan(1), out var opi)) { - // Zeroed out item? - if (cmd.PropertyName == nameof(Item.ItemId)) + var result = opi.GetValue(item) ?? throw new NullReferenceException(); + return cmd.Comparer.IsCompareOperator(pi.CompareTo(item, result)); + } + return cmd.Comparer.IsCompareOperator(pi.CompareTo(item, val)); + } + + /// + /// Checks if the object is filtered by the provided . + /// + /// Filters which must be satisfied. + /// Object to check. + /// True if matches all filters. + public static bool IsFilterMatch(IEnumerable filters, object obj) + { + foreach (var cmd in filters) + { + if (!ReflectUtil.HasProperty(obj, cmd.PropertyName, out var pi)) + return false; + try { - if (!int.TryParse(cmd.PropertyValue, out var val)) - return false; - if (val is not 0 or 0xFFFE) - return false; - item.Delete(); - return true; + if (cmd.Comparer.IsCompareOperator(pi.CompareTo(obj, cmd.PropertyValue))) + continue; + } + // User provided inputs can mismatch the type's required value format, and fail to be compared. + catch (Exception e) + { + Debug.WriteLine($"Unable to compare {cmd.PropertyName} to {cmd.PropertyValue}."); + Debug.WriteLine(e.Message); } return false; } - - /// - /// Tries to fetch the property from the cache of available properties. - /// - /// Pokémon to check - /// Property Name to check - /// Property Info retrieved (if any). - /// True if has property, false if does not. - public bool TryGetHasProperty(Item item, string name, [NotNullWhen(true)] out PropertyInfo? pi) - { - var type = item.GetType(); - return TryGetHasProperty(type, name, out pi); - } - - /// - /// Tries to fetch the property from the cache of available properties. - /// - /// Type to check - /// Property Name to check - /// Property Info retrieved (if any). - /// True if has property, false if does not. - public bool TryGetHasProperty(Type type, string name, [NotNullWhen(true)] out PropertyInfo? pi) - { - var index = Array.IndexOf(Reflect.Types, type); - if (index < 0) - { - pi = null; - return false; - } - var props = Reflect.Props[index]; - return props.TryGetValue(name, out pi); - } - - /// - /// Gets the type of the property using the saved cache of properties. - /// - /// Property Name to fetch the type for - /// Type index. Leave empty (0) for a nonspecific format. - /// Short name of the property's type. - public string? GetPropertyType(string propertyName, int typeIndex = 0) - { - if (typeIndex == 0) // Any - { - foreach (var p in Reflect.Props) - { - if (p.TryGetValue(propertyName, out var pi)) - return pi.PropertyType.Name; - } - return null; - } - - int index = typeIndex - 1 >= Reflect.Props.Length ? 0 : typeIndex - 1; // All vs Specific - var pr = Reflect.Props[index]; - if (!pr.TryGetValue(propertyName, out var info)) - return null; - return info.PropertyType.Name; - } - - /// - /// Checks if the object is filtered by the provided . - /// - /// Filters which must be satisfied. - /// Object to check. - /// True if matches all filters. - public bool IsFilterMatch(IEnumerable filters, Item item) => filters.All(z => IsFilterMatch(z, item, Reflect.Props[Array.IndexOf(Reflect.Types, item.GetType())])); - - /// - /// Checks if the should be filtered due to the provided. - /// - /// Command Filter - /// Pokémon to check. - /// PropertyInfo cache (optional) - /// True if filter matches, else false. - private static bool IsFilterMatch(StringInstruction cmd, Item item, IReadOnlyDictionary props) - { - return IsPropertyFiltered(cmd, item, props); - } - - /// - /// Checks if the should be filtered due to the provided. - /// - /// Command Filter - /// Pokémon to check. - /// PropertyInfo cache - /// True if filtered, else false. - private static bool IsPropertyFiltered(StringInstruction cmd, Item item, IReadOnlyDictionary props) - { - if (!props.TryGetValue(cmd.PropertyName, out var pi)) - return false; - if (!pi.CanRead) - return false; - return pi.IsValueEqual(item, cmd.PropertyValue) == cmd.Evaluator; - } - - /// - /// Checks if the object is filtered by the provided . - /// - /// Filters which must be satisfied. - /// Object to check. - /// True if matches all filters. - public static bool IsFilterMatch(IEnumerable filters, object obj) - { - foreach (var cmd in filters) - { - if (!ReflectUtil.HasProperty(obj, cmd.PropertyName, out var pi)) - return false; - try - { - if (pi.IsValueEqual(obj, cmd.PropertyValue) == cmd.Evaluator) - continue; - } - // User provided inputs can mismatch the type's required value format, and fail to be compared. - catch (Exception e) - { - Debug.WriteLine($"Unable to compare {cmd.PropertyName} to {cmd.PropertyValue}."); - Debug.WriteLine(e.Message); - } - return false; - } - return true; - } + return true; } -} +} \ No newline at end of file diff --git a/NHSE.Core/Editing/Batch/ItemProcessor.cs b/NHSE.Core/Editing/Batch/ItemProcessor.cs index c9d7b50..fb8dcae 100644 --- a/NHSE.Core/Editing/Batch/ItemProcessor.cs +++ b/NHSE.Core/Editing/Batch/ItemProcessor.cs @@ -1,52 +1,48 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; -namespace NHSE.Core +namespace NHSE.Core; + +public class ItemProcessor(BatchMutator mut) : BatchProcessor(mut) { - public class ItemProcessor : BatchProcessor + protected override bool CanModify(Item item) => true; + protected override bool Finalize(Item item) => true; + + /// + /// Initializes the list with a context-sensitive value. If the provided value is a string, it will attempt to convert that string to its corresponding index. + /// + /// Instructions to initialize. + public static void ScreenStrings(IEnumerable il) { - public ItemProcessor(BatchMutator mut) : base(mut) + foreach (var i in il.Where(i => !i.PropertyValue.All(char.IsDigit))) { - } + string pv = i.PropertyValue; + if (pv.StartsWith('$') && pv.Contains(',')) + i.SetRandomRange(pv); - protected override bool CanModify(Item item) => true; - protected override bool Finalize(Item item) => true; - - /// - /// Initializes the list with a context-sensitive value. If the provided value is a string, it will attempt to convert that string to its corresponding index. - /// - /// Instructions to initialize. - public void ScreenStrings(IEnumerable il) - { - foreach (var i in il.Where(i => !i.PropertyValue.All(char.IsDigit))) - { - string pv = i.PropertyValue; - if (pv.StartsWith("$") && pv.Contains(",")) - i.SetRandRange(pv); - - SetInstructionScreenedValue(i); - } - } - - /// - /// Initializes the with a context-sensitive value. If the provided value is a string, it will attempt to convert that string to its corresponding index. - /// - /// Instruction to initialize. - private static void SetInstructionScreenedValue(StringInstruction i) - { - switch (i.PropertyName) - { - case nameof(Item.ItemId) or nameof(Item.ExtensionItemId): i.SetScreenedValue(GameInfo.Strings.itemlistdisplay); return; - } - } - - protected override void Initialize(StringInstructionSet[] sets) - { - foreach (var set in sets) - { - ScreenStrings(set.Filters); - ScreenStrings(set.Instructions); - } + SetInstructionScreenedValue(i); } } -} + + /// + /// Initializes the with a context-sensitive value. If the provided value is a string, it will attempt to convert that string to its corresponding index. + /// + /// Instruction to initialize. + private static void SetInstructionScreenedValue(StringInstruction i) + { + switch (i.PropertyName) + { + case nameof(Item.ItemId) or nameof(Item.ExtensionItemId): i.SetScreenedValue(GameInfo.Strings.itemlistdisplay); return; + } + } + + protected override void Initialize(ReadOnlySpan sets) + { + foreach (var set in sets) + { + ScreenStrings(set.Filters); + ScreenStrings(set.Instructions); + } + } +} \ No newline at end of file diff --git a/NHSE.Core/Editing/Batch/ItemReflection.cs b/NHSE.Core/Editing/Batch/ItemReflection.cs index 64cbfb3..24aecc6 100644 --- a/NHSE.Core/Editing/Batch/ItemReflection.cs +++ b/NHSE.Core/Editing/Batch/ItemReflection.cs @@ -3,48 +3,82 @@ using System.Linq; using System.Reflection; -namespace NHSE.Core +namespace NHSE.Core; + +public class ItemReflection { - public class ItemReflection + public static ItemReflection Default { get; } = new(); + + public readonly Type[] Types = [typeof(Item), typeof(VillagerItem)]; + public string[][] Properties => GetProperties.Value; + + /// + /// Extra properties to show in the list of selectable properties (GUI) + /// + private static readonly string[] CustomProperties = + [ + ]; + + public readonly Dictionary.AlternateLookup>[] Props; + private readonly Lazy GetProperties; + + public ItemReflection() { - public static ItemReflection Default { get; } = new(); - - public readonly Type[] Types = { typeof(Item), typeof(VillagerItem) }; - public readonly Dictionary[] Props; - public readonly string[][] Properties; - - public ItemReflection() - { - Props = Types - .Select(z => ReflectUtil.GetAllPropertyInfoPublic(z) - .GroupBy(p => p.Name) - .Select(g => g.First()) - .ToDictionary(p => p.Name)) - .ToArray(); - - Properties = GetPropArray(); - } - - public string[][] GetPropArray() - { - var p = new string[Types.Length][]; - for (int i = 0; i < p.Length; i++) - { - var pz = ReflectUtil.GetPropertiesPublic(Types[i]); - p[i] = pz.OrderBy(a => a).ToArray(); - } - - // Properties for any - var any = ReflectUtil.GetPropertiesPublic(typeof(Item)).Union(p.SelectMany(a => a)).OrderBy(a => a).ToArray(); - // Properties shared by all - var all = p.Aggregate(new HashSet(p[0]), (h, e) => { h.IntersectWith(e); return h; }).OrderBy(a => a).ToArray(); - - var p1 = new string[Types.Length + 2][]; - Array.Copy(p, 0, p1, 1, p.Length); - p1[0] = any; - p1[p1.Length - 1] = all; - - return p1; - } + Props = GetPropertyDictionaries(Types); + GetProperties = new Lazy(() => GetPropArray(Props, CustomProperties)); } -} + + private static Dictionary.AlternateLookup>[] GetPropertyDictionaries(ReadOnlySpan types) + { + var result = new Dictionary.AlternateLookup>[types.Length]; + for (int i = 0; i < types.Length; i++) + result[i] = GetPropertyDictionary(types[i], ReflectUtil.GetAllPropertyInfoPublic).GetAlternateLookup>(); + return result; + } + + private static Dictionary GetPropertyDictionary(Type type, Func> selector) + { + const int expectedMax = 8; + var dict = new Dictionary(expectedMax); + var props = selector(type); + foreach (var p in props) + dict.TryAdd(p.Name, p); + return dict; + } + + private static string[][] GetPropArray(Dictionary.AlternateLookup>[] types, ReadOnlySpan extra) + { + // Create a list for all types, [inAny, ..types, inAll] + var result = new string[types.Length + 2][]; + var p = result.AsSpan(1, types.Length); + + for (int i = 0; i < p.Length; i++) + { + var type = types[i].Dictionary; + string[] combine = [.. type.Keys, .. extra]; + Array.Sort(combine); + p[i] = combine; + } + + // Properties for any PKM + // Properties shared by all PKM + var first = p[0]; + var any = new HashSet(first); + var all = new HashSet(first); + foreach (var set in p[1..]) + { + any.UnionWith(set); + all.IntersectWith(set); + } + + var arrAny = any.ToArray(); + Array.Sort(arrAny); + result[0] = arrAny; + + var arrAll = all.ToArray(); + Array.Sort(arrAll); + result[^1] = arrAll; + + return result; + } +} \ No newline at end of file diff --git a/NHSE.Core/Editing/Batch/ModifyResult.cs b/NHSE.Core/Editing/Batch/ModifyResult.cs index e3988e2..411503c 100644 --- a/NHSE.Core/Editing/Batch/ModifyResult.cs +++ b/NHSE.Core/Editing/Batch/ModifyResult.cs @@ -1,28 +1,27 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Batch Editor Modification result for an individual item. +/// +public enum ModifyResult { /// - /// Batch Editor Modification result for an individual item. + /// The data has invalid data and is not a suitable candidate for modification. /// - public enum ModifyResult - { - /// - /// The data has invalid data and is not a suitable candidate for modification. - /// - Invalid, + Invalid, - /// - /// An error was occurred while iterating modifications for this data. - /// - Error, + /// + /// An error was occurred while iterating modifications for this data. + /// + Error, - /// - /// The data was skipped due to a matching Filter. - /// - Filtered, + /// + /// The data was skipped due to a matching Filter. + /// + Filtered, - /// - /// The data was modified. - /// - Modified, - } -} + /// + /// The data was modified. + /// + Modified, +} \ No newline at end of file diff --git a/NHSE.Core/Editing/Batch/StringInstruction.cs b/NHSE.Core/Editing/Batch/StringInstruction.cs index e82b368..de95aa6 100644 --- a/NHSE.Core/Editing/Batch/StringInstruction.cs +++ b/NHSE.Core/Editing/Batch/StringInstruction.cs @@ -1,101 +1,375 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using static NHSE.Core.InstructionComparer; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Batch Editing instruction +/// +/// +/// Can be a filter (skip), or a modification instruction (modify) +/// +/// +/// +/// +/// Property to modify. +/// Value to set to the property. +/// Filter Comparison Type +public sealed record StringInstruction(string PropertyName, string PropertyValue, InstructionComparer Comparer) { + public string PropertyValue { get; private set; } = PropertyValue; + /// - /// Batch Editing instruction + /// Sets the to the index of the value in the input , if it exists. + /// + /// List of values to search for the . + /// True if the value was found and set, false otherwise. + public bool SetScreenedValue(ReadOnlySpan arr) + { + int index = arr.IndexOf(PropertyValue); + if ((uint)index >= arr.Length) + return false; + PropertyValue = index.ToString(); + return true; + } + + /// + /// Valid prefixes that are recognized for value comparison types. + /// + public static ReadOnlySpan Prefixes => + [ + Apply, + FilterEqual, FilterNotEqual, FilterGreaterThan, FilterGreaterThanOrEqual, FilterLessThan, FilterLessThanOrEqual, + ]; + + private const char Apply = '.'; + private const char SplitRange = ','; + + private const char FilterEqual = '='; + private const char FilterNotEqual = '!'; + private const char FilterGreaterThan = '>'; + private const char FilterLessThan = '<'; + private const char FilterGreaterThanOrEqual = '≥'; + private const char FilterLessThanOrEqual = '≤'; + + /// + /// Character which divides a property and a value. /// /// - /// Can be a filter (skip), or a modification instruction (modify) + /// Example: + /// =Species=1 + /// The second = is the split. /// - /// - /// - /// - public sealed class StringInstruction + public const char SplitInstruction = '='; + + // Extra Functionality + private int RandomMinimum, RandomMaximum; + + /// + /// Apply a instead of fixed value, based on the and values. + /// + public bool Random { get; private set; } + + /// + /// Gets a value, based on the and values. + /// + public int RandomValue => RandUtil.Rand.Next(RandomMinimum, RandomMaximum + 1); + + /// + /// Checks if the input is a valid "random range" specification. + /// + public static bool IsRandomRange(ReadOnlySpan str) { - public string PropertyName { get; } - public string PropertyValue { get; private set; } - public bool Evaluator { get; private init; } + // Need at least one character on either side of the splitter char. + int index = str.IndexOf(SplitRange); + return index > 0 && index < str.Length - 1; + } - public StringInstruction(string name, string value) + /// + /// Sets a "random range" specification to the instruction. + /// + /// When the splitter is not present. + public void SetRandomRange(ReadOnlySpan str) + { + var index = str.IndexOf(SplitRange); + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(index); + + var min = str[..index]; + var max = str[(index + 1)..]; + _ = int.TryParse(min, out RandomMinimum); + _ = int.TryParse(max, out RandomMaximum); + + if (RandomMinimum == RandomMaximum) { - PropertyName = name; - PropertyValue = value; + PropertyValue = RandomMinimum.ToString(); + Debug.WriteLine($"{PropertyName} randomization range Min/Max same?"); } - - public void SetScreenedValue(string[] arr) + else { - int index = Array.IndexOf(arr, PropertyValue); - PropertyValue = index > -1 ? index.ToString() : PropertyValue; - } - - public static readonly IReadOnlyList Prefixes = new[] { Apply, Require, Exclude }; - private const char Exclude = '!'; - private const char Require = '='; - private const char Apply = '.'; - private const char SplitRange = ','; - - /// - /// Character which divides a property and a value. - /// - /// - /// Example: - /// =Species=1 - /// The second = is the split. - /// - public const char SplitInstruction = '='; - - // Extra Functionality - private int RandomMinimum, RandomMaximum; - public bool Random { get; private set; } - public int RandomValue => RandUtil.Rand.Next(RandomMinimum, RandomMaximum + 1); - - public void SetRandRange(string pv) - { - string str = pv.Substring(1); - var split = str.Split(SplitRange); - int.TryParse(split[0], out RandomMinimum); - int.TryParse(split[1], out RandomMaximum); - - if (RandomMinimum == RandomMaximum) - { - PropertyValue = RandomMinimum.ToString(); - Debug.WriteLine(PropertyName + " randomization range Min/Max same?"); - } - else - { - Random = true; - } - } - - public static IEnumerable GetFilters(IEnumerable lines) - { - var raw = GetRelevantStrings(lines, Exclude, Require); - return from line in raw - let eval = line[0] == Require - let split = line.Substring(1).Split(SplitInstruction) - where split.Length == 2 && !string.IsNullOrWhiteSpace(split[0]) - select new StringInstruction(split[0], split[1]) { Evaluator = eval }; - } - - public static IEnumerable GetInstructions(IEnumerable lines) - { - var raw = GetRelevantStrings(lines, Apply).Select(line => line.Substring(1)); - return from line in raw - select line.Split(SplitInstruction) into split - where split.Length == 2 - select new StringInstruction(split[0], split[1]); - } - - /// - /// Weeds out invalid lines and only returns those with a valid first character. - /// - private static IEnumerable GetRelevantStrings(IEnumerable lines, params char[] pieces) - { - return lines.Where(line => !string.IsNullOrEmpty(line) && pieces.Any(z => z == line[0])); + Random = true; } } + + /// + /// Gets a list of s from the input . + /// + public static List GetFilters(ReadOnlySpan text) => GetFilters(text.EnumerateLines()); + + /// + /// Gets a list of filters from the input . + /// + public static List GetFilters(ReadOnlySpan lines) + { + var result = new List(lines.Length); + foreach (var line in lines) + { + if (TryParseFilter(line, out var entry)) + result.Add(entry); + } + return result; + } + + /// + /// Gets a list of filters from the input . + /// + public static List GetFilters(SpanLineEnumerator lines) + { + var result = new List(); + foreach (var line in lines) + { + if (TryParseFilter(line, out var entry)) + result.Add(entry); + } + return result; + } + + /// + /// Gets a list of filters from the input . + /// + public static List GetFilters(IReadOnlyList lines) + { + var result = new List(lines.Count); + foreach (var line in lines) + { + if (TryParseFilter(line, out var entry)) + result.Add(entry); + } + return result; + } + + /// + /// Gets a list of filters from the input . + /// + public static List GetFilters(IEnumerable lines) + { + var result = new List(); + foreach (var line in lines) + { + if (TryParseFilter(line, out var entry)) + result.Add(entry); + } + return result; + } + + /// + /// Gets a list of instructions from the input . + /// + public static List GetInstructions(ReadOnlySpan text) => GetInstructions(text.EnumerateLines()); + + /// + /// Gets a list of instructions from the input . + /// + public static List GetInstructions(ReadOnlySpan lines) + { + var result = new List(lines.Length); + foreach (var line in lines) + { + if (TryParseInstruction(line, out var entry)) + result.Add(entry); + } + return result; + } + + /// + /// Gets a list of instructions from the input . + /// + public static List GetInstructions(SpanLineEnumerator lines) + { + var result = new List(); + foreach (var line in lines) + { + if (TryParseInstruction(line, out var entry)) + result.Add(entry); + } + return result; + } + + /// + /// Gets a list of instructions from the input . + /// + public static List GetInstructions(IReadOnlyList lines) + { + var result = new List(lines.Count); + foreach (var line in lines) + { + if (TryParseInstruction(line, out var entry)) + result.Add(entry); + } + return result; + } + + /// + /// Gets a list of instructions from the input . + /// + public static List GetInstructions(IEnumerable lines) + { + var result = new List(); + foreach (var line in lines) + { + if (TryParseInstruction(line, out var entry)) + result.Add(entry); + } + return result; + } + + /// + /// Tries to parse a filter from the input . + /// + public static bool TryParseFilter(ReadOnlySpan line, [NotNullWhen(true)] out StringInstruction? entry) + { + entry = null; + if (line.Length is 0) + return false; + var comparer = GetComparer(line[0]); + if (!comparer.IsSupported) + return false; + return TryParseSplitTuple(line[1..], ref entry, comparer); + } + + /// + /// Tries to parse a instruction from the input . + /// + public static bool TryParseInstruction(ReadOnlySpan line, [NotNullWhen(true)] out StringInstruction? entry) + { + entry = null; + if (!line.StartsWith(Apply)) + return false; + return TryParseSplitTuple(line[1..], ref entry); + } + + /// + /// Tries to split a tuple from the input . + /// + public static bool TryParseSplitTuple(ReadOnlySpan tuple, [NotNullWhen(true)] ref StringInstruction? entry, InstructionComparer eval = default) + { + if (!TryParseSplitTuple(tuple, out var name, out var value)) + return false; + entry = new StringInstruction(name.ToString(), value.ToString(), eval); + return true; + } + + /// + /// Tries to split a tuple from the input . + /// + public static bool TryParseSplitTuple(ReadOnlySpan tuple, out ReadOnlySpan name, out ReadOnlySpan value) + { + name = default; + value = default; + var splitIndex = tuple.IndexOf(SplitInstruction); + if (splitIndex <= 0) + return false; + + name = tuple[..splitIndex]; + if (name.IsWhiteSpace()) + return false; + + value = tuple[(splitIndex + 1)..]; + var noExtra = value.IndexOf(SplitInstruction); + return noExtra == -1; + } + + /// + /// Gets the from the input . + /// + public static InstructionComparer GetComparer(char opCode) => opCode switch + { + FilterEqual => IsEqual, + FilterNotEqual => IsNotEqual, + FilterGreaterThan => IsGreaterThan, + FilterLessThan => IsLessThan, + FilterGreaterThanOrEqual => IsGreaterThanOrEqual, + FilterLessThanOrEqual => IsLessThanOrEqual, + _ => None, + }; +} + +/// +/// Value comparison type +/// +public enum InstructionComparer : byte +{ + None, + IsEqual, + IsNotEqual, + IsGreaterThan, + IsGreaterThanOrEqual, + IsLessThan, + IsLessThanOrEqual, +} + +/// +/// Extension methods for +/// +public static class InstructionComparerExtensions +{ + extension(InstructionComparer comparer) + { + /// + /// Indicates if the is supported by the logic. + /// + /// True if supported, false if unsupported. + public bool IsSupported => comparer switch + { + IsEqual => true, + IsNotEqual => true, + IsGreaterThan => true, + IsGreaterThanOrEqual => true, + IsLessThan => true, + IsLessThanOrEqual => true, + _ => false, + }; + + /// + /// Checks if the compare operator is satisfied by a boolean comparison result. + /// + /// Result from Equals comparison + /// True if satisfied + /// Only use this method if the comparison is boolean only. Use the otherwise. + public bool IsCompareEquivalence(bool compareResult) => comparer switch + { + IsEqual => compareResult, + IsNotEqual => !compareResult, + _ => false, + }; + + /// + /// Checks if the compare operator is satisfied by the result. + /// + /// Result from CompareTo + /// True if satisfied + public bool IsCompareOperator(int compareResult) => comparer switch + { + IsEqual => compareResult is 0, + IsNotEqual => compareResult is not 0, + IsGreaterThan => compareResult > 0, + IsGreaterThanOrEqual => compareResult >= 0, + IsLessThan => compareResult < 0, + IsLessThanOrEqual => compareResult <= 0, + _ => false, + }; + } } diff --git a/NHSE.Core/Editing/Batch/StringInstructionSet.cs b/NHSE.Core/Editing/Batch/StringInstructionSet.cs index f903e41..46ea193 100644 --- a/NHSE.Core/Editing/Batch/StringInstructionSet.cs +++ b/NHSE.Core/Editing/Batch/StringInstructionSet.cs @@ -1,38 +1,143 @@ -using System.Collections.Generic; -using System.Linq; +using System; +using System.Collections.Generic; +using System.Text; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Processes input of strings into a list of valid Filters and Instructions. +/// +public sealed class StringInstructionSet { /// - /// Processes input of strings into a list of valid Filters and Instructions. + /// Filters to check if the object should be modified. /// - public sealed class StringInstructionSet + public readonly IReadOnlyList Filters; + + /// + /// Instructions to modify the object. + /// + public readonly IReadOnlyList Instructions; + + private const char SetSeparatorChar = ';'; + + public StringInstructionSet(IReadOnlyList filters, IReadOnlyList instructions) { - public readonly IReadOnlyList Filters; - public readonly IReadOnlyList Instructions; - - private const string SetSeparator = ";"; - - public StringInstructionSet(IReadOnlyList filters, IReadOnlyList instructions) - { - Filters = filters; - Instructions = instructions; - } - - public StringInstructionSet(ICollection set) - { - Filters = StringInstruction.GetFilters(set).ToList(); - Instructions = StringInstruction.GetInstructions(set).ToList(); - } - - public static IEnumerable GetBatchSets(IList lines) - { - int start = 0; - while (start < lines.Count) - { - var list = lines.Skip(start).TakeWhile(_ => !lines[start++].StartsWith(SetSeparator)).ToList(); - yield return new StringInstructionSet(list); - } - } + Filters = filters; + Instructions = instructions; } -} + + public StringInstructionSet(ReadOnlySpan text) + { + var set = text.EnumerateLines(); + Filters = StringInstruction.GetFilters(set); + Instructions = StringInstruction.GetInstructions(set); + } + + public StringInstructionSet(SpanLineEnumerator set) + { + Filters = StringInstruction.GetFilters(set); + Instructions = StringInstruction.GetInstructions(set); + } + + public StringInstructionSet(ReadOnlySpan set) + { + Filters = StringInstruction.GetFilters(set); + Instructions = StringInstruction.GetInstructions(set); + } + + /// + /// Gets a list of s from the input . + /// + public static StringInstructionSet[] GetBatchSets(ReadOnlySpan lines) + { + int ctr = 0; + int start = 0; + while (start < lines.Length) + { + var slice = lines[start..]; + var count = GetInstructionSetLength(slice); + ctr++; + start += count + 1; + } + + var result = new StringInstructionSet[ctr]; + ctr = 0; + start = 0; + while (start < lines.Length) + { + var slice = lines[start..]; + var count = GetInstructionSetLength(slice); + var set = slice[..count]; + result[ctr++] = new StringInstructionSet(set); + start += count + 1; + } + return result; + } + + /// + /// Gets a list of s from the input . + /// + public static StringInstructionSet[] GetBatchSets(ReadOnlySpan text) + { + int ctr = 0; + int start = 0; + while (start < text.Length) + { + var slice = text[start..]; + var count = GetInstructionSetLength(slice); + ctr++; + start += count + 1; + } + + var result = new StringInstructionSet[ctr]; + ctr = 0; + start = 0; + while (start < text.Length) + { + var slice = text[start..]; + var count = GetInstructionSetLength(slice); + var set = slice[..count]; + result[ctr++] = new StringInstructionSet(set); + start += count + 1; + } + return result; + } + + /// + /// Scans through the to count the amount of characters to consume. + /// + /// Multi line string + /// Amount of characters comprising a set of instructions + public static int GetInstructionSetLength(ReadOnlySpan text) + { + int start = 0; + while (start < text.Length) + { + var line = text[start..]; + if (line.Length != 0 && line[0] == SetSeparatorChar) + return start; + var next = line.IndexOf('\n'); + if (next == -1) + return text.Length; + start += next + 1; + } + return start; + } + + /// + /// Scans through the to count the amount of valid lines to consume. + /// + /// Amount of lines comprising a set of instructions. + public static int GetInstructionSetLength(ReadOnlySpan lines) + { + int start = 0; + while (start < lines.Length) + { + var line = lines[start++]; + if (line.StartsWith(SetSeparatorChar)) + return start; + } + return start; + } +} \ No newline at end of file diff --git a/NHSE.Core/Editing/FieldItem/FieldItemColumn.cs b/NHSE.Core/Editing/FieldItem/FieldItemColumn.cs index ae5fe7d..c45f77f 100644 --- a/NHSE.Core/Editing/FieldItem/FieldItemColumn.cs +++ b/NHSE.Core/Editing/FieldItem/FieldItemColumn.cs @@ -1,24 +1,23 @@ -namespace NHSE.Core +namespace NHSE.Core; + +public sealed class FieldItemColumn { - public sealed class FieldItemColumn + /// X Coordinate within the Field Item Layer + public readonly int X; + + /// Y Coordinate within the Field Item Layer + public readonly int Y; + + /// Offset relative to the start of the Field Item Layer + public readonly int Offset; + + public readonly byte[] Data; + + public FieldItemColumn(int x, int y, int offset, byte[] data) { - /// X Coordinate within the Field Item Layer - public readonly int X; - - /// Y Coordinate within the Field Item Layer - public readonly int Y; - - /// Offset relative to the start of the Field Item Layer - public readonly int Offset; - - public readonly byte[] Data; - - public FieldItemColumn(int x, int y, int offset, byte[] data) - { - X = x; - Y = y; - Offset = offset; - Data = data; - } + X = x; + Y = y; + Offset = offset; + Data = data; } -} +} \ No newline at end of file diff --git a/NHSE.Core/Editing/FieldItem/FieldItemDropper.cs b/NHSE.Core/Editing/FieldItem/FieldItemDropper.cs index a7004b4..021dd9c 100644 --- a/NHSE.Core/Editing/FieldItem/FieldItemDropper.cs +++ b/NHSE.Core/Editing/FieldItem/FieldItemDropper.cs @@ -1,126 +1,126 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Converts into columns of writable Item tiles. +/// +public static class FieldItemDropper { - /// - /// Converts into columns of writable Item tiles. - /// - public static class FieldItemDropper + private const int MapHeight = FieldItemLayer.FieldItemHeight; + private const int MapWidth = FieldItemLayer.FieldItemWidth; + + // Each dropped item is a 2x2 square, with the top left tile being the root node, and the other 3 being extensions pointing back to the root. + + /// + /// Raw X coordinate for the top-left item root tile. + /// Raw Y coordinate for the top-left item root tile. + /// Total count of items to be dropped (not tiles). + /// Count of items tall the overall spawn-rectangle is. + /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. + /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. + public static bool CanFitDropped(int x, int y, int totalCount, int yCount, int borderX, int borderY) { - private const int MapHeight = FieldItemLayer.FieldItemHeight; - private const int MapWidth = FieldItemLayer.FieldItemWidth; - - // Each dropped item is a 2x2 square, with the top left tile being the root node, and the other 3 being extensions pointing back to the root. - - /// - /// Raw X coordinate for the top-left item root tile. - /// Raw Y coordinate for the top-left item root tile. - /// Total count of items to be dropped (not tiles). - /// Count of items tall the overall spawn-rectangle is. - /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. - /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. - public static bool CanFitDropped(int x, int y, int totalCount, int yCount, int borderX, int borderY) - { - return CanFitDropped(x, y, totalCount, yCount, borderX, borderX, borderY, borderY); - } - - /// - /// Checks if the requested of items can be dropped on the field item layer. Does not check terrain or existing items. - /// - /// Coordinates should be 32x32 style instead of 16x16. - /// Raw X coordinate for the top-left item root tile. - /// Raw Y coordinate for the top-left item root tile. - /// Total count of items to be dropped (not tiles). - /// Count of items tall the overall spawn-rectangle is. - /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. - /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. - /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. - /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. - /// True if can fit, false if not. - public static bool CanFitDropped(int x, int y, int totalCount, int yCount, int leftX, int rightX, int topY, int botY) - { - var xCount = totalCount / yCount; - if (x < leftX || (x + (xCount * 2)) > MapWidth - rightX) - return false; - if (y < topY || (y + (yCount * 2)) > MapHeight - botY) - return false; - - return totalCount < (MapHeight * MapWidth / 32); - } - - public static IReadOnlyList InjectItemsAsDropped(int mapX, int mapY, IReadOnlyList item) - { - int yStride = (item.Count > 16) ? 16 : item.Count; - return InjectItemsAsDropped(mapX, mapY, item, yStride); - } - - public static IReadOnlyList InjectItemsAsDropped(int mapX, int mapY, IReadOnlyList item, int yStride) - { - var xStride = item.Count / yStride; - List result = new(yStride * xStride); - for (int i = 0; i < xStride; i++) - { - var x = mapX + (i * 2); - var y = mapY; - var itemSlice = item.Skip(i * yStride).Take(yStride).ToArray(); - - // Root+ExtensionY - var offset = GetTileOffset(x, y); - var data = GetColumnRoot(itemSlice); - var column = new FieldItemColumn(x, y, offset, data); - result.Add(column); - - // Ex X/XY - ++x; - offset = GetTileOffset(x, y); - data = GetColumnExtension(itemSlice); - column = new FieldItemColumn(x, y, offset, data); - result.Add(column); - } - return result; - } - - private static byte[] GetColumnRoot(Item[] items) - { - var col = new Item[items.Length * 2]; - for (int i = 0; i < items.Length; i++) - { - var item = items[i]; - var idx = i * 2; - col[idx] = GetDroppedItem(item); - col[idx + 1] = GetExtension(item, 0, 1); - } - return Item.SetArray(col); - } - - private static byte[] GetColumnExtension(Item[] items) - { - var col = new Item[items.Length * 2]; - for (int i = 0; i < items.Length; i++) - { - var item = items[i]; - var idx = i * 2; - col[idx] = GetExtension(item, 1, 0); - col[idx + 1] = GetExtension(item, 1, 1); - } - return Item.SetArray(col); - } - - private static int GetTileOffset(int x, int y) - { - return Item.SIZE * (y + (x * MapHeight)); - } - - private static Item GetDroppedItem(Item item) - { - var copy = new Item(); - copy.CopyFrom(item); - copy.ClearFlags(); - copy.IsDropped = true; - return copy; - } - - private static Item GetExtension(Item item, byte x, byte y) => new(Item.EXTENSION) { ExtensionItemId = item.ItemId, ExtensionX = x, ExtensionY = y }; + return CanFitDropped(x, y, totalCount, yCount, borderX, borderX, borderY, borderY); } -} + + /// + /// Checks if the requested of items can be dropped on the field item layer. Does not check terrain or existing items. + /// + /// Coordinates should be 32x32 style instead of 16x16. + /// Raw X coordinate for the top-left item root tile. + /// Raw Y coordinate for the top-left item root tile. + /// Total count of items to be dropped (not tiles). + /// Count of items tall the overall spawn-rectangle is. + /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. + /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. + /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. + /// Excluded outer tile count. Useful for enforcing that beach acre tiles are skipped. + /// True if can fit, false if not. + public static bool CanFitDropped(int x, int y, int totalCount, int yCount, int leftX, int rightX, int topY, int botY) + { + var xCount = totalCount / yCount; + if (x < leftX || (x + (xCount * 2)) > MapWidth - rightX) + return false; + if (y < topY || (y + (yCount * 2)) > MapHeight - botY) + return false; + + return totalCount < (MapHeight * MapWidth / 32); + } + + public static IReadOnlyList InjectItemsAsDropped(int mapX, int mapY, IReadOnlyList item) + { + int yStride = (item.Count > 16) ? 16 : item.Count; + return InjectItemsAsDropped(mapX, mapY, item, yStride); + } + + public static IReadOnlyList InjectItemsAsDropped(int mapX, int mapY, IReadOnlyList item, int yStride) + { + var xStride = item.Count / yStride; + List result = new(yStride * xStride); + for (int i = 0; i < xStride; i++) + { + var x = mapX + (i * 2); + var y = mapY; + var itemSlice = item.Skip(i * yStride).Take(yStride).ToArray(); + + // Root+ExtensionY + var offset = GetTileOffset(x, y); + var data = GetColumnRoot(itemSlice); + var column = new FieldItemColumn(x, y, offset, data); + result.Add(column); + + // Ex X/XY + ++x; + offset = GetTileOffset(x, y); + data = GetColumnExtension(itemSlice); + column = new FieldItemColumn(x, y, offset, data); + result.Add(column); + } + return result; + } + + private static byte[] GetColumnRoot(ReadOnlySpan items) + { + var col = new Item[items.Length * 2]; + for (int i = 0; i < items.Length; i++) + { + var item = items[i]; + var idx = i * 2; + col[idx] = GetDroppedItem(item); + col[idx + 1] = GetExtension(item, 0, 1); + } + return Item.SetArray(col); + } + + private static byte[] GetColumnExtension(ReadOnlySpan items) + { + var col = new Item[items.Length * 2]; + for (int i = 0; i < items.Length; i++) + { + var item = items[i]; + var idx = i * 2; + col[idx] = GetExtension(item, 1, 0); + col[idx + 1] = GetExtension(item, 1, 1); + } + return Item.SetArray(col); + } + + private static int GetTileOffset(int x, int y) + { + return Item.SIZE * (y + (x * MapHeight)); + } + + private static Item GetDroppedItem(Item item) + { + var copy = new Item(); + copy.CopyFrom(item); + copy.ClearFlags(); + copy.IsDropped = true; + return copy; + } + + private static Item GetExtension(Item item, byte x, byte y) => new(Item.EXTENSION) { ExtensionItemId = item.ItemId, ExtensionX = x, ExtensionY = y }; +} \ No newline at end of file diff --git a/NHSE.Core/Editing/Inventory/PlayerItemSet.cs b/NHSE.Core/Editing/Inventory/PlayerItemSet.cs index b6ae103..45dc446 100644 --- a/NHSE.Core/Editing/Inventory/PlayerItemSet.cs +++ b/NHSE.Core/Editing/Inventory/PlayerItemSet.cs @@ -1,135 +1,135 @@ using System; using System.Collections.Generic; using System.Linq; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Handles operations for parsing the player inventory. +/// +/// +/// Player Inventory is comprised of multiple values, which we won't bother reimplementing as a convertible data structure. +///
Refer to GSavePlayerItemBaggage's ItemBag & ItemPocket in the dumped c-structure schema.
+///
+public static class PlayerItemSet { + private const int ItemSet_Quantity = 2; // Pouch (Bag) & Pocket. + private const int ItemSet_ItemCount = 20; // 20 items per item set. + private const int ItemSet_ItemSize = Item.SIZE * ItemSet_ItemCount; + private const int ItemSet_MetaSize = 4 + ItemSet_ItemCount; + private const int ItemSet_TotalSize = (ItemSet_ItemSize + ItemSet_MetaSize) * ItemSet_Quantity; + private const int ShiftToTopOfStructure = -ItemSet_MetaSize - (Item.SIZE * ItemSet_ItemCount); // shifts slot1 offset => top of data structure + /// - /// Handles operations for parsing the player inventory. + /// Gets the Offset and Size to read from based on the Item 1 RAM offset. /// - /// - /// Player Inventory is comprised of multiple values, which we won't bother reimplementing as a convertible data structure. - ///
Refer to GSavePlayerItemBaggage's ItemBag & ItemPocket in the dumped c-structure schema.
- ///
- public static class PlayerItemSet + /// Item Slot 1 offset in RAM + /// Offset to read from + /// Length of data to read from + public static void GetOffsetLength(uint slot1, out uint offset, out int length) { - private const int ItemSet_Quantity = 2; // Pouch (Bag) & Pocket. - private const int ItemSet_ItemCount = 20; // 20 items per item set. - private const int ItemSet_ItemSize = Item.SIZE * ItemSet_ItemCount; - private const int ItemSet_MetaSize = 4 + ItemSet_ItemCount; - private const int ItemSet_TotalSize = (ItemSet_ItemSize + ItemSet_MetaSize) * ItemSet_Quantity; - private const int ShiftToTopOfStructure = -ItemSet_MetaSize - (Item.SIZE * ItemSet_ItemCount); // shifts slot1 offset => top of data structure - - /// - /// Gets the Offset and Size to read from based on the Item 1 RAM offset. - /// - /// Item Slot 1 offset in RAM - /// Offset to read from - /// Length of data to read from - public static void GetOffsetLength(uint slot1, out uint offset, out int length) - { - offset = (uint)((int)slot1 + ShiftToTopOfStructure); - length = ItemSet_TotalSize; - } - - /// - /// Compares the raw data to the expected data layout. - /// - /// Raw RAM from the game from the offset read (as per ). - /// True if valid, false if not valid or corrupt. - public static bool ValidateItemBinary(byte[] data) - { - // Check the unlocked slot count -- expect 0,10,20 - var bagCount = BitConverter.ToUInt32(data, ItemSet_ItemSize); - if (bagCount > ItemSet_ItemCount || bagCount % 10 != 0) // pouch21-39 count - return false; - - var pocketCount = BitConverter.ToUInt32(data, ItemSet_ItemSize + ItemSet_MetaSize + ItemSet_ItemSize); - if (pocketCount != ItemSet_ItemCount) // pouch0-19 count should be 20. - return false; - - // Check the item wheel binding -- expect -1 or [0,7] - // Disallow duplicate binds! - // Don't bother checking that bind[i] (when ! -1) is not NONE at items[i]. We don't need to check everything! - var bound = new List(); - if (!ValidateBindList(data, ItemSet_ItemSize + 4, bound)) - return false; - if (!ValidateBindList(data, ItemSet_ItemSize + 4 + (ItemSet_ItemSize + ItemSet_MetaSize), bound)) - return false; - - return true; - } - - private static bool ValidateBindList(byte[] data, int bindStart, ICollection bound) - { - for (int i = 0; i < ItemSet_ItemCount; i++) - { - var bind = data[bindStart + i]; - if (bind == 0xFF) // Not bound - continue; - if (bind > 7) // Only [0,7] permitted as the wheel has 8 spots - return false; - if (bound.Contains(bind)) // Wheel index is already bound to another item slot - return false; - - bound.Add(bind); - } - - return true; - } - - /// - /// Reads the items present in the player inventory packet and returns the list of items. - /// - /// Player Inventory packet - public static Item[] ReadPlayerInventory(byte[] data) - { - var items = GetEmptyItemArray(40); - ReadPlayerInventory(data, items); - return items; - } - - private static Item[] GetEmptyItemArray(int count) - { - var items = new Item[count]; - for (int i = 0; i < items.Length; i++) - items[i] = new Item(); - return items; - } - - /// - /// Reads the items present in the player inventory packet into the list of items. - /// - /// Player Inventory packet - /// 40 Item array - public static void ReadPlayerInventory(byte[] data, IReadOnlyList destination) - { - var pocket2 = destination.Take(20).ToArray(); - var pocket1 = destination.Skip(20).ToArray(); - var p1 = Item.GetArray(data.Slice(0, ItemSet_ItemSize)); - var p2 = Item.GetArray(data.Slice(ItemSet_ItemSize + 0x18, ItemSet_ItemSize)); - - for (int i = 0; i < pocket1.Length; i++) - pocket1[i].CopyFrom(p1[i]); - - for (int i = 0; i < pocket2.Length; i++) - pocket2[i].CopyFrom(p2[i]); - } - - /// - /// Writes the items in the list of items to the player inventory packet. - /// - /// Player Inventory packet - /// 40 Item array - public static void WritePlayerInventory(byte[] data, IReadOnlyList source) - { - var pocket2 = source.Take(20).ToArray(); - var pocket1 = source.Skip(20).ToArray(); - var p1 = Item.SetArray(pocket1); - var p2 = Item.SetArray(pocket2); - - p1.CopyTo(data, 0); - p2.CopyTo(data, ItemSet_ItemSize + 0x18); - } + offset = (uint)((int)slot1 + ShiftToTopOfStructure); + length = ItemSet_TotalSize; } -} + + /// + /// Compares the raw data to the expected data layout. + /// + /// Raw RAM from the game from the offset read (as per ). + /// True if valid, false if not valid or corrupt. + public static bool ValidateItemBinary(ReadOnlySpan data) + { + // Check the unlocked slot count -- expect 0,10,20 + var bagCount = ReadUInt32LittleEndian(data[ItemSet_ItemSize..]); + if (bagCount > ItemSet_ItemCount || bagCount % 10 != 0) // pouch21-39 count + return false; + + var pocketCount = ReadUInt32LittleEndian(data[(ItemSet_ItemSize + ItemSet_MetaSize + ItemSet_ItemSize)..]); + if (pocketCount != ItemSet_ItemCount) // pouch0-19 count should be 20. + return false; + + // Check the item wheel binding -- expect -1 or [0,7] + // Disallow duplicate binds! + // Don't bother checking that bind[i] (when ! -1) is not NONE at items[i]. We don't need to check everything! + var bound = new List(); + if (!ValidateBindList(data, ItemSet_ItemSize + 4, bound)) + return false; + if (!ValidateBindList(data, ItemSet_ItemSize + 4 + (ItemSet_ItemSize + ItemSet_MetaSize), bound)) + return false; + + return true; + } + + private static bool ValidateBindList(ReadOnlySpan data, int bindStart, ICollection bound) + { + for (int i = 0; i < ItemSet_ItemCount; i++) + { + var bind = data[bindStart + i]; + if (bind == 0xFF) // Not bound + continue; + if (bind > 7) // Only [0,7] permitted as the wheel has 8 spots + return false; + if (bound.Contains(bind)) // Wheel index is already bound to another item slot + return false; + + bound.Add(bind); + } + + return true; + } + + /// + /// Reads the items present in the player inventory packet and returns the list of items. + /// + /// Player Inventory packet + public static Item[] ReadPlayerInventory(ReadOnlySpan data) + { + var items = GetEmptyItemArray(40); + ReadPlayerInventory(data, items); + return items; + } + + private static Item[] GetEmptyItemArray(int count) + { + var items = new Item[count]; + for (int i = 0; i < items.Length; i++) + items[i] = new Item(); + return items; + } + + /// + /// Reads the items present in the player inventory packet into the list of items. + /// + /// Player Inventory packet + /// 40 Item array + public static void ReadPlayerInventory(ReadOnlySpan data, IReadOnlyList destination) + { + var pocket2 = destination.Take(20).ToArray(); + var pocket1 = destination.Skip(20).ToArray(); + var p1 = Item.GetArray(data[..ItemSet_ItemSize]); + var p2 = Item.GetArray(data.Slice(ItemSet_ItemSize + 0x18, ItemSet_ItemSize)); + + for (int i = 0; i < pocket1.Length; i++) + pocket1[i].CopyFrom(p1[i]); + + for (int i = 0; i < pocket2.Length; i++) + pocket2[i].CopyFrom(p2[i]); + } + + /// + /// Writes the items in the list of items to the player inventory packet. + /// + /// Player Inventory packet + /// 40 Item array + public static void WritePlayerInventory(Span data, IReadOnlyList source) + { + var pocket2 = source.Take(20).ToArray(); + var pocket1 = source.Skip(20).ToArray(); + var p1 = Item.SetArray(pocket1); + var p2 = Item.SetArray(pocket2); + + p1.CopyTo(data); + p2.CopyTo(data[(ItemSet_ItemSize + 0x18)..]); + } +} \ No newline at end of file diff --git a/NHSE.Core/Editing/ItemRequest/IConfigItem.cs b/NHSE.Core/Editing/ItemRequest/IConfigItem.cs index 82958b1..c670df3 100644 --- a/NHSE.Core/Editing/ItemRequest/IConfigItem.cs +++ b/NHSE.Core/Editing/ItemRequest/IConfigItem.cs @@ -1,23 +1,22 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Interface describing how items should be configured prior to being dropped by the player. +/// +public interface IConfigItem { /// - /// Interface describing how items should be configured prior to being dropped by the player. + /// Checks if the item should have wrapping paper applied. /// - public interface IConfigItem - { - /// - /// Checks if the item should have wrapping paper applied. - /// - bool WrapAllItems { get; } + bool WrapAllItems { get; } - /// - /// Wrapping paper type applied if is set. - /// - ItemWrappingPaper WrappingPaper { get; } + /// + /// Wrapping paper type applied if is set. + /// + ItemWrappingPaper WrappingPaper { get; } - /// - /// Checks if the Drop Compatibility check should be skipped. - /// - bool SkipDropCheck { get; } - } -} + /// + /// Checks if the Drop Compatibility check should be skipped. + /// + bool SkipDropCheck { get; } +} \ No newline at end of file diff --git a/NHSE.Core/Editing/ItemRequest/ItemParser.cs b/NHSE.Core/Editing/ItemRequest/ItemParser.cs index 53ec045..96bd067 100644 --- a/NHSE.Core/Editing/ItemRequest/ItemParser.cs +++ b/NHSE.Core/Editing/ItemRequest/ItemParser.cs @@ -2,383 +2,385 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Logic for retrieving details based off input strings. +/// +public static class ItemParser { /// - /// Logic for retrieving details based off input strings. + /// Invert the recipe dictionary so we can look up recipe IDs from an input item ID. /// - public static class ItemParser + public static readonly IReadOnlyDictionary InvertedRecipeDictionary = + RecipeList.Recipes.ToDictionary(z => z.Value, z => z.Key); + + // Users can put spaces between item codes, or newlines. Recognize both! + private static readonly string[] SplittersHex = [" ", "\n", "\r\n"]; + private static readonly string[] SplittersName = [",", "\n", "\r\n"]; + + /// + /// Gets a list of items from the requested hex string(s). + /// + /// + /// If the first input is a language code (2 characters), the logic will try to parse item names for that language instead of item IDs. + /// + /// 8 byte hex item values (u64 format) + /// Options for packaging items + /// End destination of the item + public static IReadOnlyCollection GetItemsFromUserInput(string requestHex, IConfigItem cfg, ItemDestination type = ItemDestination.PlayerDropped) { - /// - /// Invert the recipe dictionary so we can look up recipe IDs from an input item ID. - /// - public static readonly IReadOnlyDictionary InvertedRecipeDictionary = - RecipeList.Recipes.ToDictionary(z => z.Value, z => z.Key); - - // Users can put spaces between item codes, or newlines. Recognize both! - private static readonly string[] SplittersHex = {" ", "\n", "\r\n"}; - private static readonly string[] SplittersName = {",", "\n", "\r\n"}; - - /// - /// Gets a list of items from the requested hex string(s). - /// - /// - /// If the first input is a language code (2 characters), the logic will try to parse item names for that language instead of item IDs. - /// - /// 8 byte hex item values (u64 format) - /// Options for packaging items - /// End destination of the item - public static IReadOnlyCollection GetItemsFromUserInput(string requestHex, IConfigItem cfg, ItemDestination type = ItemDestination.PlayerDropped) + try { - try - { - // having a language 2char code will cause an exception in parsing; this is fine and is handled by our catch statement. - var split = requestHex.Split(SplittersHex, StringSplitOptions.RemoveEmptyEntries); - return GetItemsHexCode(split, cfg, type); - } - catch - { - var split = requestHex.Split(SplittersName, StringSplitOptions.RemoveEmptyEntries); - return GetItemsLanguage(split, cfg, type, GameLanguage.DefaultLanguage); - } + // having a language 2char code will cause an exception in parsing; this is fine and is handled by our catch statement. + var split = requestHex.Split(SplittersHex, StringSplitOptions.RemoveEmptyEntries); + return GetItemsHexCode(split, cfg, type); } - - /// - /// Gets a list of DIY item cards from the requested list of DIY IDs. - /// - /// - /// If the first input is a language code (2 characters), the logic will try to parse item names for that language instead of DIY IDs. - /// - /// 8 byte hex item values (u64 format) - public static IReadOnlyCollection GetDIYsFromUserInput(string requestHex) + catch { - try - { - // having a language 2char code will cause an exception in parsing; this is fine and is handled by our catch statement. - var split = requestHex.Split(SplittersHex, StringSplitOptions.RemoveEmptyEntries); - return GetDIYItemsHexCode(split); - } - catch - { - var split = requestHex.Split(SplittersName, StringSplitOptions.RemoveEmptyEntries); - return GetDIYItemsLanguage(split); - } - } - - /// - /// Gets a list of items from the requested list of DIY hex code strings. - /// - /// - /// If a hex code parse fails or a recipe ID does not exist, exceptions will be thrown. - /// - /// List of recipe IDs as u16 hex - public static IReadOnlyCollection GetDIYItemsHexCode(IReadOnlyList split) - { - var result = new Item[split.Count]; - for (int i = 0; i < result.Length; i++) - { - var text = split[i].Trim(); - bool parse = ulong.TryParse(text, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var value); - if (!parse) - throw new Exception($"Item value out of expected range ({text})."); - - if (!RecipeList.Recipes.TryGetValue((ushort)value, out _)) - throw new Exception($"DIY recipe appears to be invalid ({text})."); - - result[i] = new Item(Item.DIYRecipe) { Count = (ushort)value }; - } - return result; - } - - /// - /// Gets a list of DIY item cards from the requested list of item name strings. - /// - /// - /// If a item name parse fails or a recipe ID does not exist, exceptions will be thrown. - /// - /// List of item names - /// Language code to parse with. If the first entry in is a language code, it will be used instead of . - public static IReadOnlyCollection GetDIYItemsLanguage(IReadOnlyList split, string lang = GameLanguage.DefaultLanguage) - { - if (split.Count > 1 && split[0].Length < 3) - { - var langIndex = GameLanguage.GetLanguageIndex(split[0]); - lang = GameLanguage.Language2Char(langIndex); - split = split.Skip(1).ToArray(); - } - - var result = new Item[split.Count]; - for (int i = 0; i < result.Length; i++) - { - var text = split[i].Trim(); - var item = GetItem(text, lang); - if (!InvertedRecipeDictionary.TryGetValue(item.ItemId, out var diy)) - throw new Exception($"DIY recipe appears to be invalid ({text})."); - - result[i] = new Item(Item.DIYRecipe) { Count = diy }; - } - return result; - } - - /// - /// Gets a list of items from the requested list of item name strings. - /// - /// - /// If a item name parse fails or the item ID does not exist as a known item, exceptions will be thrown. - /// - /// List of item names - /// Item packaging options - /// Destination where the item will end up at - /// Language code to parse with. If the first entry in is a language code, it will be used instead of . - public static IReadOnlyCollection GetItemsLanguage(IReadOnlyList split, IConfigItem config, ItemDestination type = ItemDestination.PlayerDropped, string lang = GameLanguage.DefaultLanguage) - { - if (split.Count > 1 && split[0].Length < 3) - { - var langIndex = GameLanguage.GetLanguageIndex(split[0]); - lang = GameLanguage.Language2Char(langIndex); - split = split.Skip(1).ToArray(); - } - - var strings = GameInfo.Strings.itemlistdisplay; - var result = new Item[split.Count]; - for (int i = 0; i < result.Length; i++) - { - var text = split[i].Trim(); - var item = CreateItem(text, i, config, type, lang); - - if (item.ItemId >= strings.Length) - throw new Exception($"Item requested is out of expected range ({item.ItemId:X4} > {strings.Length:X4})."); - if (string.IsNullOrWhiteSpace(strings[item.ItemId])) - throw new Exception($"Item requested does not have a valid name ({item.ItemId:X4})."); - - result[i] = item; - } - return result; - } - - /// - /// Gets a list of items from the requested list of item hex code strings. - /// - /// - /// If a hex code parse fails or a recipe ID does not exist, exceptions will be thrown. - /// - /// List of recipe IDs as u16 hex - /// Item packaging options - /// Destination where the item will end up at - public static IReadOnlyCollection GetItemsHexCode(IReadOnlyList split, IConfigItem config, ItemDestination type = ItemDestination.PlayerDropped) - { - var strings = GameInfo.Strings.itemlistdisplay; - var result = new Item[split.Count]; - for (int i = 0; i < result.Length; i++) - { - var text = split[i].Trim(); - var convert = GetBytesFromString(text); - var item = CreateItem(convert, i, config, type); - - if (item.ItemId >= strings.Length) - throw new Exception($"Item requested is out of expected range ({item.ItemId:X4} > {strings.Length:X4})."); - if (string.IsNullOrWhiteSpace(strings[item.ItemId])) - throw new Exception($"Item requested does not have a valid name ({item.ItemId:X4})."); - - result[i] = item; - } - return result; - } - - private static byte[] GetBytesFromString(string text) - { - if (!ulong.TryParse(text, NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out var value)) - return Item.NONE.ToBytes(); - return BitConverter.GetBytes(value); - } - - private static Item CreateItem(string name, int requestIndex, IConfigItem config, ItemDestination type, string lang = "en") - { - var item = GetItem(name, lang); - if (item.IsNone) - throw new Exception($"Failed to convert item (index {requestIndex}: {name}) for Language {lang}."); - - return FinalizeItem(requestIndex, config, type, item); - } - - private static Item CreateItem(byte[] convert, int requestIndex, IConfigItem config, ItemDestination type) - { - Item item; - try - { - if (convert.Length != Item.SIZE) - throw new Exception(); - item = convert.ToClass(); - } - catch (Exception ex) - { - throw new Exception($"Failed to convert item (index {requestIndex}: {ex.Message})."); - } - - return FinalizeItem(requestIndex, config, type, item); - } - - private static Item FinalizeItem(int requestIndex, IConfigItem config, ItemDestination type, Item item) - { - if (type == ItemDestination.PlayerDropped) - { - if (!ItemInfo.IsSaneItemForDrop(item) && !config.SkipDropCheck) - throw new Exception($"Unsupported item: (index {requestIndex})."); - if (config.WrapAllItems && item.ShouldWrapItem()) - item.SetWrapping(ItemWrapping.WrappingPaper, config.WrappingPaper, true); - } - - item.IsDropped = type == ItemDestination.FieldItemDropped; - - return item; - } - - private static readonly CompareInfo Comparer = CultureInfo.InvariantCulture.CompareInfo; - private const CompareOptions optIncludeSymbols = CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreWidth; - private const CompareOptions optIgnoreSymbols = CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreWidth; - - /// - /// Gets a sensitive compare option, depending on the input string's qualities. - /// - /// Input string - /// Default options if no symbols, - private static CompareOptions GetCompareOption(string str) => str.Any(ch => !char.IsLetterOrDigit(ch) && !char.IsWhiteSpace(ch)) ? optIgnoreSymbols & ~CompareOptions.IgnoreSymbols : optIgnoreSymbols; - - /// - /// Gets the first item name-value that contains the (case insensitive). - /// - /// Requested Item - /// Game strings language to fetch with - /// Returns if no match found. - public static Item GetItem(string itemName, string lang = "en") - { - var gStrings = GameInfo.GetStrings(lang); - var strings = gStrings.ItemDataSource; - var parsedItem = GetItem(itemName, strings); - if (parsedItem != Item.NO_ITEM) - return parsedItem; - - if (gStrings.HasAssociatedItems(itemName, out var items)) - { - if (items?.Count == 1) - return new Item((ushort)items[0].Value); - } - - return Item.NO_ITEM; - } - - /// - /// Gets the first item name-value that contains the (case insensitive). - /// - /// Requested Item - /// Game strings - /// Returns if no match found. - public static Item GetItem(string itemName, IReadOnlyList strings) - { - if (TryGetItem(itemName, strings, out var id)) - return new Item(id); - return Item.NO_ITEM; - } - - /// - /// Gets the first item name-value that contains the (case insensitive). - /// - /// Requested Item - /// List of item name-values - /// Item ID, if found. Otherwise, 0 - /// True if found, false if none. - public static bool TryGetItem(string itemName, IReadOnlyList strings, out ushort value) - { - if (TryGetItem(itemName, strings, out value, optIncludeSymbols)) - return true; - return TryGetItem(itemName, strings, out value, optIgnoreSymbols); - } - - private static bool TryGetItem(string itemName, IEnumerable strings, out ushort value, CompareOptions opt) - { - foreach (var item in strings) - { - var result = Comparer.Compare(item.Text, 0, itemName, 0, opt); - if (result != 0) - continue; - - value = (ushort)item.Value; - return true; - } - - value = Item.NONE; - return false; - } - - /// - /// Gets an enumerable list of item key-value pairs that contain (case insensitive) the requested . - /// - /// Item name - /// Item names (and their Item ID values) - public static IEnumerable GetItemsMatching(string itemName, IEnumerable strings) - { - var opt = GetCompareOption(itemName); - foreach (var item in strings) - { - var result = Comparer.IndexOf(item.Text, itemName, opt); - if (result < 0) - continue; - yield return item; - } - } - - /// - /// Gets an enumerable list of item key-value pairs that contain (case insensitive) the requested . - /// - /// - /// Orders the items based on the closest match (). - /// - /// Item name - /// Item names (and their Item ID values) - public static IEnumerable GetItemsMatchingOrdered(string itemName, IEnumerable strings) - { - var matches = GetItemsMatching(itemName, strings); - return GetItemsClosestOrdered(itemName, matches); - } - - /// - /// Gets an enumerable list of item key-value pairs ordered by the closest for the requested . - /// - /// Item name - /// Item names (and their Item ID values) - public static IEnumerable GetItemsClosestOrdered(string itemName, IEnumerable strings) - { - return strings.OrderBy(z => LevenshteinDistance.Compute(z.Text, itemName)); - } - - /// - /// Gets the Item Name and raw 8-byte value as a string. - /// - /// Item value - public static string GetItemText(Item item) - { - var value = BitConverter.ToUInt64(item.ToBytesClass(), 0); - var name = GameInfo.Strings.GetItemName(item.ItemId); - return $"{name}: {value:X16}"; - } - - /// - /// Gets the u16 item ID from the input hex code. - /// - /// Hex code for the item (preferably 4 digits) - public static ushort GetID(string text) - { - if (!ulong.TryParse(text.Trim(), NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out var value)) - return Item.NONE; - return (ushort)value; + var split = requestHex.Split(SplittersName, StringSplitOptions.RemoveEmptyEntries); + return GetItemsLanguage(split, cfg, type, GameLanguage.DefaultLanguage); } } - public enum ItemDestination + /// + /// Gets a list of DIY item cards from the requested list of DIY IDs. + /// + /// + /// If the first input is a language code (2 characters), the logic will try to parse item names for that language instead of DIY IDs. + /// + /// 8 byte hex item values (u64 format) + public static IReadOnlyCollection GetDIYsFromUserInput(string requestHex) { - PlayerDropped, - FieldItemDropped, - HeldItem, + try + { + // having a language 2char code will cause an exception in parsing; this is fine and is handled by our catch statement. + var split = requestHex.Split(SplittersHex, StringSplitOptions.RemoveEmptyEntries); + return GetDIYItemsHexCode(split); + } + catch + { + var split = requestHex.Split(SplittersName, StringSplitOptions.RemoveEmptyEntries); + return GetDIYItemsLanguage(split); + } + } + + /// + /// Gets a list of items from the requested list of DIY hex code strings. + /// + /// + /// If a hex code parse fails or a recipe ID does not exist, exceptions will be thrown. + /// + /// List of recipe IDs as u16 hex + public static IReadOnlyCollection GetDIYItemsHexCode(IReadOnlyList split) + { + var result = new Item[split.Count]; + for (int i = 0; i < result.Length; i++) + { + var text = split[i].Trim(); + bool parse = ulong.TryParse(text, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var value); + if (!parse) + throw new Exception($"Item value out of expected range ({text})."); + + if (!RecipeList.Recipes.TryGetValue((ushort)value, out _)) + throw new Exception($"DIY recipe appears to be invalid ({text})."); + + result[i] = new Item(Item.DIYRecipe) { Count = (ushort)value }; + } + return result; + } + + /// + /// Gets a list of DIY item cards from the requested list of item name strings. + /// + /// + /// If an item name parse fails or a recipe ID does not exist, exceptions will be thrown. + /// + /// List of item names + /// Language code to parse with. If the first entry in is a language code, it will be used instead of . + public static IReadOnlyCollection GetDIYItemsLanguage(IReadOnlyList split, string lang = GameLanguage.DefaultLanguage) + { + if (split.Count > 1 && split[0].Length < 3) + { + var langIndex = GameLanguage.GetLanguageIndex(split[0]); + lang = GameLanguage.Language2Char(langIndex); + split = split.Skip(1).ToArray(); + } + + var result = new Item[split.Count]; + for (int i = 0; i < result.Length; i++) + { + var text = split[i].Trim(); + var item = GetItem(text, lang); + if (!InvertedRecipeDictionary.TryGetValue(item.ItemId, out var diy)) + throw new Exception($"DIY recipe appears to be invalid ({text})."); + + result[i] = new Item(Item.DIYRecipe) { Count = diy }; + } + return result; + } + + /// + /// Gets a list of items from the requested list of item name strings. + /// + /// + /// If an item name parse fails or the item ID does not exist as a known item, exceptions will be thrown. + /// + /// List of item names + /// Item packaging options + /// Destination where the item will end up at + /// Language code to parse with. If the first entry in is a language code, it will be used instead of . + public static IReadOnlyCollection GetItemsLanguage(IReadOnlyList split, IConfigItem config, ItemDestination type = ItemDestination.PlayerDropped, string lang = GameLanguage.DefaultLanguage) + { + if (split.Count > 1 && split[0].Length < 3) + { + var langIndex = GameLanguage.GetLanguageIndex(split[0]); + lang = GameLanguage.Language2Char(langIndex); + split = split.Skip(1).ToArray(); + } + + var strings = GameInfo.Strings.itemlistdisplay; + var result = new Item[split.Count]; + for (int i = 0; i < result.Length; i++) + { + var text = split[i].Trim(); + var item = CreateItem(text, i, config, type, lang); + + if (item.ItemId >= strings.Length) + throw new Exception($"Item requested is out of expected range ({item.ItemId:X4} > {strings.Length:X4})."); + if (string.IsNullOrWhiteSpace(strings[item.ItemId])) + throw new Exception($"Item requested does not have a valid name ({item.ItemId:X4})."); + + result[i] = item; + } + return result; + } + + /// + /// Gets a list of items from the requested list of item hex code strings. + /// + /// + /// If a hex code parse fails or a recipe ID does not exist, exceptions will be thrown. + /// + /// List of recipe IDs as u16 hex + /// Item packaging options + /// Destination where the item will end up at + public static IReadOnlyCollection GetItemsHexCode(IReadOnlyList split, IConfigItem config, ItemDestination type = ItemDestination.PlayerDropped) + { + var strings = GameInfo.Strings.itemlistdisplay; + var result = new Item[split.Count]; + for (int i = 0; i < result.Length; i++) + { + var text = split[i].Trim(); + var convert = GetBytesFromString(text); + var item = CreateItem(convert, i, config, type); + + if (item.ItemId >= strings.Length) + throw new Exception($"Item requested is out of expected range ({item.ItemId:X4} > {strings.Length:X4})."); + if (string.IsNullOrWhiteSpace(strings[item.ItemId])) + throw new Exception($"Item requested does not have a valid name ({item.ItemId:X4})."); + + result[i] = item; + } + return result; + } + + private static byte[] GetBytesFromString(string text) + { + if (!ulong.TryParse(text, NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out var value)) + return Item.NONE.ToBytes(); + var bytes = new byte[sizeof(ulong)]; + WriteUInt64LittleEndian(bytes, value); + return bytes; + } + + private static Item CreateItem(string name, int requestIndex, IConfigItem config, ItemDestination type, string lang = "en") + { + var item = GetItem(name, lang); + if (item.IsNone) + throw new Exception($"Failed to convert item (index {requestIndex}: {name}) for Language {lang}."); + + return FinalizeItem(requestIndex, config, type, item); + } + + private static Item CreateItem(byte[] convert, int requestIndex, IConfigItem config, ItemDestination type) + { + Item item; + try + { + if (convert.Length != Item.SIZE) + throw new Exception(); + item = convert.ToClass(); + } + catch (Exception ex) + { + throw new Exception($"Failed to convert item (index {requestIndex}: {ex.Message})."); + } + + return FinalizeItem(requestIndex, config, type, item); + } + + private static Item FinalizeItem(int requestIndex, IConfigItem config, ItemDestination type, Item item) + { + if (type == ItemDestination.PlayerDropped) + { + if (!ItemInfo.IsSaneItemForDrop(item) && !config.SkipDropCheck) + throw new Exception($"Unsupported item: (index {requestIndex})."); + if (config.WrapAllItems && item.ShouldWrapItem()) + item.SetWrapping(ItemWrapping.WrappingPaper, config.WrappingPaper, true); + } + + item.IsDropped = type == ItemDestination.FieldItemDropped; + + return item; + } + + private static readonly CompareInfo Comparer = CultureInfo.InvariantCulture.CompareInfo; + private const CompareOptions optIncludeSymbols = CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreWidth; + private const CompareOptions optIgnoreSymbols = CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreWidth; + + /// + /// Gets a sensitive compare option, depending on the input string's qualities. + /// + /// Input string + /// Default options if no symbols, + private static CompareOptions GetCompareOption(string str) => str.Any(ch => !char.IsLetterOrDigit(ch) && !char.IsWhiteSpace(ch)) ? optIgnoreSymbols & ~CompareOptions.IgnoreSymbols : optIgnoreSymbols; + + /// + /// Gets the first item name-value that contains the (case-insensitive). + /// + /// Requested Item + /// Game strings language to fetch with + /// Returns if no match found. + public static Item GetItem(string itemName, string lang = "en") + { + var gStrings = GameInfo.GetStrings(lang); + var strings = gStrings.ItemDataSource; + var parsedItem = GetItem(itemName, strings); + if (parsedItem != Item.NO_ITEM) + return parsedItem; + + if (gStrings.HasAssociatedItems(itemName, out var items)) + { + if (items?.Count == 1) + return new Item((ushort)items[0].Value); + } + + return Item.NO_ITEM; + } + + /// + /// Gets the first item name-value that contains the (case-insensitive). + /// + /// Requested Item + /// Game strings + /// Returns if no match found. + public static Item GetItem(string itemName, IReadOnlyList strings) + { + if (TryGetItem(itemName, strings, out var id)) + return new Item(id); + return Item.NO_ITEM; + } + + /// + /// Gets the first item name-value that contains the (case-insensitive). + /// + /// Requested Item + /// List of item name-values + /// Item ID, if found. Otherwise, 0 + /// True if found, false if none. + public static bool TryGetItem(string itemName, IReadOnlyList strings, out ushort value) + { + if (TryGetItem(itemName, strings, out value, optIncludeSymbols)) + return true; + return TryGetItem(itemName, strings, out value, optIgnoreSymbols); + } + + private static bool TryGetItem(string itemName, IEnumerable strings, out ushort value, CompareOptions opt) + { + foreach (var item in strings) + { + var result = Comparer.Compare(item.Text, 0, itemName, 0, opt); + if (result != 0) + continue; + + value = (ushort)item.Value; + return true; + } + + value = Item.NONE; + return false; + } + + /// + /// Gets an enumerable list of item key-value pairs that contain (case-insensitive) the requested . + /// + /// Item name + /// Item names (and their Item ID values) + public static IEnumerable GetItemsMatching(string itemName, IEnumerable strings) + { + var opt = GetCompareOption(itemName); + foreach (var item in strings) + { + var result = Comparer.IndexOf(item.Text, itemName, opt); + if (result < 0) + continue; + yield return item; + } + } + + /// + /// Gets an enumerable list of item key-value pairs that contain (case-insensitive) the requested . + /// + /// + /// Orders the items based on the closest match (). + /// + /// Item name + /// Item names (and their Item ID values) + public static IEnumerable GetItemsMatchingOrdered(string itemName, IEnumerable strings) + { + var matches = GetItemsMatching(itemName, strings); + return GetItemsClosestOrdered(itemName, matches); + } + + /// + /// Gets an enumerable list of item key-value pairs ordered by the closest for the requested . + /// + /// Item name + /// Item names (and their Item ID values) + public static IEnumerable GetItemsClosestOrdered(string itemName, IEnumerable strings) + { + return strings.OrderBy(z => LevenshteinDistance.Compute(z.Text, itemName)); + } + + /// + /// Gets the Item Name and raw 8-byte value as a string. + /// + /// Item value + public static string GetItemText(Item item) + { + var value = ReadUInt64LittleEndian(item.ToBytesClass()); + var name = GameInfo.Strings.GetItemName(item.ItemId); + return $"{name}: {value:X16}"; + } + + /// + /// Gets the u16 item ID from the input hex code. + /// + /// Hex code for the item (preferably 4 digits) + public static ushort GetID(string text) + { + if (!ulong.TryParse(text.Trim(), NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out var value)) + return Item.NONE; + return (ushort)value; } } + +public enum ItemDestination +{ + PlayerDropped, + FieldItemDropped, + HeldItem, +} \ No newline at end of file diff --git a/NHSE.Core/Editing/ItemRequest/LevenshteinDistance.cs b/NHSE.Core/Editing/ItemRequest/LevenshteinDistance.cs index d6c6b89..cbbe73d 100644 --- a/NHSE.Core/Editing/ItemRequest/LevenshteinDistance.cs +++ b/NHSE.Core/Editing/ItemRequest/LevenshteinDistance.cs @@ -1,50 +1,49 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +public static class LevenshteinDistance { - public static class LevenshteinDistance + /// + /// Compute the distance between two strings. + /// http://www.dotnetperls.com/levenshtein + /// https://stackoverflow.com/a/13793600 + /// + public static int Compute(string s, string t) { - /// - /// Compute the distance between two strings. - /// http://www.dotnetperls.com/levenshtein - /// https://stackoverflow.com/a/13793600 - /// - public static int Compute(string s, string t) + int n = s.Length; + int m = t.Length; + int[,] d = new int[n + 1, m + 1]; + + // Step 1 + if (n == 0) + return m; + + if (m == 0) + return n; + + // Step 2 + for (int i = 0; i <= n; d[i, 0] = i++) { } + for (int j = 0; j <= m; d[0, j] = j++) { } + + // Step 3 + for (int i = 1; i <= n; i++) { - int n = s.Length; - int m = t.Length; - int[,] d = new int[n + 1, m + 1]; - - // Step 1 - if (n == 0) - return m; - - if (m == 0) - return n; - - // Step 2 - for (int i = 0; i <= n; d[i, 0] = i++) { } - for (int j = 0; j <= m; d[0, j] = j++) { } - - // Step 3 - for (int i = 1; i <= n; i++) + //Step 4 + for (int j = 1; j <= m; j++) { - //Step 4 - for (int j = 1; j <= m; j++) - { - // Step 5 - int cost = (t[j - 1] == s[i - 1]) ? 0 : 1; + // Step 5 + int cost = (t[j - 1] == s[i - 1]) ? 0 : 1; - // Step 6 - var x1 = d[i - 1, j] + 1; - var x2 = d[i, j - 1] + 1; - var x3 = d[i - 1, j - 1] + cost; - d[i, j] = Math.Min(Math.Min(x1, x2), x3); - } + // Step 6 + var x1 = d[i - 1, j] + 1; + var x2 = d[i, j - 1] + 1; + var x3 = d[i - 1, j - 1] + cost; + d[i, j] = Math.Min(Math.Min(x1, x2), x3); } - - // Step 7 - return d[n, m]; } + + // Step 7 + return d[n, m]; } -} +} \ No newline at end of file diff --git a/NHSE.Core/Encryption/Aes128Ctr.cs b/NHSE.Core/Encryption/Aes128Ctr.cs index 61c36c7..1769c80 100644 --- a/NHSE.Core/Encryption/Aes128Ctr.cs +++ b/NHSE.Core/Encryption/Aes128Ctr.cs @@ -2,122 +2,128 @@ using System.Collections.Generic; using System.Security.Cryptography; -namespace NHSE.Core +namespace NHSE.Core; +// The MIT License (MIT) + +// Copyright (c) 2014 Hans Wolff + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +public sealed class Aes128CounterMode : SymmetricAlgorithm { - // The MIT License (MIT) + private readonly byte[] _counter; + private readonly Aes _aes = GetAes(); - // Copyright (c) 2014 Hans Wolff - - // Permission is hereby granted, free of charge, to any person obtaining a copy - // of this software and associated documentation files (the "Software"), to deal - // in the Software without restriction, including without limitation the rights - // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - // copies of the Software, and to permit persons to whom the Software is - // furnished to do so, subject to the following conditions: - - // The above copyright notice and this permission notice shall be included in - // all copies or substantial portions of the Software. - - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - // THE SOFTWARE. - - public sealed class Aes128CounterMode : SymmetricAlgorithm + private static Aes GetAes() { - private readonly byte[] _counter; - private readonly AesManaged _aes = new() {Mode = CipherMode.ECB, Padding = PaddingMode.None}; - - public Aes128CounterMode(byte[] counter) - { - const int expect = 0x10; - if (counter.Length != expect) - throw new ArgumentException($"Counter size must be same as block size (actual: {counter.Length}, expected: {expect})"); - _counter = counter; - } - - public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] ignoredParameter) => new CounterModeCryptoTransform(_aes, rgbKey, _counter); - public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] ignoredParameter) => new CounterModeCryptoTransform(_aes, rgbKey, _counter); - - public override void GenerateKey() => _aes.GenerateKey(); - public override void GenerateIV() { /* IV not needed in Counter Mode */ } - protected override void Dispose(bool disposing) => _aes.Dispose(); + var result = Aes.Create(); + result.Mode = CipherMode.ECB; + result.Padding = PaddingMode.None; + return result; } - public sealed class CounterModeCryptoTransform : ICryptoTransform + public Aes128CounterMode(byte[] counter) { - private readonly byte[] _counter; - private readonly ICryptoTransform _counterEncryptor; - private readonly Queue _xorMask = new(); - private readonly SymmetricAlgorithm _symmetricAlgorithm; - - public CounterModeCryptoTransform(SymmetricAlgorithm symmetricAlgorithm, byte[] key, byte[] counter) - { - if (counter.Length != symmetricAlgorithm.BlockSize / 8) - throw new ArgumentException($"Counter size must be same as block size (actual: {counter.Length}, expected: {symmetricAlgorithm.BlockSize / 8})"); - - _symmetricAlgorithm = symmetricAlgorithm; - _encryptOutput = new byte[counter.Length]; - _counter = counter; - - var zeroIv = new byte[counter.Length]; - _counterEncryptor = symmetricAlgorithm.CreateEncryptor(key, zeroIv); - } - - public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) - { - var output = new byte[inputCount]; - TransformBlock(inputBuffer, inputOffset, inputCount, output, 0); - return output; - } - - public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) - { - var xm = _xorMask; - for (var i = 0; i < inputCount; i++) - { - if (xm.Count == 0) - EncryptCounterThenIncrement(); - - var mask = xm.Dequeue(); - outputBuffer[outputOffset + i] = (byte)(inputBuffer[inputOffset + i] ^ mask); - } - - return inputCount; - } - - private readonly byte[] _encryptOutput; - - private void EncryptCounterThenIncrement() - { - var counterModeBlock = _encryptOutput; - - _counterEncryptor.TransformBlock(_counter, 0, _counter.Length, counterModeBlock, 0); - IncrementCounter(); - - var xm = _xorMask; - foreach (var b in counterModeBlock) - xm.Enqueue(b); - } - - private void IncrementCounter() - { - var ctr = _counter; - for (var i = ctr.Length - 1; i >= 0; i--) - { - if (++ctr[i] != 0) - break; - } - } - - public int InputBlockSize => _symmetricAlgorithm.BlockSize / 8; - public int OutputBlockSize => _symmetricAlgorithm.BlockSize / 8; - public bool CanTransformMultipleBlocks => true; - public bool CanReuseTransform => false; - - public void Dispose() => _counterEncryptor.Dispose(); + const int expect = 0x10; + if (counter.Length != expect) + throw new ArgumentException($"Counter size must be same as block size (actual: {counter.Length}, expected: {expect})"); + _counter = counter; } + + public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? ignoredParameter) => new CounterModeCryptoTransform(_aes, rgbKey, _counter); + public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? ignoredParameter) => new CounterModeCryptoTransform(_aes, rgbKey, _counter); + + public override void GenerateKey() => _aes.GenerateKey(); + public override void GenerateIV() { /* IV not needed in Counter Mode */ } + protected override void Dispose(bool disposing) => _aes.Dispose(); } + +public sealed class CounterModeCryptoTransform : ICryptoTransform +{ + private readonly byte[] _counter; + private readonly ICryptoTransform _counterEncryptor; + private readonly Queue _xorMask = new(); + private readonly SymmetricAlgorithm _symmetricAlgorithm; + + public CounterModeCryptoTransform(SymmetricAlgorithm symmetricAlgorithm, byte[] key, byte[] counter) + { + if (counter.Length != symmetricAlgorithm.BlockSize / 8) + throw new ArgumentException($"Counter size must be same as block size (actual: {counter.Length}, expected: {symmetricAlgorithm.BlockSize / 8})"); + + _symmetricAlgorithm = symmetricAlgorithm; + _encryptOutput = new byte[counter.Length]; + _counter = counter; + + var zeroIv = new byte[counter.Length]; + _counterEncryptor = symmetricAlgorithm.CreateEncryptor(key, zeroIv); + } + + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + var output = new byte[inputCount]; + TransformBlock(inputBuffer, inputOffset, inputCount, output, 0); + return output; + } + + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + var xm = _xorMask; + for (var i = 0; i < inputCount; i++) + { + if (xm.Count == 0) + EncryptCounterThenIncrement(); + + var mask = xm.Dequeue(); + outputBuffer[outputOffset + i] = (byte)(inputBuffer[inputOffset + i] ^ mask); + } + + return inputCount; + } + + private readonly byte[] _encryptOutput; + + private void EncryptCounterThenIncrement() + { + var counterModeBlock = _encryptOutput; + + _counterEncryptor.TransformBlock(_counter, 0, _counter.Length, counterModeBlock, 0); + IncrementCounter(); + + var xm = _xorMask; + foreach (var b in counterModeBlock) + xm.Enqueue(b); + } + + private void IncrementCounter() + { + var ctr = _counter; + for (var i = ctr.Length - 1; i >= 0; i--) + { + if (++ctr[i] != 0) + break; + } + } + + public int InputBlockSize => _symmetricAlgorithm.BlockSize / 8; + public int OutputBlockSize => _symmetricAlgorithm.BlockSize / 8; + public bool CanTransformMultipleBlocks => true; + public bool CanReuseTransform => false; + + public void Dispose() => _counterEncryptor.Dispose(); +} \ No newline at end of file diff --git a/NHSE.Core/Encryption/CryptoFile.cs b/NHSE.Core/Encryption/CryptoFile.cs index 76644e5..fd66d1c 100644 --- a/NHSE.Core/Encryption/CryptoFile.cs +++ b/NHSE.Core/Encryption/CryptoFile.cs @@ -1,16 +1,3 @@ -namespace NHSE.Core -{ - internal readonly ref struct CryptoFile - { - public readonly byte[] Data; - public readonly byte[] Key; - public readonly byte[] Ctr; +namespace NHSE.Core; - public CryptoFile(byte[] data, byte[] key, byte[] ctr) - { - Data = data; - Key = key; - Ctr = ctr; - } - } -} +internal readonly record struct CryptoFile(byte[] Data, byte[] Key, byte[] Ctr); \ No newline at end of file diff --git a/NHSE.Core/Encryption/EncryptedInt32.cs b/NHSE.Core/Encryption/EncryptedInt32.cs index 73294b6..a6ef37b 100644 --- a/NHSE.Core/Encryption/EncryptedInt32.cs +++ b/NHSE.Core/Encryption/EncryptedInt32.cs @@ -1,81 +1,81 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +public sealed class EncryptedInt32 { - public sealed class EncryptedInt32 + // Encryption constant used to encrypt the int. + private const uint ENCRYPTION_CONSTANT = 0x80E32B11; + // Base shift count used in the encryption. + private const byte SHIFT_BASE = 3; + + public readonly uint OriginalEncrypted; + public readonly ushort Adjust; + public readonly byte Shift; + public readonly byte Checksum; + + public uint Value; + + public override string ToString() => Value.ToString(); + + public EncryptedInt32(uint encryptedValue, ushort adjust = 0, byte shift = 0, byte checksum = 0) { - // Encryption constant used to encrypt the int. - private const uint ENCRYPTION_CONSTANT = 0x80E32B11; - // Base shift count used in the encryption. - private const byte SHIFT_BASE = 3; - - public readonly uint OriginalEncrypted; - public readonly ushort Adjust; - public readonly byte Shift; - public readonly byte Checksum; - - public uint Value; - - public override string ToString() => Value.ToString(); - - public EncryptedInt32(uint encryptedValue, ushort adjust = 0, byte shift = 0, byte checksum = 0) - { - OriginalEncrypted = encryptedValue; - Adjust = adjust; - Shift = shift; - Checksum = checksum; - Value = Decrypt(encryptedValue, shift, adjust); - } - - public void Write(byte[] data, int offset) => Write(this, data, offset); - - // Calculates a checksum for a given encrypted value - // Checksum calculation is every byte of the encrypted in added together minus 0x2D. - public static byte CalculateChecksum(uint value) - { - var byteSum = value + (value >> 16) + (value >> 24) + (value >> 8); - return (byte)(byteSum - 0x2D); - } - - public static uint Decrypt(uint encrypted, byte shift, ushort adjust) - { - // Decrypt the encrypted int using the given params. - ulong val = ((ulong) encrypted) << ((32 - SHIFT_BASE - shift) & 0x3F); - val += val >> 32; - return ENCRYPTION_CONSTANT - adjust + (uint)val; - } - - public static uint Encrypt(uint value, byte shift, ushort adjust) - { - ulong val = (ulong) (value + (adjust - ENCRYPTION_CONSTANT)) << (shift + SHIFT_BASE); - return (uint) ((val >> 32) + val); - } - - public static EncryptedInt32 ReadVerify(byte[] data, int offset) - { - var val = Read(data, offset); - if (val.Checksum != CalculateChecksum(val.OriginalEncrypted)) - throw new ArgumentException($"Failed to verify the {nameof(EncryptedInt32)} at {nameof(offset)}"); - return val; - } - - public static EncryptedInt32 Read(byte[] data, int offset) - { - var enc = BitConverter.ToUInt32(data, offset + 0); - var adjust = BitConverter.ToUInt16(data, offset + 4); - var shift = data[offset + 6]; - var chk = data[offset + 7]; - return new EncryptedInt32(enc, adjust, shift, chk); - } - - public static void Write(EncryptedInt32 value, byte[] data, int offset) - { - uint enc = Encrypt(value.Value, value.Shift, value.Adjust); - byte chk = CalculateChecksum(enc); - BitConverter.GetBytes(enc).CopyTo(data, offset + 0); - BitConverter.GetBytes(value.Adjust).CopyTo(data, offset + 4); - data[offset + 6] = value.Shift; - data[offset + 7] = chk; - } + OriginalEncrypted = encryptedValue; + Adjust = adjust; + Shift = shift; + Checksum = checksum; + Value = Decrypt(encryptedValue, shift, adjust); } -} + + public void Write(Span data) => Write(this, data); + public void Write(byte[] data, int offset) => Write(data.AsSpan(offset)); + + // Calculates a checksum for a given encrypted value + // Checksum calculation is every byte of the encrypted in added together minus 0x2D. + public static byte CalculateChecksum(uint value) + { + var byteSum = value + (value >> 16) + (value >> 24) + (value >> 8); + return (byte)(byteSum - 0x2D); + } + + public static uint Decrypt(uint encrypted, byte shift, ushort adjust) + { + // Decrypt the encrypted int using the given params. + ulong val = ((ulong) encrypted) << ((32 - SHIFT_BASE - shift) & 0x3F); + val += val >> 32; + return ENCRYPTION_CONSTANT - adjust + (uint)val; + } + + public static uint Encrypt(uint value, byte shift, ushort adjust) + { + ulong val = (ulong) (value + unchecked(adjust - ENCRYPTION_CONSTANT)) << (shift + SHIFT_BASE); + return (uint) ((val >> 32) + val); + } + + public static EncryptedInt32 ReadVerify(ReadOnlySpan data, int offset) + { + var val = Read(data[offset..]); + if (val.Checksum != CalculateChecksum(val.OriginalEncrypted)) + throw new ArgumentException($"Failed to verify the {nameof(EncryptedInt32)} at {nameof(offset)}"); + return val; + } + + public static EncryptedInt32 Read(ReadOnlySpan data) + { + var encrypted = ReadUInt32LittleEndian(data); + var adjust = ReadUInt16LittleEndian(data[4..]); + var shift = data[6]; + var chk = data[7]; + return new EncryptedInt32(encrypted, adjust, shift, chk); + } + + public static void Write(EncryptedInt32 value, Span data) + { + var encrypted = Encrypt(value.Value, value.Shift, value.Adjust); + WriteUInt32LittleEndian(data, encrypted); + WriteUInt16LittleEndian(data[4..], value.Adjust); + data[6] = value.Shift; + data[7] = CalculateChecksum(encrypted); + } +} \ No newline at end of file diff --git a/NHSE.Core/Encryption/EncryptedSaveFile.cs b/NHSE.Core/Encryption/EncryptedSaveFile.cs index 858bd37..ffef86c 100644 --- a/NHSE.Core/Encryption/EncryptedSaveFile.cs +++ b/NHSE.Core/Encryption/EncryptedSaveFile.cs @@ -1,21 +1,20 @@ -namespace NHSE.Core +namespace NHSE.Core; + +public readonly ref struct EncryptedSaveFile { - public readonly ref struct EncryptedSaveFile + public readonly byte[] Data; + public readonly byte[] Header; + + public EncryptedSaveFile(byte[] data, byte[] header) { - public readonly byte[] Data; - public readonly byte[] Header; - - public EncryptedSaveFile(byte[] data, byte[] header) - { - Data = data; - Header = header; - } - - #region Equality Comparison - public override bool Equals(object obj) => false; - public override int GetHashCode() => Data.GetHashCode(); - public static bool operator !=(EncryptedSaveFile left, EncryptedSaveFile right) => !(left == right); - public static bool operator ==(EncryptedSaveFile left, EncryptedSaveFile right) => left.Data == right.Data && left.Header == right.Header; - #endregion + Data = data; + Header = header; } -} + + #region Equality Comparison + public override bool Equals(object? obj) => false; + public override int GetHashCode() => Data.GetHashCode(); + public static bool operator !=(EncryptedSaveFile left, EncryptedSaveFile right) => !(left == right); + public static bool operator ==(EncryptedSaveFile left, EncryptedSaveFile right) => left.Data == right.Data && left.Header == right.Header; + #endregion +} \ No newline at end of file diff --git a/NHSE.Core/Encryption/Encryption.cs b/NHSE.Core/Encryption/Encryption.cs index d6a5562..11bb1c4 100644 --- a/NHSE.Core/Encryption/Encryption.cs +++ b/NHSE.Core/Encryption/Encryption.cs @@ -1,82 +1,81 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +public static class Encryption { - public static class Encryption + private static byte[] GetParam(ReadOnlySpan data, in int index) { - private static byte[] GetParam(uint[] data, in int index) - { - var rand = new XorShift128(data[data[index] & 0x7F]); - var prms = data[data[index + 1] & 0x7F] & 0x7F; + var rand = new XorShift128(data[(int)data[index] & 0x7F]); + var prms = data[(int)(data[index + 1] & 0x7F)] & 0x7F; - var rndRollCount = (prms & 0xF) + 1; - for (var i = 0; i < rndRollCount; i++) - rand.GetU64(); + var rndRollCount = (prms & 0xF) + 1; + for (var i = 0; i < rndRollCount; i++) + rand.GetU64(); - var result = new byte[0x10]; - for (var i = 0; i < result.Length; i++) - result[i] = (byte)(rand.GetU32() >> 24); + var result = new byte[0x10]; + for (var i = 0; i < result.Length; i++) + result[i] = (byte)(rand.GetU32() >> 24); - return result; - } - - /// - /// Decrypts the using the in place. - /// - /// Header Data - /// Encrypted SaveData - public static void Decrypt(byte[] headerData, byte[] encData) - { - // First 256 bytes go unused - var importantData = new uint[0x80]; - Buffer.BlockCopy(headerData, 0x100, importantData, 0, 0x200); - - // Set up Key - var key = GetParam(importantData, 0); - - // Set up counter - var counter = GetParam(importantData, 2); - - // Do the AES - using var aesCtr = new Aes128CounterMode(counter); - var transform = aesCtr.CreateDecryptor(key, counter); - - transform.TransformBlock(encData, 0, encData.Length, encData, 0); - } - - private static CryptoFile GenerateHeaderFile(uint seed, byte[] versionData) - { - // Generate 128 Random uints which will be used for params - var random = new XorShift128(seed); - var encryptData = new uint[128]; - for (var i = 0; i < encryptData.Length; i++) - encryptData[i] = random.GetU32(); - - var headerData = new byte[0x300]; - Buffer.BlockCopy(versionData, 0, headerData, 0, 0x100); - Buffer.BlockCopy(encryptData, 0, headerData, 0x100, 0x200); - return new CryptoFile(headerData, GetParam(encryptData, 0), GetParam(encryptData, 2)); - } - - /// - /// Encrypts the (savedata) using the provided . - /// - /// SaveData to encrypt - /// Seed to encrypt with - /// Version data to encrypt with - /// Encrypted SaveData, and associated headerData - public static EncryptedSaveFile Encrypt(byte[] data, uint seed, byte[] versionData) - { - // Generate header file and get key and counter - var header = GenerateHeaderFile(seed, versionData); - - // Encrypt file - using var aesCtr = new Aes128CounterMode(header.Ctr); - var transform = aesCtr.CreateEncryptor(header.Key, header.Ctr); - var encData = new byte[data.Length]; - transform.TransformBlock(data, 0, data.Length, encData, 0); - - return new EncryptedSaveFile(encData, header.Data); - } + return result; } -} + + /// + /// Decrypts the using the in place. + /// + /// Header Data + /// Encrypted SaveData + public static void Decrypt(byte[] headerData, byte[] encData) + { + // First 256 bytes go unused + var importantData = new uint[0x80]; + Buffer.BlockCopy(headerData, 0x100, importantData, 0, 0x200); + + // Set up Key + var key = GetParam(importantData, 0); + + // Set up counter + var counter = GetParam(importantData, 2); + + // Do the AES + using var aesCtr = new Aes128CounterMode(counter); + var transform = aesCtr.CreateDecryptor(key, counter); + + transform.TransformBlock(encData, 0, encData.Length, encData, 0); + } + + private static CryptoFile GenerateHeaderFile(uint seed, byte[] versionData) + { + // Generate 128 Random uints which will be used for params + var random = new XorShift128(seed); + var encryptData = new uint[128]; + for (var i = 0; i < encryptData.Length; i++) + encryptData[i] = random.GetU32(); + + var headerData = new byte[0x300]; + Buffer.BlockCopy(versionData, 0, headerData, 0, 0x100); + Buffer.BlockCopy(encryptData, 0, headerData, 0x100, 0x200); + return new CryptoFile(headerData, GetParam(encryptData, 0), GetParam(encryptData, 2)); + } + + /// + /// Encrypts the (savedata) using the provided . + /// + /// SaveData to encrypt + /// Seed to encrypt with + /// Version data to encrypt with + /// Encrypted SaveData, and associated headerData + public static EncryptedSaveFile Encrypt(byte[] data, uint seed, byte[] versionData) + { + // Generate header file and get key and counter + var header = GenerateHeaderFile(seed, versionData); + + // Encrypt file + using var aesCtr = new Aes128CounterMode(header.Ctr); + var transform = aesCtr.CreateEncryptor(header.Key, header.Ctr); + var encData = new byte[data.Length]; + transform.TransformBlock(data, 0, data.Length, encData, 0); + + return new EncryptedSaveFile(encData, header.Data); + } +} \ No newline at end of file diff --git a/NHSE.Core/Hashing/FileHashDetails.cs b/NHSE.Core/Hashing/FileHashDetails.cs index 1a7b8b2..48d425b 100644 --- a/NHSE.Core/Hashing/FileHashDetails.cs +++ b/NHSE.Core/Hashing/FileHashDetails.cs @@ -1,32 +1,31 @@ using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Contains the for a . +/// +public sealed class FileHashDetails { /// - /// Contains the for a . + /// Name of the File that these apply to. /// - public sealed class FileHashDetails + public readonly string FileName; + + /// + /// Expected file size of the . + /// + public readonly uint FileSize; + + /// + /// Hash specs that are done in this file. + /// + public readonly IReadOnlyList HashRegions; + + public FileHashDetails(string fileName, uint fileSize, IReadOnlyList regions) { - /// - /// Name of the File that these apply to. - /// - public readonly string FileName; - - /// - /// Expected file size of the . - /// - public readonly uint FileSize; - - /// - /// Hash specs that are done in this file. - /// - public readonly IReadOnlyList HashRegions; - - public FileHashDetails(string fileName, uint fileSize, IReadOnlyList regions) - { - FileName = fileName; - FileSize = fileSize; - HashRegions = regions; - } + FileName = fileName; + FileSize = fileSize; + HashRegions = regions; } } \ No newline at end of file diff --git a/NHSE.Core/Hashing/FileHashInfo.cs b/NHSE.Core/Hashing/FileHashInfo.cs index 0d1ee47..68650c1 100644 --- a/NHSE.Core/Hashing/FileHashInfo.cs +++ b/NHSE.Core/Hashing/FileHashInfo.cs @@ -1,25 +1,24 @@ using System.Collections.Generic; using System.Linq; -namespace NHSE.Core +namespace NHSE.Core; + +public sealed class FileHashInfo { - public sealed class FileHashInfo + private readonly IReadOnlyDictionary List; + + public FileHashInfo(FileHashInfo dupe) : this(dupe.List.Values) { } + + public FileHashInfo(IEnumerable hashSets) { - private readonly IReadOnlyDictionary List; - - public FileHashInfo(FileHashInfo dupe) : this(dupe.List.Values) { } - - public FileHashInfo(IEnumerable hashSets) - { - var list = new Dictionary(); - foreach (var hashSet in hashSets) - list[hashSet.FileSize] = hashSet; - List = list; - } - - public FileHashDetails? GetFile(string nameData) - { - return List.Values.FirstOrDefault(z => z.FileName == nameData); - } + var list = new Dictionary(); + foreach (var hashSet in hashSets) + list[hashSet.FileSize] = hashSet; + List = list; } -} + + public FileHashDetails? GetFile(string nameData) + { + return List.Values.FirstOrDefault(z => z.FileName == nameData); + } +} \ No newline at end of file diff --git a/NHSE.Core/Hashing/FileHashRegion.cs b/NHSE.Core/Hashing/FileHashRegion.cs index e6de040..663e547 100644 --- a/NHSE.Core/Hashing/FileHashRegion.cs +++ b/NHSE.Core/Hashing/FileHashRegion.cs @@ -1,55 +1,21 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Specifies the region that a validation hash is calculated over. +/// +/// Offset of the calculated hash. +/// Length of the hashed data. +public readonly record struct FileHashRegion(int HashOffset, int Size) { /// - /// Specifies the region that a validation hash is calculated over. + /// Offset where the data to be hashed starts at (calculated). /// - public readonly struct FileHashRegion - { - /// - /// Offset of the calculated hash. - /// - public readonly int HashOffset; + public int BeginOffset => HashOffset + 4; - /// - /// Length of the hashed data. - /// - public readonly int Size; + /// + /// Offset where the data to be hashed ends at (calculated). + /// + public int EndOffset => BeginOffset + Size; - /// - /// Offset where the data to be hashed starts at (calculated). - /// - public int BeginOffset => HashOffset + 4; - - /// - /// Offset where the data to be hashed ends at (calculated). - /// - public int EndOffset => BeginOffset + Size; - - public override string ToString() => $"0x{HashOffset:X}: (0x{BeginOffset:X}-0x{EndOffset:X})"; - - public FileHashRegion(int hashOfs, int size) - { - HashOffset = hashOfs; - Size = size; - } - - #region Equality Comparison - public override bool Equals(object obj) => obj is FileHashRegion r && r == this; - // ReSharper disable once PossiblyImpureMethodCallOnReadonlyVariable - public override int GetHashCode() => BeginOffset.GetHashCode(); - - public static bool operator !=(FileHashRegion left, FileHashRegion right) => !(left == right); - - public static bool operator ==(FileHashRegion left, FileHashRegion right) - { - if (left.HashOffset != right.HashOffset) - return false; - if (left.BeginOffset != right.BeginOffset) - return false; - if (left.Size != right.Size) - return false; - return true; - } - #endregion - } + public override string ToString() => $"0x{HashOffset:X}: (0x{BeginOffset:X}-0x{EndOffset:X})"; } \ No newline at end of file diff --git a/NHSE.Core/Hashing/FileHashRevision.cs b/NHSE.Core/Hashing/FileHashRevision.cs index e418864..f5bbb8f 100644 --- a/NHSE.Core/Hashing/FileHashRevision.cs +++ b/NHSE.Core/Hashing/FileHashRevision.cs @@ -1,627 +1,559 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Provides information for hashing different revisions of the game's savedata. +/// +public static class FileHashRevision { - /// - /// Provides information for hashing different revisions of the game's savedata. - /// - public static class FileHashRevision - { - private const string FN_MAIN = "main.dat"; - private const string FN_PERSONAL = "personal.dat"; - private const string FN_POSTBOX = "postbox.dat"; - private const string FN_PHOTO = "photo_studio_island.dat"; - private const string FN_PROFILE = "profile.dat"; - private const string FN_WHEREAREN = "wherearen.dat"; + private const string FN_MAIN = "main.dat"; + private const string FN_PERSONAL = "personal.dat"; + private const string FN_POSTBOX = "postbox.dat"; + private const string FN_PHOTO = "photo_studio_island.dat"; + private const string FN_PROFILE = "profile.dat"; + private const string FN_WHEREAREN = "wherearen.dat"; - #region REVISION 1.0.0 + #region REVISION 1.0.0 - internal const int REV_100_MAIN = 0xAC0938; - internal const int REV_100_PERSONAL = 0x6BC50; - internal const int REV_100_POSTBOX = 0xB44580; - internal const int REV_100_PHOTO = 0x263B4; - internal const int REV_100_PROFILE = 0x69508; + internal const int REV_100_MAIN = 0xAC0938; + internal const int REV_100_PERSONAL = 0x6BC50; + internal const int REV_100_POSTBOX = 0xB44580; + internal const int REV_100_PHOTO = 0x263B4; + internal const int REV_100_PROFILE = 0x69508; - public static readonly FileHashInfo REV_100 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_100_MAIN, new FileHashRegion[] - { - new(0x000108, 0x1D6D4C), - new(0x1D6E58, 0x323384), - new(0x4FA2E8, 0x035AC4), - new(0x52FDB0, 0x03607C), - new(0x565F38, 0x035AC4), - new(0x59BA00, 0x03607C), - new(0x5D1B88, 0x035AC4), - new(0x607650, 0x03607C), - new(0x63D7D8, 0x035AC4), - new(0x6732A0, 0x03607C), - new(0x6A9428, 0x035AC4), - new(0x6DEEF0, 0x03607C), - new(0x715078, 0x035AC4), - new(0x74AB40, 0x03607C), - new(0x780CC8, 0x035AC4), - new(0x7B6790, 0x03607C), - new(0x7EC918, 0x035AC4), - new(0x8223E0, 0x03607C), - new(0x858460, 0x2684D4) - }), - new(FN_PERSONAL, REV_100_PERSONAL, new FileHashRegion[] - { - new(0x00108, 0x35AC4), - new(0x35BD0, 0x3607C) - }), - new(FN_POSTBOX, REV_100_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0xB4447C) - }), - new(FN_PHOTO, REV_100_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x262B0) - }), - new(FN_PROFILE, REV_100_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x69404) - }), - }); + public static readonly FileHashInfo REV_100 = new([ + new(FN_MAIN, REV_100_MAIN, [ + new(0x000108, 0x1D6D4C), + new(0x1D6E58, 0x323384), + new(0x4FA2E8, 0x035AC4), + new(0x52FDB0, 0x03607C), + new(0x565F38, 0x035AC4), + new(0x59BA00, 0x03607C), + new(0x5D1B88, 0x035AC4), + new(0x607650, 0x03607C), + new(0x63D7D8, 0x035AC4), + new(0x6732A0, 0x03607C), + new(0x6A9428, 0x035AC4), + new(0x6DEEF0, 0x03607C), + new(0x715078, 0x035AC4), + new(0x74AB40, 0x03607C), + new(0x780CC8, 0x035AC4), + new(0x7B6790, 0x03607C), + new(0x7EC918, 0x035AC4), + new(0x8223E0, 0x03607C), + new(0x858460, 0x2684D4) + ]), + new(FN_PERSONAL, REV_100_PERSONAL, [ + new(0x00108, 0x35AC4), + new(0x35BD0, 0x3607C) + ]), + new(FN_POSTBOX, REV_100_POSTBOX, [ + new(0x000100, 0xB4447C) + ]), + new(FN_PHOTO, REV_100_PHOTO, [ + new(0x000100, 0x262B0) + ]), + new(FN_PROFILE, REV_100_PROFILE, [ + new(0x000100, 0x69404) + ]) + ]); - #endregion + #endregion - #region REVISION 1.1.0 + #region REVISION 1.1.0 - internal const int REV_110_MAIN = 0xAC2AA0; - internal const int REV_110_PERSONAL = 0x6BED0; - internal const int REV_110_POSTBOX = 0xB44590; - internal const int REV_110_PHOTO = 0x263C0; - internal const int REV_110_PROFILE = 0x69560; + internal const int REV_110_MAIN = 0xAC2AA0; + internal const int REV_110_PERSONAL = 0x6BED0; + internal const int REV_110_POSTBOX = 0xB44590; + internal const int REV_110_PHOTO = 0x263C0; + internal const int REV_110_PROFILE = 0x69560; - public static readonly FileHashInfo REV_110 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_110_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1D6D5C), - new(0x1D6E70, 0x323C0C), - new(0x4FAB90, 0x035AFC), - new(0x530690, 0x0362BC), - new(0x566A60, 0x035AFC), - new(0x59C560, 0x0362BC), - new(0x5D2930, 0x035AFC), - new(0x608430, 0x0362BC), - new(0x63E800, 0x035AFC), - new(0x674300, 0x0362BC), - new(0x6AA6D0, 0x035AFC), - new(0x6E01D0, 0x0362BC), - new(0x7165A0, 0x035AFC), - new(0x74C0A0, 0x0362BC), - new(0x782470, 0x035AFC), - new(0x7B7F70, 0x0362BC), - new(0x7EE340, 0x035AFC), - new(0x823E40, 0x0362BC), - new(0x85A100, 0x26899C) - }), - new(FN_PERSONAL, REV_110_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x35AFC), - new(0x35C10, 0x362BC) - }), - new(FN_POSTBOX, REV_110_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0xB4448C) - }), - new(FN_PHOTO, REV_110_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x262BC) - }), - new(FN_PROFILE, REV_110_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x6945C) - }), - }); + public static readonly FileHashInfo REV_110 = new([ + new(FN_MAIN, REV_110_MAIN, [ + new(0x000110, 0x1D6D5C), + new(0x1D6E70, 0x323C0C), + new(0x4FAB90, 0x035AFC), + new(0x530690, 0x0362BC), + new(0x566A60, 0x035AFC), + new(0x59C560, 0x0362BC), + new(0x5D2930, 0x035AFC), + new(0x608430, 0x0362BC), + new(0x63E800, 0x035AFC), + new(0x674300, 0x0362BC), + new(0x6AA6D0, 0x035AFC), + new(0x6E01D0, 0x0362BC), + new(0x7165A0, 0x035AFC), + new(0x74C0A0, 0x0362BC), + new(0x782470, 0x035AFC), + new(0x7B7F70, 0x0362BC), + new(0x7EE340, 0x035AFC), + new(0x823E40, 0x0362BC), + new(0x85A100, 0x26899C) + ]), + new(FN_PERSONAL, REV_110_PERSONAL, [ + new(0x00110, 0x35AFC), + new(0x35C10, 0x362BC) + ]), + new(FN_POSTBOX, REV_110_POSTBOX, [ + new(0x000100, 0xB4448C) + ]), + new(FN_PHOTO, REV_110_PHOTO, [ + new(0x000100, 0x262BC) + ]), + new(FN_PROFILE, REV_110_PROFILE, [ + new(0x000100, 0x6945C) + ]) + ]); - #endregion + #endregion - #region REVISION 1.2.0 + #region REVISION 1.2.0 - internal const int REV_120_MAIN = 0xACECD0; - internal const int REV_120_PERSONAL = 0x6D6C0; - internal const int REV_120_POSTBOX = REV_110_POSTBOX; - internal const int REV_120_PHOTO = 0x2C9C0; - internal const int REV_120_PROFILE = REV_110_PROFILE; + internal const int REV_120_MAIN = 0xACECD0; + internal const int REV_120_PERSONAL = 0x6D6C0; + internal const int REV_120_POSTBOX = REV_110_POSTBOX; + internal const int REV_120_PHOTO = 0x2C9C0; + internal const int REV_120_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_120 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_120_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1D6D5C), - new(0x1D6E70, 0x323EBC), - new(0x4FAE40, 0x035D2C), - new(0x530B70, 0x03787C), - new(0x568500, 0x035D2C), - new(0x59E230, 0x03787C), - new(0x5D5BC0, 0x035D2C), - new(0x60B8F0, 0x03787C), - new(0x643280, 0x035D2C), - new(0x678FB0, 0x03787C), - new(0x6B0940, 0x035D2C), - new(0x6E6670, 0x03787C), - new(0x71E000, 0x035D2C), - new(0x753D30, 0x03787C), - new(0x78B6C0, 0x035D2C), - new(0x7C13F0, 0x03787C), - new(0x7F8D80, 0x035D2C), - new(0x82EAB0, 0x03787C), - new(0x866330, 0x26899C) - }), - new(FN_PERSONAL, REV_120_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x35D2C), - new(0x35E40, 0x3787C) - }), - new(FN_POSTBOX, REV_120_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0xB4448C) - }), - new(FN_PHOTO, REV_120_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x2C8BC) - }), - new(FN_PROFILE, REV_120_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x6945C) - }), - }); + public static readonly FileHashInfo REV_120 = new([ + new(FN_MAIN, REV_120_MAIN, [ + new(0x000110, 0x1D6D5C), + new(0x1D6E70, 0x323EBC), + new(0x4FAE40, 0x035D2C), + new(0x530B70, 0x03787C), + new(0x568500, 0x035D2C), + new(0x59E230, 0x03787C), + new(0x5D5BC0, 0x035D2C), + new(0x60B8F0, 0x03787C), + new(0x643280, 0x035D2C), + new(0x678FB0, 0x03787C), + new(0x6B0940, 0x035D2C), + new(0x6E6670, 0x03787C), + new(0x71E000, 0x035D2C), + new(0x753D30, 0x03787C), + new(0x78B6C0, 0x035D2C), + new(0x7C13F0, 0x03787C), + new(0x7F8D80, 0x035D2C), + new(0x82EAB0, 0x03787C), + new(0x866330, 0x26899C) + ]), + new(FN_PERSONAL, REV_120_PERSONAL, [ + new(0x00110, 0x35D2C), + new(0x35E40, 0x3787C) + ]), + new(FN_POSTBOX, REV_120_POSTBOX, [ + new(0x000100, 0xB4448C) + ]), + new(FN_PHOTO, REV_120_PHOTO, [ + new(0x000100, 0x2C8BC) + ]), + new(FN_PROFILE, REV_120_PROFILE, [ + new(0x000100, 0x6945C) + ]) + ]); - #endregion + #endregion - #region REVISION 1.3.0 + #region REVISION 1.3.0 - internal const int REV_130_MAIN = 0xACED80; - internal const int REV_130_PERSONAL = 0x6D6D0; - internal const int REV_130_POSTBOX = REV_110_POSTBOX; - internal const int REV_130_PHOTO = REV_120_PHOTO; - internal const int REV_130_PROFILE = REV_110_PROFILE; + internal const int REV_130_MAIN = 0xACED80; + internal const int REV_130_PERSONAL = 0x6D6D0; + internal const int REV_130_POSTBOX = REV_110_POSTBOX; + internal const int REV_130_PHOTO = REV_120_PHOTO; + internal const int REV_130_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_130 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_130_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1D6D5C), - new(0x1D6E70, 0x323EEC), - new(0x4FAE70, 0x035D2C), - new(0x530BA0, 0x03788C), - new(0x568540, 0x035D2C), - new(0x59E270, 0x03788C), - new(0x5D5c10, 0x035D2C), - new(0x60B940, 0x03788C), - new(0x6432E0, 0x035D2C), - new(0x679010, 0x03788C), - new(0x6B09B0, 0x035D2C), - new(0x6E66E0, 0x03788C), - new(0x71E080, 0x035D2C), - new(0x753DB0, 0x03788C), - new(0x78B750, 0x035D2C), - new(0x7C1480, 0x03788C), - new(0x7F8E20, 0x035D2C), - new(0x82EB50, 0x03788C), - new(0x8663E0, 0x26899C) - }), - new(FN_PERSONAL, REV_130_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x35D2C), - new(0x35E40, 0x3788C) - }), - new(FN_POSTBOX, REV_130_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0xB4448C) - }), - new(FN_PHOTO, REV_130_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x2C8BC) - }), - new(FN_PROFILE, REV_130_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x6945C) - }), - }); + public static readonly FileHashInfo REV_130 = new([ + new(FN_MAIN, REV_130_MAIN, [ + new(0x000110, 0x1D6D5C), + new(0x1D6E70, 0x323EEC), + new(0x4FAE70, 0x035D2C), + new(0x530BA0, 0x03788C), + new(0x568540, 0x035D2C), + new(0x59E270, 0x03788C), + new(0x5D5c10, 0x035D2C), + new(0x60B940, 0x03788C), + new(0x6432E0, 0x035D2C), + new(0x679010, 0x03788C), + new(0x6B09B0, 0x035D2C), + new(0x6E66E0, 0x03788C), + new(0x71E080, 0x035D2C), + new(0x753DB0, 0x03788C), + new(0x78B750, 0x035D2C), + new(0x7C1480, 0x03788C), + new(0x7F8E20, 0x035D2C), + new(0x82EB50, 0x03788C), + new(0x8663E0, 0x26899C) + ]), + new(FN_PERSONAL, REV_130_PERSONAL, [ + new(0x00110, 0x35D2C), + new(0x35E40, 0x3788C) + ]), + new(FN_POSTBOX, REV_130_POSTBOX, [ + new(0x000100, 0xB4448C) + ]), + new(FN_PHOTO, REV_130_PHOTO, [ + new(0x000100, 0x2C8BC) + ]), + new(FN_PROFILE, REV_130_PROFILE, [ + new(0x000100, 0x6945C) + ]) + ]); - #endregion + #endregion - #region REVISION 1.4.0 + #region REVISION 1.4.0 - internal const int REV_140_MAIN = 0xB05790; - internal const int REV_140_PERSONAL = 0x74420; - internal const int REV_140_POSTBOX = REV_110_POSTBOX; - internal const int REV_140_PHOTO = REV_120_PHOTO; - internal const int REV_140_PROFILE = REV_110_PROFILE; + internal const int REV_140_MAIN = 0xB05790; + internal const int REV_140_PERSONAL = 0x74420; + internal const int REV_140_POSTBOX = REV_110_POSTBOX; + internal const int REV_140_PHOTO = REV_120_PHOTO; + internal const int REV_140_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_140 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_140_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1d6d5c), - new(0x1d6e70, 0x323f2c), - new(0x4faeb0, 0x035d2c), - new(0x530be0, 0x03e5dc), - new(0x56f2d0, 0x035d2c), - new(0x5a5000, 0x03e5dc), - new(0x5e36f0, 0x035d2c), - new(0x619420, 0x03e5dc), - new(0x657b10, 0x035d2c), - new(0x68d840, 0x03e5dc), - new(0x6cbf30, 0x035d2c), - new(0x701c60, 0x03e5dc), - new(0x740350, 0x035d2c), - new(0x776080, 0x03e5dc), - new(0x7b4770, 0x035d2c), - new(0x7ea4a0, 0x03e5dc), - new(0x828b90, 0x035d2c), - new(0x85e8c0, 0x03e5dc), - new(0x89cea0, 0x2688ec) - }), - new(FN_PERSONAL, REV_140_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x35D2C), - new(0x35E40, 0x3E5DC) - }), - new(FN_POSTBOX, REV_140_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0xB4448C) - }), - new(FN_PHOTO, REV_140_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x2C8BC) - }), - new(FN_PROFILE, REV_140_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x6945C) - }), - }); + public static readonly FileHashInfo REV_140 = new([ + new(FN_MAIN, REV_140_MAIN, [ + new(0x000110, 0x1d6d5c), + new(0x1d6e70, 0x323f2c), + new(0x4faeb0, 0x035d2c), + new(0x530be0, 0x03e5dc), + new(0x56f2d0, 0x035d2c), + new(0x5a5000, 0x03e5dc), + new(0x5e36f0, 0x035d2c), + new(0x619420, 0x03e5dc), + new(0x657b10, 0x035d2c), + new(0x68d840, 0x03e5dc), + new(0x6cbf30, 0x035d2c), + new(0x701c60, 0x03e5dc), + new(0x740350, 0x035d2c), + new(0x776080, 0x03e5dc), + new(0x7b4770, 0x035d2c), + new(0x7ea4a0, 0x03e5dc), + new(0x828b90, 0x035d2c), + new(0x85e8c0, 0x03e5dc), + new(0x89cea0, 0x2688ec) + ]), + new(FN_PERSONAL, REV_140_PERSONAL, [ + new(0x00110, 0x35D2C), + new(0x35E40, 0x3E5DC) + ]), + new(FN_POSTBOX, REV_140_POSTBOX, [ + new(0x000100, 0xB4448C) + ]), + new(FN_PHOTO, REV_140_PHOTO, [ + new(0x000100, 0x2C8BC) + ]), + new(FN_PROFILE, REV_140_PROFILE, [ + new(0x000100, 0x6945C) + ]) + ]); - #endregion + #endregion - #region REVISION 1.5.0 + #region REVISION 1.5.0 - internal const int REV_150_MAIN = 0xB20750; - internal const int REV_150_PERSONAL = 0x76390; - internal const int REV_150_POSTBOX = REV_110_POSTBOX; - internal const int REV_150_PHOTO = REV_120_PHOTO; - internal const int REV_150_PROFILE = REV_110_PROFILE; + internal const int REV_150_MAIN = 0xB20750; + internal const int REV_150_PERSONAL = 0x76390; + internal const int REV_150_POSTBOX = REV_110_POSTBOX; + internal const int REV_150_PHOTO = REV_120_PHOTO; + internal const int REV_150_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_150 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_150_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1e215c), - new(0x1e2270, 0x323f6c), - new(0x5062f0, 0x03693c), - new(0x53cc30, 0x03f93c), - new(0x57c680, 0x03693c), - new(0x5b2fc0, 0x03f93c), - new(0x5f2a10, 0x03693c), - new(0x629350, 0x03f93c), - new(0x668da0, 0x03693c), - new(0x69f6e0, 0x03f93c), - new(0x6df130, 0x03693c), - new(0x715a70, 0x03f93c), - new(0x7554c0, 0x03693c), - new(0x78be00, 0x03f93c), - new(0x7cb850, 0x03693c), - new(0x802190, 0x03f93c), - new(0x841be0, 0x03693c), - new(0x878520, 0x03f93c), - new(0x8b7e60, 0x2688ec) - }), - new(FN_PERSONAL, REV_150_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x3693c), - new(0x36a50, 0x3f93c) - }), - new(FN_POSTBOX, REV_150_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0xB4448C) - }), - new(FN_PHOTO, REV_150_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x2C8BC) - }), - new(FN_PROFILE, REV_150_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x6945C) - }), - }); + public static readonly FileHashInfo REV_150 = new([ + new(FN_MAIN, REV_150_MAIN, [ + new(0x000110, 0x1e215c), + new(0x1e2270, 0x323f6c), + new(0x5062f0, 0x03693c), + new(0x53cc30, 0x03f93c), + new(0x57c680, 0x03693c), + new(0x5b2fc0, 0x03f93c), + new(0x5f2a10, 0x03693c), + new(0x629350, 0x03f93c), + new(0x668da0, 0x03693c), + new(0x69f6e0, 0x03f93c), + new(0x6df130, 0x03693c), + new(0x715a70, 0x03f93c), + new(0x7554c0, 0x03693c), + new(0x78be00, 0x03f93c), + new(0x7cb850, 0x03693c), + new(0x802190, 0x03f93c), + new(0x841be0, 0x03693c), + new(0x878520, 0x03f93c), + new(0x8b7e60, 0x2688ec) + ]), + new(FN_PERSONAL, REV_150_PERSONAL, [ + new(0x00110, 0x3693c), + new(0x36a50, 0x3f93c) + ]), + new(FN_POSTBOX, REV_150_POSTBOX, [ + new(0x000100, 0xB4448C) + ]), + new(FN_PHOTO, REV_150_PHOTO, [ + new(0x000100, 0x2C8BC) + ]), + new(FN_PROFILE, REV_150_PROFILE, [ + new(0x000100, 0x6945C) + ]) + ]); - #endregion + #endregion - #region REVISION 1.6.0 + #region REVISION 1.6.0 - internal const int REV_160_MAIN = 0xB258E0; - internal const int REV_160_PERSONAL = 0x76CF0; - internal const int REV_160_POSTBOX = REV_110_POSTBOX; - internal const int REV_160_PHOTO = REV_120_PHOTO; - internal const int REV_160_PROFILE = REV_110_PROFILE; + internal const int REV_160_MAIN = 0xB258E0; + internal const int REV_160_PERSONAL = 0x76CF0; + internal const int REV_160_POSTBOX = REV_110_POSTBOX; + internal const int REV_160_PHOTO = REV_120_PHOTO; + internal const int REV_160_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_160 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_160_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1e215c), - new(0x1e2270, 0x32403c), - new(0x5063c0, 0x03693c), - new(0x53cd00, 0x04029c), - new(0x57d0b0, 0x03693c), - new(0x5b39f0, 0x04029c), - new(0x5f3da0, 0x03693c), - new(0x62a6e0, 0x04029c), - new(0x66aa90, 0x03693c), - new(0x6a13d0, 0x04029c), - new(0x6e1780, 0x03693c), - new(0x7180c0, 0x04029c), - new(0x758470, 0x03693c), - new(0x78edb0, 0x04029c), - new(0x7cf160, 0x03693c), - new(0x805aa0, 0x04029c), - new(0x845e50, 0x03693c), - new(0x87c790, 0x04029c), - new(0x8bca30, 0x268eac) - }), - new(FN_PERSONAL, REV_160_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x3693c), - new(0x36a50, 0x4029c) - }), - new(FN_POSTBOX, REV_160_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0xB4448C) - }), - new(FN_PHOTO, REV_160_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x2C8BC) - }), - new(FN_PROFILE, REV_160_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x6945C) - }), - }); + public static readonly FileHashInfo REV_160 = new([ + new(FN_MAIN, REV_160_MAIN, [ + new(0x000110, 0x1e215c), + new(0x1e2270, 0x32403c), + new(0x5063c0, 0x03693c), + new(0x53cd00, 0x04029c), + new(0x57d0b0, 0x03693c), + new(0x5b39f0, 0x04029c), + new(0x5f3da0, 0x03693c), + new(0x62a6e0, 0x04029c), + new(0x66aa90, 0x03693c), + new(0x6a13d0, 0x04029c), + new(0x6e1780, 0x03693c), + new(0x7180c0, 0x04029c), + new(0x758470, 0x03693c), + new(0x78edb0, 0x04029c), + new(0x7cf160, 0x03693c), + new(0x805aa0, 0x04029c), + new(0x845e50, 0x03693c), + new(0x87c790, 0x04029c), + new(0x8bca30, 0x268eac) + ]), + new(FN_PERSONAL, REV_160_PERSONAL, [ + new(0x00110, 0x3693c), + new(0x36a50, 0x4029c) + ]), + new(FN_POSTBOX, REV_160_POSTBOX, [ + new(0x000100, 0xB4448C) + ]), + new(FN_PHOTO, REV_160_PHOTO, [ + new(0x000100, 0x2C8BC) + ]), + new(FN_PROFILE, REV_160_PROFILE, [ + new(0x000100, 0x6945C) + ]) + ]); - #endregion + #endregion - #region REVISION 1.7.0 + #region REVISION 1.7.0 - internal const int REV_170_MAIN = 0x849C30; // reduced size - internal const int REV_170_PERSONAL = 0x64140; // reduced size - internal const int REV_170_POSTBOX = 0x47430; // reduced size - internal const int REV_170_PHOTO = REV_120_PHOTO; - internal const int REV_170_PROFILE = REV_110_PROFILE; + internal const int REV_170_MAIN = 0x849C30; // reduced size + internal const int REV_170_PERSONAL = 0x64140; // reduced size + internal const int REV_170_POSTBOX = 0x47430; // reduced size + internal const int REV_170_PHOTO = REV_120_PHOTO; + internal const int REV_170_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_170 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_170_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1e215c), - new(0x1e2270, 0x3221fc), - new(0x504580, 0x03693c), - new(0x53aec0, 0x02d6ec), - new(0x5686c0, 0x03693c), - new(0x59f000, 0x02d6ec), - new(0x5cc800, 0x03693c), - new(0x603140, 0x02d6ec), - new(0x630940, 0x03693c), - new(0x667280, 0x02d6ec), - new(0x694a80, 0x03693c), - new(0x6cb3c0, 0x02d6ec), - new(0x6f8bc0, 0x03693c), - new(0x72f500, 0x02d6ec), - new(0x75cd00, 0x03693c), - new(0x793640, 0x02d6ec), - new(0x7c0e40, 0x03693c), - new(0x7f7780, 0x02d6ec), - new(0x824e70, 0x024dbc), - }), - new(FN_PERSONAL, REV_170_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x3693c), - new(0x36a50, 0x2d6ec), - }), - new(FN_POSTBOX, REV_170_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0x4732c) - }), - new(FN_PHOTO, REV_170_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x2C8BC) - }), - new(FN_PROFILE, REV_170_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x6945C) - }), - }); + public static readonly FileHashInfo REV_170 = new([ + new(FN_MAIN, REV_170_MAIN, [ + new(0x000110, 0x1e215c), + new(0x1e2270, 0x3221fc), + new(0x504580, 0x03693c), + new(0x53aec0, 0x02d6ec), + new(0x5686c0, 0x03693c), + new(0x59f000, 0x02d6ec), + new(0x5cc800, 0x03693c), + new(0x603140, 0x02d6ec), + new(0x630940, 0x03693c), + new(0x667280, 0x02d6ec), + new(0x694a80, 0x03693c), + new(0x6cb3c0, 0x02d6ec), + new(0x6f8bc0, 0x03693c), + new(0x72f500, 0x02d6ec), + new(0x75cd00, 0x03693c), + new(0x793640, 0x02d6ec), + new(0x7c0e40, 0x03693c), + new(0x7f7780, 0x02d6ec), + new(0x824e70, 0x024dbc) + ]), + new(FN_PERSONAL, REV_170_PERSONAL, [ + new(0x00110, 0x3693c), + new(0x36a50, 0x2d6ec) + ]), + new(FN_POSTBOX, REV_170_POSTBOX, [ + new(0x000100, 0x4732c) + ]), + new(FN_PHOTO, REV_170_PHOTO, [ + new(0x000100, 0x2C8BC) + ]), + new(FN_PROFILE, REV_170_PROFILE, [ + new(0x000100, 0x6945C) + ]) + ]); - #endregion + #endregion - #region REVISION 1.8.0 // Same as 1.7.0 + #region REVISION 1.8.0 // Same as 1.7.0 - internal const int REV_180_MAIN = REV_170_MAIN; - internal const int REV_180_PERSONAL = REV_170_PERSONAL; - internal const int REV_180_POSTBOX = REV_170_POSTBOX; - internal const int REV_180_PHOTO = REV_120_PHOTO; - internal const int REV_180_PROFILE = REV_110_PROFILE; + internal const int REV_180_MAIN = REV_170_MAIN; + internal const int REV_180_PERSONAL = REV_170_PERSONAL; + internal const int REV_180_POSTBOX = REV_170_POSTBOX; + internal const int REV_180_PHOTO = REV_120_PHOTO; + internal const int REV_180_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_180 = new(REV_170); + public static readonly FileHashInfo REV_180 = new(REV_170); - #endregion + #endregion - #region REVISION 1.9.0 + #region REVISION 1.9.0 - internal const int REV_190_MAIN = 0x86D560; - internal const int REV_190_PERSONAL = 0x64160; - internal const int REV_190_POSTBOX = REV_170_POSTBOX; - internal const int REV_190_PHOTO = REV_120_PHOTO; - internal const int REV_190_PROFILE = REV_110_PROFILE; + internal const int REV_190_MAIN = 0x86D560; + internal const int REV_190_PERSONAL = 0x64160; + internal const int REV_190_POSTBOX = REV_170_POSTBOX; + internal const int REV_190_PHOTO = REV_120_PHOTO; + internal const int REV_190_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_190 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_190_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1e215c), - new(0x1e2270, 0x34582c), - new(0x527bb0, 0x03693c), - new(0x55e4f0, 0x02d70c), - new(0x58bd10, 0x03693c), - new(0x5c2650, 0x02d70c), - new(0x5efe70, 0x03693c), - new(0x6267b0, 0x02d70c), - new(0x653fd0, 0x03693c), - new(0x68a910, 0x02d70c), - new(0x6b8130, 0x03693c), - new(0x6eea70, 0x02d70c), - new(0x71c290, 0x03693c), - new(0x752bd0, 0x02d70c), - new(0x7803f0, 0x03693c), - new(0x7b6d30, 0x02d70c), - new(0x7e4550, 0x03693c), - new(0x81ae90, 0x02d70c), - new(0x8485a0, 0x024fbc), - }), - new(FN_PERSONAL, REV_190_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x3693c), - new(0x36a50, 0x2d70c), - }), - new(FN_POSTBOX, REV_190_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0x4732c) - }), - new(FN_PHOTO, REV_190_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x2C8BC) - }), - new(FN_PROFILE, REV_190_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x6945C) - }), - }); + public static readonly FileHashInfo REV_190 = new([ + new(FN_MAIN, REV_190_MAIN, [ + new(0x000110, 0x1e215c), + new(0x1e2270, 0x34582c), + new(0x527bb0, 0x03693c), + new(0x55e4f0, 0x02d70c), + new(0x58bd10, 0x03693c), + new(0x5c2650, 0x02d70c), + new(0x5efe70, 0x03693c), + new(0x6267b0, 0x02d70c), + new(0x653fd0, 0x03693c), + new(0x68a910, 0x02d70c), + new(0x6b8130, 0x03693c), + new(0x6eea70, 0x02d70c), + new(0x71c290, 0x03693c), + new(0x752bd0, 0x02d70c), + new(0x7803f0, 0x03693c), + new(0x7b6d30, 0x02d70c), + new(0x7e4550, 0x03693c), + new(0x81ae90, 0x02d70c), + new(0x8485a0, 0x024fbc) + ]), + new(FN_PERSONAL, REV_190_PERSONAL, [ + new(0x00110, 0x3693c), + new(0x36a50, 0x2d70c) + ]), + new(FN_POSTBOX, REV_190_POSTBOX, [ + new(0x000100, 0x4732c) + ]), + new(FN_PHOTO, REV_190_PHOTO, [ + new(0x000100, 0x2C8BC) + ]), + new(FN_PROFILE, REV_190_PROFILE, [ + new(0x000100, 0x6945C) + ]) + ]); - #endregion + #endregion - #region REVISION 1.10.0 + #region REVISION 1.10.0 - internal const int REV_1100_MAIN = 0x86D570; - internal const int REV_1100_PERSONAL = REV_190_PERSONAL; - internal const int REV_1100_POSTBOX = REV_170_POSTBOX; - internal const int REV_1100_PHOTO = 0x2C9D0; - internal const int REV_1100_PROFILE = REV_110_PROFILE; + internal const int REV_1100_MAIN = 0x86D570; + internal const int REV_1100_PERSONAL = REV_190_PERSONAL; + internal const int REV_1100_POSTBOX = REV_170_POSTBOX; + internal const int REV_1100_PHOTO = 0x2C9D0; + internal const int REV_1100_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_1100 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_1100_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1e216c), - new(0x1e2280, 0x34582c), - new(0x527bc0, 0x03693c), - new(0x55e500, 0x02d70c), - new(0x58bd20, 0x03693c), - new(0x5c2660, 0x02d70c), - new(0x5efe80, 0x03693c), - new(0x6267c0, 0x02d70c), - new(0x653fe0, 0x03693c), - new(0x68a920, 0x02d70c), - new(0x6b8140, 0x03693c), - new(0x6eea80, 0x02d70c), - new(0x71c2a0, 0x03693c), - new(0x752be0, 0x02d70c), - new(0x780400, 0x03693c), - new(0x7b6d40, 0x02d70c), - new(0x7e4560, 0x03693c), - new(0x81aea0, 0x02d70c), - new(0x8485b0, 0x024fbc), - }), - new(FN_PERSONAL, REV_1100_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x3693c), - new(0x36a50, 0x2d70c), - }), - new(FN_POSTBOX, REV_1100_POSTBOX, new FileHashRegion[] - { - new(0x000100, 0x4732c) - }), - new(FN_PHOTO, REV_1100_PHOTO, new FileHashRegion[] - { - new(0x000100, 0x2c8cc) - }), - new(FN_PROFILE, REV_1100_PROFILE, new FileHashRegion[] - { - new(0x000100, 0x6945C) - }), - }); + public static readonly FileHashInfo REV_1100 = new([ + new(FN_MAIN, REV_1100_MAIN, [ + new(0x000110, 0x1e216c), + new(0x1e2280, 0x34582c), + new(0x527bc0, 0x03693c), + new(0x55e500, 0x02d70c), + new(0x58bd20, 0x03693c), + new(0x5c2660, 0x02d70c), + new(0x5efe80, 0x03693c), + new(0x6267c0, 0x02d70c), + new(0x653fe0, 0x03693c), + new(0x68a920, 0x02d70c), + new(0x6b8140, 0x03693c), + new(0x6eea80, 0x02d70c), + new(0x71c2a0, 0x03693c), + new(0x752be0, 0x02d70c), + new(0x780400, 0x03693c), + new(0x7b6d40, 0x02d70c), + new(0x7e4560, 0x03693c), + new(0x81aea0, 0x02d70c), + new(0x8485b0, 0x024fbc) + ]), + new(FN_PERSONAL, REV_1100_PERSONAL, [ + new(0x00110, 0x3693c), + new(0x36a50, 0x2d70c) + ]), + new(FN_POSTBOX, REV_1100_POSTBOX, [ + new(0x000100, 0x4732c) + ]), + new(FN_PHOTO, REV_1100_PHOTO, [ + new(0x000100, 0x2c8cc) + ]), + new(FN_PROFILE, REV_1100_PROFILE, [ + new(0x000100, 0x6945C) + ]) + ]); - #endregion + #endregion - #region REVISION 1.11.0 // Same as 1.10.0 + #region REVISION 1.11.0 // Same as 1.10.0 - internal const int REV_1110_MAIN = REV_1100_MAIN; - internal const int REV_1110_PERSONAL = REV_190_PERSONAL; - internal const int REV_1110_POSTBOX = REV_170_POSTBOX; - internal const int REV_1110_PHOTO = REV_1100_PHOTO; - internal const int REV_1110_PROFILE = REV_110_PROFILE; + internal const int REV_1110_MAIN = REV_1100_MAIN; + internal const int REV_1110_PERSONAL = REV_190_PERSONAL; + internal const int REV_1110_POSTBOX = REV_170_POSTBOX; + internal const int REV_1110_PHOTO = REV_1100_PHOTO; + internal const int REV_1110_PROFILE = REV_110_PROFILE; - public static readonly FileHashInfo REV_1110 = REV_1100; + public static readonly FileHashInfo REV_1110 = REV_1100; - #endregion + #endregion - #region REVISION 2.0.0 + #region REVISION 2.0.0 - internal const int REV_200_MAIN = 0x8F1BB0; - internal const int REV_200_PERSONAL = 0x6A520; - internal const int REV_200_POSTBOX = REV_170_POSTBOX; - internal const int REV_200_PHOTO = 0x2F650; - internal const int REV_200_PROFILE = REV_110_PROFILE; - internal const int REV_200_WHEREAREN = 0xB8A4E0; + internal const int REV_200_MAIN = 0x8F1BB0; + internal const int REV_200_PERSONAL = 0x6A520; + internal const int REV_200_POSTBOX = REV_170_POSTBOX; + internal const int REV_200_PHOTO = 0x2F650; + internal const int REV_200_PROFILE = REV_110_PROFILE; + internal const int REV_200_WHEREAREN = 0xB8A4E0; - public static readonly FileHashInfo REV_200 = new(new FileHashDetails[] - { - new(FN_MAIN, REV_200_MAIN, new FileHashRegion[] - { - new(0x000110, 0x1e339c), - new(0x1e34b0, 0x36406c), - new(0x547630, 0x03693c), - new(0x57df70, 0x033acc), - new(0x5b1b50, 0x03693c), - new(0x5e8490, 0x033acc), - new(0x61c070, 0x03693c), - new(0x6529b0, 0x033acc), - new(0x686590, 0x03693c), - new(0x6bced0, 0x033acc), - new(0x6f0ab0, 0x03693c), - new(0x7273f0, 0x033acc), - new(0x75afd0, 0x03693c), - new(0x791910, 0x033acc), - new(0x7c54f0, 0x03693c), - new(0x7fbe30, 0x033acc), - new(0x82fa10, 0x03693c), - new(0x866350, 0x033acc), - new(0x899e20, 0x057d8c), - }), - new(FN_PERSONAL, REV_200_PERSONAL, new FileHashRegion[] - { - new(0x00110, 0x3693c), - new(0x36a50, 0x33acc), - }), - new(FN_POSTBOX, REV_200_POSTBOX, new FileHashRegion[] - { - new(0x100, 0x4732c), - }), - new(FN_PHOTO, REV_200_PHOTO, new FileHashRegion[] - { - new(0x100, 0x2f54c), - }), - new(FN_PROFILE, REV_200_PROFILE, new FileHashRegion[] - { - new(0x100, 0x6945c), - }), - new(FN_WHEREAREN, REV_200_WHEREAREN, new FileHashRegion[] - { - new(0x100, 0xB8A3DC), - }), - } ); + public static readonly FileHashInfo REV_200 = new([ + new(FN_MAIN, REV_200_MAIN, [ + new(0x000110, 0x1e339c), + new(0x1e34b0, 0x36406c), + new(0x547630, 0x03693c), + new(0x57df70, 0x033acc), + new(0x5b1b50, 0x03693c), + new(0x5e8490, 0x033acc), + new(0x61c070, 0x03693c), + new(0x6529b0, 0x033acc), + new(0x686590, 0x03693c), + new(0x6bced0, 0x033acc), + new(0x6f0ab0, 0x03693c), + new(0x7273f0, 0x033acc), + new(0x75afd0, 0x03693c), + new(0x791910, 0x033acc), + new(0x7c54f0, 0x03693c), + new(0x7fbe30, 0x033acc), + new(0x82fa10, 0x03693c), + new(0x866350, 0x033acc), + new(0x899e20, 0x057d8c) + ]), + new(FN_PERSONAL, REV_200_PERSONAL, [ + new(0x00110, 0x3693c), + new(0x36a50, 0x33acc) + ]), + new(FN_POSTBOX, REV_200_POSTBOX, [ + new(0x100, 0x4732c) + ]), + new(FN_PHOTO, REV_200_PHOTO, [ + new(0x100, 0x2f54c) + ]), + new(FN_PROFILE, REV_200_PROFILE, [ + new(0x100, 0x6945c) + ]), + new(FN_WHEREAREN, REV_200_WHEREAREN, [ + new(0x100, 0xB8A3DC) + ]) + ]); - #endregion - } -} + #endregion +} \ No newline at end of file diff --git a/NHSE.Core/Hashing/Murmur3.cs b/NHSE.Core/Hashing/Murmur3.cs index 1c85a6c..8fa46e0 100644 --- a/NHSE.Core/Hashing/Murmur3.cs +++ b/NHSE.Core/Hashing/Murmur3.cs @@ -1,85 +1,77 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// MurmurHash implementation used by Animal Crossing New Horizons +/// +public static class Murmur3 { - /// - /// MurmurHash implementation used by Animal Crossing New Horizons - /// - public static class Murmur3 + private static uint Murmur32_Scramble(uint k) { - private static uint Murmur32_Scramble(uint k) - { - k = (k * 0x16A88000) | ((k * 0xCC9E2D51) >> 17); - k *= 0x1B873593; - return k; - } - - /// - /// Updates the hash at the specified offset, using the input parameters. - /// - /// Data to hash - /// Where the data-to-be-hashed starts - /// Amount of data to hash - /// Initial Murmur seed (optional) - /// Calculated hash. - public static uint GetMurmur3Hash(byte[] data, int offset, uint size, uint seed = 0) - { - uint checksum = seed; - if (size > 3) - { - for (var i = 0; i < (size / sizeof(uint)); i++) - { - var val = BitConverter.ToUInt32(data, offset); - checksum ^= Murmur32_Scramble(val); - checksum = (checksum >> 19) | (checksum << 13); - checksum = (checksum * 5) + 0xE6546B64; - offset += 4; - } - } - - var remainder = size % sizeof(uint); - if (remainder != 0) - { - uint val = BitConverter.ToUInt32(data, (int)((offset + size) - remainder)); - for (var i = 0; i < (sizeof(uint) - remainder); i++) - val >>= 8; - checksum ^= Murmur32_Scramble(val); - } - - checksum ^= size; - checksum ^= checksum >> 16; - checksum *= 0x85EBCA6B; - checksum ^= checksum >> 13; - checksum *= 0xC2B2AE35; - checksum ^= checksum >> 16; - return checksum; - } - - /// - /// Updates the hash at the specified offset, using the input parameters. - /// - /// Data to hash - /// Offset to write the hash - /// Where the data-to-be-hashed starts - /// Amount of data to hash - /// Calculated hash that was written back to the data. - public static uint UpdateMurmur32(byte[] data, int hashOffset, int readOffset, uint readSize) - { - var newHash = GetMurmur3Hash(data, readOffset, readSize); - var hashBytes = BitConverter.GetBytes(newHash); - hashBytes.CopyTo(data, hashOffset); - return newHash; - } - - /// - /// Checks the hash at the specified offset to see if the stored value matches the calculated value. - /// - /// Data to hash - /// Offset to write the hash - /// Where the data-to-be-hashed starts - /// Amount of data to hash - /// Calculated hash matches the currently stored hash. - public static bool VerifyMurmur32(byte[] data, int hashOffset, int readOffset, uint readSize) - => BitConverter.ToUInt32(data, hashOffset) == GetMurmur3Hash(data, readOffset, readSize); + k = (k * 0x16A88000) | ((k * 0xCC9E2D51) >> 17); + k *= 0x1B873593; + return k; } -} + + /// + /// Updates the hash at the specified offset, using the input parameters. + /// + /// Data to hash + /// Initial Murmur seed (optional) + /// Calculated hash. + public static uint GetMurmur3Hash(ReadOnlySpan data, uint seed = 0) + { + var checksum = seed; + var remaining = data; + while (remaining.Length >= sizeof(uint)) + { + var val = ReadUInt32LittleEndian(remaining); + checksum ^= Murmur32_Scramble(val); + checksum = (checksum >> 19) | (checksum << 13); + checksum = (checksum * 5) + 0xE6546B64; + remaining = remaining[sizeof(uint)..]; + } + + if (!remaining.IsEmpty) + { + uint val = 0; + switch (remaining.Length) + { + case 3: + val |= (uint)remaining[2] << 16; + goto case 2; + case 2: + val |= (uint)remaining[1] << 8; + goto case 1; + case 1: + val |= remaining[0]; + break; + } + + checksum ^= Murmur32_Scramble(val); + } + + checksum ^= (uint)data.Length; + checksum ^= checksum >> 16; + checksum *= 0x85EBCA6B; + checksum ^= checksum >> 13; + checksum *= 0xC2B2AE35; + checksum ^= checksum >> 16; + return checksum; + } + + /// + /// Updates the hash at the specified offset, using the input parameters. + /// + /// Data to hash + /// Location two write the hash + /// Calculated hash that was written back to the data. + public static uint UpdateMurmur32(ReadOnlySpan data, Span hashDestination) + { + var newHash = GetMurmur3Hash(data); + WriteUInt32LittleEndian(hashDestination, newHash); + return newHash; + } +} \ No newline at end of file diff --git a/NHSE.Core/NHSE.Core.csproj b/NHSE.Core/NHSE.Core.csproj index 1b25623..758ad54 100644 --- a/NHSE.Core/NHSE.Core.csproj +++ b/NHSE.Core/NHSE.Core.csproj @@ -1,9 +1,5 @@  - - net46;netstandard2.0 - - diff --git a/NHSE.Core/Save/Files/MainSave.cs b/NHSE.Core/Save/Files/MainSave.cs index 1dad702..0e1df1f 100644 --- a/NHSE.Core/Save/Files/MainSave.cs +++ b/NHSE.Core/Save/Files/MainSave.cs @@ -1,266 +1,262 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// main.dat +/// +public sealed class MainSave : EncryptedFilePair { - /// - /// main.dat - /// - public sealed class MainSave : EncryptedFilePair + public readonly MainSaveOffsets Offsets; + public MainSave(string folder) : base(folder, "main") => Offsets = MainSaveOffsets.GetOffsets(Info); + + public Hemisphere Hemisphere { get => (Hemisphere)Data[Offsets.WeatherArea]; set => Data[Offsets.WeatherArea] = (byte)value; } + public AirportColor AirportThemeColor { get => (AirportColor)Data[Offsets.AirportThemeColor]; set => Data[Offsets.AirportThemeColor] = (byte)value; } + + public uint WeatherSeed { - public readonly MainSaveOffsets Offsets; - public MainSave(string folder) : base(folder, "main") => Offsets = MainSaveOffsets.GetOffsets(Info); - - public Hemisphere Hemisphere { get => (Hemisphere)Data[Offsets.WeatherArea]; set => Data[Offsets.WeatherArea] = (byte)value; } - public AirportColor AirportThemeColor { get => (AirportColor)Data[Offsets.AirportThemeColor]; set => Data[Offsets.AirportThemeColor] = (byte)value; } - public uint WeatherSeed { get => BitConverter.ToUInt32(Data, Offsets.WeatherRandSeed); set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.WeatherRandSeed); } - - public IVillager GetVillager(int index) => Offsets.ReadVillager(Data, index); - public void SetVillager(IVillager value, int index) => Offsets.WriteVillager(value, Data, index); - - public IVillagerHouse GetVillagerHouse(int index) => Offsets.ReadVillagerHouse(Data, index); - public void SetVillagerHouse(IVillagerHouse value, int index) => Offsets.WriteVillagerHouse(value, Data, index); - - public IVillager[] GetVillagers() - { - var villagers = new IVillager[MainSaveOffsets.VillagerCount]; - for (int i = 0; i < villagers.Length; i++) - villagers[i] = GetVillager(i); - return villagers; - } - - public void SetVillagers(IReadOnlyList villagers) - { - for (int i = 0; i < villagers.Count; i++) - SetVillager(villagers[i], i); - } - - public IVillagerHouse[] GetVillagerHouses() - { - var villagers = new IVillagerHouse[MainSaveOffsets.VillagerCount]; - for (int i = 0; i < villagers.Length; i++) - villagers[i] = GetVillagerHouse(i); - return villagers; - } - - public void SetVillagerHouses(IReadOnlyList villagers) - { - for (int i = 0; i < villagers.Count; i++) - SetVillagerHouse(villagers[i], i); - } - - public DesignPattern GetDesign(int index) => Offsets.ReadPattern(Data, index); - public void SetDesign(DesignPattern value, int index, byte[] playerID, byte[] townID) => Offsets.WritePattern(value, Data, index, playerID, townID); - public DesignPatternPRO GetDesignPRO(int index) => Offsets.ReadPatternPRO(Data, index); - public void SetDesignPRO(DesignPatternPRO value, int index, byte[] playerID, byte[] townID) => Offsets.WritePatternPRO(value, Data, index, playerID, townID); - - public IReadOnlyList RecycleBin - { - get => Item.GetArray(Data.Slice(Offsets.LostItemBox, MainSaveOffsets.RecycleBinCount * Item.SIZE)); - set => Item.SetArray(value).CopyTo(Data, Offsets.LostItemBox); - } - - public IReadOnlyList Buildings - { - get => Building.GetArray(Data.Slice(Offsets.MainFieldStructure, MainSaveOffsets.BuildingCount * Building.SIZE)); - set => Building.SetArray(value).CopyTo(Data, Offsets.MainFieldStructure); - } - - public IPlayerHouse GetPlayerHouse(int index) => Offsets.ReadPlayerHouse(Data, index); - public void SetPlayerHouse(IPlayerHouse value, int index) => Offsets.WritePlayerHouse(value, Data, index); - - public IPlayerHouse[] GetPlayerHouses() - { - var players = new IPlayerHouse[MainSaveOffsets.PlayerCount]; - for (int i = 0; i < players.Length; i++) - players[i] = GetPlayerHouse(i); - return players; - } - - public void SetPlayerHouses(IReadOnlyList houses) - { - for (int i = 0; i < houses.Count; i++) - SetPlayerHouse(houses[i], i); - } - - public DesignPattern[] GetDesigns() - { - var result = new DesignPattern[Offsets.PatternCount]; - for (int i = 0; i value, byte[] playerID, byte[] townID) - { - var count = Math.Min(Offsets.PatternCount, value.Count); - for (int i = 0; i < count; i++) - SetDesign(value[i], i, playerID, townID); - } - - public DesignPatternPRO[] GetDesignsPRO() - { - var result = new DesignPatternPRO[Offsets.PatternCount]; - for (int i = 0; i < result.Length; i++) - result[i] = GetDesignPRO(i); - return result; - } - - public void SetDesignsPRO(IReadOnlyList value, byte[] playerID, byte[] townID) - { - var count = Math.Min(Offsets.PatternCount, value.Count); - for (int i = 0; i < count; i++) - SetDesignPRO(value[i], i, playerID, townID); - } - - public DesignPattern FlagMyDesign - { - get => MainSaveOffsets.ReadPatternAtOffset(Data, Offsets.PatternFlag); - set => value.Data.CopyTo(Data, Offsets.PatternFlag); - } - - public DesignPatternPRO[] GetDesignsTailor() - { - var result = new DesignPatternPRO[MainSaveOffsets.PatternTailorCount]; - for (int i = 0; i < result.Length; i++) - result[i] = MainSaveOffsets.ReadPatternPROAtOffset(Data, Offsets.PatternTailor + (i * DesignPatternPRO.SIZE)); - return result; - } - - public void SetDesignsTailor(IReadOnlyList value) - { - var count = Math.Min(Offsets.PatternCount, value.Count); - for (int i = 0; i < count; i++) - value[i].Data.CopyTo(Data, Offsets.PatternTailor + (i * DesignPatternPRO.SIZE)); - } - - private const int EventFlagsSaveCount = 0x400; - - public short[] GetEventFlagLand() - { - var value = new short[EventFlagsSaveCount]; - Buffer.BlockCopy(Data, Offsets.EventFlagLand, value, 0, sizeof(short) * value.Length); - return value; - } - - public void SetEventFlagLand(short[] value) - { - Buffer.BlockCopy(value, 0, Data, Offsets.EventFlagLand, sizeof(short) * value.Length); - } - - public TurnipStonk Turnips - { - get => Data.Slice(Offsets.ShopKabu, TurnipStonk.SIZE).ToClass(); - set => value.ToBytesClass().CopyTo(Data, Offsets.ShopKabu); - } - - public Museum Museum - { - get => new(Data.Slice(Offsets.Museum, Museum.SIZE)); - set => value.Data.CopyTo(Data, Offsets.Museum); - } - - public const int AcreWidth = 7 + (2 * 1); // 1 on each side cannot be traversed - private const int AcreHeight = 6 + (2 * 1); // 1 on each side cannot be traversed - private const int AcreMax = AcreWidth * AcreHeight; - private const int AcreSizeAll = AcreMax * 2; - - public ushort GetAcre(int index) - { - if ((uint)index > AcreMax) - throw new ArgumentOutOfRangeException(nameof(index)); - return BitConverter.ToUInt16(Data, Offsets.OutsideField + (index * 2)); - } - - public void SetAcre(int index, ushort value) - { - if ((uint)index > AcreMax) - throw new ArgumentOutOfRangeException(nameof(index)); - BitConverter.GetBytes(value).CopyTo(Data, Offsets.OutsideField + (index * 2)); - } - - public byte[] GetAcreBytes() => Data.Slice(Offsets.OutsideField, AcreSizeAll); - - public void SetAcreBytes(byte[] data) - { - if (data.Length != AcreSizeAll) - throw new ArgumentOutOfRangeException(nameof(data.Length)); - data.CopyTo(Data, Offsets.OutsideField); - } - - public TerrainTile[] GetTerrainTiles() => TerrainTile.GetArray(Data.Slice(Offsets.LandMakingMap, MapGrid.MapTileCount16x16 * TerrainTile.SIZE)); - public void SetTerrainTiles(IReadOnlyList array) => TerrainTile.SetArray(array).CopyTo(Data, Offsets.LandMakingMap); - - public const int MapDesignNone = 0xF800; - - public ushort[] GetMapDesignTiles() - { - var value = new ushort[112*96]; - Buffer.BlockCopy(Data, Offsets.MyDesignMap, value, 0, sizeof(ushort) * value.Length); - return value; - } - - public void SetMapDesignTiles(ushort[] value) - { - Buffer.BlockCopy(value, 0, Data, Offsets.MyDesignMap, sizeof(ushort) * value.Length); - } - - private const int FieldItemLayerSize = MapGrid.MapTileCount32x32 * Item.SIZE; - private const int FieldItemFlagSize = MapGrid.MapTileCount32x32 / 8; // bitflags - - private int FieldItemLayer1 => Offsets.FieldItem; - private int FieldItemLayer2 => Offsets.FieldItem + FieldItemLayerSize; - public int FieldItemFlag1 => Offsets.FieldItem + (FieldItemLayerSize * 2); - public int FieldItemFlag2 => Offsets.FieldItem + (FieldItemLayerSize * 2) + FieldItemFlagSize; - - public Item[] GetFieldItemLayer1() => Item.GetArray(Data.Slice(FieldItemLayer1, FieldItemLayerSize)); - public void SetFieldItemLayer1(IReadOnlyList array) => Item.SetArray(array).CopyTo(Data, FieldItemLayer1); - - public Item[] GetFieldItemLayer2() => Item.GetArray(Data.Slice(FieldItemLayer2, FieldItemLayerSize)); - public void SetFieldItemLayer2(IReadOnlyList array) => Item.SetArray(array).CopyTo(Data, FieldItemLayer2); - - public ushort OutsideFieldTemplateUniqueId - { - get => BitConverter.ToUInt16(Data, Offsets.OutsideField + AcreSizeAll); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.OutsideField + AcreSizeAll); - } - - public ushort MainFieldParamUniqueID - { - get => BitConverter.ToUInt16(Data, Offsets.OutsideField + AcreSizeAll + 2); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.OutsideField + AcreSizeAll + 2); - } - - public uint EventPlazaLeftUpX - { - get => BitConverter.ToUInt32(Data, Offsets.OutsideField + AcreSizeAll + 4); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.OutsideField + AcreSizeAll + 4); - } - - public uint EventPlazaLeftUpZ - { - get => BitConverter.ToUInt32(Data, Offsets.OutsideField + AcreSizeAll + 8); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.OutsideField + AcreSizeAll + 8); - } - - public GSaveVisitorNpc Visitor - { - get => Data.ToClass(Offsets.Visitor, GSaveVisitorNpc.SIZE); - set => value.ToBytesClass().CopyTo(Data, Offsets.Visitor); - } - - public GSaveFg SaveFg - { - get => Data.ToClass(Offsets.SaveFg, GSaveFg.SIZE); - set => value.ToBytesClass().CopyTo(Data, Offsets.SaveFg); - } - - public GSaveTime LastSaved => Data.Slice(Offsets.LastSavedTime, GSaveTime.SIZE).ToStructure(); - - public GSaveBulletinBoard Bulletin - { - get => Data.Slice(Offsets.BulletinBoard, GSaveBulletinBoard.SIZE).ToStructure(); - set => value.ToBytes().CopyTo(Data, Offsets.BulletinBoard); - } + get => ReadUInt32LittleEndian(Data[Offsets.WeatherRandSeed..]); + set => WriteUInt32LittleEndian(Data[Offsets.WeatherRandSeed..], value); } -} + + public IVillager GetVillager(int index) => Offsets.ReadVillager(Data, index); + public void SetVillager(IVillager value, int index) => Offsets.WriteVillager(value, Data, index); + + public IVillagerHouse GetVillagerHouse(int index) => Offsets.ReadVillagerHouse(Data, index); + public void SetVillagerHouse(IVillagerHouse value, int index) => Offsets.WriteVillagerHouse(value, Data, index); + + public IVillager[] GetVillagers() + { + var villagers = new IVillager[MainSaveOffsets.VillagerCount]; + for (int i = 0; i < villagers.Length; i++) + villagers[i] = GetVillager(i); + return villagers; + } + + public void SetVillagers(IReadOnlyList villagers) + { + for (int i = 0; i < villagers.Count; i++) + SetVillager(villagers[i], i); + } + + public IVillagerHouse[] GetVillagerHouses() + { + var villagers = new IVillagerHouse[MainSaveOffsets.VillagerCount]; + for (int i = 0; i < villagers.Length; i++) + villagers[i] = GetVillagerHouse(i); + return villagers; + } + + public void SetVillagerHouses(IReadOnlyList villagers) + { + for (int i = 0; i < villagers.Count; i++) + SetVillagerHouse(villagers[i], i); + } + + public DesignPattern GetDesign(int index) => Offsets.ReadPattern(Data, index); + public void SetDesign(DesignPattern value, int index, Span playerID, Span townID) => Offsets.WritePattern(value, Data, index, playerID, townID); + public DesignPatternPRO GetDesignPRO(int index) => Offsets.ReadPatternPRO(Data, index); + public void SetDesignPRO(DesignPatternPRO value, int index, Span playerID, Span townID) => Offsets.WritePatternPRO(value, Data, index, playerID, townID); + + public IReadOnlyList RecycleBin + { + get => Item.GetArray(Data.Slice(Offsets.LostItemBox, MainSaveOffsets.RecycleBinCount * Item.SIZE)); + set => Item.SetArray(value).CopyTo(Data[Offsets.LostItemBox..]); + } + + public IReadOnlyList Buildings + { + get => Building.GetArray(Data.Slice(Offsets.MainFieldStructure, MainSaveOffsets.BuildingCount * Building.SIZE)); + set => Building.SetArray(value).CopyTo(Data[Offsets.MainFieldStructure..]); + } + + public IPlayerHouse GetPlayerHouse(int index) => Offsets.ReadPlayerHouse(Data, index); + public void SetPlayerHouse(IPlayerHouse value, int index) => Offsets.WritePlayerHouse(value, Data, index); + + public IPlayerHouse[] GetPlayerHouses() + { + var players = new IPlayerHouse[MainSaveOffsets.PlayerCount]; + for (int i = 0; i < players.Length; i++) + players[i] = GetPlayerHouse(i); + return players; + } + + public void SetPlayerHouses(IReadOnlyList houses) + { + for (int i = 0; i < houses.Count; i++) + SetPlayerHouse(houses[i], i); + } + + public DesignPattern[] GetDesigns() + { + var result = new DesignPattern[Offsets.PatternCount]; + for (int i = 0; i value, Span playerID, Span townID) + { + var count = Math.Min(Offsets.PatternCount, value.Count); + for (int i = 0; i < count; i++) + SetDesign(value[i], i, playerID, townID); + } + + public DesignPatternPRO[] GetDesignsPRO() + { + var result = new DesignPatternPRO[Offsets.PatternCount]; + for (int i = 0; i < result.Length; i++) + result[i] = GetDesignPRO(i); + return result; + } + + public void SetDesignsPRO(IReadOnlyList value, Span playerID, Span townID) + { + var count = Math.Min(Offsets.PatternCount, value.Count); + for (int i = 0; i < count; i++) + SetDesignPRO(value[i], i, playerID, townID); + } + + public DesignPattern FlagMyDesign + { + get => MainSaveOffsets.ReadPatternAtOffset(Data, Offsets.PatternFlag); + set => value.Data.CopyTo(Data[Offsets.PatternFlag..]); + } + + public DesignPatternPRO[] GetDesignsTailor() + { + var result = new DesignPatternPRO[MainSaveOffsets.PatternTailorCount]; + for (int i = 0; i < result.Length; i++) + result[i] = MainSaveOffsets.ReadPatternPROAtOffset(Data, Offsets.PatternTailor + (i * DesignPatternPRO.SIZE)); + return result; + } + + public void SetDesignsTailor(IReadOnlyList value) + { + var count = Math.Min(Offsets.PatternCount, value.Count); + for (int i = 0; i < count; i++) + value[i].Data.CopyTo(Data.Slice(Offsets.PatternTailor + (i * DesignPatternPRO.SIZE))); + } + + private const int EventFlagsSaveCount = 0x400; + + public Span EventFlagLand => MemoryMarshal.Cast(Data.Slice(Offsets.EventFlagLand, sizeof(short) * EventFlagsSaveCount)); + + public TurnipStonk Turnips + { + get => Data.Slice(Offsets.ShopKabu, TurnipStonk.SIZE).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[Offsets.ShopKabu..]); + } + + public Museum Museum + { + get => new(Data.Slice(Offsets.Museum, Museum.SIZE).ToArray()); + set => value.Data.CopyTo(Data[Offsets.Museum..]); + } + + public const int AcreWidth = 7 + (2 * 1); // 1 on each side cannot be traversed + private const int AcreHeight = 6 + (2 * 1); // 1 on each side cannot be traversed + private const int AcreMax = AcreWidth * AcreHeight; + private const int AcreSizeAll = AcreMax * 2; + + public ushort GetAcre(int index) + { + if ((uint)index > AcreMax) + throw new ArgumentOutOfRangeException(nameof(index)); + return ReadUInt16LittleEndian(Data.Slice(Offsets.OutsideField + (index * 2))); + } + + public void SetAcre(int index, ushort value) + { + if ((uint)index > AcreMax) + throw new ArgumentOutOfRangeException(nameof(index)); + WriteUInt16LittleEndian(Data.Slice(Offsets.OutsideField + (index * 2)), value); + } + + public byte[] GetAcreBytes() => Data.Slice(Offsets.OutsideField, AcreSizeAll).ToArray(); + + public void SetAcreBytes(ReadOnlySpan data) + { + if (data.Length != AcreSizeAll) + throw new ArgumentOutOfRangeException(nameof(data.Length)); + data.CopyTo(Data.Slice(Offsets.OutsideField)); + } + + public TerrainTile[] GetTerrainTiles() => TerrainTile.GetArray(Data.Slice(Offsets.LandMakingMap, MapGrid.MapTileCount16x16 * TerrainTile.SIZE)); + public void SetTerrainTiles(IReadOnlyList array) => TerrainTile.SetArray(array).CopyTo(Data[Offsets.LandMakingMap..]); + + public const int MapDesignNone = 0xF800; + + public ushort[] GetMapDesignTiles() + { + var slice = Data.Slice(Offsets.MyDesignMap, 112 * 96 * sizeof(ushort)); + return MemoryMarshal.Cast(slice).ToArray(); + } + + public void SetMapDesignTiles(ReadOnlySpan value) + { + var cast = MemoryMarshal.Cast(value); + cast.CopyTo(Data[Offsets.MyDesignMap..]); + } + + private const int FieldItemLayerSize = MapGrid.MapTileCount32x32 * Item.SIZE; + private const int FieldItemFlagSize = MapGrid.MapTileCount32x32 / 8; // bitflags + + private int FieldItemLayer1 => Offsets.FieldItem; + private int FieldItemLayer2 => Offsets.FieldItem + FieldItemLayerSize; + public int FieldItemFlag1 => Offsets.FieldItem + (FieldItemLayerSize * 2); + public int FieldItemFlag2 => Offsets.FieldItem + (FieldItemLayerSize * 2) + FieldItemFlagSize; + + public Item[] GetFieldItemLayer1() => Item.GetArray(Data.Slice(FieldItemLayer1, FieldItemLayerSize)); + public void SetFieldItemLayer1(IReadOnlyList array) => Item.SetArray(array).CopyTo(Data[FieldItemLayer1..]); + + public Item[] GetFieldItemLayer2() => Item.GetArray(Data.Slice(FieldItemLayer2, FieldItemLayerSize)); + public void SetFieldItemLayer2(IReadOnlyList array) => Item.SetArray(array).CopyTo(Data[FieldItemLayer2..]); + + public ushort OutsideFieldTemplateUniqueId + { + get => ReadUInt16LittleEndian(Data[(Offsets.OutsideField + AcreSizeAll)..]); + set => WriteUInt16LittleEndian(Data[(Offsets.OutsideField + AcreSizeAll)..], value); + } + + public ushort MainFieldParamUniqueID + { + get => ReadUInt16LittleEndian(Data.Slice(Offsets.OutsideField + AcreSizeAll + 2)); + set => WriteUInt16LittleEndian(Data.Slice(Offsets.OutsideField + AcreSizeAll + 2), value); + } + + public uint EventPlazaLeftUpX + { + get => ReadUInt32LittleEndian(Data.Slice(Offsets.OutsideField + AcreSizeAll + 4)); + set => WriteUInt32LittleEndian(Data.Slice(Offsets.OutsideField + AcreSizeAll + 4), value); + } + + public uint EventPlazaLeftUpZ + { + get => ReadUInt32LittleEndian(Data.Slice(Offsets.OutsideField + AcreSizeAll + 8)); + set => WriteUInt32LittleEndian(Data.Slice(Offsets.OutsideField + AcreSizeAll + 8), value); + } + + public GSaveVisitorNpc Visitor + { + get => Data.Slice(Offsets.Visitor, GSaveVisitorNpc.SIZE).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[Offsets.Visitor..]); + } + + public GSaveFg SaveFg + { + get => Data.Slice(Offsets.SaveFg, GSaveFg.SIZE).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[Offsets.SaveFg..]); + } + + public GSaveTime LastSaved => Data.Slice(Offsets.LastSavedTime, GSaveTime.SIZE).ToStructure(); + + public GSaveBulletinBoard Bulletin + { + get => Data.Slice(Offsets.BulletinBoard, GSaveBulletinBoard.SIZE).ToStructure(); + set => value.ToBytes().CopyTo(Data[Offsets.BulletinBoard..]); + } +} \ No newline at end of file diff --git a/NHSE.Core/Save/Files/Personal.cs b/NHSE.Core/Save/Files/Personal.cs index f95ee3d..7ca9801 100644 --- a/NHSE.Core/Save/Files/Personal.cs +++ b/NHSE.Core/Save/Files/Personal.cs @@ -1,172 +1,177 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// personal.dat +/// +public sealed class Personal : EncryptedFilePair, IVillagerOrigin { - /// - /// personal.dat - /// - public sealed class Personal : EncryptedFilePair, IVillagerOrigin + public readonly PersonalOffsets Offsets; + public Personal(string folder) : base(folder, "personal") => Offsets = PersonalOffsets.GetOffsets(Info); + public override string ToString() => PlayerName; + + public uint TownID { - public readonly PersonalOffsets Offsets; - public Personal(string folder) : base(folder, "personal") => Offsets = PersonalOffsets.GetOffsets(Info); - public override string ToString() => PlayerName; - - public uint TownID - { - get => BitConverter.ToUInt32(Data, Offsets.PersonalId + 0x00); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.PersonalId + 0x00); - } - - public string TownName - { - get => GetString(Offsets.PersonalId + 0x04, 10); - set => GetBytes(value, 10).CopyTo(Data, Offsets.PersonalId + 0x04); - } - - public byte[] GetTownIdentity() => Data.Slice(Offsets.PersonalId + 0x00, 4 + 20); - - public uint PlayerID - { - get => BitConverter.ToUInt32(Data, Offsets.PersonalId + 0x1C); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.PersonalId + 0x1C); - } - - public string PlayerName - { - get => GetString(Offsets.PersonalId + 0x20, 10); - set => GetBytes(value, 10).CopyTo(Data, Offsets.PersonalId + 0x20); - } - - public byte[] GetPlayerIdentity() => Data.Slice(Offsets.PersonalId + 0x1C, 4 + 20); - - public EncryptedInt32 Wallet - { - get => EncryptedInt32.ReadVerify(Data, Offsets.Wallet); - set => value.Write(Data, Offsets.Wallet); - } - - public EncryptedInt32 Bank - { - get => EncryptedInt32.ReadVerify(Data, Offsets.Bank); - set => value.Write(Data, Offsets.Bank); - } - - public EncryptedInt32 NookMiles - { - get => EncryptedInt32.ReadVerify(Data, Offsets.NowPoint); - set => value.Write(Data, Offsets.NowPoint); - } - - public EncryptedInt32 TotalNookMiles - { - get => EncryptedInt32.ReadVerify(Data, Offsets.TotalPoint); - set => value.Write(Data, Offsets.TotalPoint); - } - - public IReadOnlyList Bag // Slots 21-40 - { - get => Item.GetArray(Data.Slice(Offsets.Pockets1, Offsets.Pockets1Count * Item.SIZE)); - set => Item.SetArray(value).CopyTo(Data, Offsets.Pockets1); - } - - public uint BagCount // Count of the Bag Slots that are available for use - { - get => BitConverter.ToUInt32(Data, Offsets.Pockets1 + (Offsets.Pockets1Count * Item.SIZE)); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.Pockets1 + (Offsets.Pockets1Count * Item.SIZE)); - } - - public IReadOnlyList Pocket // Slots 1-20 - { - get => Item.GetArray(Data.Slice(Offsets.Pockets2, Offsets.Pockets2Count * Item.SIZE)); - set => Item.SetArray(value).CopyTo(Data, Offsets.Pockets2); - } - - public uint PocketCount // Count of the Pocket Slots that are available for use - { - get => BitConverter.ToUInt32(Data, Offsets.Pockets2 + (Offsets.Pockets2Count * Item.SIZE)); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.Pockets2 + (Offsets.Pockets2Count * Item.SIZE)); - } - - public IReadOnlyList ItemChest - { - get => Item.GetArray(Data.Slice(Offsets.ItemChest, Offsets.ItemChestCount * Item.SIZE)); - set => Item.SetArray(value).CopyTo(Data, Offsets.ItemChest); - } - - public uint ItemChestCount // Count of the Item Chest Slots that are available for use - { - get => BitConverter.ToUInt32(Data, Offsets.ItemChest + (Offsets.ItemChestCount * Item.SIZE)); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.ItemChest + (Offsets.ItemChestCount * Item.SIZE)); - } - - public IReactionStore Reactions - { - get => Offsets.ReadReactions(Data); - set => Offsets.SetReactions(Data, value); - } - - public AchievementList Achievements - { - get => Data.Slice(Offsets.CountAchievement, AchievementList.SIZE).ToStructure(); - set => value.ToBytes().CopyTo(Data, Offsets.CountAchievement); - } - - public RecipeBook GetRecipeBook() => new(Data.Slice(Offsets.Recipes, RecipeBook.SIZE)); - public void SetRecipeBook(RecipeBook book) => book.Save(Data, Offsets.Recipes); - - public short[] GetEventFlagsPlayer() - { - var result = new short[0xE00/2]; - Buffer.BlockCopy(Data, Offsets.EventFlagsPlayer, result, 0, result.Length * sizeof(short)); - return result; - } - - public void SetEventFlagsPlayer(short[] value) => Buffer.BlockCopy(value, 0, Data, Offsets.EventFlagsPlayer, value.Length * sizeof(short)); - - public GSaveDateMD Birthday - { - get => Data.ToStructure(Offsets.Birthday, GSaveDateMD.SIZE); - set => value.ToBytes().CopyTo(Data, Offsets.Birthday); - } - - #region Profile - - public byte[] GetPhotoData() - { - var offset = Offsets.ProfilePhoto; - - // Expect jpeg marker - if (BitConverter.ToUInt16(Data, offset) != 0xD8FF) - return Array.Empty(); - var len = BitConverter.ToInt32(Data, offset - 4); - return Data.Slice(offset, len); - } - - public GSaveDateMD ProfileBirthday - { - get => Data.ToStructure(Offsets.ProfileBirthday, GSaveDateMD.SIZE); - set => value.ToBytes().CopyTo(Data, Offsets.ProfileBirthday); - } - - public ushort ProfileFruit - { - get => BitConverter.ToUInt16(Data, Offsets.ProfileFruit); - set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.ProfileFruit); - } - - public GSaveDate ProfileTimestamp - { - get => Data.ToStructure(Offsets.ProfileTimestamp, GSaveDate.SIZE); - set => value.ToBytes().CopyTo(Data, Offsets.ProfileTimestamp); - } - - public bool ProfileIsMakeVillage - { - get => Data[Offsets.ProfileIsMakeVillage] != 0; - set => Data[Offsets.ProfileIsMakeVillage] = (byte)(value ? 1 : 0); - } - - #endregion + get => ReadUInt32LittleEndian(Data[(Offsets.PersonalId + 0x00)..]); + set => WriteUInt32LittleEndian(Data[(Offsets.PersonalId + 0x00)..], value); } + + public string TownName + { + get => GetString(Offsets.PersonalId + 0x04, 10); + set => GetBytes(value, 10).CopyTo(Data[(Offsets.PersonalId + 0x04)..]); + } + + public Span GetTownIdentity() => Data.Slice(Offsets.PersonalId + 0x00, 4 + 20); + + public uint PlayerID + { + get => ReadUInt32LittleEndian(Data[(Offsets.PersonalId + 0x1C)..]); + set => WriteUInt32LittleEndian(Data[(Offsets.PersonalId + 0x1C)..], value); + } + + public string PlayerName + { + get => GetString(Offsets.PersonalId + 0x20, 10); + set => GetBytes(value, 10).CopyTo(Data[(Offsets.PersonalId + 0x20)..]); + } + + public Span GetPlayerIdentity() => Data.Slice(Offsets.PersonalId + 0x1C, 4 + 20); + + public EncryptedInt32 Wallet + { + get => EncryptedInt32.ReadVerify(Data, Offsets.Wallet); + set => value.Write(Data[Offsets.Wallet..]); + } + + public EncryptedInt32 Bank + { + get => EncryptedInt32.ReadVerify(Data, Offsets.Bank); + set => value.Write(Data[Offsets.Bank..]); + } + + public EncryptedInt32 NookMiles + { + get => EncryptedInt32.ReadVerify(Data, Offsets.NowPoint); + set => value.Write(Data[Offsets.NowPoint..]); + } + + public EncryptedInt32 TotalNookMiles + { + get => EncryptedInt32.ReadVerify(Data, Offsets.TotalPoint); + set => value.Write(Data[Offsets.TotalPoint..]); + } + + public IReadOnlyList Bag // Slots 21-40 + { + get => Item.GetArray(Data.Slice(Offsets.Pockets1, Offsets.Pockets1Count * Item.SIZE)); + set => Item.SetArray(value).CopyTo(Data[Offsets.Pockets1..]); + } + + public uint BagCount // Count of the Bag Slots that are available for use + { + get => ReadUInt32LittleEndian(Data[(Offsets.Pockets1 + (Offsets.Pockets1Count * Item.SIZE))..]); + set => WriteUInt32LittleEndian(Data[(Offsets.Pockets1 + (Offsets.Pockets1Count * Item.SIZE))..], value); + } + + public IReadOnlyList Pocket // Slots 1-20 + { + get => Item.GetArray(Data.Slice(Offsets.Pockets2, Offsets.Pockets2Count * Item.SIZE)); + set => Item.SetArray(value).CopyTo(Data[Offsets.Pockets2..]); + } + + public uint PocketCount // Count of the Pocket Slots that are available for use + { + get => ReadUInt32LittleEndian(Data[(Offsets.Pockets2 + (Offsets.Pockets2Count * Item.SIZE))..]); + set => WriteUInt32LittleEndian(Data[(Offsets.Pockets2 + (Offsets.Pockets2Count * Item.SIZE))..], value); + } + + public IReadOnlyList ItemChest + { + get => Item.GetArray(Data.Slice(Offsets.ItemChest, Offsets.ItemChestCount * Item.SIZE)); + set => Item.SetArray(value).CopyTo(Data[Offsets.ItemChest..]); + } + + public uint ItemChestCount // Count of the Item Chest Slots that are available for use + { + get => ReadUInt32LittleEndian(Data[(Offsets.ItemChest + (Offsets.ItemChestCount * Item.SIZE))..]); + set => WriteUInt32LittleEndian(Data[(Offsets.ItemChest + (Offsets.ItemChestCount * Item.SIZE))..], value); + } + + public IReactionStore Reactions + { + get => Offsets.ReadReactions(Data); + set => Offsets.SetReactions(Data, value); + } + + public AchievementList Achievements + { + get => Data.Slice(Offsets.CountAchievement, AchievementList.SIZE).ToStructure(); + set => value.ToBytes().CopyTo(Data[Offsets.CountAchievement..]); + } + + public RecipeBook GetRecipeBook() => new(Data.Slice(Offsets.Recipes, RecipeBook.SIZE).ToArray()); + public void SetRecipeBook(RecipeBook book) => book.Save(Data[Offsets.Recipes..]); + + public short[] GetEventFlagsPlayer() + { + var slice = Data.Slice(Offsets.EventFlagsPlayer, 0xE00); + return MemoryMarshal.Cast(slice).ToArray(); + } + + public void SetEventFlagsPlayer(Span value) + { + var slice = Data.Slice(Offsets.EventFlagsPlayer, 0xE00); + var cast = MemoryMarshal.Cast(slice); + value.CopyTo(cast); + } + + public GSaveDateMD Birthday + { + get => Data.ToStructure(Offsets.Birthday, GSaveDateMD.SIZE); + set => value.ToBytes().CopyTo(Data[Offsets.Birthday..]); + } + + #region Profile + + public byte[] GetPhotoData() + { + var offset = Offsets.ProfilePhoto; + + // Expect jpeg marker + if (ReadUInt16LittleEndian(Data[offset..]) != 0xD8FF) + return []; + var len = ReadInt32LittleEndian(Data[(offset - 4)..]); + return Data.Slice(offset, len).ToArray(); + } + + public GSaveDateMD ProfileBirthday + { + get => Data.ToStructure(Offsets.ProfileBirthday, GSaveDateMD.SIZE); + set => value.ToBytes().CopyTo(Data[Offsets.ProfileBirthday..]); + } + + public ushort ProfileFruit + { + get => ReadUInt16LittleEndian(Data[Offsets.ProfileFruit..]); + set => WriteUInt16LittleEndian(Data[Offsets.ProfileFruit..], value); + } + + public GSaveDate ProfileTimestamp + { + get => Data.ToStructure(Offsets.ProfileTimestamp, GSaveDate.SIZE); + set => value.ToBytes().CopyTo(Data[Offsets.ProfileTimestamp..]); + } + + public bool ProfileIsMakeVillage + { + get => Data[Offsets.ProfileIsMakeVillage] != 0; + set => Data[Offsets.ProfileIsMakeVillage] = (byte)(value ? 1 : 0); + } + + #endregion } \ No newline at end of file diff --git a/NHSE.Core/Save/Files/PhotoStudioIsland.cs b/NHSE.Core/Save/Files/PhotoStudioIsland.cs index 27c5177..988b7bb 100644 --- a/NHSE.Core/Save/Files/PhotoStudioIsland.cs +++ b/NHSE.Core/Save/Files/PhotoStudioIsland.cs @@ -1,10 +1,9 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// photo_studio_island.dat +/// +public sealed class PhotoStudioIsland : EncryptedFilePair { - /// - /// photo_studio_island.dat - /// - public sealed class PhotoStudioIsland : EncryptedFilePair - { - public PhotoStudioIsland(string folder) : base(folder, "photo_studio_island") { } - } + public PhotoStudioIsland(string folder) : base(folder, "photo_studio_island") { } } \ No newline at end of file diff --git a/NHSE.Core/Save/Files/PostBox.cs b/NHSE.Core/Save/Files/PostBox.cs index 2858ea8..7dc5f74 100644 --- a/NHSE.Core/Save/Files/PostBox.cs +++ b/NHSE.Core/Save/Files/PostBox.cs @@ -1,10 +1,9 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// postbox.dat +/// +public sealed class PostBox : EncryptedFilePair { - /// - /// postbox.dat - /// - public sealed class PostBox : EncryptedFilePair - { - public PostBox(string folder) : base(folder, "postbox") { } - } + public PostBox(string folder) : base(folder, "postbox") { } } \ No newline at end of file diff --git a/NHSE.Core/Save/Files/Profile.cs b/NHSE.Core/Save/Files/Profile.cs index 3fed18f..027ca32 100644 --- a/NHSE.Core/Save/Files/Profile.cs +++ b/NHSE.Core/Save/Files/Profile.cs @@ -1,12 +1,11 @@ -namespace NHSE.Core -{ - /// - /// profile.dat - /// - public sealed class Profile : EncryptedFilePair - { - public Profile(string folder) : base(folder, "profile") { } +namespace NHSE.Core; - // pretty much just a jpeg -- which is also stored in Personal. - } +/// +/// profile.dat +/// +public sealed class Profile : EncryptedFilePair +{ + public Profile(string folder) : base(folder, "profile") { } + + // pretty much just a jpeg -- which is also stored in Personal. } \ No newline at end of file diff --git a/NHSE.Core/Save/Files/WhereAreN.cs b/NHSE.Core/Save/Files/WhereAreN.cs index e03705f..1542111 100644 --- a/NHSE.Core/Save/Files/WhereAreN.cs +++ b/NHSE.Core/Save/Files/WhereAreN.cs @@ -1,18 +1,17 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// +public sealed class WhereAreN : EncryptedFilePair { - /// - /// - public sealed class WhereAreN : EncryptedFilePair + public const string FileName = "wherearen"; + + public readonly WhereAreNOffsets Offsets; + public WhereAreN(string folder) : base(folder, FileName) => Offsets = WhereAreNOffsets.GetOffsets(Info); + + public EncryptedInt32 Poki { - public const string FileName = "wherearen"; - - public readonly WhereAreNOffsets Offsets; - public WhereAreN(string folder) : base(folder, FileName) => Offsets = WhereAreNOffsets.GetOffsets(Info); - - public EncryptedInt32 Poki - { - get => EncryptedInt32.ReadVerify(Data, Offsets.Poki); - set => value.Write(Data, Offsets.Poki); - } + get => EncryptedInt32.ReadVerify(Data, Offsets.Poki); + set => value.Write(Data[Offsets.Poki..]); } -} +} \ No newline at end of file diff --git a/NHSE.Core/Save/Meta/EncryptedFilePair.cs b/NHSE.Core/Save/Meta/EncryptedFilePair.cs index 8b78ff5..acb88d4 100644 --- a/NHSE.Core/Save/Meta/EncryptedFilePair.cs +++ b/NHSE.Core/Save/Meta/EncryptedFilePair.cs @@ -1,91 +1,94 @@ using System; using System.Collections.Generic; using System.IO; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Represents two files -- and and their decrypted data. +/// +public abstract class EncryptedFilePair { - /// - /// Represents two files -- and and their decrypted data. - /// - public abstract class EncryptedFilePair + private readonly byte[] RawData; + private readonly byte[] RawHeader; + + public Span Data => RawData; + public Span Header => RawHeader; + + public readonly FileHeaderInfo Info; + + public readonly string DataPath; + public readonly string HeaderPath; + public readonly string NameData; + public readonly string NameHeader; + + public static bool Exists(string folder, string name) { - public readonly byte[] Data; - public readonly byte[] Header; - - public readonly FileHeaderInfo Info; - - public readonly string DataPath; - public readonly string HeaderPath; - public readonly string NameData; - public readonly string NameHeader; - - public static bool Exists(string folder, string name) - { - var NameData = $"{name}.dat"; - var NameHeader = $"{name}Header.dat"; - var hdr = Path.Combine(folder, NameHeader); - var dat = Path.Combine(folder, NameData); - return File.Exists(hdr) && File.Exists(dat); - } - - protected EncryptedFilePair(string folder, string name) - { - NameData = $"{name}.dat"; - NameHeader = $"{name}Header.dat"; - var hdr = Path.Combine(folder, NameHeader); - var dat = Path.Combine(folder, NameData); - - var hd = File.ReadAllBytes(hdr); - var md = File.ReadAllBytes(dat); - - Encryption.Decrypt(hd, md); - - Header = hd; - Data = md; - DataPath = dat; - HeaderPath = hdr; - - Info = Header.Slice(0, FileHeaderInfo.SIZE).ToClass(); - } - - public void Save(uint seed) - { - var encrypt = Encryption.Encrypt(Data, seed, Header); - File.WriteAllBytes(DataPath, encrypt.Data); - File.WriteAllBytes(HeaderPath, encrypt.Header); - } - - /// - /// Updates all hashes of . - /// - public void Hash() - { - var ver = Info.GetKnownRevisionIndex(); - var hash = RevisionChecker.HashInfo[ver]; - var details = hash.GetFile(NameData); - if (details == null) - throw new ArgumentNullException(nameof(NameData)); - foreach (var h in details.HashRegions) - Murmur3.UpdateMurmur32(Data, h.HashOffset, h.BeginOffset, (uint)h.Size); - } - - public IEnumerable InvalidHashes() - { - var ver = Info.GetKnownRevisionIndex(); - var hash = RevisionChecker.HashInfo[ver]; - var details = hash.GetFile(NameData); - if (details == null) - throw new ArgumentNullException(nameof(NameData)); - foreach (var h in details.HashRegions) - { - var current = Murmur3.GetMurmur3Hash(Data, h.BeginOffset, (uint)h.Size); - var saved = BitConverter.ToUInt32(Data, h.HashOffset); - if (current != saved) - yield return h; - } - } - - protected string GetString(int offset, int maxLength) => StringUtil.GetString(Data, offset, maxLength); - protected static byte[] GetBytes(string value, int maxLength) => StringUtil.GetBytes(value, maxLength); + var NameData = $"{name}.dat"; + var NameHeader = $"{name}Header.dat"; + var hdr = Path.Combine(folder, NameHeader); + var dat = Path.Combine(folder, NameData); + return File.Exists(hdr) && File.Exists(dat); } + + protected EncryptedFilePair(string folder, string name) + { + NameData = $"{name}.dat"; + NameHeader = $"{name}Header.dat"; + var hdr = Path.Combine(folder, NameHeader); + var dat = Path.Combine(folder, NameData); + + var hd = File.ReadAllBytes(hdr); + var md = File.ReadAllBytes(dat); + + Encryption.Decrypt(hd, md); + + RawHeader = hd; + RawData = md; + DataPath = dat; + HeaderPath = hdr; + + Info = RawHeader[..FileHeaderInfo.SIZE].ToClass(); + } + + public void Save(uint seed) + { + var encrypt = Encryption.Encrypt(RawData, seed, RawHeader); + File.WriteAllBytes(DataPath, encrypt.Data); + File.WriteAllBytes(HeaderPath, encrypt.Header); + } + + /// + /// Updates all hashes of . + /// + public void Hash() + { + var ver = Info.GetKnownRevisionIndex(); + var hash = RevisionChecker.HashInfo[ver]; + var details = hash.GetFile(NameData); + if (details == null) + throw new ArgumentNullException(nameof(NameData)); + foreach (var h in details.HashRegions) + Murmur3.UpdateMurmur32(Data.Slice(h.BeginOffset, h.Size), Data[h.HashOffset..]); + } + + public IEnumerable InvalidHashes() + { + var ver = Info.GetKnownRevisionIndex(); + var hash = RevisionChecker.HashInfo[ver]; + var details = hash.GetFile(NameData); + if (details == null) + throw new ArgumentNullException(nameof(NameData)); + foreach (var h in details.HashRegions) + { + var current = Murmur3.GetMurmur3Hash(Data.Slice(h.BeginOffset, h.Size)); + var saved = ReadUInt32LittleEndian(Data[h.HashOffset..]); + if (current != saved) + yield return h; + } + } + + protected string GetString(int offset, int maxLength) => StringUtil.GetString(Data, offset, maxLength); + protected static byte[] GetBytes(string value, int maxLength) => StringUtil.GetBytes(value, maxLength); } \ No newline at end of file diff --git a/NHSE.Core/Save/Meta/FileHeaderInfo.cs b/NHSE.Core/Save/Meta/FileHeaderInfo.cs index 3c8bfcc..47b704b 100644 --- a/NHSE.Core/Save/Meta/FileHeaderInfo.cs +++ b/NHSE.Core/Save/Meta/FileHeaderInfo.cs @@ -1,21 +1,20 @@ using System.Runtime.InteropServices; // ReSharper disable NonReadonlyMemberInGetHashCode -namespace NHSE.Core -{ - /// - /// Metadata stored in a file's Header, indicating the revision information. - /// - [StructLayout(LayoutKind.Explicit)] - public sealed record FileHeaderInfo - { - public const int SIZE = 0x40; +namespace NHSE.Core; - [field: FieldOffset(0x00)] public uint Major { get; init; } - [field: FieldOffset(0x04)] public uint Minor { get; init; } - [field: FieldOffset(0x08)] public ushort Unk1 { get; init; } - [field: FieldOffset(0x0A)] public ushort HeaderRevision { get; init; } - [field: FieldOffset(0x0C)] public ushort Unk2 { get; init; } - [field: FieldOffset(0x0E)] public ushort SaveRevision { get; init; } - } -} +/// +/// Metadata stored in a file's Header, indicating the revision information. +/// +[StructLayout(LayoutKind.Explicit)] +public sealed record FileHeaderInfo +{ + public const int SIZE = 0x40; + + [field: FieldOffset(0x00)] public uint Major { get; init; } + [field: FieldOffset(0x04)] public uint Minor { get; init; } + [field: FieldOffset(0x08)] public ushort Unk1 { get; init; } + [field: FieldOffset(0x0A)] public ushort HeaderRevision { get; init; } + [field: FieldOffset(0x0C)] public ushort Unk2 { get; init; } + [field: FieldOffset(0x0E)] public ushort SaveRevision { get; init; } +} \ No newline at end of file diff --git a/NHSE.Core/Save/Meta/HorizonSave.cs b/NHSE.Core/Save/Meta/HorizonSave.cs index 573ca0f..5cbae60 100644 --- a/NHSE.Core/Save/Meta/HorizonSave.cs +++ b/NHSE.Core/Save/Meta/HorizonSave.cs @@ -1,102 +1,102 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Represents all saved data that is stored on the device for the New Horizon's game. +/// +public class HorizonSave { - /// - /// Represents all saved data that is stored on the device for the New Horizon's game. - /// - public class HorizonSave + public readonly MainSave Main; + public readonly Player[] Players; + public override string ToString() => $"{Players[0].Personal.TownName} - {Players[0]}"; + + public HorizonSave(string folder) { - public readonly MainSave Main; - public readonly Player[] Players; - public override string ToString() => $"{Players[0].Personal.TownName} - {Players[0]}"; + Main = new MainSave(folder); + Players = Player.ReadMany(folder); + } - public HorizonSave(string folder) + /// + /// Saves the data using the provided crypto . + /// + /// Seed to initialize the RNG with when encrypting the files. + public void Save(uint seed) + { + Main.Hash(); + Main.Save(seed); + foreach (var player in Players) { - Main = new MainSave(folder); - Players = Player.ReadMany(folder); - } - - /// - /// Saves the data using the provided crypto . - /// - /// Seed to initialize the RNG with when encrypting the files. - public void Save(uint seed) - { - Main.Hash(); - Main.Save(seed); - foreach (var player in Players) + foreach (var pair in player) { - foreach (var pair in player) - { - pair.Hash(); - pair.Save(seed); - } + pair.Hash(); + pair.Save(seed); } } - - /// - /// Gets every that is deemed invalid. - /// - /// - /// Doesn't return any metadata about which file the hashes were bad for. - /// Just check what's returned with what's implemented; the offsets are unique enough. - /// - public IEnumerable GetInvalidHashes() - { - foreach (var hash in Main.InvalidHashes()) - yield return hash; - foreach (var hash in Players.SelectMany(z => z).SelectMany(z => z.InvalidHashes())) - yield return hash; - } - - public void ChangeIdentity(byte[] original, byte[] updated) - { - Main.Data.ReplaceOccurrences(original, updated); - foreach (var pair in Players.SelectMany(z => z)) - pair.Data.ReplaceOccurrences(original, updated); - } - - public bool ValidateSizes() - { - var info = Main.Info.GetKnownRevisionIndex(); - if (info < 0) - return false; - var sizes = RevisionChecker.SizeInfo[info]; - if (Main.Data.Length != sizes.Main) - return false; - - // Each player present in the savedata must have been migrated to this revision. - foreach (var p in Players) - { - if (p.Personal.Data.Length != sizes.Personal) - return false; - if (p.Photo.Data.Length != sizes.PhotoStudioIsland) - return false; - if (p.PostBox.Data.Length != sizes.PostBox) - return false; - if (p.Profile.Data.Length != sizes.Profile) - return false; - if (p.WhereAreN is { } x && x.Data.Length != sizes.WhereAreN) - return false; - } - return true; - } - - public string GetSaveTitle(string prefix) - { - var townName = Players[0].Personal.TownName; - var timestamp = Main.LastSaved.TimeStamp; - - return $"{prefix} - {townName} @ {timestamp}"; - } - - public string GetBackupFolderTitle() - { - var townName = Players[0].Personal.TownName; - var timestamp = Main.LastSaved.TimeStamp.Replace(':', '.'); - return StringUtil.CleanFileName($"{townName} - {timestamp}"); - } } -} + + /// + /// Gets every that is deemed invalid. + /// + /// + /// Doesn't return any metadata about which file the hashes were bad for. + /// Just check what's returned with what's implemented; the offsets are unique enough. + /// + public IEnumerable GetInvalidHashes() + { + foreach (var hash in Main.InvalidHashes()) + yield return hash; + foreach (var hash in Players.SelectMany(z => z).SelectMany(z => z.InvalidHashes())) + yield return hash; + } + + public void ChangeIdentity(ReadOnlySpan original, ReadOnlySpan updated) + { + Main.Data.ReplaceOccurrences(original, updated); + foreach (var pair in Players.SelectMany(z => z)) + pair.Data.ReplaceOccurrences(original, updated); + } + + public bool ValidateSizes() + { + var info = Main.Info.GetKnownRevisionIndex(); + if (info < 0) + return false; + var sizes = RevisionChecker.SizeInfo[info]; + if (Main.Data.Length != sizes.Main) + return false; + + // Each player present in the savedata must have been migrated to this revision. + foreach (var p in Players) + { + if (p.Personal.Data.Length != sizes.Personal) + return false; + if (p.Photo.Data.Length != sizes.PhotoStudioIsland) + return false; + if (p.PostBox.Data.Length != sizes.PostBox) + return false; + if (p.Profile.Data.Length != sizes.Profile) + return false; + if (p.WhereAreN is { } x && x.Data.Length != sizes.WhereAreN) + return false; + } + return true; + } + + public string GetSaveTitle(string prefix) + { + var townName = Players[0].Personal.TownName; + var timestamp = Main.LastSaved.TimeStamp; + + return $"{prefix} - {townName} @ {timestamp}"; + } + + public string GetBackupFolderTitle() + { + var townName = Players[0].Personal.TownName; + var timestamp = Main.LastSaved.TimeStamp.Replace(':', '.'); + return StringUtil.CleanFileName($"{townName} - {timestamp}"); + } +} \ No newline at end of file diff --git a/NHSE.Core/Save/Meta/Player.cs b/NHSE.Core/Save/Meta/Player.cs index 5df8394..42e5c8f 100644 --- a/NHSE.Core/Save/Meta/Player.cs +++ b/NHSE.Core/Save/Meta/Player.cs @@ -3,63 +3,62 @@ using System.IO; using System.Linq; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Stores references for all files in the Villager () folder. +/// +public sealed class Player : IEnumerable { + public readonly Personal Personal; + public readonly PhotoStudioIsland Photo; + public readonly PostBox PostBox; + public readonly Profile Profile; + public readonly WhereAreN? WhereAreN; + /// - /// Stores references for all files in the Villager () folder. + /// Directory Name where the player data was loaded from. Not the full path. /// - public sealed class Player : IEnumerable + public readonly string DirectoryName; + + #region Override Implementations + public IEnumerator GetEnumerator() { - public readonly Personal Personal; - public readonly PhotoStudioIsland Photo; - public readonly PostBox PostBox; - public readonly Profile Profile; - public readonly WhereAreN? WhereAreN; - - /// - /// Directory Name where the player data was loaded from. Not the full path. - /// - public readonly string DirectoryName; - - #region Override Implementations - public IEnumerator GetEnumerator() - { - IEnumerable baseFiles = new EncryptedFilePair[] { Personal, Photo, PostBox, Profile }; - if (WhereAreN is not null) - baseFiles = baseFiles.Concat(new EncryptedFilePair[] { WhereAreN }); - return baseFiles.AsEnumerable().GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public override string ToString() => Personal.PlayerName; - #endregion - - /// - /// Imports Player data from the requested . - /// - /// Folder that contains the Player Villager sub-folders. - /// Player object array loaded from the . - public static Player[] ReadMany(string folder) - { - var dirs = Directory.GetDirectories(folder, "Villager*", SearchOption.TopDirectoryOnly); - var result = new Player[dirs.Length]; - for (int i = 0; i < result.Length; i++) - result[i] = new Player(dirs[i]); - return result; - } - - private Player(string folder) - { - DirectoryName = new DirectoryInfo(folder).Name; - - Personal = new Personal(folder); - Photo = new PhotoStudioIsland(folder); - PostBox = new PostBox(folder); - Profile = new Profile(folder); - - if (EncryptedFilePair.Exists(folder, WhereAreN.FileName)) - WhereAreN = new WhereAreN(folder); - } + IEnumerable baseFiles = [Personal, Photo, PostBox, Profile]; + if (WhereAreN is not null) + baseFiles = baseFiles.Concat([WhereAreN]); + return baseFiles.AsEnumerable().GetEnumerator(); } -} + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public override string ToString() => Personal.PlayerName; + #endregion + + /// + /// Imports Player data from the requested . + /// + /// Folder that contains the Player Villager sub-folders. + /// Player object array loaded from the . + public static Player[] ReadMany(string folder) + { + var dirs = Directory.GetDirectories(folder, "Villager*", SearchOption.TopDirectoryOnly); + var result = new Player[dirs.Length]; + for (int i = 0; i < result.Length; i++) + result[i] = new Player(dirs[i]); + return result; + } + + private Player(string folder) + { + DirectoryName = new DirectoryInfo(folder).Name; + + Personal = new Personal(folder); + Photo = new PhotoStudioIsland(folder); + PostBox = new PostBox(folder); + Profile = new Profile(folder); + + if (EncryptedFilePair.Exists(folder, WhereAreN.FileName)) + WhereAreN = new WhereAreN(folder); + } +} \ No newline at end of file diff --git a/NHSE.Core/Save/Meta/RevisionChecker.cs b/NHSE.Core/Save/Meta/RevisionChecker.cs index 1eccd5e..0ea2849 100644 --- a/NHSE.Core/Save/Meta/RevisionChecker.cs +++ b/NHSE.Core/Save/Meta/RevisionChecker.cs @@ -2,139 +2,141 @@ using System.Collections.Generic; using static NHSE.Core.FileHashRevision; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Logic for detecting a revision. +/// +public static class RevisionChecker { /// - /// Logic for detecting a revision. + /// Unique save file size list by patch. /// - public static class RevisionChecker + private static readonly SaveFileSizes[] SizesByRevision = + [ + new(REV_100_MAIN, REV_100_PERSONAL, REV_100_PHOTO, REV_100_POSTBOX, REV_100_PROFILE), // 1.0.0 + new(REV_110_MAIN, REV_110_PERSONAL, REV_110_PHOTO, REV_110_POSTBOX, REV_110_PROFILE), // 1.1.0 + new(REV_120_MAIN, REV_120_PERSONAL, REV_120_PHOTO, REV_120_POSTBOX, REV_120_PROFILE), // 1.2.0 + new(REV_130_MAIN, REV_130_PERSONAL, REV_130_PHOTO, REV_130_POSTBOX, REV_130_PROFILE), // 1.3.0 + new(REV_140_MAIN, REV_140_PERSONAL, REV_140_PHOTO, REV_140_POSTBOX, REV_140_PROFILE), // 1.4.0 + new(REV_150_MAIN, REV_150_PERSONAL, REV_150_PHOTO, REV_150_POSTBOX, REV_150_PROFILE), // 1.5.0 + new(REV_160_MAIN, REV_160_PERSONAL, REV_160_PHOTO, REV_160_POSTBOX, REV_160_PROFILE), // 1.6.0 + new(REV_170_MAIN, REV_170_PERSONAL, REV_170_PHOTO, REV_170_POSTBOX, REV_170_PROFILE), // 1.7.0 + new(REV_180_MAIN, REV_180_PERSONAL, REV_180_PHOTO, REV_180_POSTBOX, REV_180_PROFILE), // 1.8.0 + new(REV_190_MAIN, REV_190_PERSONAL, REV_190_PHOTO, REV_190_POSTBOX, REV_190_PROFILE), // 1.9.0 + new(REV_1100_MAIN,REV_1100_PERSONAL,REV_1100_PHOTO,REV_1100_POSTBOX,REV_1100_PROFILE),// 1.10.0 + new(REV_1110_MAIN,REV_1110_PERSONAL,REV_1110_PHOTO,REV_1110_POSTBOX,REV_1110_PROFILE),// 1.11.0 + new(REV_200_MAIN, REV_200_PERSONAL, REV_200_PHOTO, REV_200_POSTBOX, REV_200_PROFILE, REV_200_WHEREAREN) // 2.0.0 + ]; + + private static readonly FileHeaderInfo[] RevisionInfo = + [ + new() { Major = 0x00067, Minor = 0x0006F, HeaderRevision = 0, Unk1 = 2, SaveRevision = 00, Unk2 = 2 }, // 1.0.0 + new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 01, Unk2 = 2 }, // 1.1.0 + new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 02, Unk2 = 2 }, // 1.1.1 + new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 03, Unk2 = 2 }, // 1.1.2 + new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 04, Unk2 = 2 }, // 1.1.3 + new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 05, Unk2 = 2 }, // 1.1.4 + new() { Major = 0x20006, Minor = 0x20008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 06, Unk2 = 2 }, // 1.2.0 + new() { Major = 0x20006, Minor = 0x20008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 07, Unk2 = 2 }, // 1.2.1 + new() { Major = 0x40002, Minor = 0x40008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 08, Unk2 = 2 }, // 1.3.0 + new() { Major = 0x40002, Minor = 0x40008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 09, Unk2 = 2 }, // 1.3.1 + new() { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 10, Unk2 = 2 }, // 1.4.0 + new() { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 11, Unk2 = 2 }, // 1.4.1 + new() { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 12, Unk2 = 2 }, // 1.4.2 + new() { Major = 0x60001, Minor = 0x6000C, HeaderRevision = 0, Unk1 = 2, SaveRevision = 13, Unk2 = 2 }, // 1.5.0 + new() { Major = 0x60001, Minor = 0x6000C, HeaderRevision = 0, Unk1 = 2, SaveRevision = 14, Unk2 = 2 }, // 1.5.1 + new() { Major = 0x70001, Minor = 0x70006, HeaderRevision = 0, Unk1 = 2, SaveRevision = 15, Unk2 = 2 }, // 1.6.0 + new() { Major = 0x74001, Minor = 0x74005, HeaderRevision = 0, Unk1 = 2, SaveRevision = 16, Unk2 = 2 }, // 1.7.0 + new() { Major = 0x78001, Minor = 0x78001, HeaderRevision = 0, Unk1 = 2, SaveRevision = 17, Unk2 = 2 }, // 1.8.0 + new() { Major = 0x7C001, Minor = 0x7C006, HeaderRevision = 0, Unk1 = 2, SaveRevision = 18, Unk2 = 2 }, // 1.9.0 + new() { Major = 0x7D001, Minor = 0x7D004, HeaderRevision = 0, Unk1 = 2, SaveRevision = 19, Unk2 = 2 }, // 1.10.0 + new() { Major = 0x7E001, Minor = 0x7E001, HeaderRevision = 0, Unk1 = 2, SaveRevision = 20, Unk2 = 2 }, // 1.11.0 + new() { Major = 0x7E001, Minor = 0x7E001, HeaderRevision = 0, Unk1 = 2, SaveRevision = 21, Unk2 = 2 }, // 1.11.1 + new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 22, Unk2 = 2 }, // 2.0.0 + new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 23, Unk2 = 2 }, // 2.0.1 + new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 24, Unk2 = 2 }, // 2.0.2 + new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 25, Unk2 = 2 }, // 2.0.3 + new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 26, Unk2 = 2 }, // 2.0.4 + new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 27, Unk2 = 2 }, // 2.0.5 + new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 28, Unk2 = 2 }, // 2.0.6 + new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 29, Unk2 = 2 }, // 2.0.7 + new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 30, Unk2 = 2 } // 2.0.8 + ]; + + public static readonly IReadOnlyList SizeInfo = + [ + SizesByRevision[0], // 1.0.0 + SizesByRevision[1], // 1.1.0 + SizesByRevision[1], // 1.1.1 + SizesByRevision[1], // 1.1.2 + SizesByRevision[1], // 1.1.3 + SizesByRevision[1], // 1.1.4 + SizesByRevision[2], // 1.2.0 + SizesByRevision[2], // 1.2.1 + SizesByRevision[3], // 1.3.0 + SizesByRevision[3], // 1.3.1 + SizesByRevision[4], // 1.4.0 + SizesByRevision[4], // 1.4.1 + SizesByRevision[4], // 1.4.2 + SizesByRevision[5], // 1.5.0 + SizesByRevision[5], // 1.5.1 + SizesByRevision[6], // 1.6.0 + SizesByRevision[7], // 1.7.0 + SizesByRevision[8], // 1.8.0 + SizesByRevision[9], // 1.9.0 + SizesByRevision[10], // 1.10.0 + SizesByRevision[11], // 1.11.0 + SizesByRevision[11], // 1.11.1 + SizesByRevision[12], // 2.0.0 + SizesByRevision[12], // 2.0.1 + SizesByRevision[12], // 2.0.2 + SizesByRevision[12], // 2.0.3 + SizesByRevision[12], // 2.0.4 + SizesByRevision[12], // 2.0.5 + SizesByRevision[12], // 2.0.6 + SizesByRevision[12], // 2.0.7 + SizesByRevision[12] // 2.0.8 + ]; + + public static readonly IReadOnlyList HashInfo = + [ + REV_100, // 1.0.0 + REV_110, // 1.1.0 + REV_110, // 1.1.1 + REV_110, // 1.1.2 + REV_110, // 1.1.3 + REV_110, // 1.1.4 + REV_120, // 1.2.0 + REV_120, // 1.2.1 + REV_130, // 1.3.0 + REV_130, // 1.3.1 + REV_140, // 1.4.0 + REV_140, // 1.4.1 + REV_140, // 1.4.2 + REV_150, // 1.5.0 + REV_150, // 1.5.1 + REV_160, // 1.6.0 + REV_170, // 1.7.0 + REV_180, // 1.8.0 + REV_190, // 1.9.0 + REV_1100, // 1.10.0 + REV_1110, // 1.11.0 + REV_1110, // 1.11.1 + REV_200, // 2.0.0 + REV_200, // 2.0.1 + REV_200, // 2.0.2 + REV_200, // 2.0.3 + REV_200, // 2.0.4 + REV_200, // 2.0.5 + REV_200, // 2.0.6 + REV_200, // 2.0.7 + REV_200 // 2.0.8 + ]; + + extension(FileHeaderInfo info) { - /// - /// Unique save file size list by patch. - /// - private static readonly SaveFileSizes[] SizesByRevision = - { - new(REV_100_MAIN, REV_100_PERSONAL, REV_100_PHOTO, REV_100_POSTBOX, REV_100_PROFILE), // 1.0.0 - new(REV_110_MAIN, REV_110_PERSONAL, REV_110_PHOTO, REV_110_POSTBOX, REV_110_PROFILE), // 1.1.0 - new(REV_120_MAIN, REV_120_PERSONAL, REV_120_PHOTO, REV_120_POSTBOX, REV_120_PROFILE), // 1.2.0 - new(REV_130_MAIN, REV_130_PERSONAL, REV_130_PHOTO, REV_130_POSTBOX, REV_130_PROFILE), // 1.3.0 - new(REV_140_MAIN, REV_140_PERSONAL, REV_140_PHOTO, REV_140_POSTBOX, REV_140_PROFILE), // 1.4.0 - new(REV_150_MAIN, REV_150_PERSONAL, REV_150_PHOTO, REV_150_POSTBOX, REV_150_PROFILE), // 1.5.0 - new(REV_160_MAIN, REV_160_PERSONAL, REV_160_PHOTO, REV_160_POSTBOX, REV_160_PROFILE), // 1.6.0 - new(REV_170_MAIN, REV_170_PERSONAL, REV_170_PHOTO, REV_170_POSTBOX, REV_170_PROFILE), // 1.7.0 - new(REV_180_MAIN, REV_180_PERSONAL, REV_180_PHOTO, REV_180_POSTBOX, REV_180_PROFILE), // 1.8.0 - new(REV_190_MAIN, REV_190_PERSONAL, REV_190_PHOTO, REV_190_POSTBOX, REV_190_PROFILE), // 1.9.0 - new(REV_1100_MAIN,REV_1100_PERSONAL,REV_1100_PHOTO,REV_1100_POSTBOX,REV_1100_PROFILE),// 1.10.0 - new(REV_1110_MAIN,REV_1110_PERSONAL,REV_1110_PHOTO,REV_1110_POSTBOX,REV_1110_PROFILE),// 1.11.0 - new(REV_200_MAIN, REV_200_PERSONAL, REV_200_PHOTO, REV_200_POSTBOX, REV_200_PROFILE, REV_200_WHEREAREN), // 2.0.0 - }; - - private static readonly FileHeaderInfo[] RevisionInfo = - { - new() { Major = 0x00067, Minor = 0x0006F, HeaderRevision = 0, Unk1 = 2, SaveRevision = 00, Unk2 = 2 }, // 1.0.0 - new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 01, Unk2 = 2 }, // 1.1.0 - new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 02, Unk2 = 2 }, // 1.1.1 - new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 03, Unk2 = 2 }, // 1.1.2 - new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 04, Unk2 = 2 }, // 1.1.3 - new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 05, Unk2 = 2 }, // 1.1.4 - new() { Major = 0x20006, Minor = 0x20008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 06, Unk2 = 2 }, // 1.2.0 - new() { Major = 0x20006, Minor = 0x20008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 07, Unk2 = 2 }, // 1.2.1 - new() { Major = 0x40002, Minor = 0x40008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 08, Unk2 = 2 }, // 1.3.0 - new() { Major = 0x40002, Minor = 0x40008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 09, Unk2 = 2 }, // 1.3.1 - new() { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 10, Unk2 = 2 }, // 1.4.0 - new() { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 11, Unk2 = 2 }, // 1.4.1 - new() { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 12, Unk2 = 2 }, // 1.4.2 - new() { Major = 0x60001, Minor = 0x6000C, HeaderRevision = 0, Unk1 = 2, SaveRevision = 13, Unk2 = 2 }, // 1.5.0 - new() { Major = 0x60001, Minor = 0x6000C, HeaderRevision = 0, Unk1 = 2, SaveRevision = 14, Unk2 = 2 }, // 1.5.1 - new() { Major = 0x70001, Minor = 0x70006, HeaderRevision = 0, Unk1 = 2, SaveRevision = 15, Unk2 = 2 }, // 1.6.0 - new() { Major = 0x74001, Minor = 0x74005, HeaderRevision = 0, Unk1 = 2, SaveRevision = 16, Unk2 = 2 }, // 1.7.0 - new() { Major = 0x78001, Minor = 0x78001, HeaderRevision = 0, Unk1 = 2, SaveRevision = 17, Unk2 = 2 }, // 1.8.0 - new() { Major = 0x7C001, Minor = 0x7C006, HeaderRevision = 0, Unk1 = 2, SaveRevision = 18, Unk2 = 2 }, // 1.9.0 - new() { Major = 0x7D001, Minor = 0x7D004, HeaderRevision = 0, Unk1 = 2, SaveRevision = 19, Unk2 = 2 }, // 1.10.0 - new() { Major = 0x7E001, Minor = 0x7E001, HeaderRevision = 0, Unk1 = 2, SaveRevision = 20, Unk2 = 2 }, // 1.11.0 - new() { Major = 0x7E001, Minor = 0x7E001, HeaderRevision = 0, Unk1 = 2, SaveRevision = 21, Unk2 = 2 }, // 1.11.1 - new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 22, Unk2 = 2 }, // 2.0.0 - new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 23, Unk2 = 2 }, // 2.0.1 - new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 24, Unk2 = 2 }, // 2.0.2 - new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 25, Unk2 = 2 }, // 2.0.3 - new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 26, Unk2 = 2 }, // 2.0.4 - new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 27, Unk2 = 2 }, // 2.0.5 - new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 28, Unk2 = 2 }, // 2.0.6 - new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 29, Unk2 = 2 }, // 2.0.7 - new() { Major = 0x80009, Minor = 0x80085, HeaderRevision = 0, Unk1 = 2, SaveRevision = 30, Unk2 = 2 }, // 2.0.8 - }; - - public static readonly IReadOnlyList SizeInfo = new[] - { - SizesByRevision[0], // 1.0.0 - SizesByRevision[1], // 1.1.0 - SizesByRevision[1], // 1.1.1 - SizesByRevision[1], // 1.1.2 - SizesByRevision[1], // 1.1.3 - SizesByRevision[1], // 1.1.4 - SizesByRevision[2], // 1.2.0 - SizesByRevision[2], // 1.2.1 - SizesByRevision[3], // 1.3.0 - SizesByRevision[3], // 1.3.1 - SizesByRevision[4], // 1.4.0 - SizesByRevision[4], // 1.4.1 - SizesByRevision[4], // 1.4.2 - SizesByRevision[5], // 1.5.0 - SizesByRevision[5], // 1.5.1 - SizesByRevision[6], // 1.6.0 - SizesByRevision[7], // 1.7.0 - SizesByRevision[8], // 1.8.0 - SizesByRevision[9], // 1.9.0 - SizesByRevision[10], // 1.10.0 - SizesByRevision[11], // 1.11.0 - SizesByRevision[11], // 1.11.1 - SizesByRevision[12], // 2.0.0 - SizesByRevision[12], // 2.0.1 - SizesByRevision[12], // 2.0.2 - SizesByRevision[12], // 2.0.3 - SizesByRevision[12], // 2.0.4 - SizesByRevision[12], // 2.0.5 - SizesByRevision[12], // 2.0.6 - SizesByRevision[12], // 2.0.7 - SizesByRevision[12], // 2.0.8 - }; - - public static readonly IReadOnlyList HashInfo = new[] - { - REV_100, // 1.0.0 - REV_110, // 1.1.0 - REV_110, // 1.1.1 - REV_110, // 1.1.2 - REV_110, // 1.1.3 - REV_110, // 1.1.4 - REV_120, // 1.2.0 - REV_120, // 1.2.1 - REV_130, // 1.3.0 - REV_130, // 1.3.1 - REV_140, // 1.4.0 - REV_140, // 1.4.1 - REV_140, // 1.4.2 - REV_150, // 1.5.0 - REV_150, // 1.5.1 - REV_160, // 1.6.0 - REV_170, // 1.7.0 - REV_180, // 1.8.0 - REV_190, // 1.9.0 - REV_1100, // 1.10.0 - REV_1110, // 1.11.0 - REV_1110, // 1.11.1 - REV_200, // 2.0.0 - REV_200, // 2.0.1 - REV_200, // 2.0.2 - REV_200, // 2.0.3 - REV_200, // 2.0.4 - REV_200, // 2.0.5 - REV_200, // 2.0.6 - REV_200, // 2.0.7 - REV_200, // 2.0.8 - }; - - public static bool IsRevisionKnown(this FileHeaderInfo info) => info.GetKnownRevisionIndex() >= 0; - public static int GetKnownRevisionIndex(this FileHeaderInfo info) => Array.FindIndex(RevisionInfo, z => z.Equals(info)); + public bool IsRevisionKnown() => info.GetKnownRevisionIndex() >= 0; + public int GetKnownRevisionIndex() => Array.FindIndex(RevisionInfo, z => z.Equals(info)); } } \ No newline at end of file diff --git a/NHSE.Core/Save/Meta/SaveFileSizes.cs b/NHSE.Core/Save/Meta/SaveFileSizes.cs index 2eaadb0..5b298fd 100644 --- a/NHSE.Core/Save/Meta/SaveFileSizes.cs +++ b/NHSE.Core/Save/Meta/SaveFileSizes.cs @@ -1,25 +1,24 @@ -namespace NHSE.Core -{ - /// - /// Stores file sizes for various savedata files at different patch revisions. - /// - public class SaveFileSizes - { - public readonly uint Main; - public readonly uint Personal; - public readonly uint PhotoStudioIsland; - public readonly uint PostBox; - public readonly uint Profile; - public readonly uint WhereAreN; +namespace NHSE.Core; - public SaveFileSizes(uint main, uint personal, uint photo, uint postbox, uint profile, uint wherearen = 0) - { - Main = main; - Personal = personal; - PhotoStudioIsland = photo; - PostBox = postbox; - Profile = profile; - WhereAreN = wherearen; - } +/// +/// Stores file sizes for various savedata files at different patch revisions. +/// +public class SaveFileSizes +{ + public readonly uint Main; + public readonly uint Personal; + public readonly uint PhotoStudioIsland; + public readonly uint PostBox; + public readonly uint Profile; + public readonly uint WhereAreN; + + public SaveFileSizes(uint main, uint personal, uint photo, uint postbox, uint profile, uint wherearen = 0) + { + Main = main; + Personal = personal; + PhotoStudioIsland = photo; + PostBox = postbox; + Profile = profile; + WhereAreN = wherearen; } -} +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets.cs index b1e739a..fc9aa42 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets.cs @@ -1,209 +1,208 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Offset info and object retrieval logic for +/// +public abstract class MainSaveOffsets { - /// - /// Offset info and object retrieval logic for - /// - public abstract class MainSaveOffsets + public const int PlayerCount = 8; + public const int VillagerCount = 10; + public virtual int PatternCount => PatternCount1; + protected const int PatternCount1 = 50; + protected const int PatternCount2 = 100; + public const int PatternTailorCount = 8; + public const int BuildingCount = 46; + public const int RecycleBinCount = 40; + + public abstract int Animal { get; } + + public abstract int LandMyDesign { get; } + public abstract int PatternsPRO { get; } + public abstract int PatternFlag { get; } + public abstract int PatternTailor { get; } + + public abstract int PatternsEditFlagStart { get; } + public abstract int PatternsProEditFlagStart { get; } + + public abstract int WeatherArea { get; } + public abstract int WeatherRandSeed { get; } + + public abstract int MainFieldStructure { get; } + + public abstract int EventFlagLand { get; } + public abstract int FieldItem { get; } + public abstract int LandMakingMap { get; } + public abstract int OutsideField { get; } + public abstract int MyDesignMap { get; } + public abstract int PlayerHouseList { get; } + public abstract int NpcHouseList { get; } + public abstract int ShopKabu { get; } + public abstract int Museum { get; } + public abstract int Visitor { get; } + + public abstract int SaveFg { get; } + public abstract int BulletinBoard { get; } + public abstract int AirportThemeColor { get; } + + public abstract int LostItemBox { get; } + public abstract int LastSavedTime { get; } + + public abstract int VillagerSize { get; } + public abstract int VillagerHouseSize { get; } + public abstract int PlayerHouseSize { get; } + public abstract int PlayerRoomSize { get; } + + public abstract IVillager ReadVillager(Memory data); + public abstract IVillagerHouse ReadVillagerHouse(Memory data); + public abstract IPlayerHouse ReadPlayerHouse(Memory data); + public abstract IPlayerRoom ReadPlayerRoom(Memory data); + + public static MainSaveOffsets GetOffsets(FileHeaderInfo Info) { - public const int PlayerCount = 8; - public const int VillagerCount = 10; - public virtual int PatternCount => PatternCount1; - protected const int PatternCount1 = 50; - protected const int PatternCount2 = 100; - public const int PatternTailorCount = 8; - public const int BuildingCount = 46; - public const int RecycleBinCount = 40; - - public abstract int Animal { get; } - - public abstract int LandMyDesign { get; } - public abstract int PatternsPRO { get; } - public abstract int PatternFlag { get; } - public abstract int PatternTailor { get; } - - public abstract int PatternsEditFlagStart { get; } - public abstract int PatternsProEditFlagStart { get; } - - public abstract int WeatherArea { get; } - public abstract int WeatherRandSeed { get; } - - public abstract int MainFieldStructure { get; } - - public abstract int EventFlagLand { get; } - public abstract int FieldItem { get; } - public abstract int LandMakingMap { get; } - public abstract int OutsideField { get; } - public abstract int MyDesignMap { get; } - public abstract int PlayerHouseList { get; } - public abstract int NpcHouseList { get; } - public abstract int ShopKabu { get; } - public abstract int Museum { get; } - public abstract int Visitor { get; } - - public abstract int SaveFg { get; } - public abstract int BulletinBoard { get; } - public abstract int AirportThemeColor { get; } - - public abstract int LostItemBox { get; } - public abstract int LastSavedTime { get; } - - public abstract int VillagerSize { get; } - public abstract int VillagerHouseSize { get; } - public abstract int PlayerHouseSize { get; } - public abstract int PlayerRoomSize { get; } - - public abstract IVillager ReadVillager(byte[] data); - public abstract IVillagerHouse ReadVillagerHouse(byte[] data); - public abstract IPlayerHouse ReadPlayerHouse(byte[] data); - public abstract IPlayerRoom ReadPlayerRoom(byte[] data); - - public static MainSaveOffsets GetOffsets(FileHeaderInfo Info) + var rev = Info.GetKnownRevisionIndex(); + return rev switch { - var rev = Info.GetKnownRevisionIndex(); - return rev switch - { - 0 => new MainSaveOffsets10(), - 1 => new MainSaveOffsets11(), - 2 => new MainSaveOffsets11(), - 3 => new MainSaveOffsets11(), - 4 => new MainSaveOffsets11(), - 5 => new MainSaveOffsets11(), - 6 => new MainSaveOffsets12(), - 7 => new MainSaveOffsets12(), - 8 => new MainSaveOffsets13(), - 9 => new MainSaveOffsets13(), - 10 => new MainSaveOffsets14(), - 11 => new MainSaveOffsets14(), - 12 => new MainSaveOffsets14(), - 13 => new MainSaveOffsets15(), - 14 => new MainSaveOffsets15(), - 15 => new MainSaveOffsets16(), - 16 => new MainSaveOffsets17(), - 17 => new MainSaveOffsets18(), - 18 => new MainSaveOffsets19(), - 19 => new MainSaveOffsets110(), - 20 => new MainSaveOffsets111(), - 21 => new MainSaveOffsets111(), - 22 => new MainSaveOffsets20(), - 23 => new MainSaveOffsets20(), - 24 => new MainSaveOffsets20(), - 25 => new MainSaveOffsets20(), - 26 => new MainSaveOffsets20(), - 27 => new MainSaveOffsets20(), - 28 => new MainSaveOffsets20(), - 29 => new MainSaveOffsets20(), - 30 => new MainSaveOffsets20(), - _ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info), - }; - } - - public DesignPattern ReadPattern(byte[] data, int index) - { - if ((uint)index >= PatternCount) - throw new ArgumentOutOfRangeException(nameof(index)); - return ReadPatternAtOffset(data, LandMyDesign + (index * DesignPattern.SIZE)); - } - - public static DesignPattern ReadPatternAtOffset(byte[] data, int offset) - { - var v = data.Slice(offset, DesignPattern.SIZE); - return new DesignPattern(v); - } - - public void WritePattern(DesignPattern p, byte[] data, int index, byte[] playerID, byte[] townID) - { - if ((uint)index >= PatternCount) - throw new ArgumentOutOfRangeException(nameof(index)); - playerID.CopyTo(p.Data, 0x54); // overwrite playerID bytes so player owns - townID.CopyTo(p.Data, 0x38); // overwrite townID bytes so player owns - byte[] wipeflag = new byte[] { 0x02, 0xEE, 0x00, 0x00 }; // wipe so player owns - wipeflag.CopyTo(p.Data, 0x70); - p.Data.CopyTo(data, LandMyDesign + (index * DesignPattern.SIZE)); - byte[] editedflag = new byte[] { 0x00 }; - editedflag.CopyTo(data, PatternsEditFlagStart + index); // set edited flag for name import to work - } - - public DesignPatternPRO ReadPatternPRO(byte[] data, int index) - { - if ((uint)index >= PatternCount) - throw new ArgumentOutOfRangeException(nameof(index)); - var ofs = PatternsPRO + (index * DesignPatternPRO.SIZE); - return ReadPatternPROAtOffset(data, ofs); - } - - public static DesignPatternPRO ReadPatternPROAtOffset(byte[] data, int ofs) - { - var v = data.Slice(ofs, DesignPatternPRO.SIZE); - return new DesignPatternPRO(v); - } - - public void WritePatternPRO(DesignPatternPRO p, byte[] data, int index, byte[] playerID, byte[] townID) - { - if ((uint)index >= PatternCount) - throw new ArgumentOutOfRangeException(nameof(index)); - playerID.CopyTo(p.Data, 0x54); // overwrite playerID bytes so player owns - townID.CopyTo(p.Data, 0x38); // overwrite townID bytes so player owns - byte[] wipeflag = new byte[] { 0x00, 0x00, 0x00, 0x00 }; // wipe so player owns - wipeflag.CopyTo(p.Data, 0x70); - p.Data.CopyTo(data, PatternsPRO + (index * DesignPatternPRO.SIZE)); - byte[] editedflag = new byte[] { 0x00 }; - editedflag.CopyTo(data, PatternsProEditFlagStart + index); - } - - public IVillager ReadVillager(byte[] data, int index) - { - if ((uint)index >= VillagerCount) - throw new ArgumentOutOfRangeException(nameof(index)); - - var size = VillagerSize; - var v = data.Slice(Animal + (index * size), size); - return ReadVillager(v); - } - - public void WriteVillager(IVillager v, byte[] data, int index) - { - if ((uint)index >= VillagerCount) - throw new ArgumentOutOfRangeException(nameof(index)); - var size = VillagerSize; - v.Write().CopyTo(data, Animal + (index * size)); - } - - public IVillagerHouse ReadVillagerHouse(byte[] data, int index) - { - if ((uint)index >= VillagerCount) - throw new ArgumentOutOfRangeException(nameof(index)); - - var size = VillagerHouseSize; - var v = data.Slice(NpcHouseList + (index * size), size); - return ReadVillagerHouse(v); - } - - public void WriteVillagerHouse(IVillagerHouse v, byte[] data, int index) - { - if ((uint)index >= VillagerCount) - throw new ArgumentOutOfRangeException(nameof(index)); - var size = VillagerHouseSize; - v.Write().CopyTo(data, NpcHouseList + (index * size)); - } - - public IPlayerHouse ReadPlayerHouse(byte[] data, int index) - { - if ((uint)index >= PlayerCount) - throw new ArgumentOutOfRangeException(nameof(index)); - - var size = PlayerHouseSize; - var v = data.Slice(PlayerHouseList + (index * size), size); - return ReadPlayerHouse(v); - } - - public void WritePlayerHouse(IPlayerHouse v, byte[] data, int index) - { - if ((uint)index >= PlayerCount) - throw new ArgumentOutOfRangeException(nameof(index)); - var size = PlayerHouseSize; - v.Write().CopyTo(data, PlayerHouseList + (index * size)); - } + 0 => new MainSaveOffsets10(), + 1 => new MainSaveOffsets11(), + 2 => new MainSaveOffsets11(), + 3 => new MainSaveOffsets11(), + 4 => new MainSaveOffsets11(), + 5 => new MainSaveOffsets11(), + 6 => new MainSaveOffsets12(), + 7 => new MainSaveOffsets12(), + 8 => new MainSaveOffsets13(), + 9 => new MainSaveOffsets13(), + 10 => new MainSaveOffsets14(), + 11 => new MainSaveOffsets14(), + 12 => new MainSaveOffsets14(), + 13 => new MainSaveOffsets15(), + 14 => new MainSaveOffsets15(), + 15 => new MainSaveOffsets16(), + 16 => new MainSaveOffsets17(), + 17 => new MainSaveOffsets18(), + 18 => new MainSaveOffsets19(), + 19 => new MainSaveOffsets110(), + 20 => new MainSaveOffsets111(), + 21 => new MainSaveOffsets111(), + 22 => new MainSaveOffsets20(), + 23 => new MainSaveOffsets20(), + 24 => new MainSaveOffsets20(), + 25 => new MainSaveOffsets20(), + 26 => new MainSaveOffsets20(), + 27 => new MainSaveOffsets20(), + 28 => new MainSaveOffsets20(), + 29 => new MainSaveOffsets20(), + 30 => new MainSaveOffsets20(), + _ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info), + }; } -} + + public DesignPattern ReadPattern(ReadOnlySpan data, int index) + { + if ((uint)index >= PatternCount) + throw new ArgumentOutOfRangeException(nameof(index)); + return ReadPatternAtOffset(data, LandMyDesign + (index * DesignPattern.SIZE)); + } + + public static DesignPattern ReadPatternAtOffset(ReadOnlySpan data, int offset) + { + var v = data.Slice(offset, DesignPattern.SIZE).ToArray(); + return new DesignPattern(v); + } + + public void WritePattern(DesignPattern p, Span data, int index, Span playerID, Span townID) + { + if ((uint)index >= PatternCount) + throw new ArgumentOutOfRangeException(nameof(index)); + playerID.CopyTo(p.Data[0x54..]); // overwrite playerID bytes so player owns + townID.CopyTo(p.Data[0x38..]); // overwrite townID bytes so player owns + ReadOnlySpan wipeflag = [0x02, 0xEE, 0x00, 0x00]; // wipe so player owns + wipeflag.CopyTo(p.Data[0x70..]); + p.Data.CopyTo(data[(LandMyDesign + (index * DesignPattern.SIZE))..]); + ReadOnlySpan editedflag = [0x00]; + editedflag.CopyTo(data[(PatternsEditFlagStart + index)..]); // set edited flag for name import to work + } + + public DesignPatternPRO ReadPatternPRO(ReadOnlySpan data, int index) + { + if ((uint)index >= PatternCount) + throw new ArgumentOutOfRangeException(nameof(index)); + var ofs = PatternsPRO + (index * DesignPatternPRO.SIZE); + return ReadPatternPROAtOffset(data, ofs); + } + + public static DesignPatternPRO ReadPatternPROAtOffset(ReadOnlySpan data, int ofs) + { + var v = data.Slice(ofs, DesignPatternPRO.SIZE).ToArray(); + return new DesignPatternPRO(v); + } + + public void WritePatternPRO(DesignPatternPRO p, Span data, int index, Span playerID, Span townID) + { + if ((uint)index >= PatternCount) + throw new ArgumentOutOfRangeException(nameof(index)); + playerID.CopyTo(p.Data[0x54..]); // overwrite playerID bytes so player owns + townID.CopyTo(p.Data[0x38..]); // overwrite townID bytes so player owns + ReadOnlySpan wipeflag = [0x00, 0x00, 0x00, 0x00]; // wipe so player owns + wipeflag.CopyTo(p.Data[0x70..]); + p.Data.CopyTo(data[(PatternsPRO + (index * DesignPatternPRO.SIZE))..]); + ReadOnlySpan editedflag = [0x00]; + editedflag.CopyTo(data[(PatternsProEditFlagStart + index)..]); // set edited flag for name import to work + } + + public IVillager ReadVillager(ReadOnlySpan data, int index) + { + if ((uint)index >= VillagerCount) + throw new ArgumentOutOfRangeException(nameof(index)); + + var size = VillagerSize; + var v = data.Slice(Animal + (index * size), size).ToArray(); + return ReadVillager(v); + } + + public void WriteVillager(IVillager v, Span data, int index) + { + if ((uint)index >= VillagerCount) + throw new ArgumentOutOfRangeException(nameof(index)); + var size = VillagerSize; + v.Write().CopyTo(data[(Animal + (index * size))..]); + } + + public IVillagerHouse ReadVillagerHouse(ReadOnlySpan data, int index) + { + if ((uint)index >= VillagerCount) + throw new ArgumentOutOfRangeException(nameof(index)); + + var size = VillagerHouseSize; + var v = data.Slice(NpcHouseList + (index * size), size).ToArray(); + return ReadVillagerHouse(v); + } + + public void WriteVillagerHouse(IVillagerHouse v, Span data, int index) + { + if ((uint)index >= VillagerCount) + throw new ArgumentOutOfRangeException(nameof(index)); + var size = VillagerHouseSize; + v.Write().CopyTo(data[(NpcHouseList + (index * size))..]); + } + + public IPlayerHouse ReadPlayerHouse(ReadOnlySpan data, int index) + { + if ((uint)index >= PlayerCount) + throw new ArgumentOutOfRangeException(nameof(index)); + + var size = PlayerHouseSize; + var v = data.Slice(PlayerHouseList + (index * size), size).ToArray(); + return ReadPlayerHouse(v); + } + + public void WritePlayerHouse(IPlayerHouse v, Span data, int index) + { + if ((uint)index >= PlayerCount) + throw new ArgumentOutOfRangeException(nameof(index)); + var size = PlayerHouseSize; + v.Write().CopyTo(data[(PlayerHouseList + (index * size))..]); + } +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets10.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets10.cs index 233fe2a..19d496b 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets10.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets10.cs @@ -1,65 +1,66 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets10 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets10 : MainSaveOffsets - { - #region GSaveLand - public const int GSaveLandStart = 0x108; - public override int Animal => GSaveLandStart + 0x08; + #region GSaveLand + public const int GSaveLandStart = 0x108; + public override int Animal => GSaveLandStart + 0x08; - public override int LandMyDesign => GSaveLandStart + 0x1D71E8; - public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1D71E8; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1D6FB0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1D6FB0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x200FF4; + public override int EventFlagLand => GSaveLandStart + 0x200FF4; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x2017F4; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x2017F4; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x2DBAA0; - public override int NpcHouseList => GSaveLandStart + 0x40DAA0; + public override int PlayerHouseList => GSaveLandStart + 0x2DBAA0; + public override int NpcHouseList => GSaveLandStart + 0x40DAA0; - public const int GSaveShop = GSaveLandStart + 0x40ECE8; - public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop - public override int Museum => GSaveLandStart + 0x411A80; - public override int Visitor => GSaveLandStart + 0x414E84; - public override int SaveFg => GSaveLandStart + 0x4150B4; - public override int BulletinBoard => GSaveLandStart + 0x4159F8; - public override int AirportThemeColor => GSaveLandStart + 0x4F6600; - #endregion + public const int GSaveShop = GSaveLandStart + 0x40ECE8; + public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop + public override int Museum => GSaveLandStart + 0x411A80; + public override int Visitor => GSaveLandStart + 0x414E84; + public override int SaveFg => GSaveLandStart + 0x4150B4; + public override int BulletinBoard => GSaveLandStart + 0x4159F8; + public override int AirportThemeColor => GSaveLandStart + 0x4F6600; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x4FA1E0; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x4FA1E0; - public override int LostItemBox => GSaveLandOtherStart + 0x5C1E20; - public override int LastSavedTime => GSaveLandOtherStart + 0x5C6748; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x5C1E20; + public override int LastSavedTime => GSaveLandOtherStart + 0x5C6748; + #endregion - public override int VillagerSize => Villager1.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager1(data); + public override int VillagerSize => Villager1.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager1(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets11.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets11.cs index 5b885a0..f954718 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets11.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets11.cs @@ -1,64 +1,65 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets11 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets11 : MainSaveOffsets - { - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1D7200; - public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1D7200; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1D6F98; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1D6F98; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x20100C; + public override int EventFlagLand => GSaveLandStart + 0x20100C; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x20180C; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x20180C; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x2DC238; - public override int NpcHouseList => GSaveLandStart + 0x40E238; + public override int PlayerHouseList => GSaveLandStart + 0x2DC238; + public override int NpcHouseList => GSaveLandStart + 0x40E238; - public const int GSaveShop = GSaveLandStart + 0x40F480; - public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop - public override int Museum => GSaveLandStart + 0x412218; - public override int Visitor => GSaveLandStart + 0x41561C; - public override int SaveFg => GSaveLandStart + 0x41584C; - public override int BulletinBoard => GSaveLandStart + 0x416190; - public override int AirportThemeColor => GSaveLandStart + 0x4F6D98; - #endregion + public const int GSaveShop = GSaveLandStart + 0x40F480; + public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop + public override int Museum => GSaveLandStart + 0x412218; + public override int Visitor => GSaveLandStart + 0x41561C; + public override int SaveFg => GSaveLandStart + 0x41584C; + public override int BulletinBoard => GSaveLandStart + 0x416190; + public override int AirportThemeColor => GSaveLandStart + 0x4F6D98; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x4FAA80; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x4FAA80; - public override int LostItemBox => GSaveLandOtherStart + 0x5C33F0; - public override int LastSavedTime => GSaveLandOtherStart + 0x5C7D48; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x5C33F0; + public override int LastSavedTime => GSaveLandOtherStart + 0x5C7D48; + #endregion - public override int VillagerSize => Villager1.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager1(data); + public override int VillagerSize => Villager1.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager1(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets110.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets110.cs index 8c5c91a..6340b54 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets110.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets110.cs @@ -1,66 +1,67 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets110 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets110 : MainSaveOffsets - { - public override int PatternCount => PatternCount2; + public override int PatternCount => PatternCount2; - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1e2610; - public override int PatternsPRO => LandMyDesign + (PatternCount2 * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount2 * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1e2610; + public override int PatternsPRO => LandMyDesign + (PatternCount2 * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount2 * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1e23c0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1e23c0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x22d9b8; + public override int EventFlagLand => GSaveLandStart + 0x22d9b8; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x22e1b8; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x22e1b8; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x308be4; - public override int NpcHouseList => GSaveLandStart + 0x43abe4; + public override int PlayerHouseList => GSaveLandStart + 0x308be4; + public override int NpcHouseList => GSaveLandStart + 0x43abe4; - public const int GSaveShop = GSaveLandStart + 0x43be2c; - public override int ShopKabu => GSaveShop + 0x2d40; // part of shop; tailor & zakka increased size - public override int Museum => GSaveLandStart + 0x43f1e0; - public override int Visitor => GSaveLandStart + 0x4425e4; - public override int SaveFg => GSaveLandStart + 0x442814; - public override int BulletinBoard => GSaveLandStart + 0x443158; - public override int AirportThemeColor => GSaveLandStart + 0x523d60; - #endregion + public const int GSaveShop = GSaveLandStart + 0x43be2c; + public override int ShopKabu => GSaveShop + 0x2d40; // part of shop; tailor & zakka increased size + public override int Museum => GSaveLandStart + 0x43f1e0; + public override int Visitor => GSaveLandStart + 0x4425e4; + public override int SaveFg => GSaveLandStart + 0x442814; + public override int BulletinBoard => GSaveLandStart + 0x443158; + public override int AirportThemeColor => GSaveLandStart + 0x523d60; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x527ab0; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x527ab0; - public override int LostItemBox => GSaveLandOtherStart + 0x3408c0; - public override int LastSavedTime => GSaveLandOtherStart + 0x345220; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x3408c0; + public override int LastSavedTime => GSaveLandOtherStart + 0x345220; + #endregion - public override int VillagerSize => Villager2.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager2(data); + public override int VillagerSize => Villager2.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager2(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets111.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets111.cs index e60f4d7..6e43ae7 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets111.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets111.cs @@ -1,67 +1,68 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +/// Same as +public class MainSaveOffsets111 : MainSaveOffsets { - /// - /// - /// - /// Same as - public class MainSaveOffsets111 : MainSaveOffsets - { - public override int PatternCount => PatternCount2; + public override int PatternCount => PatternCount2; - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1e2610; - public override int PatternsPRO => LandMyDesign + (PatternCount2 * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount2 * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1e2610; + public override int PatternsPRO => LandMyDesign + (PatternCount2 * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount2 * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1e23c0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1e23c0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x22d9b8; + public override int EventFlagLand => GSaveLandStart + 0x22d9b8; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x22e1b8; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x22e1b8; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x308be4; - public override int NpcHouseList => GSaveLandStart + 0x43abe4; + public override int PlayerHouseList => GSaveLandStart + 0x308be4; + public override int NpcHouseList => GSaveLandStart + 0x43abe4; - public const int GSaveShop = GSaveLandStart + 0x43be2c; - public override int ShopKabu => GSaveShop + 0x2d40; // part of shop; tailor & zakka increased size - public override int Museum => GSaveLandStart + 0x43f1e0; - public override int Visitor => GSaveLandStart + 0x4425e4; - public override int SaveFg => GSaveLandStart + 0x442814; - public override int BulletinBoard => GSaveLandStart + 0x443158; - public override int AirportThemeColor => GSaveLandStart + 0x523d60; - #endregion + public const int GSaveShop = GSaveLandStart + 0x43be2c; + public override int ShopKabu => GSaveShop + 0x2d40; // part of shop; tailor & zakka increased size + public override int Museum => GSaveLandStart + 0x43f1e0; + public override int Visitor => GSaveLandStart + 0x4425e4; + public override int SaveFg => GSaveLandStart + 0x442814; + public override int BulletinBoard => GSaveLandStart + 0x443158; + public override int AirportThemeColor => GSaveLandStart + 0x523d60; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x527ab0; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x527ab0; - public override int LostItemBox => GSaveLandOtherStart + 0x3408c0; - public override int LastSavedTime => GSaveLandOtherStart + 0x345220; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x3408c0; + public override int LastSavedTime => GSaveLandOtherStart + 0x345220; + #endregion - public override int VillagerSize => Villager2.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager2(data); + public override int VillagerSize => Villager2.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager2(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets12.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets12.cs index cb30647..bf0495c 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets12.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets12.cs @@ -1,64 +1,65 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets12 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets12 : MainSaveOffsets - { - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1D7200; - public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1D7200; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1D6FB0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1D6FB0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x20100C; + public override int EventFlagLand => GSaveLandStart + 0x20100C; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x20180C; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x20180C; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x2DC238; - public override int NpcHouseList => GSaveLandStart + 0x40E238; + public override int PlayerHouseList => GSaveLandStart + 0x2DC238; + public override int NpcHouseList => GSaveLandStart + 0x40E238; - public const int GSaveShop = GSaveLandStart + 0x40F480; - public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop - public override int Museum => GSaveLandStart + 0x4124C4; - public override int Visitor => GSaveLandStart + 0x4158C8; - public override int SaveFg => GSaveLandStart + 0x415AF8; - public override int BulletinBoard => GSaveLandStart + 0x416440; - public override int AirportThemeColor => GSaveLandStart + 0x4F7048; - #endregion + public const int GSaveShop = GSaveLandStart + 0x40F480; + public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop + public override int Museum => GSaveLandStart + 0x4124C4; + public override int Visitor => GSaveLandStart + 0x4158C8; + public override int SaveFg => GSaveLandStart + 0x415AF8; + public override int BulletinBoard => GSaveLandStart + 0x416440; + public override int AirportThemeColor => GSaveLandStart + 0x4F7048; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x4FAD30; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x4FAD30; - public override int LostItemBox => GSaveLandOtherStart + 0x5CF370; - public override int LastSavedTime => GSaveLandOtherStart + 0x5D3CC8; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x5CF370; + public override int LastSavedTime => GSaveLandOtherStart + 0x5D3CC8; + #endregion - public override int VillagerSize => Villager1.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager1(data); + public override int VillagerSize => Villager1.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager1(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets13.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets13.cs index f36a6d3..67a04fb 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets13.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets13.cs @@ -1,64 +1,65 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets13 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets13 : MainSaveOffsets - { - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1D7200; - public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1D7200; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1D6FB0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1D6FB0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x20100C; + public override int EventFlagLand => GSaveLandStart + 0x20100C; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x20180C; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x20180C; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x2DC238; - public override int NpcHouseList => GSaveLandStart + 0x40E238; + public override int PlayerHouseList => GSaveLandStart + 0x2DC238; + public override int NpcHouseList => GSaveLandStart + 0x40E238; - public const int GSaveShop = GSaveLandStart + 0x40F480; - public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop - public override int Museum => GSaveLandStart + 0x4124C4; - public override int Visitor => GSaveLandStart + 0x4158C8; - public override int SaveFg => GSaveLandStart + 0x415AF8; - public override int BulletinBoard => GSaveLandStart + 0x416440; - public override int AirportThemeColor => GSaveLandStart + 0x4F7048; - #endregion + public const int GSaveShop = GSaveLandStart + 0x40F480; + public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop + public override int Museum => GSaveLandStart + 0x4124C4; + public override int Visitor => GSaveLandStart + 0x4158C8; + public override int SaveFg => GSaveLandStart + 0x415AF8; + public override int BulletinBoard => GSaveLandStart + 0x416440; + public override int AirportThemeColor => GSaveLandStart + 0x4F7048; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x4FAD60; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x4FAD60; - public override int LostItemBox => GSaveLandOtherStart + 0x5CF3F0; - public override int LastSavedTime => GSaveLandOtherStart + 0x5D3D48; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x5CF3F0; + public override int LastSavedTime => GSaveLandOtherStart + 0x5D3D48; + #endregion - public override int VillagerSize => Villager1.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager1(data); + public override int VillagerSize => Villager1.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager1(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets14.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets14.cs index 418955b..1036468 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets14.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets14.cs @@ -1,64 +1,65 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets14 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets14 : MainSaveOffsets - { - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1D7200; - public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1D7200; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1D6FB0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1D6FB0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x20100C; + public override int EventFlagLand => GSaveLandStart + 0x20100C; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x20180C; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x20180C; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x2DC238; - public override int NpcHouseList => GSaveLandStart + 0x40E238; + public override int PlayerHouseList => GSaveLandStart + 0x2DC238; + public override int NpcHouseList => GSaveLandStart + 0x40E238; - public const int GSaveShop = GSaveLandStart + 0x40F480; - public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop - public override int Museum => GSaveLandStart + 0x4124C4; - public override int Visitor => GSaveLandStart + 0x4158C8; - public override int SaveFg => GSaveLandStart + 0x415AF8; - public override int BulletinBoard => GSaveLandStart + 0x416440; - public override int AirportThemeColor => GSaveLandStart + 0x4F7048; - #endregion + public const int GSaveShop = GSaveLandStart + 0x40F480; + public override int ShopKabu => GSaveShop + 0x2AD0; // part of shop + public override int Museum => GSaveLandStart + 0x4124C4; + public override int Visitor => GSaveLandStart + 0x4158C8; + public override int SaveFg => GSaveLandStart + 0x415AF8; + public override int BulletinBoard => GSaveLandStart + 0x416440; + public override int AirportThemeColor => GSaveLandStart + 0x4F7048; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x4FADA0; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x4FADA0; - public override int LostItemBox => GSaveLandOtherStart + 0x605E70; - public override int LastSavedTime => GSaveLandOtherStart + 0x60A708; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x605E70; + public override int LastSavedTime => GSaveLandOtherStart + 0x60A708; + #endregion - public override int VillagerSize => Villager1.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager1(data); + public override int VillagerSize => Villager1.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager1(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets15.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets15.cs index 4e01aa3..0d8a50a 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets15.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets15.cs @@ -1,64 +1,65 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets15 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets15 : MainSaveOffsets - { - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1e2600; - public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1e2600; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1e23B0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1e23B0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x20c40c; + public override int EventFlagLand => GSaveLandStart + 0x20c40c; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x20cc0c; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x20cc0c; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x2e7638; - public override int NpcHouseList => GSaveLandStart + 0x419638; + public override int PlayerHouseList => GSaveLandStart + 0x2e7638; + public override int NpcHouseList => GSaveLandStart + 0x419638; - public const int GSaveShop = GSaveLandStart + 0x41a880; - public override int ShopKabu => GSaveShop + 0x2b10; // part of shop - public override int Museum => GSaveLandStart + 0x41d904; - public override int Visitor => GSaveLandStart + 0x420d08; - public override int SaveFg => GSaveLandStart + 0x420f38; - public override int BulletinBoard => GSaveLandStart + 0x421880; - public override int AirportThemeColor => GSaveLandStart + 0x502488; - #endregion + public const int GSaveShop = GSaveLandStart + 0x41a880; + public override int ShopKabu => GSaveShop + 0x2b10; // part of shop + public override int Museum => GSaveLandStart + 0x41d904; + public override int Visitor => GSaveLandStart + 0x420d08; + public override int SaveFg => GSaveLandStart + 0x420f38; + public override int BulletinBoard => GSaveLandStart + 0x421880; + public override int AirportThemeColor => GSaveLandStart + 0x502488; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x5061e0; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x5061e0; - public override int LostItemBox => GSaveLandOtherStart + 0x6159f0; - public override int LastSavedTime => GSaveLandOtherStart + 0x61a288; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x6159f0; + public override int LastSavedTime => GSaveLandOtherStart + 0x61a288; + #endregion - public override int VillagerSize => Villager2.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager2(data); + public override int VillagerSize => Villager2.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager2(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets16.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets16.cs index c655a87..d43af7f 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets16.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets16.cs @@ -1,64 +1,65 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets16 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets16 : MainSaveOffsets - { - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1e2600; - public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1e2600; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1e23B0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1e23B0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x20c40c; + public override int EventFlagLand => GSaveLandStart + 0x20c40c; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x20cc0c; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x20cc0c; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x2e7638; - public override int NpcHouseList => GSaveLandStart + 0x419638; + public override int PlayerHouseList => GSaveLandStart + 0x2e7638; + public override int NpcHouseList => GSaveLandStart + 0x419638; - public const int GSaveShop = GSaveLandStart + 0x41a880; - public override int ShopKabu => GSaveShop + 0x2be0; // part of shop; tailor increased size - public override int Museum => GSaveLandStart + 0x41d9d4; - public override int Visitor => GSaveLandStart + 0x420dd8; - public override int SaveFg => GSaveLandStart + 0x421008; - public override int BulletinBoard => GSaveLandStart + 0x421950; - public override int AirportThemeColor => GSaveLandStart + 0x502558; - #endregion + public const int GSaveShop = GSaveLandStart + 0x41a880; + public override int ShopKabu => GSaveShop + 0x2be0; // part of shop; tailor increased size + public override int Museum => GSaveLandStart + 0x41d9d4; + public override int Visitor => GSaveLandStart + 0x420dd8; + public override int SaveFg => GSaveLandStart + 0x421008; + public override int BulletinBoard => GSaveLandStart + 0x421950; + public override int AirportThemeColor => GSaveLandStart + 0x502558; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x5062b0; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x5062b0; - public override int LostItemBox => GSaveLandOtherStart + 0x61a4f0; - public override int LastSavedTime => GSaveLandOtherStart + 0x61ed88; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x61a4f0; + public override int LastSavedTime => GSaveLandOtherStart + 0x61ed88; + #endregion - public override int VillagerSize => Villager2.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager2(data); + public override int VillagerSize => Villager2.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager2(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets17.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets17.cs index afe99db..230a574 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets17.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets17.cs @@ -1,64 +1,65 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets17 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets17 : MainSaveOffsets - { - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1e2600; - public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1e2600; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1e23B0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1e23B0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x20a408; + public override int EventFlagLand => GSaveLandStart + 0x20a408; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x20ac08; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x20ac08; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x2e5634; - public override int NpcHouseList => GSaveLandStart + 0x417634; + public override int PlayerHouseList => GSaveLandStart + 0x2e5634; + public override int NpcHouseList => GSaveLandStart + 0x417634; - public const int GSaveShop = GSaveLandStart + 0x41887c; - public override int ShopKabu => GSaveShop + 0x2cb0; // part of shop; tailor increased size - public override int Museum => GSaveLandStart + 0x41bba0; - public override int Visitor => GSaveLandStart + 0x41efa4; - public override int SaveFg => GSaveLandStart + 0x41f1d4; - public override int BulletinBoard => GSaveLandStart + 0x41fb18; - public override int AirportThemeColor => GSaveLandStart + 0x500720; - #endregion + public const int GSaveShop = GSaveLandStart + 0x41887c; + public override int ShopKabu => GSaveShop + 0x2cb0; // part of shop; tailor increased size + public override int Museum => GSaveLandStart + 0x41bba0; + public override int Visitor => GSaveLandStart + 0x41efa4; + public override int SaveFg => GSaveLandStart + 0x41f1d4; + public override int BulletinBoard => GSaveLandStart + 0x41fb18; + public override int AirportThemeColor => GSaveLandStart + 0x500720; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x504470; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x504470; - public override int LostItemBox => GSaveLandOtherStart + 0x340680; - public override int LastSavedTime => GSaveLandOtherStart + 0x344f18; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x340680; + public override int LastSavedTime => GSaveLandOtherStart + 0x344f18; + #endregion - public override int VillagerSize => Villager2.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager2(data); + public override int VillagerSize => Villager2.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager2(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets18.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets18.cs index 20f3043..0229ca0 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets18.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets18.cs @@ -1,65 +1,66 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +/// Same as . +public class MainSaveOffsets18 : MainSaveOffsets { - /// - /// - /// - /// Same as . - public class MainSaveOffsets18 : MainSaveOffsets - { - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1e2600; - public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1e2600; + public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1e23B0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1e23B0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x20a408; + public override int EventFlagLand => GSaveLandStart + 0x20a408; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x20ac08; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x20ac08; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x2e5634; - public override int NpcHouseList => GSaveLandStart + 0x417634; + public override int PlayerHouseList => GSaveLandStart + 0x2e5634; + public override int NpcHouseList => GSaveLandStart + 0x417634; - public const int GSaveShop = GSaveLandStart + 0x41887c; - public override int ShopKabu => GSaveShop + 0x2cb0; // part of shop; tailor increased size - public override int Museum => GSaveLandStart + 0x41bba0; - public override int Visitor => GSaveLandStart + 0x41efa4; - public override int SaveFg => GSaveLandStart + 0x41f1d4; - public override int BulletinBoard => GSaveLandStart + 0x41fb18; - public override int AirportThemeColor => GSaveLandStart + 0x500720; - #endregion + public const int GSaveShop = GSaveLandStart + 0x41887c; + public override int ShopKabu => GSaveShop + 0x2cb0; // part of shop; tailor increased size + public override int Museum => GSaveLandStart + 0x41bba0; + public override int Visitor => GSaveLandStart + 0x41efa4; + public override int SaveFg => GSaveLandStart + 0x41f1d4; + public override int BulletinBoard => GSaveLandStart + 0x41fb18; + public override int AirportThemeColor => GSaveLandStart + 0x500720; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x504470; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x504470; - public override int LostItemBox => GSaveLandOtherStart + 0x340680; - public override int LastSavedTime => GSaveLandOtherStart + 0x344f18; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x340680; + public override int LastSavedTime => GSaveLandOtherStart + 0x344f18; + #endregion - public override int VillagerSize => Villager2.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager2(data); + public override int VillagerSize => Villager2.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager2(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets19.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets19.cs index 600ff1b..78540c2 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets19.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets19.cs @@ -1,66 +1,67 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public class MainSaveOffsets19 : MainSaveOffsets { - /// - /// - /// - public class MainSaveOffsets19 : MainSaveOffsets - { - public override int PatternCount => PatternCount2; + public override int PatternCount => PatternCount2; - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1e2600; - public override int PatternsPRO => LandMyDesign + (PatternCount2 * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount2 * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1e2600; + public override int PatternsPRO => LandMyDesign + (PatternCount2 * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount2 * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1e23B0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1e23B0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x22d9a8; + public override int EventFlagLand => GSaveLandStart + 0x22d9a8; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x22e1a8; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x22e1a8; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x308bd4; - public override int NpcHouseList => GSaveLandStart + 0x43abd4; + public override int PlayerHouseList => GSaveLandStart + 0x308bd4; + public override int NpcHouseList => GSaveLandStart + 0x43abd4; - public const int GSaveShop = GSaveLandStart + 0x43be1c; - public override int ShopKabu => GSaveShop + 0x2d40; // part of shop; tailor & zakka increased size - public override int Museum => GSaveLandStart + 0x43f1d0; - public override int Visitor => GSaveLandStart + 0x4425d4; - public override int SaveFg => GSaveLandStart + 0x442804; - public override int BulletinBoard => GSaveLandStart + 0x443148; - public override int AirportThemeColor => GSaveLandStart + 0x523d50; - #endregion + public const int GSaveShop = GSaveLandStart + 0x43be1c; + public override int ShopKabu => GSaveShop + 0x2d40; // part of shop; tailor & zakka increased size + public override int Museum => GSaveLandStart + 0x43f1d0; + public override int Visitor => GSaveLandStart + 0x4425d4; + public override int SaveFg => GSaveLandStart + 0x442804; + public override int BulletinBoard => GSaveLandStart + 0x443148; + public override int AirportThemeColor => GSaveLandStart + 0x523d50; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x527aa0; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x527aa0; - public override int LostItemBox => GSaveLandOtherStart + 0x3408c0; - public override int LastSavedTime => GSaveLandOtherStart + 0x345220; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x3408c0; + public override int LastSavedTime => GSaveLandOtherStart + 0x345220; + #endregion - public override int VillagerSize => Villager2.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager2(data); + public override int VillagerSize => Villager2.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager2(data); - public override int VillagerHouseSize => VillagerHouse1.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data); + public override int VillagerHouseSize => VillagerHouse1.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse1(data); - public override int PlayerHouseSize => PlayerHouse1.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data); - public override int PlayerRoomSize => PlayerRoom1.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data); - } -} + public override int PlayerHouseSize => PlayerHouse1.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse1(data); + public override int PlayerRoomSize => PlayerRoom1.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom1(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/MainSaveOffsets20.cs b/NHSE.Core/Save/Offsets/MainSaveOffsets20.cs index a2b058e..b8c7c39 100644 --- a/NHSE.Core/Save/Offsets/MainSaveOffsets20.cs +++ b/NHSE.Core/Save/Offsets/MainSaveOffsets20.cs @@ -1,67 +1,68 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +/// Same as +public class MainSaveOffsets20 : MainSaveOffsets { - /// - /// - /// - /// Same as - public class MainSaveOffsets20 : MainSaveOffsets - { - public override int PatternCount => PatternCount2; + public override int PatternCount => PatternCount2; - #region GSaveLand - public const int GSaveLandStart = 0x110; - public override int Animal => GSaveLandStart + 0x10; + #region GSaveLand + public const int GSaveLandStart = 0x110; + public override int Animal => GSaveLandStart + 0x10; - public override int LandMyDesign => GSaveLandStart + 0x1e3848; - public override int PatternsPRO => LandMyDesign + (PatternCount2 * DesignPattern.SIZE); - public override int PatternFlag => PatternsPRO + (PatternCount2 * DesignPatternPRO.SIZE); - public override int PatternTailor => PatternFlag + DesignPattern.SIZE; + public override int LandMyDesign => GSaveLandStart + 0x1e3848; + public override int PatternsPRO => LandMyDesign + (PatternCount2 * DesignPattern.SIZE); + public override int PatternFlag => PatternsPRO + (PatternCount2 * DesignPatternPRO.SIZE); + public override int PatternTailor => PatternFlag + DesignPattern.SIZE; - public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? - public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? + public override int PatternsEditFlagStart => GSaveLandStart + 0x8BE150; // x100, HasPlayerEdited? + public override int PatternsProEditFlagStart => PatternsEditFlagStart + 0x64; // x100, HasPlayerEdited? - public const int GSaveWeather = GSaveLandStart + 0x1e35f0; - public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere - public override int WeatherRandSeed => GSaveWeather + 0x18; + public const int GSaveWeather = GSaveLandStart + 0x1e35f0; + public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere + public override int WeatherRandSeed => GSaveWeather + 0x18; - public override int EventFlagLand => GSaveLandStart + 0x22ebf0; + public override int EventFlagLand => GSaveLandStart + 0x22ebf0; - // GSaveMainField - public const int GSaveMainFieldStart = GSaveLandStart + 0x22f3f0; - public override int FieldItem => GSaveMainFieldStart + 0x00000; - public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; - public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; - public override int OutsideField => GSaveMainFieldStart + 0xCF998; - public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; + // GSaveMainField + public const int GSaveMainFieldStart = GSaveLandStart + 0x22f3f0; + public override int FieldItem => GSaveMainFieldStart + 0x00000; + public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00; + public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600; + public override int OutsideField => GSaveMainFieldStart + 0xCF998; + public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34; - public override int PlayerHouseList => GSaveLandStart + 0x30a6bc; - public override int NpcHouseList => GSaveLandStart + 0x44f7fc; + public override int PlayerHouseList => GSaveLandStart + 0x30a6bc; + public override int NpcHouseList => GSaveLandStart + 0x44f7fc; - public const int GSaveShop = GSaveLandStart + 0x45b50c; - public override int ShopKabu => GSaveShop + 0x2d40; // part of shop; tailor & zakka increased size - public override int Museum => GSaveLandStart + 0x45ec44; - public override int Visitor => GSaveLandStart + 0x462048; - public override int SaveFg => GSaveLandStart + 0x462278; - public override int BulletinBoard => GSaveLandStart + 0x462bc0; - public override int AirportThemeColor => GSaveLandStart + 0x5437c8; - #endregion + public const int GSaveShop = GSaveLandStart + 0x45b50c; + public override int ShopKabu => GSaveShop + 0x2d40; // part of shop; tailor & zakka increased size + public override int Museum => GSaveLandStart + 0x45ec44; + public override int Visitor => GSaveLandStart + 0x462048; + public override int SaveFg => GSaveLandStart + 0x462278; + public override int BulletinBoard => GSaveLandStart + 0x462bc0; + public override int AirportThemeColor => GSaveLandStart + 0x5437c8; + #endregion - #region GSaveLandOther - public const int GSaveLandOtherStart = 0x547520; + #region GSaveLandOther + public const int GSaveLandOtherStart = 0x547520; - public override int LostItemBox => GSaveLandOtherStart + 0x3726c0; - public override int LastSavedTime => GSaveLandOtherStart + 0x377020; - #endregion + public override int LostItemBox => GSaveLandOtherStart + 0x3726c0; + public override int LastSavedTime => GSaveLandOtherStart + 0x377020; + #endregion - public override int VillagerSize => Villager2.SIZE; - public override IVillager ReadVillager(byte[] data) => new Villager2(data); + public override int VillagerSize => Villager2.SIZE; + public override IVillager ReadVillager(Memory data) => new Villager2(data); - public override int VillagerHouseSize => VillagerHouse2.SIZE; - public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse2(data); + public override int VillagerHouseSize => VillagerHouse2.SIZE; + public override IVillagerHouse ReadVillagerHouse(Memory data) => new VillagerHouse2(data); - public override int PlayerHouseSize => PlayerHouse2.SIZE; - public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse2(data); - public override int PlayerRoomSize => PlayerRoom2.SIZE; - public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom2(data); - } -} + public override int PlayerHouseSize => PlayerHouse2.SIZE; + public override IPlayerHouse ReadPlayerHouse(Memory data) => new PlayerHouse2(data); + public override int PlayerRoomSize => PlayerRoom2.SIZE; + public override IPlayerRoom ReadPlayerRoom(Memory data) => new PlayerRoom2(data); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets.cs b/NHSE.Core/Save/Offsets/PersonalOffsets.cs index 43cf2ff..54aafa1 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets.cs @@ -1,85 +1,84 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Offset info and object retrieval logic for +/// +public abstract class PersonalOffsets { - /// - /// Offset info and object retrieval logic for - /// - public abstract class PersonalOffsets + public abstract int PersonalId { get; } + public abstract int EventFlagsPlayer { get; } + public abstract int CountAchievement { get; } + public abstract int Wallet { get; } + public abstract int NowPoint { get; } + public abstract int TotalPoint { get; } + public abstract int Birthday { get; } + + public abstract int ProfileMain { get; } + public abstract int ProfilePhoto { get; } + public abstract int ProfileBirthday { get; } + public abstract int ProfileFruit { get; } + public abstract int ProfileTimestamp { get; } + public abstract int ProfileIsMakeVillage { get; } + + public abstract int Pockets1 { get; } + public abstract int Pockets2 { get; } + public abstract int ItemChest { get; } + public abstract int ItemCollectBit { get; } + public abstract int ItemRemakeCollectBit { get; } + public abstract int Manpu { get; } // reactions + + public abstract int Bank { get; } + public abstract int Recipes { get; } + + public int MaxAchievementID { get; } = 512; + public int Pockets1Count { get; } = 20; + public int Pockets2Count { get; } = 20; + public int ItemChestCount { get; } = 5000; + public abstract int MaxRecipeID { get; } + public abstract int MaxRemakeBitFlag { get; } + + public static PersonalOffsets GetOffsets(FileHeaderInfo Info) { - public abstract int PersonalId { get; } - public abstract int EventFlagsPlayer { get; } - public abstract int CountAchievement { get; } - public abstract int Wallet { get; } - public abstract int NowPoint { get; } - public abstract int TotalPoint { get; } - public abstract int Birthday { get; } - - public abstract int ProfileMain { get; } - public abstract int ProfilePhoto { get; } - public abstract int ProfileBirthday { get; } - public abstract int ProfileFruit { get; } - public abstract int ProfileTimestamp { get; } - public abstract int ProfileIsMakeVillage { get; } - - public abstract int Pockets1 { get; } - public abstract int Pockets2 { get; } - public abstract int ItemChest { get; } - public abstract int ItemCollectBit { get; } - public abstract int ItemRemakeCollectBit { get; } - public abstract int Manpu { get; } // reactions - - public abstract int Bank { get; } - public abstract int Recipes { get; } - - public int MaxAchievementID { get; } = 512; - public int Pockets1Count { get; } = 20; - public int Pockets2Count { get; } = 20; - public int ItemChestCount { get; } = 5000; - public abstract int MaxRecipeID { get; } - public abstract int MaxRemakeBitFlag { get; } - - public static PersonalOffsets GetOffsets(FileHeaderInfo Info) + var rev = Info.GetKnownRevisionIndex(); + return rev switch { - var rev = Info.GetKnownRevisionIndex(); - return rev switch - { - 0 => new PersonalOffsets10(), - 1 => new PersonalOffsets11(), - 2 => new PersonalOffsets11(), - 3 => new PersonalOffsets11(), - 4 => new PersonalOffsets11(), - 5 => new PersonalOffsets11(), - 6 => new PersonalOffsets12(), - 7 => new PersonalOffsets12(), - 8 => new PersonalOffsets13(), - 9 => new PersonalOffsets13(), - 10 => new PersonalOffsets14(), - 11 => new PersonalOffsets14(), - 12 => new PersonalOffsets14(), - 13 => new PersonalOffsets15(), - 14 => new PersonalOffsets15(), - 15 => new PersonalOffsets16(), - 16 => new PersonalOffsets17(), - 17 => new PersonalOffsets18(), - 18 => new PersonalOffsets19(), - 19 => new PersonalOffsets110(), - 20 => new PersonalOffsets111(), - 21 => new PersonalOffsets111(), - 22 => new PersonalOffsets20(), - 23 => new PersonalOffsets20(), - 24 => new PersonalOffsets20(), - 25 => new PersonalOffsets20(), - 26 => new PersonalOffsets20(), - 27 => new PersonalOffsets20(), - 28 => new PersonalOffsets20(), - 29 => new PersonalOffsets20(), - 30 => new PersonalOffsets20(), - _ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info), - }; - } - - public abstract IReactionStore ReadReactions(byte[] data); - public abstract void SetReactions(byte[] data, IReactionStore value); + 0 => new PersonalOffsets10(), + 1 => new PersonalOffsets11(), + 2 => new PersonalOffsets11(), + 3 => new PersonalOffsets11(), + 4 => new PersonalOffsets11(), + 5 => new PersonalOffsets11(), + 6 => new PersonalOffsets12(), + 7 => new PersonalOffsets12(), + 8 => new PersonalOffsets13(), + 9 => new PersonalOffsets13(), + 10 => new PersonalOffsets14(), + 11 => new PersonalOffsets14(), + 12 => new PersonalOffsets14(), + 13 => new PersonalOffsets15(), + 14 => new PersonalOffsets15(), + 15 => new PersonalOffsets16(), + 16 => new PersonalOffsets17(), + 17 => new PersonalOffsets18(), + 18 => new PersonalOffsets19(), + 19 => new PersonalOffsets110(), + 20 => new PersonalOffsets111(), + 21 => new PersonalOffsets111(), + 22 => new PersonalOffsets20(), + 23 => new PersonalOffsets20(), + 24 => new PersonalOffsets20(), + 25 => new PersonalOffsets20(), + 26 => new PersonalOffsets20(), + 27 => new PersonalOffsets20(), + 28 => new PersonalOffsets20(), + 29 => new PersonalOffsets20(), + 30 => new PersonalOffsets20(), + _ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info), + }; } + + public abstract IReactionStore ReadReactions(ReadOnlySpan data); + public abstract void SetReactions(Span data, IReactionStore value); } \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets10.cs b/NHSE.Core/Save/Offsets/PersonalOffsets10.cs index 4614551..17b1e61 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets10.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets10.cs @@ -1,47 +1,48 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public sealed class PersonalOffsets10 : PersonalOffsets { - /// - /// - /// - public sealed class PersonalOffsets10 : PersonalOffsets - { - private const int Player = 0x108; + private const int Player = 0x108; - public override int PersonalId => Player + 0xAF98; - public override int EventFlagsPlayer => Player + 0xAFD0; + public override int PersonalId => Player + 0xAF98; + public override int EventFlagsPlayer => Player + 0xAFD0; - private const int GSaveLifeSupport = Player + 0xBFD0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFD0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x11478; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x11478; - public override int ProfileMain => Player + 0x11488; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23040; - public override int ProfileFruit => ProfileMain + 0x23044; - public override int ProfileTimestamp => ProfileMain + 0x230B4; - public override int ProfileIsMakeVillage => ProfileMain + 0x230B8; + public override int ProfileMain => Player + 0x11488; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23040; + public override int ProfileFruit => ProfileMain + 0x23044; + public override int ProfileTimestamp => ProfileMain + 0x230B4; + public override int ProfileIsMakeVillage => ProfileMain + 0x230B8; - // end player + // end player - private const int PlayerOther = 0x35BD0; + private const int PlayerOther = 0x35BD0; - public override int Pockets1 => PlayerOther + 0x4; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x180; - public override int ItemCollectBit => PlayerOther + 0xA04C; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7A0; - public override int Manpu => PlayerOther + 0xAF70; - public override int Bank => PlayerOther + 0x33014; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x4; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x180; + public override int ItemCollectBit => PlayerOther + 0xA04C; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7A0; + public override int Manpu => PlayerOther + 0xAF70; + public override int Bank => PlayerOther + 0x33014; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x2A0; - public override int MaxRemakeBitFlag => 0x754 * 32; + public override int MaxRecipeID => 0x2A0; + public override int MaxRemakeBitFlag => 0x754 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets11.cs b/NHSE.Core/Save/Offsets/PersonalOffsets11.cs index da1b04c..f9db77c 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets11.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets11.cs @@ -1,47 +1,48 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public sealed class PersonalOffsets11 : PersonalOffsets { - /// - /// - /// - public sealed class PersonalOffsets11 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x11488; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x11488; - public override int ProfileMain => Player + 0x114A0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x114A0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x35C10; + private const int PlayerOther = 0x35C10; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x33024; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x33024; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x2C8; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x2C8; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets110.cs b/NHSE.Core/Save/Offsets/PersonalOffsets110.cs index 57c2204..2cf666e 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets110.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets110.cs @@ -1,48 +1,49 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +/// Same as . +public sealed class PersonalOffsets110 : PersonalOffsets { - /// - /// - /// - /// Same as . - public sealed class PersonalOffsets110 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1228c; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1228c; - public override int ProfileMain => Player + 0x122a0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x122a0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x36a50; + private const int PlayerOther = 0x36a50; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x22594; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x22594; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x308; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x308; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets111.cs b/NHSE.Core/Save/Offsets/PersonalOffsets111.cs index 76a1844..1707fd0 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets111.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets111.cs @@ -1,48 +1,49 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +/// Same as . +public sealed class PersonalOffsets111 : PersonalOffsets { - /// - /// - /// - /// Same as . - public sealed class PersonalOffsets111 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1228c; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1228c; - public override int ProfileMain => Player + 0x122a0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x122a0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x36a50; + private const int PlayerOther = 0x36a50; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x22594; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x22594; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x3D6; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x3D6; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu); - } + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data[Manpu..]); } \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets12.cs b/NHSE.Core/Save/Offsets/PersonalOffsets12.cs index 8fbf6cd..04f6691 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets12.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets12.cs @@ -1,47 +1,48 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public sealed class PersonalOffsets12 : PersonalOffsets { - /// - /// - /// - public sealed class PersonalOffsets12 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1168C; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1168C; - public override int ProfileMain => Player + 0x116A0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x116A0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x35E40; + private const int PlayerOther = 0x35E40; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x345E4; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x345E4; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x2DA; // mermaid stuff - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x2DA; // mermaid stuff + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets13.cs b/NHSE.Core/Save/Offsets/PersonalOffsets13.cs index f566ebf..d34e1d0 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets13.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets13.cs @@ -1,47 +1,48 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public sealed class PersonalOffsets13 : PersonalOffsets { - /// - /// - /// - public sealed class PersonalOffsets13 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1168C; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1168C; - public override int ProfileMain => Player + 0x116A0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x116A0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x35E40; + private const int PlayerOther = 0x35E40; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x345E4; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x345E4; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x2DA; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x2DA; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets14.cs b/NHSE.Core/Save/Offsets/PersonalOffsets14.cs index a4fb2c6..df61690 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets14.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets14.cs @@ -1,47 +1,48 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public sealed class PersonalOffsets14 : PersonalOffsets { - /// - /// - /// - public sealed class PersonalOffsets14 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1168C; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1168C; - public override int ProfileMain => Player + 0x116A0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x116A0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x35E40; + private const int PlayerOther = 0x35E40; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x350C4; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x350C4; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x2DA; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x2DA; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets15.cs b/NHSE.Core/Save/Offsets/PersonalOffsets15.cs index dc2bd37..908f964 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets15.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets15.cs @@ -1,47 +1,48 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public sealed class PersonalOffsets15 : PersonalOffsets { - /// - /// - /// - public sealed class PersonalOffsets15 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1228c; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1228c; - public override int ProfileMain => Player + 0x122a0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x122a0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x36a50; + private const int PlayerOther = 0x36a50; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x35244; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x35244; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x2E1; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x2E1; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets16.cs b/NHSE.Core/Save/Offsets/PersonalOffsets16.cs index 0c75901..e29532a 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets16.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets16.cs @@ -1,47 +1,48 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public sealed class PersonalOffsets16 : PersonalOffsets { - /// - /// - /// - public sealed class PersonalOffsets16 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1228c; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1228c; - public override int ProfileMain => Player + 0x122a0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x122a0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x36a50; + private const int PlayerOther = 0x36a50; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x35244; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x35244; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x2E1; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x2E1; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets17.cs b/NHSE.Core/Save/Offsets/PersonalOffsets17.cs index ec92269..dea5629 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets17.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets17.cs @@ -1,47 +1,48 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public sealed class PersonalOffsets17 : PersonalOffsets { - /// - /// - /// - public sealed class PersonalOffsets17 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1228c; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1228c; - public override int ProfileMain => Player + 0x122a0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x122a0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x36a50; + private const int PlayerOther = 0x36a50; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x22594; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x22594; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x308; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x308; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets18.cs b/NHSE.Core/Save/Offsets/PersonalOffsets18.cs index 022f893..bb5a27f 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets18.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets18.cs @@ -1,48 +1,49 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +/// Same as . +public sealed class PersonalOffsets18 : PersonalOffsets { - /// - /// - /// - /// Same as . - public sealed class PersonalOffsets18 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1228c; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1228c; - public override int ProfileMain => Player + 0x122a0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x122a0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x36a50; + private const int PlayerOther = 0x36a50; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x22594; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x22594; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x308; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x308; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets19.cs b/NHSE.Core/Save/Offsets/PersonalOffsets19.cs index a37f8e2..607f34f 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets19.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets19.cs @@ -1,48 +1,49 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +/// Same as . +public sealed class PersonalOffsets19 : PersonalOffsets { - /// - /// - /// - /// Same as . - public sealed class PersonalOffsets19 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1228c; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1228c; - public override int ProfileMain => Player + 0x122a0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x122a0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x36a50; + private const int PlayerOther = 0x36a50; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x22594; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x22594; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x308; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x308; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/PersonalOffsets20.cs b/NHSE.Core/Save/Offsets/PersonalOffsets20.cs index 236c85e..95434af 100644 --- a/NHSE.Core/Save/Offsets/PersonalOffsets20.cs +++ b/NHSE.Core/Save/Offsets/PersonalOffsets20.cs @@ -1,47 +1,48 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// +/// +public sealed class PersonalOffsets20 : PersonalOffsets { - /// - /// - /// - public sealed class PersonalOffsets20 : PersonalOffsets - { - private const int Player = 0x110; + private const int Player = 0x110; - public override int PersonalId => Player + 0xAFA8; - public override int EventFlagsPlayer => Player + 0xAFE0; + public override int PersonalId => Player + 0xAFA8; + public override int EventFlagsPlayer => Player + 0xAFE0; - private const int GSaveLifeSupport = Player + 0xBFE0; - public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement + private const int GSaveLifeSupport = Player + 0xBFE0; + public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement - public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles - public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned - public override int Birthday => Player + 0x1228c; + public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles + public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned + public override int Birthday => Player + 0x1228c; - public override int ProfileMain => Player + 0x122a0; - public override int ProfilePhoto => ProfileMain + 0x14; - public override int ProfileBirthday => ProfileMain + 0x23058; - public override int ProfileFruit => ProfileMain + 0x2305C; - public override int ProfileTimestamp => ProfileMain + 0x230CC; - public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; + public override int ProfileMain => Player + 0x122a0; + public override int ProfilePhoto => ProfileMain + 0x14; + public override int ProfileBirthday => ProfileMain + 0x23058; + public override int ProfileFruit => ProfileMain + 0x2305C; + public override int ProfileTimestamp => ProfileMain + 0x230CC; + public override int ProfileIsMakeVillage => ProfileMain + 0x230D0; - // end player + // end player - private const int PlayerOther = 0x36a50; + private const int PlayerOther = 0x36a50; - public override int Pockets1 => PlayerOther + 0x10; - public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; - public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; - public override int ItemChest => PlayerOther + 0x18C; - public override int ItemCollectBit => PlayerOther + 0xA058; - public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; - public override int Manpu => PlayerOther + 0xAF7C; - public override int Bank => PlayerOther + 0x24afc; - public override int Recipes => Bank + 0x10; + public override int Pockets1 => PlayerOther + 0x10; + public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18; + public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18; + public override int ItemChest => PlayerOther + 0x18C; + public override int ItemCollectBit => PlayerOther + 0xA058; + public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC; + public override int Manpu => PlayerOther + 0xAF7C; + public override int Bank => PlayerOther + 0x24afc; + public override int Recipes => Bank + 0x10; - public override int MaxRecipeID => 0x430; - public override int MaxRemakeBitFlag => 0x7D0 * 32; + public override int MaxRecipeID => 0x430; + public override int MaxRemakeBitFlag => 0x7D0 * 32; - public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); - public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu); - } -} + public override IReactionStore ReadReactions(ReadOnlySpan data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure(); + public override void SetReactions(Span data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data[Manpu..]); +} \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/WhereAreNOffsets.cs b/NHSE.Core/Save/Offsets/WhereAreNOffsets.cs index af7dd57..1919dca 100644 --- a/NHSE.Core/Save/Offsets/WhereAreNOffsets.cs +++ b/NHSE.Core/Save/Offsets/WhereAreNOffsets.cs @@ -1,30 +1,29 @@ using System; -namespace NHSE.Core -{ - /// - /// Offset info and object retrieval logic for - /// - public abstract class WhereAreNOffsets - { - public abstract int Poki { get; } +namespace NHSE.Core; - public static WhereAreNOffsets GetOffsets(FileHeaderInfo Info) +/// +/// Offset info and object retrieval logic for +/// +public abstract class WhereAreNOffsets +{ + public abstract int Poki { get; } + + public static WhereAreNOffsets GetOffsets(FileHeaderInfo Info) + { + var rev = Info.GetKnownRevisionIndex(); + return rev switch { - var rev = Info.GetKnownRevisionIndex(); - return rev switch - { - 22 => new WhereAreNOffsets20(), - 23 => new WhereAreNOffsets20(), - 24 => new WhereAreNOffsets20(), - 25 => new WhereAreNOffsets20(), - 26 => new WhereAreNOffsets20(), - 27 => new WhereAreNOffsets20(), - 28 => new WhereAreNOffsets20(), - 29 => new WhereAreNOffsets20(), - 30 => new WhereAreNOffsets20(), - _ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info), - }; - } + 22 => new WhereAreNOffsets20(), + 23 => new WhereAreNOffsets20(), + 24 => new WhereAreNOffsets20(), + 25 => new WhereAreNOffsets20(), + 26 => new WhereAreNOffsets20(), + 27 => new WhereAreNOffsets20(), + 28 => new WhereAreNOffsets20(), + 29 => new WhereAreNOffsets20(), + 30 => new WhereAreNOffsets20(), + _ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info), + }; } } \ No newline at end of file diff --git a/NHSE.Core/Save/Offsets/WhereAreNOffsets20.cs b/NHSE.Core/Save/Offsets/WhereAreNOffsets20.cs index 90cc233..e170811 100644 --- a/NHSE.Core/Save/Offsets/WhereAreNOffsets20.cs +++ b/NHSE.Core/Save/Offsets/WhereAreNOffsets20.cs @@ -1,10 +1,9 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// +/// +public sealed class WhereAreNOffsets20 : WhereAreNOffsets { - /// - /// - /// - public sealed class WhereAreNOffsets20 : WhereAreNOffsets - { - public override int Poki => 0xB84228; - } -} + public override int Poki => 0xB84228; +} \ No newline at end of file diff --git a/NHSE.Core/Strings/GameInfo.cs b/NHSE.Core/Strings/GameInfo.cs index cd33d17..ffb0702 100644 --- a/NHSE.Core/Strings/GameInfo.cs +++ b/NHSE.Core/Strings/GameInfo.cs @@ -1,36 +1,35 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Global repository for game strings; initialized to a specified language. +/// +public static class GameInfo { + private static readonly GameStrings?[] Languages = new GameStrings[GameLanguage.LanguageCount]; + + public static string CurrentLanguage { get; private set; } = GameLanguage.DefaultLanguage; + public static GameStrings Strings { get; private set; } = GetStrings(CurrentLanguage); + /// - /// Global repository for game strings; initialized to a specified language. + /// Gets the Game Strings for a specific language. /// - public static class GameInfo + /// 2 character language ID + public static GameStrings GetStrings(string lang) { - private static readonly GameStrings?[] Languages = new GameStrings[GameLanguage.LanguageCount]; - - public static string CurrentLanguage { get; private set; } = GameLanguage.DefaultLanguage; - public static GameStrings Strings { get; private set; } = GetStrings(CurrentLanguage); - - /// - /// Gets the Game Strings for a specific language. - /// - /// 2 character language ID - public static GameStrings GetStrings(string lang) - { - int index = GameLanguage.GetLanguageIndex(lang); - return GetStrings(index); - } - - public static GameStrings GetStrings(int index) - { - return Languages[index] ??= new GameStrings(GameLanguage.Language2Char(index)); - } - - public static string SetLanguage2Char(int index) - { - var lang = GameLanguage.Language2Char(index); - CurrentLanguage = lang; - Strings = GetStrings(lang); - return lang; - } + int index = GameLanguage.GetLanguageIndex(lang); + return GetStrings(index); } -} + + public static GameStrings GetStrings(int index) + { + return Languages[index] ??= new GameStrings(GameLanguage.Language2Char(index)); + } + + public static string SetLanguage2Char(int index) + { + var lang = GameLanguage.Language2Char(index); + CurrentLanguage = lang; + Strings = GetStrings(lang); + return lang; + } +} \ No newline at end of file diff --git a/NHSE.Core/Strings/GameLanguage.cs b/NHSE.Core/Strings/GameLanguage.cs index ad45b03..431cfc4 100644 --- a/NHSE.Core/Strings/GameLanguage.cs +++ b/NHSE.Core/Strings/GameLanguage.cs @@ -1,36 +1,35 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Metadata for dealing with language codes +/// +public static class GameLanguage { - /// - /// Metadata for dealing with language codes - /// - public static class GameLanguage + public const string DefaultLanguage = "en"; // English + public static int DefaultLanguageIndex => Array.IndexOf(LanguageCodes, DefaultLanguage); + public static string Language2Char(int lang) => lang > LanguageCodes.Length ? DefaultLanguage : LanguageCodes[lang]; + + public static int LanguageCount => LanguageCodes.Length; + + public static int GetLanguageIndex(string lang) { - public const string DefaultLanguage = "en"; // English - public static int DefaultLanguageIndex => Array.IndexOf(LanguageCodes, DefaultLanguage); - public static string Language2Char(int lang) => lang > LanguageCodes.Length ? DefaultLanguage : LanguageCodes[lang]; + int l = Array.IndexOf(LanguageCodes, lang); + return l < 0 ? DefaultLanguageIndex : l; + } - public static int LanguageCount => LanguageCodes.Length; + /// + /// Language codes supported for loading string resources + /// + private static readonly string[] LanguageCodes = ["en", "jp", "de", "es", "fr", "it", "ko", "zhs", "zht"]; - public static int GetLanguageIndex(string lang) - { - int l = Array.IndexOf(LanguageCodes, lang); - return l < 0 ? DefaultLanguageIndex : l; - } + public static string[] GetStrings(string ident, string lang, string type = "text") + { + string[] data = ResourceUtil.GetStringList(ident, lang, type); + if (data.Length == 0) + data = ResourceUtil.GetStringList(ident, DefaultLanguage, type); - /// - /// Language codes supported for loading string resources - /// - private static readonly string[] LanguageCodes = { "en", "jp", "de", "es", "fr", "it", "ko", "zhs", "zht" }; - - public static string[] GetStrings(string ident, string lang, string type = "text") - { - string[] data = ResourceUtil.GetStringList(ident, lang, type); - if (data.Length == 0) - data = ResourceUtil.GetStringList(ident, DefaultLanguage, type); - - return data; - } + return data; } } \ No newline at end of file diff --git a/NHSE.Core/Strings/GameStrings.cs b/NHSE.Core/Strings/GameStrings.cs index df4a07d..0014ea0 100644 --- a/NHSE.Core/Strings/GameStrings.cs +++ b/NHSE.Core/Strings/GameStrings.cs @@ -1,255 +1,246 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Stores game localization strings for use by logic. +/// +public sealed class GameStrings : IRemakeString { - /// - /// Stores game localization strings for use by logic. - /// - public sealed class GameStrings : IRemakeString + private readonly string lang; + + public readonly string[] villagers; + public readonly string[] itemlist; + public readonly string[] itemlistdisplay; + public readonly string[] villagerDefaultPhrases; + public readonly Dictionary VillagerMap; + public readonly Dictionary VillagerDefaultPhraseMap; + public readonly List ItemDataSource; + public readonly Dictionary InternalNameTranslation = []; + + public IReadOnlyDictionary BodyParts { get; } + public IReadOnlyDictionary BodyColor { get; } + public IReadOnlyDictionary FabricParts { get; } + public IReadOnlyDictionary FabricColor { get; } + + private string[] Get(string ident) => GameLanguage.GetStrings(ident, lang); + + public GameStrings(string l) { - private readonly string lang; + lang = l; + villagers = Get("villager"); + VillagerMap = GetMap(villagers); + villagerDefaultPhrases = Get("phrase"); + VillagerDefaultPhraseMap = GetMap(villagerDefaultPhrases); + itemlist = Get("item"); + itemlistdisplay = GetItemDisplayList(itemlist); + ItemDataSource = CreateItemDataSource(itemlistdisplay); - public readonly string[] villagers; - public readonly string[] itemlist; - public readonly string[] itemlistdisplay; - public readonly string[] villagerDefaultPhrases; - public readonly Dictionary VillagerMap; - public readonly Dictionary VillagerDefaultPhraseMap; - public readonly List ItemDataSource; - public readonly Dictionary InternalNameTranslation = new(); - - public IReadOnlyDictionary BodyParts { get; } - public IReadOnlyDictionary BodyColor { get; } - public IReadOnlyDictionary FabricParts { get; } - public IReadOnlyDictionary FabricColor { get; } - - private string[] Get(string ident) => GameLanguage.GetStrings(ident, lang); - - public GameStrings(string l) - { - lang = l; - villagers = Get("villager"); - VillagerMap = GetMap(villagers); - villagerDefaultPhrases = Get("phrase"); - VillagerDefaultPhraseMap = GetMap(villagerDefaultPhrases); - itemlist = Get("item"); - itemlistdisplay = GetItemDisplayList(itemlist); - ItemDataSource = CreateItemDataSource(itemlistdisplay); - - BodyParts = GetDictionary(Get("body_parts")); - BodyColor = GetDictionary(Get("body_color")); - FabricParts = GetDictionary(Get("fabric_parts")); - FabricColor = GetDictionary(Get("fabric_color")); - } - - private static IReadOnlyDictionary GetDictionary(IEnumerable lines, char split = '\t') - { - var result = new Dictionary(); - foreach (var s in lines) - { - if (s.Length == 0) - continue; - var index = s.IndexOf(split); - var key = s.Substring(0, index); - var value = s.Substring(index + 1); - result.Add(key, value); - } - return result; - } - - private List CreateItemDataSource(string[] strings) - { - var dataSource = ComboItemUtil.GetArray(strings); - - // load special - dataSource.Add(new ComboItem(itemlist[0], Item.NONE)); - dataSource.SortByText(); - - return dataSource; - } - - public List CreateItemDataSource(IReadOnlyCollection dict, bool none = true) - { - var display = itemlistdisplay; - var result = new List(dict.Count); - foreach (var x in dict) - result.Add(new ComboItem(display[x], x)); - - if (none) - result.Add(new ComboItem(itemlist[0], Item.NONE)); - - result.SortByText(); - return result; - } - - public List CreateItemDataSource(IReadOnlyCollection> dict, bool none = true) - { - var display = itemlistdisplay; - var result = new List(dict.Count); - foreach (var x in dict) - result.Add(new ComboItem(display[x.Value], x.Key)); - - if (none) - result.Add(new ComboItem(itemlist[0], Item.NONE)); - - result.SortByText(); - return result; - } - - private static Dictionary GetMap(IReadOnlyCollection arr) - { - var map = new Dictionary(arr.Count); - foreach (var kvp in arr) - { - var index = kvp.IndexOf('\t'); - if (index < 0) - continue; - var abbrev = kvp.Substring(0, index); - var name = kvp.Substring(index + 1); - map.Add(abbrev, name); - } - return map; - } - - public string GetVillager(string name) - { - return VillagerMap.TryGetValue(name, out var result) ? result : name; - } - - public string GetVillagerDefaultPhrase(string name) - { - return VillagerDefaultPhraseMap.TryGetValue(name, out var result) ? result : name; // I know it shouldn't be name but I have to return something - } - - public static string[] GetItemDisplayList(string[] items) - { - items = (string[])items.Clone(); - items[0] = string.Empty; - var set = new HashSet(); - for (int i = 0; i < items.Length; i++) - { - var item = items[i]; - if (string.IsNullOrEmpty(item)) - items[i] = $"(Item #{i:000})"; - else if (set.Contains(item)) - items[i] += $" (#{i:000})"; - else - set.Add(item); - } - return items; - } - - public string GetItemName(Item item) - { - var index = item.ItemId; - if (index == Item.NONE) - return itemlist[0]; - if (index == Item.EXTENSION) - return GetItemName(item.ExtensionItemId); - - var kind = ItemInfo.GetItemKind(index); - - if (kind.IsFlowerGene(index)) - { - var display = GetItemName(index); - if (item.Genes != 0) - return $"{display} - {item.Genes}"; - } - - if (kind == ItemKind.Kind_DIYRecipe || kind == ItemKind.Kind_MessageBottle) - { - var display = itemlistdisplay[index]; - var recipeID = (ushort)item.FreeParam; - var isKnown = RecipeList.Recipes.TryGetValue(recipeID, out var result); - var makes = isKnown ? GetItemName(result) : recipeID.ToString("000"); - return $"{display} - {makes}"; - } - - if (kind == ItemKind.Kind_FossilUnknown) - { - var display = itemlistdisplay[index]; - var fossilID = (ushort)item.FreeParam; - var fossilName = GetItemName(fossilID); - return $"{display} - {fossilName}"; - } - - if (kind == ItemKind.Kind_Tree) - { - var display = GetItemName(index); - var willDrop = item.Count; - if (willDrop != 0) - { - var dropName = GetItemName(willDrop); - return $"{display} - {dropName}"; - } - } - - return GetItemName(index); - } - - public string GetItemName(ushort index) - { - if (index >= itemlistdisplay.Length) - return GetItemName60000(index); - return itemlistdisplay[index]; - } - - private static string GetItemName60000(ushort index) - { - if (FieldItemList.Items.TryGetValue(index, out var val)) - return val.Name; - - // 63,000 ??? - if (index == Item.LLOYD) - return "Lloyd"; - - return "???"; - } - - /// - /// Returns clothing or item recolors not a part of ItemRemake with brackets in their names - /// - /// ItemID of the color variation search - /// Item name without the associated recolors - /// Map of ItemID, ItemName - public List GetAssociatedItems(ushort id, out string baseItemName) - { - baseItemName = string.Empty; - var stringMatch = GetItemName(id); - var index = stringMatch.IndexOf('('); - if (index < 0) - return new List(); - - var search = baseItemName = stringMatch.Substring(0, index); - if (!string.IsNullOrWhiteSpace(search)) - return ItemDataSource.FindAll(x => x.Text.StartsWith(search)); - else - return new List(); - } - - public bool HasAssociatedItems(string baseName, out List? items) - { - if (string.IsNullOrWhiteSpace(baseName)) - { - items = null; - return false; - } - - baseName = baseName.Trim().ToLower(); - if (!baseName.EndsWith(" ")) - baseName += " "; - baseName += "("; - - items = ItemDataSource.FindAll(x => x.Text.ToLower().StartsWith(baseName)); - return items.Count > 0; - } + BodyParts = GetDictionary(Get("body_parts")); + BodyColor = GetDictionary(Get("body_color")); + FabricParts = GetDictionary(Get("fabric_parts")); + FabricColor = GetDictionary(Get("fabric_color")); } - public interface IRemakeString + private static Dictionary GetDictionary(ReadOnlySpan lines, char split = '\t') { - IReadOnlyDictionary BodyParts { get; } - IReadOnlyDictionary BodyColor { get; } - IReadOnlyDictionary FabricParts { get; } - IReadOnlyDictionary FabricColor { get; } + var result = new Dictionary(); + foreach (var s in lines) + { + if (s.Length == 0) + continue; + var index = s.IndexOf(split); + var key = s[..index]; + var value = s[(index + 1)..]; + result.Add(key, value); + } + return result; + } + + private List CreateItemDataSource(ReadOnlySpan strings) + { + var dataSource = ComboItemUtil.GetArray(strings); + + // load special + dataSource.Add(new ComboItem(itemlist[0], Item.NONE)); + dataSource.SortByText(); + + return dataSource; + } + + public List CreateItemDataSource(ReadOnlySpan dict, bool none = true) + { + var display = itemlistdisplay; + var result = new List(dict.Length); + foreach (var x in dict) + result.Add(new ComboItem(display[x], x)); + + if (none) + result.Add(new ComboItem(itemlist[0], Item.NONE)); + + result.SortByText(); + return result; + } + + public List CreateItemDataSource(IReadOnlyCollection> dict, bool none = true) + { + var display = itemlistdisplay; + var result = new List(dict.Count); + foreach (var x in dict) + result.Add(new ComboItem(display[x.Value], x.Key)); + + if (none) + result.Add(new ComboItem(itemlist[0], Item.NONE)); + + result.SortByText(); + return result; + } + + private static Dictionary GetMap(ReadOnlySpan arr) + { + var map = new Dictionary(arr.Length); + foreach (var kvp in arr) + { + var index = kvp.IndexOf('\t'); + if (index < 0) + continue; + var abbrev = kvp[..index]; + var name = kvp[(index + 1)..]; + map.Add(abbrev, name); + } + return map; + } + + public string GetVillager(string name) => VillagerMap.GetValueOrDefault(name, name); + + public string GetVillagerDefaultPhrase(string name) => VillagerDefaultPhraseMap.GetValueOrDefault(name, name); // I know it shouldn't be `name` but I have to return something + + public static string[] GetItemDisplayList(ReadOnlySpan arr) + { + var items = arr.ToArray(); + items[0] = string.Empty; + var set = new HashSet(); + for (int i = 0; i < items.Length; i++) + { + var item = items[i]; + if (string.IsNullOrEmpty(item)) + items[i] = $"(Item #{i:000})"; + else if (!set.Add(item)) + items[i] += $" (#{i:000})"; + } + return items; + } + + public string GetItemName(Item item) + { + var index = item.ItemId; + if (index == Item.NONE) + return itemlist[0]; + if (index == Item.EXTENSION) + return GetItemName(item.ExtensionItemId); + + var kind = ItemInfo.GetItemKind(index); + + if (kind.IsFlowerGene(index)) + { + var display = GetItemName(index); + if (item.Genes != 0) + return $"{display} - {item.Genes}"; + } + + if (kind is ItemKind.Kind_DIYRecipe or ItemKind.Kind_MessageBottle) + { + var display = itemlistdisplay[index]; + var recipeID = (ushort)item.FreeParam; + var isKnown = RecipeList.Recipes.TryGetValue(recipeID, out var result); + var makes = isKnown ? GetItemName(result) : recipeID.ToString("000"); + return $"{display} - {makes}"; + } + + if (kind == ItemKind.Kind_FossilUnknown) + { + var display = itemlistdisplay[index]; + var fossilID = (ushort)item.FreeParam; + var fossilName = GetItemName(fossilID); + return $"{display} - {fossilName}"; + } + + if (kind == ItemKind.Kind_Tree) + { + var display = GetItemName(index); + var willDrop = item.Count; + if (willDrop != 0) + { + var dropName = GetItemName(willDrop); + return $"{display} - {dropName}"; + } + } + + return GetItemName(index); + } + + public string GetItemName(ushort index) + { + if (index >= itemlistdisplay.Length) + return GetItemName60000(index); + return itemlistdisplay[index]; + } + + private static string GetItemName60000(ushort index) + { + if (FieldItemList.Items.TryGetValue(index, out var val)) + return val.Name; + + // 63,000 ??? + if (index == Item.LLOYD) + return "Lloyd"; + + return "???"; + } + + /// + /// Returns clothing or item recolors not a part of ItemRemake with brackets in their names + /// + /// ItemID of the color variation search + /// Item name without the associated recolors + /// Map of ItemID, ItemName + public List GetAssociatedItems(ushort id, out string baseItemName) + { + baseItemName = string.Empty; + var stringMatch = GetItemName(id); + var index = stringMatch.IndexOf('('); + if (index < 0) + return []; + + var search = baseItemName = stringMatch[..index]; + if (!string.IsNullOrWhiteSpace(search)) + return ItemDataSource.FindAll(x => x.Text.StartsWith(search)); + return []; + } + + public bool HasAssociatedItems(string baseName, out List? items) + { + if (string.IsNullOrWhiteSpace(baseName)) + { + items = null; + return false; + } + + baseName = baseName.Trim().ToLower(); + if (!baseName.EndsWith(' ')) + baseName += " "; + baseName += "("; + + items = ItemDataSource.FindAll(x => x.Text.StartsWith(baseName, StringComparison.CurrentCultureIgnoreCase)); + return items.Count > 0; } } + +public interface IRemakeString +{ + IReadOnlyDictionary BodyParts { get; } + IReadOnlyDictionary BodyColor { get; } + IReadOnlyDictionary FabricParts { get; } + IReadOnlyDictionary FabricColor { get; } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/BridgeMaterial.cs b/NHSE.Core/Structures/Building/BridgeMaterial.cs index d8e3fc2..782793f 100644 --- a/NHSE.Core/Structures/Building/BridgeMaterial.cs +++ b/NHSE.Core/Structures/Building/BridgeMaterial.cs @@ -1,18 +1,17 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Material used for a construction (footstep sounds?). +/// +public enum BridgeMaterial : byte { - /// - /// Material used for a construction (footstep sounds?). - /// - public enum BridgeMaterial : byte - { - BridgeStone = 0x00, - BridgeSuspension = 0x01, - BridgeJapanese = 0x02, - BridgeLog = 0x04, - BridgeRed = 0x05, - BridgeIron = 0x06, - BridgeReserved = 0x07, - BridgeWood = 0x0A, - BridgeBricks = 0x0B, - } -} + BridgeStone = 0x00, + BridgeSuspension = 0x01, + BridgeJapanese = 0x02, + BridgeLog = 0x04, + BridgeRed = 0x05, + BridgeIron = 0x06, + BridgeReserved = 0x07, + BridgeWood = 0x0A, + BridgeBricks = 0x0B, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/BridgeType.cs b/NHSE.Core/Structures/Building/BridgeType.cs index d76e01c..7d06215 100644 --- a/NHSE.Core/Structures/Building/BridgeType.cs +++ b/NHSE.Core/Structures/Building/BridgeType.cs @@ -1,63 +1,62 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Bridge model +/// +public enum BridgeType : ushort { - /// - /// Bridge model - /// - public enum BridgeType : ushort - { - BridgeStone03 = 0x00, - BridgeStone04 = 0x01, - BridgeStone05 = 0x02, - BridgeStoneDiagonal025 = 0x03, - BridgeStoneDiagonal030 = 0x04, - BridgeStoneDiagonal035 = 0x05, - BridgeSuspension04 = 0x06, - BridgeSuspension03 = 0x07, - BridgeSuspension05 = 0x08, - BridgeSuspensionDiagonal025 = 0x09, - BridgeSuspensionDiagonal030 = 0x0A, - BridgeSuspensionDiagonal035 = 0x0B, - BridgeJapanese04 = 0x0C, - BridgeLog04 = 0x0D, - BridgeLog03 = 0x0E, - BridgeLog05 = 0x0F, - BridgeLogDiagonal025 = 0x10, - BridgeLogDiagonal030 = 0x11, - BridgeLogDiagonal035 = 0x12, - BridgeJapanese03 = 0x13, - BridgeJapanese05 = 0x14, - BridgeJapaneseDiagonal025 = 0x15, - BridgeJapaneseDiagonal030 = 0x16, - BridgeJapaneseDiagonal035 = 0x17, - BridgeRed04 = 0x18, - BridgeIron04 = 0x19, - BridgeReserved03 = 0x1A, - BridgeReserved04 = 0x1B, - BridgeReserved05 = 0x1C, - BridgeReservedDiagonal025 = 0x1D, - BridgeReservedDiagonal030 = 0x1E, - BridgeReservedDiagonal035 = 0x1F, - BridgeRed03 = 0x20, - BridgeRed05 = 0x21, - BridgeRedDiagonal025 = 0x22, - BridgeRedDiagonal030 = 0x23, - BridgeRedDiagonal035 = 0x24, - BridgeWood04 = 0x25, - BridgeBricks04 = 0x26, - BridgeIron03 = 0x27, - BridgeIron05 = 0x28, - BridgeIronDiagonal025 = 0x29, - BridgeIronDiagonal030 = 0x2A, - BridgeIronDiagonal035 = 0x2B, - BridgeWood03 = 0x2C, - BridgeWood05 = 0x2D, - BridgeWoodDiagonal025 = 0x2E, - BridgeWoodDiagonal030 = 0x2F, - BridgeWoodDiagonal035 = 0x30, - BridgeBricks03 = 0x31, - BridgeBricks05 = 0x34, - BridgeBricksDiagonal025 = 0x35, - BridgeBricksDiagonal030 = 0x36, - BridgeBricksDiagonal035 = 0x37, - } -} + BridgeStone03 = 0x00, + BridgeStone04 = 0x01, + BridgeStone05 = 0x02, + BridgeStoneDiagonal025 = 0x03, + BridgeStoneDiagonal030 = 0x04, + BridgeStoneDiagonal035 = 0x05, + BridgeSuspension04 = 0x06, + BridgeSuspension03 = 0x07, + BridgeSuspension05 = 0x08, + BridgeSuspensionDiagonal025 = 0x09, + BridgeSuspensionDiagonal030 = 0x0A, + BridgeSuspensionDiagonal035 = 0x0B, + BridgeJapanese04 = 0x0C, + BridgeLog04 = 0x0D, + BridgeLog03 = 0x0E, + BridgeLog05 = 0x0F, + BridgeLogDiagonal025 = 0x10, + BridgeLogDiagonal030 = 0x11, + BridgeLogDiagonal035 = 0x12, + BridgeJapanese03 = 0x13, + BridgeJapanese05 = 0x14, + BridgeJapaneseDiagonal025 = 0x15, + BridgeJapaneseDiagonal030 = 0x16, + BridgeJapaneseDiagonal035 = 0x17, + BridgeRed04 = 0x18, + BridgeIron04 = 0x19, + BridgeReserved03 = 0x1A, + BridgeReserved04 = 0x1B, + BridgeReserved05 = 0x1C, + BridgeReservedDiagonal025 = 0x1D, + BridgeReservedDiagonal030 = 0x1E, + BridgeReservedDiagonal035 = 0x1F, + BridgeRed03 = 0x20, + BridgeRed05 = 0x21, + BridgeRedDiagonal025 = 0x22, + BridgeRedDiagonal030 = 0x23, + BridgeRedDiagonal035 = 0x24, + BridgeWood04 = 0x25, + BridgeBricks04 = 0x26, + BridgeIron03 = 0x27, + BridgeIron05 = 0x28, + BridgeIronDiagonal025 = 0x29, + BridgeIronDiagonal030 = 0x2A, + BridgeIronDiagonal035 = 0x2B, + BridgeWood03 = 0x2C, + BridgeWood05 = 0x2D, + BridgeWoodDiagonal025 = 0x2E, + BridgeWoodDiagonal030 = 0x2F, + BridgeWoodDiagonal035 = 0x30, + BridgeBricks03 = 0x31, + BridgeBricks05 = 0x34, + BridgeBricksDiagonal025 = 0x35, + BridgeBricksDiagonal030 = 0x36, + BridgeBricksDiagonal035 = 0x37, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/Building.cs b/NHSE.Core/Structures/Building/Building.cs index 13bb33a..92b4e16 100644 --- a/NHSE.Core/Structures/Building/Building.cs +++ b/NHSE.Core/Structures/Building/Building.cs @@ -1,54 +1,54 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Interact-able structure that can be entered by the player. +/// +[StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] +public class Building { - /// - /// Interact-able structure that can be entered by the player. - /// - [StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] - public class Building + public const int SIZE = 0x14; + + [field: FieldOffset(0x00)] public BuildingType BuildingType { get; set; } + [field: FieldOffset(0x02)] public ushort X { get; set; } + [field: FieldOffset(0x04)] public ushort Y { get; set; } + + [field: FieldOffset(0x06)] public byte Angle { get; set; } + [field: FieldOffset(0x07)] public sbyte Bit { get; set; } + + [field: FieldOffset(0x08)] public ushort Type { get; set; } + [field: FieldOffset(0x0A)] public byte TypeArg { get; set; } + + [field: FieldOffset(0x0C)] public ushort UniqueID { get; set; } + [field: FieldOffset(0x10)] public uint Unused { get; set; } + + public void Clear() { - public const int SIZE = 0x14; - - [field: FieldOffset(0x00)] public BuildingType BuildingType { get; set; } - [field: FieldOffset(0x02)] public ushort X { get; set; } - [field: FieldOffset(0x04)] public ushort Y { get; set; } - - [field: FieldOffset(0x06)] public byte Angle { get; set; } - [field: FieldOffset(0x07)] public sbyte Bit { get; set; } - - [field: FieldOffset(0x08)] public ushort Type { get; set; } - [field: FieldOffset(0x0A)] public byte TypeArg { get; set; } - - [field: FieldOffset(0x0C)] public ushort UniqueID { get; set; } - [field: FieldOffset(0x10)] public uint Unused { get; set; } - - public void Clear() - { - BuildingType = 0; - X = Y = Angle = 0; - Bit = 0; - Type = TypeArg = 0; - UniqueID = 0; - Unused = 0; - } - - public void CopyFrom(Building building) - { - BuildingType = building.BuildingType; - X = building.X; - Y = building.Y; - Angle = building.Angle; - Bit = building.Bit; - Type = building.Type; - TypeArg = building.TypeArg; - UniqueID = building.UniqueID; - Unused = building.Unused; - } - - public static Building[] GetArray(byte[] data) => data.GetArray(SIZE); - public static byte[] SetArray(IReadOnlyList data) => data.SetArray(SIZE); - public override string ToString() => $"{X:000},{Y:000} - {BuildingType}"; + BuildingType = 0; + X = Y = Angle = 0; + Bit = 0; + Type = TypeArg = 0; + UniqueID = 0; + Unused = 0; } -} + + public void CopyFrom(Building building) + { + BuildingType = building.BuildingType; + X = building.X; + Y = building.Y; + Angle = building.Angle; + Bit = building.Bit; + Type = building.Type; + TypeArg = building.TypeArg; + UniqueID = building.UniqueID; + Unused = building.Unused; + } + + public static Building[] GetArray(ReadOnlySpan data) => data.GetArray(SIZE); + public static byte[] SetArray(IReadOnlyList data) => data.SetArray(SIZE); + public override string ToString() => $"{X:000},{Y:000} - {BuildingType}"; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/BuildingType.cs b/NHSE.Core/Structures/Building/BuildingType.cs index 8c0ef12..6618d65 100644 --- a/NHSE.Core/Structures/Building/BuildingType.cs +++ b/NHSE.Core/Structures/Building/BuildingType.cs @@ -1,39 +1,38 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Building model & interior that is loaded when the is entered. +/// +public enum BuildingType : ushort { - /// - /// Building model & interior that is loaded when the is entered. - /// - public enum BuildingType : ushort - { - None = 0, - PlayerHouse1 = 1, - PlayerHouse2 = 2, - PlayerHouse3 = 3, - PlayerHouse4 = 4, - PlayerHouse5 = 5, - PlayerHouse6 = 6, - PlayerHouse7 = 7, - PlayerHouse8 = 8, - Villager1 = 9, - Villager2 = 10, - Villager3 = 11, - Villager4 = 12, - Villager5 = 13, - Villager6 = 14, - Villager7 = 15, - Villager8 = 16, - Villager9 = 17, - Villager10 = 18, - NooksCranny = 19, - ResidentCenterStructure = 20, - Museum = 21, - Airport = 22, - ResidentCenterTent = 23, - AblesSisters = 24, - Campsite = 25, - Bridge = 26, - Incline = 27, - ReddsTreasureTrawler = 28, - Studio = 29, - } -} + None = 0, + PlayerHouse1 = 1, + PlayerHouse2 = 2, + PlayerHouse3 = 3, + PlayerHouse4 = 4, + PlayerHouse5 = 5, + PlayerHouse6 = 6, + PlayerHouse7 = 7, + PlayerHouse8 = 8, + Villager1 = 9, + Villager2 = 10, + Villager3 = 11, + Villager4 = 12, + Villager5 = 13, + Villager6 = 14, + Villager7 = 15, + Villager8 = 16, + Villager9 = 17, + Villager10 = 18, + NooksCranny = 19, + ResidentCenterStructure = 20, + Museum = 21, + Airport = 22, + ResidentCenterTent = 23, + AblesSisters = 24, + Campsite = 25, + Bridge = 26, + Incline = 27, + ReddsTreasureTrawler = 28, + Studio = 29, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/DoorKind.cs b/NHSE.Core/Structures/Building/DoorKind.cs index b62817d..fea5dcb 100644 --- a/NHSE.Core/Structures/Building/DoorKind.cs +++ b/NHSE.Core/Structures/Building/DoorKind.cs @@ -1,262 +1,261 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Door model for a house. +/// +public enum DoorKind : ushort { - /// - /// Door model for a house. - /// - public enum DoorKind : ushort - { - HouseDoorStandardAR = 0x00, - HouseDoorStandardAS = 0x02, - HouseDoorIronAS = 0x03, - HouseDoorIronAR = 0x04, - HouseDoorIronpartsAS = 0x05, - HouseDoorIronpartsAR = 0x06, - HouseTentPADoor = 0x07, - HouseTentNADoor = 0x08, - HouseDoorReliefAS = 0x09, - HouseDoorReliefAR = 0x0A, - HouseDoorJapaneseAS = 0x0E, - HouseDoorJapaneseAR = 0x0F, - HouseDoorWindowAS = 0x10, - HouseDoorWindowAR = 0x11, - HouseDoorIronGrillAS = 0x12, - HouseDoorIronGrillAR = 0x13, - HouseDoorChineseAS = 0x14, - HouseDoorChineseAR = 0x15, - HouseDoorSimpleAS = 0x16, - HouseDoorSimpleAR = 0x17, - _1 = 0x18, - _2 = 0x19, - HouseDoorCarvingAS = 0x1A, - HouseDoorCarvingAR = 0x1B, - HouseDoorCercleWindowAS = 0x1C, - HouseDoorCercleWindowAR = 0x1D, - HouseDoorVerticalWindowAS = 0x1E, - HouseDoorVerticalWindowAR = 0x1F, - HouseDoorLatticeAS = 0x20, - HouseDoorLatticeAR = 0x21, - HouseDoorSimplicityAS = 0x22, - HouseDoorSimplicityAR = 0x23, - _3 = 0x25, - _4 = 0x26, - HouseTentNBDoor = 0x27, - HouseDoorIronGrillBS = 0x28, - HouseDoorIronGrillCS = 0x29, - HouseDoorIronGrillDS = 0x2A, - HouseDoorIronGrillES = 0x2B, - HouseDoorIronGrillFS = 0x2C, - HouseDoorIronGrillBR = 0x2D, - HouseDoorIronGrillCR = 0x2E, - HouseDoorIronGrillDR = 0x2F, - HouseDoorIronGrillER = 0x30, - HouseDoorIronGrillFR = 0x31, - HouseDoorCarvingBS = 0x32, - HouseDoorCarvingCS = 0x33, - HouseDoorCarvingDS = 0x34, - HouseDoorCarvingES = 0x35, - HouseDoorCarvingBR = 0x36, - HouseDoorCarvingCR = 0x37, - HouseDoorCarvingDR = 0x38, - HouseDoorCarvingER = 0x39, - HouseDoorIronGrillGS = 0x3A, - HouseDoorIronGrillGR = 0x3B, - HouseDoorIronGrillHS = 0x3C, - HouseDoorIronGrillHR = 0x3D, - HouseDoorVerticalWindowBS = 0x3E, - HouseDoorVerticalWindowCS = 0x3F, - HouseDoorVerticalWindowDS = 0x40, - HouseDoorVerticalWindowES = 0x41, - HouseDoorVerticalWindowFS = 0x42, - HouseDoorVerticalWindowGS = 0x43, - HouseDoorVerticalWindowHS = 0x44, - HouseDoorVerticalWindowBR = 0x45, - HouseDoorVerticalWindowCR = 0x46, - HouseDoorVerticalWindowDR = 0x47, - HouseDoorVerticalWindowER = 0x48, - HouseDoorVerticalWindowFR = 0x49, - HouseDoorVerticalWindowGR = 0x4A, - HouseDoorVerticalWindowHR = 0x4B, - HouseDoorReliefBS = 0x4C, - HouseDoorReliefCS = 0x4D, - HouseDoorReliefDS = 0x4E, - HouseDoorReliefES = 0x4F, - HouseDoorReliefFS = 0x50, - HouseDoorReliefGS = 0x51, - HouseDoorReliefHS = 0x52, - HouseDoorReliefBR = 0x53, - HouseDoorReliefCR = 0x54, - HouseDoorReliefDR = 0x55, - HouseDoorReliefER = 0x56, - HouseDoorReliefFR = 0x57, - HouseDoorReliefGR = 0x58, - HouseDoorReliefHR = 0x59, - HouseDoorIronpartsBS = 0x5A, - HouseDoorIronpartsCS = 0x5B, - HouseDoorIronpartsDS = 0x5C, - HouseDoorIronpartsES = 0x5D, - HouseDoorIronpartsFS = 0x5E, - HouseDoorIronpartsGS = 0x5F, - HouseDoorIronpartsHS = 0x60, - HouseDoorIronpartsBR = 0x61, - HouseDoorIronpartsCR = 0x62, - HouseDoorIronpartsDR = 0x63, - HouseDoorIronpartsER = 0x64, - HouseDoorIronpartsFR = 0x65, - HouseDoorIronpartsGR = 0x66, - HouseDoorIronpartsHR = 0x67, - HouseDoorSimpleBS = 0x84, - HouseDoorSimpleCS = 0x85, - HouseDoorSimpleDS = 0x86, - HouseDoorSimpleES = 0x87, - HouseDoorSimpleFS = 0x88, - HouseDoorSimpleGS = 0x89, - HouseDoorSimpleHS = 0x8A, - HouseDoorSimpleBR = 0x8B, - HouseDoorSimpleCR = 0x8C, - HouseDoorSimpleDR = 0x8D, - HouseDoorSimpleER = 0x8E, - HouseDoorSimpleFR = 0x8F, - HouseDoorSimpleGR = 0x90, - HouseDoorSimpleHR = 0x91, - HouseDoorJapaneseBS = 0x92, - HouseDoorJapaneseCS = 0x93, - HouseDoorJapaneseDS = 0x94, - HouseDoorJapaneseES = 0x95, - HouseDoorJapaneseFS = 0x96, - HouseDoorJapaneseBR = 0x97, - HouseDoorJapaneseCR = 0x98, - HouseDoorJapaneseDR = 0x99, - HouseDoorJapaneseER = 0x9A, - HouseDoorJapaneseFR = 0x9B, - HouseDoorLatticeBS = 0x9C, - HouseDoorLatticeCS = 0x9D, - HouseDoorLatticeDS = 0x9E, - HouseDoorLatticeES = 0x9F, - HouseDoorLatticeFS = 0xA0, - HouseDoorLatticeGS = 0xA1, - HouseDoorLatticeHS = 0xA2, - HouseDoorLatticeBR = 0xA3, - HouseDoorLatticeCR = 0xA4, - HouseDoorLatticeDR = 0xA5, - HouseDoorLatticeER = 0xA6, - HouseDoorLatticeFR = 0xA7, - HouseDoorLatticeGR = 0xA8, - HouseDoorLatticeHR = 0xA9, - HouseDoorCercleWindowBS = 0xAA, - HouseDoorCercleWindowCS = 0xAB, - HouseDoorCercleWindowDS = 0xAC, - HouseDoorCercleWindowES = 0xAD, - HouseDoorCercleWindowFS = 0xAE, - HouseDoorCercleWindowGS = 0xAF, - HouseDoorCercleWindowHS = 0xB0, - HouseDoorCercleWindowBR = 0xB1, - HouseDoorCercleWindowCR = 0xB2, - HouseDoorCercleWindowDR = 0xB3, - HouseDoorCercleWindowER = 0xB4, - HouseDoorCercleWindowFR = 0xB5, - HouseDoorCercleWindowGR = 0xB6, - HouseDoorCercleWindowHR = 0xB7, - HouseDoorJapaneseGS = 0xB8, - HouseDoorJapaneseGR = 0xB9, - HouseDoorSimplicityBS = 0xBA, - HouseDoorSimplicityCS = 0xBB, - HouseDoorSimplicityDS = 0xBC, - HouseDoorSimplicityES = 0xBD, - HouseDoorSimplicityFS = 0xBE, - HouseDoorSimplicityGS = 0xBF, - HouseDoorSimplicityHS = 0xC0, - HouseDoorSimplicityBR = 0xC1, - HouseDoorSimplicityCR = 0xC2, - HouseDoorSimplicityDR = 0xC3, - HouseDoorSimplicityER = 0xC4, - HouseDoorSimplicityFR = 0xC5, - HouseDoorSimplicityGR = 0xC6, - HouseDoorSimplicityHR = 0xC7, - HouseDoorChineseBS = 0xC8, - HouseDoorChineseCS = 0xC9, - HouseDoorChineseDS = 0xCA, - HouseDoorChineseES = 0xCB, - HouseDoorChineseFS = 0xCC, - HouseDoorChineseGS = 0xCD, - HouseDoorChineseHS = 0xCE, - HouseDoorChineseBR = 0xCF, - HouseDoorChineseCR = 0xD0, - HouseDoorChineseDR = 0xD1, - HouseDoorChineseER = 0xD2, - HouseDoorChineseFR = 0xD3, - HouseDoorChineseGR = 0xD4, - HouseDoorChineseHR = 0xD5, - HouseDoorWindowBS = 0xDD, - HouseDoorWindowCS = 0xDE, - HouseDoorWindowDS = 0xDF, - HouseDoorWindowES = 0xE0, - HouseDoorWindowFS = 0xE1, - HouseDoorWindowGS = 0xE2, - HouseDoorWindowHS = 0xE3, - HouseDoorWindowBR = 0xE4, - HouseDoorWindowCR = 0xE5, - HouseDoorWindowDR = 0xE6, - HouseDoorWindowER = 0xE7, - HouseDoorWindowFR = 0xE8, - HouseDoorWindowGR = 0xE9, - HouseDoorWindowHR = 0xEA, - HouseDoorIronBS = 0xEB, - HouseDoorIronCS = 0xEC, - HouseDoorIronDS = 0xED, - HouseDoorIronES = 0xEE, - HouseDoorIronFS = 0xEF, - HouseDoorIronGS = 0xF0, - HouseDoorIronHS = 0xF1, - HouseDoorIronBR = 0xF2, - HouseDoorIronCR = 0xF3, - HouseDoorIronDR = 0xF4, - HouseDoorIronER = 0xF5, - HouseDoorIronFR = 0xF6, - HouseDoorIronGR = 0xF7, - HouseDoorIronHR = 0xF8, - HouseDoorStandardBS = 0xF9, - HouseDoorStandardCS = 0xFA, - HouseDoorStandardDS = 0xFB, - HouseDoorStandardES = 0xFC, - HouseDoorStandardFS = 0xFD, - HouseDoorStandardGS = 0xFE, - HouseDoorStandardHS = 0xFF, - HouseDoorStandardBR = 0x100, - HouseDoorStandardCR = 0x101, - HouseDoorStandardDR = 0x102, - HouseDoorStandardER = 0x103, - HouseDoorStandardFR = 0x104, - HouseDoorStandardGR = 0x105, - HouseDoorStandardHR = 0x106, - HouseDoorReliefIS = 0x107, - HouseDoorReliefIR = 0x108, - HouseDoorReliefJS = 0x109, - HouseDoorReliefJR = 0x10A, - HouseDoorCarvingFS = 0x10B, - HouseDoorCarvingFR = 0x10C, - HouseDoorCercleWindowIS = 0x10D, - HouseDoorCercleWindowIR = 0x10E, - HouseDoorCercleWindowJS = 0x10F, - HouseDoorCercleWindowJR = 0x110, - HouseDoorVerticalWindowIS = 0x111, - HouseDoorVerticalWindowIR = 0x112, - HouseDoorVerticalWindowJS = 0x113, - HouseDoorVerticalWindowJR = 0x114, - HouseDoorWindowIS = 0x115, - HouseDoorWindowIR = 0x116, - HouseDoorWindowJS = 0x117, - HouseDoorWindowJR = 0x118, - HouseDoorStandardIS = 0x119, - HouseDoorStandardIR = 0x11A, - HouseDoorStandardJS = 0x11B, - HouseDoorStandardJR = 0x11C, - HouseDoorSimplicityIS = 0x11D, - HouseDoorSimplicityIR = 0x11E, - HouseDoorSimplicityJS = 0x11F, - HouseDoorSimplicityJR = 0x120, - HouseDoorIronGrillIS = 0x121, - HouseDoorIronGrillIR = 0x122, - HouseDoorIronGrillJS = 0x123, - HouseDoorIronGrillJR = 0x124, - } -} + HouseDoorStandardAR = 0x00, + HouseDoorStandardAS = 0x02, + HouseDoorIronAS = 0x03, + HouseDoorIronAR = 0x04, + HouseDoorIronpartsAS = 0x05, + HouseDoorIronpartsAR = 0x06, + HouseTentPADoor = 0x07, + HouseTentNADoor = 0x08, + HouseDoorReliefAS = 0x09, + HouseDoorReliefAR = 0x0A, + HouseDoorJapaneseAS = 0x0E, + HouseDoorJapaneseAR = 0x0F, + HouseDoorWindowAS = 0x10, + HouseDoorWindowAR = 0x11, + HouseDoorIronGrillAS = 0x12, + HouseDoorIronGrillAR = 0x13, + HouseDoorChineseAS = 0x14, + HouseDoorChineseAR = 0x15, + HouseDoorSimpleAS = 0x16, + HouseDoorSimpleAR = 0x17, + _1 = 0x18, + _2 = 0x19, + HouseDoorCarvingAS = 0x1A, + HouseDoorCarvingAR = 0x1B, + HouseDoorCercleWindowAS = 0x1C, + HouseDoorCercleWindowAR = 0x1D, + HouseDoorVerticalWindowAS = 0x1E, + HouseDoorVerticalWindowAR = 0x1F, + HouseDoorLatticeAS = 0x20, + HouseDoorLatticeAR = 0x21, + HouseDoorSimplicityAS = 0x22, + HouseDoorSimplicityAR = 0x23, + _3 = 0x25, + _4 = 0x26, + HouseTentNBDoor = 0x27, + HouseDoorIronGrillBS = 0x28, + HouseDoorIronGrillCS = 0x29, + HouseDoorIronGrillDS = 0x2A, + HouseDoorIronGrillES = 0x2B, + HouseDoorIronGrillFS = 0x2C, + HouseDoorIronGrillBR = 0x2D, + HouseDoorIronGrillCR = 0x2E, + HouseDoorIronGrillDR = 0x2F, + HouseDoorIronGrillER = 0x30, + HouseDoorIronGrillFR = 0x31, + HouseDoorCarvingBS = 0x32, + HouseDoorCarvingCS = 0x33, + HouseDoorCarvingDS = 0x34, + HouseDoorCarvingES = 0x35, + HouseDoorCarvingBR = 0x36, + HouseDoorCarvingCR = 0x37, + HouseDoorCarvingDR = 0x38, + HouseDoorCarvingER = 0x39, + HouseDoorIronGrillGS = 0x3A, + HouseDoorIronGrillGR = 0x3B, + HouseDoorIronGrillHS = 0x3C, + HouseDoorIronGrillHR = 0x3D, + HouseDoorVerticalWindowBS = 0x3E, + HouseDoorVerticalWindowCS = 0x3F, + HouseDoorVerticalWindowDS = 0x40, + HouseDoorVerticalWindowES = 0x41, + HouseDoorVerticalWindowFS = 0x42, + HouseDoorVerticalWindowGS = 0x43, + HouseDoorVerticalWindowHS = 0x44, + HouseDoorVerticalWindowBR = 0x45, + HouseDoorVerticalWindowCR = 0x46, + HouseDoorVerticalWindowDR = 0x47, + HouseDoorVerticalWindowER = 0x48, + HouseDoorVerticalWindowFR = 0x49, + HouseDoorVerticalWindowGR = 0x4A, + HouseDoorVerticalWindowHR = 0x4B, + HouseDoorReliefBS = 0x4C, + HouseDoorReliefCS = 0x4D, + HouseDoorReliefDS = 0x4E, + HouseDoorReliefES = 0x4F, + HouseDoorReliefFS = 0x50, + HouseDoorReliefGS = 0x51, + HouseDoorReliefHS = 0x52, + HouseDoorReliefBR = 0x53, + HouseDoorReliefCR = 0x54, + HouseDoorReliefDR = 0x55, + HouseDoorReliefER = 0x56, + HouseDoorReliefFR = 0x57, + HouseDoorReliefGR = 0x58, + HouseDoorReliefHR = 0x59, + HouseDoorIronpartsBS = 0x5A, + HouseDoorIronpartsCS = 0x5B, + HouseDoorIronpartsDS = 0x5C, + HouseDoorIronpartsES = 0x5D, + HouseDoorIronpartsFS = 0x5E, + HouseDoorIronpartsGS = 0x5F, + HouseDoorIronpartsHS = 0x60, + HouseDoorIronpartsBR = 0x61, + HouseDoorIronpartsCR = 0x62, + HouseDoorIronpartsDR = 0x63, + HouseDoorIronpartsER = 0x64, + HouseDoorIronpartsFR = 0x65, + HouseDoorIronpartsGR = 0x66, + HouseDoorIronpartsHR = 0x67, + HouseDoorSimpleBS = 0x84, + HouseDoorSimpleCS = 0x85, + HouseDoorSimpleDS = 0x86, + HouseDoorSimpleES = 0x87, + HouseDoorSimpleFS = 0x88, + HouseDoorSimpleGS = 0x89, + HouseDoorSimpleHS = 0x8A, + HouseDoorSimpleBR = 0x8B, + HouseDoorSimpleCR = 0x8C, + HouseDoorSimpleDR = 0x8D, + HouseDoorSimpleER = 0x8E, + HouseDoorSimpleFR = 0x8F, + HouseDoorSimpleGR = 0x90, + HouseDoorSimpleHR = 0x91, + HouseDoorJapaneseBS = 0x92, + HouseDoorJapaneseCS = 0x93, + HouseDoorJapaneseDS = 0x94, + HouseDoorJapaneseES = 0x95, + HouseDoorJapaneseFS = 0x96, + HouseDoorJapaneseBR = 0x97, + HouseDoorJapaneseCR = 0x98, + HouseDoorJapaneseDR = 0x99, + HouseDoorJapaneseER = 0x9A, + HouseDoorJapaneseFR = 0x9B, + HouseDoorLatticeBS = 0x9C, + HouseDoorLatticeCS = 0x9D, + HouseDoorLatticeDS = 0x9E, + HouseDoorLatticeES = 0x9F, + HouseDoorLatticeFS = 0xA0, + HouseDoorLatticeGS = 0xA1, + HouseDoorLatticeHS = 0xA2, + HouseDoorLatticeBR = 0xA3, + HouseDoorLatticeCR = 0xA4, + HouseDoorLatticeDR = 0xA5, + HouseDoorLatticeER = 0xA6, + HouseDoorLatticeFR = 0xA7, + HouseDoorLatticeGR = 0xA8, + HouseDoorLatticeHR = 0xA9, + HouseDoorCercleWindowBS = 0xAA, + HouseDoorCercleWindowCS = 0xAB, + HouseDoorCercleWindowDS = 0xAC, + HouseDoorCercleWindowES = 0xAD, + HouseDoorCercleWindowFS = 0xAE, + HouseDoorCercleWindowGS = 0xAF, + HouseDoorCercleWindowHS = 0xB0, + HouseDoorCercleWindowBR = 0xB1, + HouseDoorCercleWindowCR = 0xB2, + HouseDoorCercleWindowDR = 0xB3, + HouseDoorCercleWindowER = 0xB4, + HouseDoorCercleWindowFR = 0xB5, + HouseDoorCercleWindowGR = 0xB6, + HouseDoorCercleWindowHR = 0xB7, + HouseDoorJapaneseGS = 0xB8, + HouseDoorJapaneseGR = 0xB9, + HouseDoorSimplicityBS = 0xBA, + HouseDoorSimplicityCS = 0xBB, + HouseDoorSimplicityDS = 0xBC, + HouseDoorSimplicityES = 0xBD, + HouseDoorSimplicityFS = 0xBE, + HouseDoorSimplicityGS = 0xBF, + HouseDoorSimplicityHS = 0xC0, + HouseDoorSimplicityBR = 0xC1, + HouseDoorSimplicityCR = 0xC2, + HouseDoorSimplicityDR = 0xC3, + HouseDoorSimplicityER = 0xC4, + HouseDoorSimplicityFR = 0xC5, + HouseDoorSimplicityGR = 0xC6, + HouseDoorSimplicityHR = 0xC7, + HouseDoorChineseBS = 0xC8, + HouseDoorChineseCS = 0xC9, + HouseDoorChineseDS = 0xCA, + HouseDoorChineseES = 0xCB, + HouseDoorChineseFS = 0xCC, + HouseDoorChineseGS = 0xCD, + HouseDoorChineseHS = 0xCE, + HouseDoorChineseBR = 0xCF, + HouseDoorChineseCR = 0xD0, + HouseDoorChineseDR = 0xD1, + HouseDoorChineseER = 0xD2, + HouseDoorChineseFR = 0xD3, + HouseDoorChineseGR = 0xD4, + HouseDoorChineseHR = 0xD5, + HouseDoorWindowBS = 0xDD, + HouseDoorWindowCS = 0xDE, + HouseDoorWindowDS = 0xDF, + HouseDoorWindowES = 0xE0, + HouseDoorWindowFS = 0xE1, + HouseDoorWindowGS = 0xE2, + HouseDoorWindowHS = 0xE3, + HouseDoorWindowBR = 0xE4, + HouseDoorWindowCR = 0xE5, + HouseDoorWindowDR = 0xE6, + HouseDoorWindowER = 0xE7, + HouseDoorWindowFR = 0xE8, + HouseDoorWindowGR = 0xE9, + HouseDoorWindowHR = 0xEA, + HouseDoorIronBS = 0xEB, + HouseDoorIronCS = 0xEC, + HouseDoorIronDS = 0xED, + HouseDoorIronES = 0xEE, + HouseDoorIronFS = 0xEF, + HouseDoorIronGS = 0xF0, + HouseDoorIronHS = 0xF1, + HouseDoorIronBR = 0xF2, + HouseDoorIronCR = 0xF3, + HouseDoorIronDR = 0xF4, + HouseDoorIronER = 0xF5, + HouseDoorIronFR = 0xF6, + HouseDoorIronGR = 0xF7, + HouseDoorIronHR = 0xF8, + HouseDoorStandardBS = 0xF9, + HouseDoorStandardCS = 0xFA, + HouseDoorStandardDS = 0xFB, + HouseDoorStandardES = 0xFC, + HouseDoorStandardFS = 0xFD, + HouseDoorStandardGS = 0xFE, + HouseDoorStandardHS = 0xFF, + HouseDoorStandardBR = 0x100, + HouseDoorStandardCR = 0x101, + HouseDoorStandardDR = 0x102, + HouseDoorStandardER = 0x103, + HouseDoorStandardFR = 0x104, + HouseDoorStandardGR = 0x105, + HouseDoorStandardHR = 0x106, + HouseDoorReliefIS = 0x107, + HouseDoorReliefIR = 0x108, + HouseDoorReliefJS = 0x109, + HouseDoorReliefJR = 0x10A, + HouseDoorCarvingFS = 0x10B, + HouseDoorCarvingFR = 0x10C, + HouseDoorCercleWindowIS = 0x10D, + HouseDoorCercleWindowIR = 0x10E, + HouseDoorCercleWindowJS = 0x10F, + HouseDoorCercleWindowJR = 0x110, + HouseDoorVerticalWindowIS = 0x111, + HouseDoorVerticalWindowIR = 0x112, + HouseDoorVerticalWindowJS = 0x113, + HouseDoorVerticalWindowJR = 0x114, + HouseDoorWindowIS = 0x115, + HouseDoorWindowIR = 0x116, + HouseDoorWindowJS = 0x117, + HouseDoorWindowJR = 0x118, + HouseDoorStandardIS = 0x119, + HouseDoorStandardIR = 0x11A, + HouseDoorStandardJS = 0x11B, + HouseDoorStandardJR = 0x11C, + HouseDoorSimplicityIS = 0x11D, + HouseDoorSimplicityIR = 0x11E, + HouseDoorSimplicityJS = 0x11F, + HouseDoorSimplicityJR = 0x120, + HouseDoorIronGrillIS = 0x121, + HouseDoorIronGrillIR = 0x122, + HouseDoorIronGrillJS = 0x123, + HouseDoorIronGrillJR = 0x124, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/RoofType.cs b/NHSE.Core/Structures/Building/RoofType.cs index 489e3f0..682aebf 100644 --- a/NHSE.Core/Structures/Building/RoofType.cs +++ b/NHSE.Core/Structures/Building/RoofType.cs @@ -1,175 +1,174 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Roof model for a house. +/// +public enum RoofType : ushort { - /// - /// Roof model for a house. - /// - public enum RoofType : ushort - { - HouseRoofPA04StandardA = 0x00, - HouseRoofPA04StandardB = 0x03, - _1 = 0x04, - _2 = 0x05, - HouseRoofPA04ThatchedA = 0x06, - HouseRoofPA04StoneA = 0x07, - HouseRoofPA04WesterntileA = 0x08, - _3 = 0x09, - HouseRoofPA00StandardA = 0x0A, - HouseRoofPA00StandardB = 0x0B, - HouseRoofPA00StandardC = 0x0C, - HouseRoofPA00StandardD = 0x0D, - HouseRoofPA00StandardE = 0x0E, - HouseRoofPA00StandardF = 0x0F, - HouseRoofPA00StandardG = 0x10, - HouseRoofPA00StandardH = 0x11, - _4 = 0x12, - HouseRoofNASlateA = 0x13, - HouseRoofNAMetalA = 0x14, - HouseRoofNATileA = 0x15, - HouseRoofPA04ThatchedB = 0x17, - HouseRoofPA04ThatchedC = 0x18, - HouseRoofPA04ThatchedD = 0x19, - HouseRoofPA04ThatchedE = 0x1A, - HouseRoofNBWoodtileA = 0x1B, - HouseRoofNBThatchedA = 0x1C, - HouseRoofNBWoodpanelA = 0x1D, - HouseRoofNCJapaneseA = 0x1E, - HouseRoofNCThatchedA = 0x1F, - HouseRoofNCStoneweightA = 0x20, - _5 = 0x21, - _6 = 0x22, - HouseRoofNDStoneA = 0x23, - HouseRoofNDThatchedA = 0x24, - HouseRoofNDWoodA = 0x25, - HouseRoofPA01StandardA = 0x26, - HouseRoofPA03StandardA = 0x27, - HouseRoofNATileB = 0x28, - HouseRoofNATileC = 0x29, - HouseRoofNATileD = 0x2A, - HouseRoofNATileE = 0x2B, - HouseRoofNATileF = 0x2C, - HouseRoofNATileG = 0x2D, - HouseRoofNATileH = 0x2E, - HouseRoofPA02StandardA = 0x2F, - HouseRoofNAMetalB = 0x30, - HouseRoofNAMetalC = 0x31, - HouseRoofNAMetalD = 0x32, - HouseRoofNAMetalE = 0x33, - HouseRoofNAMetalF = 0x34, - HouseRoofNAMetalG = 0x35, - HouseRoofNAMetalH = 0x36, - HouseRoofNASlateB = 0x37, - HouseRoofNASlateC = 0x38, - HouseRoofNASlateD = 0x39, - HouseRoofNASlateE = 0x3A, - HouseRoofNASlateF = 0x3B, - HouseRoofNASlateG = 0x3C, - HouseRoofNASlateH = 0x3D, - HouseRoofNBWoodtileB = 0x3E, - HouseRoofNBWoodtileC = 0x3F, - HouseRoofNBWoodtileD = 0x40, - HouseRoofNBWoodtileE = 0x41, - HouseRoofNBWoodtileF = 0x42, - HouseRoofNBWoodtileG = 0x43, - HouseRoofNBWoodtileH = 0x44, - HouseRoofNBWoodpanelB = 0x45, - HouseRoofNBWoodpanelC = 0x46, - HouseRoofNBWoodpanelD = 0x47, - HouseRoofNBWoodpanelE = 0x48, - HouseRoofNBWoodpanelF = 0x49, - HouseRoofNBWoodpanelG = 0x4A, - HouseRoofNBWoodpanelH = 0x4B, - HouseRoofPA01StandardB = 0x4C, - HouseRoofPA01StandardC = 0x4D, - HouseRoofPA01StandardD = 0x4E, - HouseRoofPA01StandardE = 0x4F, - HouseRoofPA01StandardF = 0x50, - HouseRoofPA01StandardG = 0x51, - HouseRoofPA01StandardH = 0x52, - HouseRoofNBThatchedB = 0x53, - HouseRoofNBThatchedC = 0x54, - HouseRoofNBThatchedD = 0x55, - HouseRoofNBThatchedE = 0x56, - HouseRoofNBThatchedF = 0x57, - HouseRoofNBThatchedG = 0x58, - HouseRoofNBThatchedH = 0x59, - HouseRoofNCJapaneseB = 0x5A, - HouseRoofNCJapaneseC = 0x5B, - HouseRoofNCJapaneseD = 0x5C, - HouseRoofNCJapaneseE = 0x5D, - HouseRoofNCJapaneseF = 0x5E, - HouseRoofNCJapaneseG = 0x5F, - HouseRoofNCJapaneseH = 0x60, - HouseRoofNCStoneweightB = 0x61, - HouseRoofNCStoneweightC = 0x62, - HouseRoofNCStoneweightD = 0x63, - HouseRoofNCStoneweightE = 0x64, - HouseRoofNCStoneweightF = 0x65, - HouseRoofNDWoodB = 0x66, - HouseRoofNDWoodC = 0x67, - HouseRoofNDWoodD = 0x68, - HouseRoofNDWoodE = 0x69, - HouseRoofNDWoodF = 0x6A, - HouseRoofNDWoodG = 0x6B, - HouseRoofNDWoodH = 0x6C, - HouseRoofNDStoneB = 0x6D, - HouseRoofNDStoneC = 0x6E, - HouseRoofNDStoneD = 0x6F, - HouseRoofNDStoneE = 0x70, - HouseRoofNDStoneF = 0x71, - HouseRoofNDStoneG = 0x72, - HouseRoofNDStoneH = 0x73, - HouseRoofNCThatchedB = 0x74, - HouseRoofNCThatchedC = 0x75, - HouseRoofNCThatchedD = 0x76, - HouseRoofNCThatchedE = 0x77, - HouseRoofNCThatchedF = 0x78, - HouseRoofNDThatchedB = 0x79, - HouseRoofNDThatchedC = 0x7A, - HouseRoofNDThatchedD = 0x7B, - HouseRoofNDThatchedE = 0x7C, - HouseRoofNDThatchedF = 0x7D, - HouseRoofPA02StandardB = 0x7E, - HouseRoofPA02StandardC = 0x7F, - HouseRoofPA02StandardD = 0x80, - HouseRoofPA02StandardE = 0x81, - HouseRoofPA02StandardF = 0x82, - HouseRoofPA02StandardG = 0x83, - HouseRoofPA02StandardH = 0x84, - HouseRoofPA03StandardB = 0x85, - HouseRoofPA03StandardC = 0x86, - HouseRoofPA03StandardD = 0x87, - HouseRoofPA03StandardE = 0x88, - HouseRoofPA03StandardF = 0x89, - HouseRoofPA03StandardG = 0x8A, - HouseRoofPA03StandardH = 0x8B, - HouseRoofPA04StandardC = 0x93, - HouseRoofPA04StandardD = 0x94, - HouseRoofPA04StandardE = 0x95, - HouseRoofPA04StandardF = 0x96, - HouseRoofPA04StandardG = 0x97, - HouseRoofPA04StandardH = 0x98, - HouseRoofPA04StoneB = 0x99, - HouseRoofPA04StoneC = 0x9A, - HouseRoofPA04StoneD = 0x9B, - HouseRoofPA04StoneE = 0x9C, - HouseRoofPA04StoneF = 0x9D, - HouseRoofPA04StoneG = 0x9E, - HouseRoofPA04StoneH = 0x9F, - HouseRoofPA04WesterntileB = 0xA0, - HouseRoofPA04WesterntileC = 0xA1, - HouseRoofPA04WesterntileD = 0xA2, - HouseRoofPA04WesterntileE = 0xA3, - HouseRoofPA04WesterntileF = 0xA4, - HouseRoofPA04WesterntileG = 0xA5, - HouseRoofPA04WesterntileH = 0xA6, - HouseRoofPA04ThatchedF = 0xA7, - HouseRoofPA04ThatchedG = 0xA8, - HouseRoofPA04ThatchedH = 0xA9, - HouseRoofNAMetalI = 0xAA, - HouseRoofNBWoodtileI = 0xAB, - HouseRoofNBWoodtileJ = 0xAC, - HouseRoofNASlateI = 0xAD, - HouseRoofNDWoodI = 0xAE, - HouseRoofNDWoodJ = 0xAF, - } -} + HouseRoofPA04StandardA = 0x00, + HouseRoofPA04StandardB = 0x03, + _1 = 0x04, + _2 = 0x05, + HouseRoofPA04ThatchedA = 0x06, + HouseRoofPA04StoneA = 0x07, + HouseRoofPA04WesterntileA = 0x08, + _3 = 0x09, + HouseRoofPA00StandardA = 0x0A, + HouseRoofPA00StandardB = 0x0B, + HouseRoofPA00StandardC = 0x0C, + HouseRoofPA00StandardD = 0x0D, + HouseRoofPA00StandardE = 0x0E, + HouseRoofPA00StandardF = 0x0F, + HouseRoofPA00StandardG = 0x10, + HouseRoofPA00StandardH = 0x11, + _4 = 0x12, + HouseRoofNASlateA = 0x13, + HouseRoofNAMetalA = 0x14, + HouseRoofNATileA = 0x15, + HouseRoofPA04ThatchedB = 0x17, + HouseRoofPA04ThatchedC = 0x18, + HouseRoofPA04ThatchedD = 0x19, + HouseRoofPA04ThatchedE = 0x1A, + HouseRoofNBWoodtileA = 0x1B, + HouseRoofNBThatchedA = 0x1C, + HouseRoofNBWoodpanelA = 0x1D, + HouseRoofNCJapaneseA = 0x1E, + HouseRoofNCThatchedA = 0x1F, + HouseRoofNCStoneweightA = 0x20, + _5 = 0x21, + _6 = 0x22, + HouseRoofNDStoneA = 0x23, + HouseRoofNDThatchedA = 0x24, + HouseRoofNDWoodA = 0x25, + HouseRoofPA01StandardA = 0x26, + HouseRoofPA03StandardA = 0x27, + HouseRoofNATileB = 0x28, + HouseRoofNATileC = 0x29, + HouseRoofNATileD = 0x2A, + HouseRoofNATileE = 0x2B, + HouseRoofNATileF = 0x2C, + HouseRoofNATileG = 0x2D, + HouseRoofNATileH = 0x2E, + HouseRoofPA02StandardA = 0x2F, + HouseRoofNAMetalB = 0x30, + HouseRoofNAMetalC = 0x31, + HouseRoofNAMetalD = 0x32, + HouseRoofNAMetalE = 0x33, + HouseRoofNAMetalF = 0x34, + HouseRoofNAMetalG = 0x35, + HouseRoofNAMetalH = 0x36, + HouseRoofNASlateB = 0x37, + HouseRoofNASlateC = 0x38, + HouseRoofNASlateD = 0x39, + HouseRoofNASlateE = 0x3A, + HouseRoofNASlateF = 0x3B, + HouseRoofNASlateG = 0x3C, + HouseRoofNASlateH = 0x3D, + HouseRoofNBWoodtileB = 0x3E, + HouseRoofNBWoodtileC = 0x3F, + HouseRoofNBWoodtileD = 0x40, + HouseRoofNBWoodtileE = 0x41, + HouseRoofNBWoodtileF = 0x42, + HouseRoofNBWoodtileG = 0x43, + HouseRoofNBWoodtileH = 0x44, + HouseRoofNBWoodpanelB = 0x45, + HouseRoofNBWoodpanelC = 0x46, + HouseRoofNBWoodpanelD = 0x47, + HouseRoofNBWoodpanelE = 0x48, + HouseRoofNBWoodpanelF = 0x49, + HouseRoofNBWoodpanelG = 0x4A, + HouseRoofNBWoodpanelH = 0x4B, + HouseRoofPA01StandardB = 0x4C, + HouseRoofPA01StandardC = 0x4D, + HouseRoofPA01StandardD = 0x4E, + HouseRoofPA01StandardE = 0x4F, + HouseRoofPA01StandardF = 0x50, + HouseRoofPA01StandardG = 0x51, + HouseRoofPA01StandardH = 0x52, + HouseRoofNBThatchedB = 0x53, + HouseRoofNBThatchedC = 0x54, + HouseRoofNBThatchedD = 0x55, + HouseRoofNBThatchedE = 0x56, + HouseRoofNBThatchedF = 0x57, + HouseRoofNBThatchedG = 0x58, + HouseRoofNBThatchedH = 0x59, + HouseRoofNCJapaneseB = 0x5A, + HouseRoofNCJapaneseC = 0x5B, + HouseRoofNCJapaneseD = 0x5C, + HouseRoofNCJapaneseE = 0x5D, + HouseRoofNCJapaneseF = 0x5E, + HouseRoofNCJapaneseG = 0x5F, + HouseRoofNCJapaneseH = 0x60, + HouseRoofNCStoneweightB = 0x61, + HouseRoofNCStoneweightC = 0x62, + HouseRoofNCStoneweightD = 0x63, + HouseRoofNCStoneweightE = 0x64, + HouseRoofNCStoneweightF = 0x65, + HouseRoofNDWoodB = 0x66, + HouseRoofNDWoodC = 0x67, + HouseRoofNDWoodD = 0x68, + HouseRoofNDWoodE = 0x69, + HouseRoofNDWoodF = 0x6A, + HouseRoofNDWoodG = 0x6B, + HouseRoofNDWoodH = 0x6C, + HouseRoofNDStoneB = 0x6D, + HouseRoofNDStoneC = 0x6E, + HouseRoofNDStoneD = 0x6F, + HouseRoofNDStoneE = 0x70, + HouseRoofNDStoneF = 0x71, + HouseRoofNDStoneG = 0x72, + HouseRoofNDStoneH = 0x73, + HouseRoofNCThatchedB = 0x74, + HouseRoofNCThatchedC = 0x75, + HouseRoofNCThatchedD = 0x76, + HouseRoofNCThatchedE = 0x77, + HouseRoofNCThatchedF = 0x78, + HouseRoofNDThatchedB = 0x79, + HouseRoofNDThatchedC = 0x7A, + HouseRoofNDThatchedD = 0x7B, + HouseRoofNDThatchedE = 0x7C, + HouseRoofNDThatchedF = 0x7D, + HouseRoofPA02StandardB = 0x7E, + HouseRoofPA02StandardC = 0x7F, + HouseRoofPA02StandardD = 0x80, + HouseRoofPA02StandardE = 0x81, + HouseRoofPA02StandardF = 0x82, + HouseRoofPA02StandardG = 0x83, + HouseRoofPA02StandardH = 0x84, + HouseRoofPA03StandardB = 0x85, + HouseRoofPA03StandardC = 0x86, + HouseRoofPA03StandardD = 0x87, + HouseRoofPA03StandardE = 0x88, + HouseRoofPA03StandardF = 0x89, + HouseRoofPA03StandardG = 0x8A, + HouseRoofPA03StandardH = 0x8B, + HouseRoofPA04StandardC = 0x93, + HouseRoofPA04StandardD = 0x94, + HouseRoofPA04StandardE = 0x95, + HouseRoofPA04StandardF = 0x96, + HouseRoofPA04StandardG = 0x97, + HouseRoofPA04StandardH = 0x98, + HouseRoofPA04StoneB = 0x99, + HouseRoofPA04StoneC = 0x9A, + HouseRoofPA04StoneD = 0x9B, + HouseRoofPA04StoneE = 0x9C, + HouseRoofPA04StoneF = 0x9D, + HouseRoofPA04StoneG = 0x9E, + HouseRoofPA04StoneH = 0x9F, + HouseRoofPA04WesterntileB = 0xA0, + HouseRoofPA04WesterntileC = 0xA1, + HouseRoofPA04WesterntileD = 0xA2, + HouseRoofPA04WesterntileE = 0xA3, + HouseRoofPA04WesterntileF = 0xA4, + HouseRoofPA04WesterntileG = 0xA5, + HouseRoofPA04WesterntileH = 0xA6, + HouseRoofPA04ThatchedF = 0xA7, + HouseRoofPA04ThatchedG = 0xA8, + HouseRoofPA04ThatchedH = 0xA9, + HouseRoofNAMetalI = 0xAA, + HouseRoofNBWoodtileI = 0xAB, + HouseRoofNBWoodtileJ = 0xAC, + HouseRoofNASlateI = 0xAD, + HouseRoofNDWoodI = 0xAE, + HouseRoofNDWoodJ = 0xAF, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/SlopeType.cs b/NHSE.Core/Structures/Building/SlopeType.cs index ef7e9c0..060ebc1 100644 --- a/NHSE.Core/Structures/Building/SlopeType.cs +++ b/NHSE.Core/Structures/Building/SlopeType.cs @@ -1,18 +1,17 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Incline / Slope model +/// +public enum SlopeType : ushort { - /// - /// Incline / Slope model - /// - public enum SlopeType : ushort - { - SlopeStoneStair = 0x00, - SlopeIronStair = 0x01, - SlopeWood = 0x02, - SlopeWoodStair = 0x03, - SlopeBrickStair = 0x04, - SlopeReserved = 0x05, - SlopeNatural = 0x1D, - SlopeWoodBlue = 0x1E, - SlopeIronStairBlue = 0x1F, - } -} + SlopeStoneStair = 0x00, + SlopeIronStair = 0x01, + SlopeWood = 0x02, + SlopeWoodStair = 0x03, + SlopeBrickStair = 0x04, + SlopeReserved = 0x05, + SlopeNatural = 0x1D, + SlopeWoodBlue = 0x1E, + SlopeIronStairBlue = 0x1F, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/SoundAmbientKind.cs b/NHSE.Core/Structures/Building/SoundAmbientKind.cs index 0fbf9d7..9e81818 100644 --- a/NHSE.Core/Structures/Building/SoundAmbientKind.cs +++ b/NHSE.Core/Structures/Building/SoundAmbientKind.cs @@ -1,33 +1,32 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Ambient sound for a house. +/// +public enum SoundAmbientKind : byte { - /// - /// Ambient sound for a house. - /// - public enum SoundAmbientKind : byte - { - Silence = 0x0, - Rain = 0x1, - Sea = 0x2, - InWater = 0x3, - Wind = 0x4, - Plateau = 0x5, - Jungle = 0x6, - Crowd = 0x7, - Cheers = 0x8, - City = 0x9, - Train = 0xA, - Construction = 0xB, - Space = 0xC, - Echo = 0xD, - Storm = 0xE, - Cave = 0x10, - Earthquake = 0x11, - Squeak = 0x12, - Country = 0x14, - Factory = 0x15, - Cyber = 0x1A, - Healing = 0x1B, - Forest = 0x1C, - Duct = 0x1D, - } -} + Silence = 0x0, + Rain = 0x1, + Sea = 0x2, + InWater = 0x3, + Wind = 0x4, + Plateau = 0x5, + Jungle = 0x6, + Crowd = 0x7, + Cheers = 0x8, + City = 0x9, + Train = 0xA, + Construction = 0xB, + Space = 0xC, + Echo = 0xD, + Storm = 0xE, + Cave = 0x10, + Earthquake = 0x11, + Squeak = 0x12, + Country = 0x14, + Factory = 0x15, + Cyber = 0x1A, + Healing = 0x1B, + Forest = 0x1C, + Duct = 0x1D, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/StructureUtil.cs b/NHSE.Core/Structures/Building/StructureUtil.cs index bbe4ec9..596ec39 100644 --- a/NHSE.Core/Structures/Building/StructureUtil.cs +++ b/NHSE.Core/Structures/Building/StructureUtil.cs @@ -1,28 +1,27 @@ using System.Collections.Generic; using System.Linq; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Retrieves value metadata for customizing structures. +/// +public static class StructureUtil { - /// - /// Retrieves value metadata for customizing structures. - /// - public static class StructureUtil + public static Dictionary GetStructureHelpList() { - public static Dictionary GetStructureHelpList() + var kvpa = new[] { - var kvpa = new[] - { - EnumUtil.GetEnumList(), + EnumUtil.GetEnumList(), - EnumUtil.GetEnumList(), - EnumUtil.GetEnumList(), - EnumUtil.GetEnumList(), + EnumUtil.GetEnumList(), + EnumUtil.GetEnumList(), + EnumUtil.GetEnumList(), - EnumUtil.GetEnumList(), - EnumUtil.GetEnumList(), - EnumUtil.GetEnumList(), - }; - return kvpa.ToDictionary(x => x.Key, x => x.Value); - } + EnumUtil.GetEnumList(), + EnumUtil.GetEnumList(), + EnumUtil.GetEnumList(), + }; + return kvpa.ToDictionary(x => x.Key, x => x.Value); } -} +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Building/WallType.cs b/NHSE.Core/Structures/Building/WallType.cs index 0b42807..9029aa7 100644 --- a/NHSE.Core/Structures/Building/WallType.cs +++ b/NHSE.Core/Structures/Building/WallType.cs @@ -1,158 +1,157 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Wall model for a house. +/// +public enum WallType : ushort { - /// - /// Wall model for a house. - /// - public enum WallType : ushort - { - HouseWallPA04StandardA = 0x00, - HouseWallPA04StandardB = 0x05, - HouseWallPA04StandardC = 0x06, - HouseTentPA = 0x07, - HouseTentNA = 0x08, - HouseWallPA04WoodframeA = 0x09, - HouseWallPA04StoneA = 0x0A, - HouseWallNForSale = 0x0B, - HouseWallNSoldOut = 0x0C, - HouseWallPA00StandardA = 0x0D, - HouseWallNAWoodsidingA = 0x0E, - HouseWallNABrickA = 0x0F, - HouseWallNAStuccoA = 0x10, - HouseWallPA04StuccoA = 0x13, - HouseWallPA04WoodframeB = 0x14, - HouseWallPA04WoodframeC = 0x15, - HouseWallPA04WoodframeD = 0x16, - HouseWallPA04WoodframeE = 0x17, - HouseWallNBStuccoA = 0x18, - HouseWallNBLogA = 0x19, - HouseWallNBStoneA = 0x1A, - HouseWallNCJapaneseA = 0x1B, - HouseWallNCOrientalA = 0x1C, - HouseWallNCWoodA = 0x1D, - HouseWallHouseMovingPA = 0x1E, - HouseWallHouseMovingNA = 0x1F, - HouseWallNDStuccoA = 0x20, - HouseWallNDSoilA = 0x21, - HouseWallNDWoodA = 0x22, - HouseWallPA01StandardA = 0x23, - HouseTentNB = 0x24, - HouseWallPA03StandardA = 0x25, - HouseWallNAStuccoB = 0x2A, - HouseWallNAStuccoC = 0x2B, - HouseWallNAStuccoD = 0x2C, - HouseWallNAStuccoE = 0x2D, - HouseWallNAStuccoF = 0x2E, - HouseWallNAStuccoG = 0x2F, - HouseWallNAStuccoH = 0x30, - HouseWallNABrickB = 0x39, - HouseWallNABrickC = 0x3A, - HouseWallNABrickD = 0x3B, - HouseWallNABrickE = 0x3C, - HouseWallNABrickF = 0x3D, - HouseWallNABrickG = 0x3E, - HouseWallNABrickH = 0x3F, - HouseWallPA02StandardA = 0x40, - HouseWallNAWoodsidingB = 0x41, - HouseWallNAWoodsidingC = 0x42, - HouseWallNAWoodsidingD = 0x43, - HouseWallNAWoodsidingE = 0x44, - HouseWallNAWoodsidingF = 0x45, - HouseWallNAWoodsidingG = 0x46, - HouseWallNAWoodsidingH = 0x47, - HouseWallNBStuccoB = 0x48, - HouseWallNBStuccoC = 0x49, - HouseWallNBStuccoD = 0x4A, - HouseWallNBStuccoE = 0x4B, - HouseWallNBStuccoF = 0x4C, - HouseWallNBStuccoG = 0x4D, - HouseWallNBStuccoH = 0x4E, - HouseWallNBStoneB = 0x4F, - HouseWallNBStoneC = 0x50, - HouseWallNBStoneD = 0x51, - HouseWallNBStoneE = 0x52, - HouseWallNBStoneF = 0x53, - HouseWallNBStoneG = 0x54, - HouseWallNBStoneH = 0x55, - HouseWallNBLogB = 0x56, - HouseWallNBLogC = 0x57, - HouseWallNBLogD = 0x58, - HouseWallNBLogE = 0x59, - HouseWallNBLogF = 0x5A, - HouseWallNBLogG = 0x5B, - HouseWallNBLogH = 0x5C, - HouseWallNCOrientalB = 0x64, - HouseWallNCOrientalC = 0x65, - HouseWallNCOrientalD = 0x66, - HouseWallNCOrientalE = 0x67, - HouseWallNCOrientalF = 0x68, - HouseWallNCOrientalG = 0x69, - HouseWallNCOrientalH = 0x6A, - HouseWallNCJapaneseB = 0x6B, - HouseWallNCJapaneseC = 0x6C, - HouseWallNCJapaneseD = 0x6D, - HouseWallNCJapaneseE = 0x6E, - HouseWallNCJapaneseF = 0x6F, - HouseWallNCJapaneseG = 0x70, - HouseWallNCJapaneseH = 0x71, - HouseWallNCWoodB = 0x72, - HouseWallNCWoodC = 0x73, - HouseWallNCWoodD = 0x74, - HouseWallNCWoodE = 0x75, - HouseWallNCWoodF = 0x76, - HouseWallNCWoodG = 0x77, - HouseWallNCWoodH = 0x78, - HouseWallNDSoilB = 0x79, - HouseWallNDSoilC = 0x7A, - HouseWallNDSoilD = 0x7B, - HouseWallNDSoilE = 0x7C, - HouseWallNDSoilF = 0x7D, - HouseWallNDSoilG = 0x7E, - HouseWallNDSoilH = 0x7F, - HouseWallNDStuccoB = 0x80, - HouseWallNDStuccoC = 0x81, - HouseWallNDStuccoD = 0x82, - HouseWallNDStuccoE = 0x83, - HouseWallNDStuccoF = 0x84, - HouseWallNDStuccoG = 0x85, - HouseWallNDStuccoH = 0x86, - HouseWallNDWoodB = 0x87, - HouseWallNDWoodC = 0x88, - HouseWallNDWoodD = 0x89, - HouseWallNDWoodE = 0x8A, - HouseWallNDWoodF = 0x8B, - HouseWallNDWoodG = 0x8C, - HouseWallNDWoodH = 0x8D, - HouseWallPA04WoodframeF = 0x8E, - HouseWallPA04WoodframeG = 0x8F, - HouseWallPA04WoodframeH = 0x90, - HouseWallPA04StoneB = 0x91, - HouseWallPA04StoneC = 0x92, - HouseWallPA04StoneD = 0x93, - HouseWallPA04StoneE = 0x94, - HouseWallPA04StoneF = 0x95, - HouseWallPA04StoneG = 0x96, - HouseWallPA04StoneH = 0x97, - HouseWallPA04StuccoB = 0x98, - HouseWallPA04StuccoC = 0x99, - HouseWallPA04StuccoD = 0x9A, - HouseWallPA04StuccoE = 0x9B, - HouseWallPA04StuccoF = 0x9C, - HouseWallPA04StuccoG = 0x9D, - HouseWallPA04StuccoH = 0x9E, - HouseWallPA04StandardD = 0x9F, - HouseWallPA04StandardE = 0xA0, - HouseWallPA04StandardF = 0xA1, - HouseWallPA04StandardG = 0xA2, - HouseWallPA04StandardH = 0xA3, - HouseWallNAMetalA = 0xA4, - HouseWallNAMetalB = 0xA5, - HouseWallNAMetalC = 0xA6, - HouseWallNAMetalD = 0xA7, - HouseWallNAMetalE = 0xA8, - HouseWallNAMetalF = 0xA9, - HouseWallNAMetalG = 0xAA, - HouseWallNAMetalH = 0xAB, - HouseWallNAWoodsidingI = 0xAC, - HouseWallNAWoodsidingJ = 0xAD, - } -} + HouseWallPA04StandardA = 0x00, + HouseWallPA04StandardB = 0x05, + HouseWallPA04StandardC = 0x06, + HouseTentPA = 0x07, + HouseTentNA = 0x08, + HouseWallPA04WoodframeA = 0x09, + HouseWallPA04StoneA = 0x0A, + HouseWallNForSale = 0x0B, + HouseWallNSoldOut = 0x0C, + HouseWallPA00StandardA = 0x0D, + HouseWallNAWoodsidingA = 0x0E, + HouseWallNABrickA = 0x0F, + HouseWallNAStuccoA = 0x10, + HouseWallPA04StuccoA = 0x13, + HouseWallPA04WoodframeB = 0x14, + HouseWallPA04WoodframeC = 0x15, + HouseWallPA04WoodframeD = 0x16, + HouseWallPA04WoodframeE = 0x17, + HouseWallNBStuccoA = 0x18, + HouseWallNBLogA = 0x19, + HouseWallNBStoneA = 0x1A, + HouseWallNCJapaneseA = 0x1B, + HouseWallNCOrientalA = 0x1C, + HouseWallNCWoodA = 0x1D, + HouseWallHouseMovingPA = 0x1E, + HouseWallHouseMovingNA = 0x1F, + HouseWallNDStuccoA = 0x20, + HouseWallNDSoilA = 0x21, + HouseWallNDWoodA = 0x22, + HouseWallPA01StandardA = 0x23, + HouseTentNB = 0x24, + HouseWallPA03StandardA = 0x25, + HouseWallNAStuccoB = 0x2A, + HouseWallNAStuccoC = 0x2B, + HouseWallNAStuccoD = 0x2C, + HouseWallNAStuccoE = 0x2D, + HouseWallNAStuccoF = 0x2E, + HouseWallNAStuccoG = 0x2F, + HouseWallNAStuccoH = 0x30, + HouseWallNABrickB = 0x39, + HouseWallNABrickC = 0x3A, + HouseWallNABrickD = 0x3B, + HouseWallNABrickE = 0x3C, + HouseWallNABrickF = 0x3D, + HouseWallNABrickG = 0x3E, + HouseWallNABrickH = 0x3F, + HouseWallPA02StandardA = 0x40, + HouseWallNAWoodsidingB = 0x41, + HouseWallNAWoodsidingC = 0x42, + HouseWallNAWoodsidingD = 0x43, + HouseWallNAWoodsidingE = 0x44, + HouseWallNAWoodsidingF = 0x45, + HouseWallNAWoodsidingG = 0x46, + HouseWallNAWoodsidingH = 0x47, + HouseWallNBStuccoB = 0x48, + HouseWallNBStuccoC = 0x49, + HouseWallNBStuccoD = 0x4A, + HouseWallNBStuccoE = 0x4B, + HouseWallNBStuccoF = 0x4C, + HouseWallNBStuccoG = 0x4D, + HouseWallNBStuccoH = 0x4E, + HouseWallNBStoneB = 0x4F, + HouseWallNBStoneC = 0x50, + HouseWallNBStoneD = 0x51, + HouseWallNBStoneE = 0x52, + HouseWallNBStoneF = 0x53, + HouseWallNBStoneG = 0x54, + HouseWallNBStoneH = 0x55, + HouseWallNBLogB = 0x56, + HouseWallNBLogC = 0x57, + HouseWallNBLogD = 0x58, + HouseWallNBLogE = 0x59, + HouseWallNBLogF = 0x5A, + HouseWallNBLogG = 0x5B, + HouseWallNBLogH = 0x5C, + HouseWallNCOrientalB = 0x64, + HouseWallNCOrientalC = 0x65, + HouseWallNCOrientalD = 0x66, + HouseWallNCOrientalE = 0x67, + HouseWallNCOrientalF = 0x68, + HouseWallNCOrientalG = 0x69, + HouseWallNCOrientalH = 0x6A, + HouseWallNCJapaneseB = 0x6B, + HouseWallNCJapaneseC = 0x6C, + HouseWallNCJapaneseD = 0x6D, + HouseWallNCJapaneseE = 0x6E, + HouseWallNCJapaneseF = 0x6F, + HouseWallNCJapaneseG = 0x70, + HouseWallNCJapaneseH = 0x71, + HouseWallNCWoodB = 0x72, + HouseWallNCWoodC = 0x73, + HouseWallNCWoodD = 0x74, + HouseWallNCWoodE = 0x75, + HouseWallNCWoodF = 0x76, + HouseWallNCWoodG = 0x77, + HouseWallNCWoodH = 0x78, + HouseWallNDSoilB = 0x79, + HouseWallNDSoilC = 0x7A, + HouseWallNDSoilD = 0x7B, + HouseWallNDSoilE = 0x7C, + HouseWallNDSoilF = 0x7D, + HouseWallNDSoilG = 0x7E, + HouseWallNDSoilH = 0x7F, + HouseWallNDStuccoB = 0x80, + HouseWallNDStuccoC = 0x81, + HouseWallNDStuccoD = 0x82, + HouseWallNDStuccoE = 0x83, + HouseWallNDStuccoF = 0x84, + HouseWallNDStuccoG = 0x85, + HouseWallNDStuccoH = 0x86, + HouseWallNDWoodB = 0x87, + HouseWallNDWoodC = 0x88, + HouseWallNDWoodD = 0x89, + HouseWallNDWoodE = 0x8A, + HouseWallNDWoodF = 0x8B, + HouseWallNDWoodG = 0x8C, + HouseWallNDWoodH = 0x8D, + HouseWallPA04WoodframeF = 0x8E, + HouseWallPA04WoodframeG = 0x8F, + HouseWallPA04WoodframeH = 0x90, + HouseWallPA04StoneB = 0x91, + HouseWallPA04StoneC = 0x92, + HouseWallPA04StoneD = 0x93, + HouseWallPA04StoneE = 0x94, + HouseWallPA04StoneF = 0x95, + HouseWallPA04StoneG = 0x96, + HouseWallPA04StoneH = 0x97, + HouseWallPA04StuccoB = 0x98, + HouseWallPA04StuccoC = 0x99, + HouseWallPA04StuccoD = 0x9A, + HouseWallPA04StuccoE = 0x9B, + HouseWallPA04StuccoF = 0x9C, + HouseWallPA04StuccoG = 0x9D, + HouseWallPA04StuccoH = 0x9E, + HouseWallPA04StandardD = 0x9F, + HouseWallPA04StandardE = 0xA0, + HouseWallPA04StandardF = 0xA1, + HouseWallPA04StandardG = 0xA2, + HouseWallPA04StandardH = 0xA3, + HouseWallNAMetalA = 0xA4, + HouseWallNAMetalB = 0xA5, + HouseWallNAMetalC = 0xA6, + HouseWallNAMetalD = 0xA7, + HouseWallNAMetalE = 0xA8, + HouseWallNAMetalF = 0xA9, + HouseWallNAMetalG = 0xAA, + HouseWallNAMetalH = 0xAB, + HouseWallNAWoodsidingI = 0xAC, + HouseWallNAWoodsidingJ = 0xAD, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Designs/DesignPattern.cs b/NHSE.Core/Structures/Designs/DesignPattern.cs index 2505863..262f116 100644 --- a/NHSE.Core/Structures/Designs/DesignPattern.cs +++ b/NHSE.Core/Structures/Designs/DesignPattern.cs @@ -1,152 +1,154 @@ using System; +using System.Runtime.InteropServices; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Simple design pattern +/// +public class DesignPattern : IVillagerOrigin { - /// - /// Simple design pattern - /// - public class DesignPattern : IVillagerOrigin + public const int Width = 32; + public const int Height = 32; + + public const int SIZE = 0x2A8; // 3 bytes unused at end + private const int PersonalOffset = 0x38; + private const int PaletteDataStart = 0x78; + public const int PaletteColorCount = 15; // y not 16??? + private const int PaletteColorSize = 3; // R, G, B + private const int PixelDataOffset = PaletteDataStart + (PaletteColorCount * PaletteColorSize); // 0xA5 + private const int PixelCount = 0x400; // Width * Height + //private const int PixelDataSize = PixelCount / 2; // 4bit|4bit pixel packing + + public readonly Memory Raw; + public Span Data => Raw.Span; + + public DesignPattern(Memory data) => Raw = data; + + public uint Hash { - public const int Width = 32; - public const int Height = 32; + get => ReadUInt32LittleEndian(Data); + set => WriteUInt32LittleEndian(Data, value); + } - public const int SIZE = 0x2A8; // 3 bytes unused at end - private const int PersonalOffset = 0x38; - private const int PaletteDataStart = 0x78; - public const int PaletteColorCount = 15; // y not 16??? - private const int PaletteColorSize = 3; // R, G, B - private const int PixelDataOffset = PaletteDataStart + (PaletteColorCount * PaletteColorSize); // 0xA5 - private const int PixelCount = 0x400; // Width * Height - //private const int PixelDataSize = PixelCount / 2; // 4bit|4bit pixel packing + public uint Version + { + get => ReadUInt32LittleEndian(Data[0x04..]); + set => WriteUInt32LittleEndian(Data[0x04..], value); + } - public readonly byte[] Data; + public string DesignName + { + get => StringUtil.GetString(Data, 0x10, 20); + set => StringUtil.GetBytes(value, 20).CopyTo(Data[0x10..]); + } - public DesignPattern(byte[] data) => Data = data; + public uint TownID + { + get => ReadUInt32LittleEndian(Data[PersonalOffset..]); + set => WriteUInt32LittleEndian(Data[PersonalOffset..], value); + } - public uint Hash + public string TownName + { + get => StringUtil.GetString(Data, PersonalOffset + 0x04, 10); + set => StringUtil.GetBytes(value, 10).CopyTo(Data[(PersonalOffset + 0x04)..]); + } + + public Span GetTownIdentity() => Data.Slice(PersonalOffset + 0x00, 4 + 20); + + public uint PlayerID + { + get => ReadUInt32LittleEndian(Data[(PersonalOffset + 0x1C)..]); + set => WriteUInt32LittleEndian(Data[(PersonalOffset + 0x1C)..], value); + } + + public string PlayerName + { + get => StringUtil.GetString(Data, PersonalOffset + 0x20, 10); + set => StringUtil.GetBytes(value, 10).CopyTo(Data[(PersonalOffset + 0x20)..]); + } + + public Span GetPlayerIdentity() => Data.Slice(PersonalOffset + 0x1C, 4 + 20); + + /// + /// Gets/Sets the color choice (1-15) for the pixel at the given . + /// + /// Pixel index + public int this[int index] + { + get { - get => BitConverter.ToUInt32(Data, 0x00); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); + var ofs = PixelDataOffset + (index / 2); + var val = Data[ofs]; + return (index & 1) == 0 ? (val & 0x0F) : (val >> 4); } - - public uint Version + set { - get => BitConverter.ToUInt32(Data, 0x04); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); - } - - public string DesignName - { - get => StringUtil.GetString(Data, 0x10, 20); - set => StringUtil.GetBytes(value, 20).CopyTo(Data, 0x10); - } - - public uint TownID - { - get => BitConverter.ToUInt32(Data, PersonalOffset); - set => BitConverter.GetBytes(value).CopyTo(Data, PersonalOffset); - } - - public string TownName - { - get => StringUtil.GetString(Data, PersonalOffset + 0x04, 10); - set => StringUtil.GetBytes(value, 10).CopyTo(Data, PersonalOffset + 0x04); - } - - public byte[] GetTownIdentity() => Data.Slice(PersonalOffset + 0x00, 4 + 20); - - public uint PlayerID - { - get => BitConverter.ToUInt32(Data, PersonalOffset + 0x1C); - set => BitConverter.GetBytes(value).CopyTo(Data, PersonalOffset + 0x1C); - } - - public string PlayerName - { - get => StringUtil.GetString(Data, PersonalOffset + 0x20, 10); - set => StringUtil.GetBytes(value, 10).CopyTo(Data, PersonalOffset + 0x20); - } - - public byte[] GetPlayerIdentity() => Data.Slice(PersonalOffset + 0x1C, 4 + 20); - - /// - /// Gets/Sets the color choice (1-15) for the pixel at the given . - /// - /// Pixel index - public int this[int index] - { - get - { - var ofs = PixelDataOffset + (index / 2); - var val = Data[ofs]; - return (index & 1) == 0 ? (val & 0x0F) : (val >> 4); - } - set - { - var ofs = PixelDataOffset + (index / 2); - var val = Data[ofs]; - var update = ((index & 1) == 0) - ? (val & 0xF0) | (value & 0xF) - : (value & 0xF) << 4 | (val & 0xF); - Data[ofs] = (byte)update; - } - } - - public static int GetPixelIndex(int x, int y) => (y * Height) + x; - - public int GetPixel(int x, int y) - { - if ((uint)x >= Width) - throw new ArgumentException($"Argument out of range (0-{Width})", nameof(x)); - if ((uint)y >= Height) - throw new ArgumentException($"Argument out of range (0-{Height})", nameof(y)); - - var index = GetPixelIndex(x, y); - return this[index]; - } - - public static int GetColorOffset(int index) - { - if ((uint)index >= PaletteColorCount) - throw new ArgumentException($"Argument out of range (0-{PaletteColorCount})", nameof(index)); - return PaletteDataStart + (index * PaletteColorSize); - } - - /// - /// Builds a new array with unpacked 32bit pixel data. - /// - public byte[] GetBitmap() - { - byte[] data = new byte[4 * Width * Height]; - for (int i = 0; i < PixelCount; i++) - { - var choice = this[i]; - if (choice == PaletteColorCount) - continue; // transparent? - var palette = GetColorOffset(choice); - var ofs = i * 4; - data[ofs + 2] = Data[palette + 0]; - data[ofs + 1] = Data[palette + 1]; - data[ofs + 0] = Data[palette + 2]; - data[ofs + 3] = 0xFF; // opaque - } - return data; - } - - /// - /// Returns a raw slice of data containing the 24bit color pixels. - /// - public byte[] GetPaletteBitmap() - { - var result = new byte[3 * PaletteColorCount]; - for (int i = 0; i < PaletteColorCount; i++) - { - var ofs = PaletteDataStart + (i * 3); - result[(i * 3) + 2] = Data[ofs + 0]; - result[(i * 3) + 1] = Data[ofs + 1]; - result[(i * 3) + 0] = Data[ofs + 2]; - } - return result; + var ofs = PixelDataOffset + (index / 2); + var val = Data[ofs]; + var update = ((index & 1) == 0) + ? (val & 0xF0) | (value & 0xF) + : ((value & 0xF) << 4) | (val & 0xF); + Data[ofs] = (byte)update; } } -} + + public static int GetPixelIndex(int x, int y) => (y * Height) + x; + + public int GetPixel(int x, int y) + { + if ((uint)x >= Width) + throw new ArgumentException($"Argument out of range (0-{Width})", nameof(x)); + if ((uint)y >= Height) + throw new ArgumentException($"Argument out of range (0-{Height})", nameof(y)); + + var index = GetPixelIndex(x, y); + return this[index]; + } + + public static int GetColorOffset(int index) + { + if ((uint)index >= PaletteColorCount) + throw new ArgumentException($"Argument out of range (0-{PaletteColorCount})", nameof(index)); + return PaletteDataStart + (index * PaletteColorSize); + } + + /// + /// Builds a new array with unpacked 32bit pixel data. + /// + public byte[] GetBitmap() + { + byte[] data = new byte[4 * Width * Height]; + for (int i = 0; i < PixelCount; i++) + { + var choice = this[i]; + if (choice == PaletteColorCount) + continue; // transparent? + var palette = GetColorOffset(choice); + var ofs = i * 4; + data[ofs + 2] = Data[palette + 0]; + data[ofs + 1] = Data[palette + 1]; + data[ofs + 0] = Data[palette + 2]; + data[ofs + 3] = 0xFF; // opaque + } + return data; + } + + /// + /// Returns a raw slice of data containing the 24bit color pixels. + /// + public byte[] GetPaletteBitmap() + { + var result = new byte[3 * PaletteColorCount]; + for (int i = 0; i < PaletteColorCount; i++) + { + var ofs = PaletteDataStart + (i * 3); + result[(i * 3) + 2] = Data[ofs + 0]; + result[(i * 3) + 1] = Data[ofs + 1]; + result[(i * 3) + 0] = Data[ofs + 2]; + } + return result; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Designs/DesignPatternPRO.cs b/NHSE.Core/Structures/Designs/DesignPatternPRO.cs index 9661103..faa2188 100644 --- a/NHSE.Core/Structures/Designs/DesignPatternPRO.cs +++ b/NHSE.Core/Structures/Designs/DesignPatternPRO.cs @@ -1,147 +1,149 @@ using System; +using System.Runtime.InteropServices; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Advanced design pattern with 4 sheets arranged in a square. +/// +public class DesignPatternPRO : IVillagerOrigin { - /// - /// Advanced design pattern with 4 sheets arranged in a square. - /// - public class DesignPatternPRO : IVillagerOrigin + public const int Width = 32; + public const int Height = 32; + + public const int SIZE = 0x8A8; // 3 bytes unused at end + public const int SheetCount = 4; + private const int PersonalOffset = 0x38; + private const int PaletteDataStart = 0x78; + public const int PaletteColorCount = 15; // y not 16??? + private const int PaletteColorSize = 3; // R, G, B + private const int PixelDataOffset = PaletteDataStart + (PaletteColorCount * PaletteColorSize); // 0xA5 + private const int PixelCount = 0x400; // Width * Height + private const int SheetDataSize = PixelCount / 2; // 4bit|4bit pixel packing + + public readonly Memory Raw; + public Span Data => Raw.Span; + + public DesignPatternPRO(Memory data) => Raw = data; + + public uint Hash { - public const int Width = 32; - public const int Height = 32; - - public const int SIZE = 0x8A8; // 3 bytes unused at end - public const int SheetCount = 4; - private const int PersonalOffset = 0x38; - private const int PaletteDataStart = 0x78; - public const int PaletteColorCount = 15; // y not 16??? - private const int PaletteColorSize = 3; // R, G, B - private const int PixelDataOffset = PaletteDataStart + (PaletteColorCount * PaletteColorSize); // 0xA5 - private const int PixelCount = 0x400; // Width * Height - private const int SheetDataSize = PixelCount / 2; // 4bit|4bit pixel packing - - public readonly byte[] Data; - - public DesignPatternPRO(byte[] data) => Data = data; - - public uint Hash - { - get => BitConverter.ToUInt32(Data, 0x00); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); - } - - public uint Version - { - get => BitConverter.ToUInt32(Data, 0x04); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); - } - - public string DesignName - { - get => StringUtil.GetString(Data, 0x10, 20); - set => StringUtil.GetBytes(value, 20).CopyTo(Data, 0x10); - } - - public uint TownID - { - get => BitConverter.ToUInt32(Data, PersonalOffset); - set => BitConverter.GetBytes(value).CopyTo(Data, PersonalOffset); - } - - public string TownName - { - get => StringUtil.GetString(Data, PersonalOffset + 0x04, 10); - set => StringUtil.GetBytes(value, 10).CopyTo(Data, PersonalOffset + 0x04); - } - - public byte[] GetTownIdentity() => Data.Slice(PersonalOffset + 0x00, 4 + 20); - - public uint PlayerID - { - get => BitConverter.ToUInt32(Data, PersonalOffset + 0x1C); - set => BitConverter.GetBytes(value).CopyTo(Data, PersonalOffset + 0x1C); - } - - public string PlayerName - { - get => StringUtil.GetString(Data, PersonalOffset + 0x20, 10); - set => StringUtil.GetBytes(value, 10).CopyTo(Data, PersonalOffset + 0x20); - } - - public byte[] GetPlayerIdentity() => Data.Slice(PersonalOffset + 0x1C, 4 + 20); - - public void SetPixelAtIndex(int sheet, int index, int value) - { - var ofs = PixelDataOffset + (index / 2) + (sheet * SheetDataSize); - var val = Data[ofs]; - var update = ((index & 1) == 0) - ? (val & 0xF0) | (value & 0xF) - : (value & 0xF) << 4 | (val & 0xF); - Data[ofs] = (byte) update; - } - - private int GetPixelAtIndex(int sheet, int index) - { - var ofs = PixelDataOffset + (index / 2) + (sheet * SheetDataSize); - var val = Data[ofs]; - return (index & 1) == 0 ? (val & 0x0F) : (val >> 4); - } - - public static int GetPixelIndex(int sheet, int x, int y) => (sheet * SheetDataSize) + (y * Height) + x; - - public int GetPixel(int sheet, int x, int y) - { - if ((uint)x >= Width) - throw new ArgumentException($"Argument out of range (0-{Width})", nameof(x)); - if ((uint)y >= Height) - throw new ArgumentException($"Argument out of range (0-{Height})", nameof(y)); - - var index = GetPixelIndex(sheet, x, y); - return GetPixelAtIndex(sheet, index); - } - - public static int GetColorOffset(int index) - { - if ((uint)index >= PaletteColorCount) - throw new ArgumentException($"Argument out of range (0-{PaletteColorCount})", nameof(index)); - return PaletteDataStart + (index * PaletteColorSize); - } - - /// - /// Builds a new array with unpacked 32bit pixel data. - /// - public byte[] GetBitmap(int sheet) - { - byte[] data = new byte[4 * Width * Height]; - for (int i = 0; i < PixelCount; i++) - { - var choice = GetPixelAtIndex(sheet, i); - if (choice == PaletteColorCount) - continue; // transparent? - var palette = GetColorOffset(choice); - var ofs = i * 4; - data[ofs + 2] = Data[palette + 0]; - data[ofs + 1] = Data[palette + 1]; - data[ofs + 0] = Data[palette + 2]; - data[ofs + 3] = 0xFF; // opaque - } - return data; - } - - /// - /// Returns a raw slice of data containing the 24bit color pixels. - /// - public byte[] GetPaletteBitmap() - { - var result = new byte[3 * PaletteColorCount]; - for (int i = 0; i < PaletteColorCount; i++) - { - var ofs = PaletteDataStart + (i * 3); - result[(i * 3) + 2] = Data[ofs + 0]; - result[(i * 3) + 1] = Data[ofs + 1]; - result[(i * 3) + 0] = Data[ofs + 2]; - } - return result; - } + get => ReadUInt32LittleEndian(Data); + set => WriteUInt32LittleEndian(Data, value); } -} + + public uint Version + { + get => ReadUInt32LittleEndian(Data[0x04..]); + set => WriteUInt32LittleEndian(Data[0x04..], value); + } + + public string DesignName + { + get => StringUtil.GetString(Data, 0x10, 20); + set => StringUtil.GetBytes(value, 20).CopyTo(Data[0x10..]); + } + + public uint TownID + { + get => ReadUInt32LittleEndian(Data[PersonalOffset..]); + set => WriteUInt32LittleEndian(Data[PersonalOffset..], value); + } + + public string TownName + { + get => StringUtil.GetString(Data, PersonalOffset + 0x04, 10); + set => StringUtil.GetBytes(value, 10).CopyTo(Data[(PersonalOffset + 0x04)..]); + } + + public Span GetTownIdentity() => Data.Slice(PersonalOffset + 0x00, 4 + 20); + + public uint PlayerID + { + get => ReadUInt32LittleEndian(Data[(PersonalOffset + 0x1C)..]); + set => WriteUInt32LittleEndian(Data[(PersonalOffset + 0x1C)..], value); + } + + public string PlayerName + { + get => StringUtil.GetString(Data, PersonalOffset + 0x20, 10); + set => StringUtil.GetBytes(value, 10).CopyTo(Data[(PersonalOffset + 0x20)..]); + } + + public Span GetPlayerIdentity() => Data.Slice(PersonalOffset + 0x1C, 4 + 20); + + public void SetPixelAtIndex(int sheet, int index, int value) + { + var ofs = PixelDataOffset + (index / 2) + (sheet * SheetDataSize); + var val = Data[ofs]; + var update = ((index & 1) == 0) + ? (val & 0xF0) | (value & 0xF) + : (value & 0xF) << 4 | (val & 0xF); + Data[ofs] = (byte) update; + } + + private int GetPixelAtIndex(int sheet, int index) + { + var ofs = PixelDataOffset + (index / 2) + (sheet * SheetDataSize); + var val = Data[ofs]; + return (index & 1) == 0 ? (val & 0x0F) : (val >> 4); + } + + public static int GetPixelIndex(int sheet, int x, int y) => (sheet * SheetDataSize) + (y * Height) + x; + + public int GetPixel(int sheet, int x, int y) + { + if ((uint)x >= Width) + throw new ArgumentException($"Argument out of range (0-{Width})", nameof(x)); + if ((uint)y >= Height) + throw new ArgumentException($"Argument out of range (0-{Height})", nameof(y)); + + var index = GetPixelIndex(sheet, x, y); + return GetPixelAtIndex(sheet, index); + } + + public static int GetColorOffset(int index) + { + if ((uint)index >= PaletteColorCount) + throw new ArgumentException($"Argument out of range (0-{PaletteColorCount})", nameof(index)); + return PaletteDataStart + (index * PaletteColorSize); + } + + /// + /// Builds a new array with unpacked 32bit pixel data. + /// + public byte[] GetBitmap(int sheet) + { + byte[] data = new byte[4 * Width * Height]; + for (int i = 0; i < PixelCount; i++) + { + var choice = GetPixelAtIndex(sheet, i); + if (choice == PaletteColorCount) + continue; // transparent? + var palette = GetColorOffset(choice); + var ofs = i * 4; + data[ofs + 2] = Data[palette + 0]; + data[ofs + 1] = Data[palette + 1]; + data[ofs + 0] = Data[palette + 2]; + data[ofs + 3] = 0xFF; // opaque + } + return data; + } + + /// + /// Returns a raw slice of data containing the 24bit color pixels. + /// + public byte[] GetPaletteBitmap() + { + var result = new byte[3 * PaletteColorCount]; + for (int i = 0; i < PaletteColorCount; i++) + { + var ofs = PaletteDataStart + (i * 3); + result[(i * 3) + 2] = Data[ofs + 0]; + result[(i * 3) + 1] = Data[ofs + 1]; + result[(i * 3) + 0] = Data[ofs + 2]; + } + return result; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/GameFileDumper.cs b/NHSE.Core/Structures/GameFileDumper.cs index 35faffe..a68ba0d 100644 --- a/NHSE.Core/Structures/GameFileDumper.cs +++ b/NHSE.Core/Structures/GameFileDumper.cs @@ -2,279 +2,278 @@ using System.Collections.Generic; using System.IO; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Logic for dumping decrypted game files. +/// +/// +public static class GameFileDumper { /// - /// Logic for dumping decrypted game files. + /// Dumps a copy of the 's files in their decrypted state to the requested . /// - /// - public static class GameFileDumper + /// Save Data to dump + /// Path to dump to + public static void Dump(this HorizonSave sav, string path) { - /// - /// Dumps a copy of the 's files in their decrypted state to the requested . - /// - /// Save Data to dump - /// Path to dump to - public static void Dump(this HorizonSave sav, string path) + sav.Main.Dump(path); + foreach (var p in sav.Players) { - sav.Main.Dump(path); - foreach (var p in sav.Players) - { - var dir = Path.Combine(path, p.DirectoryName); - p.Dump(dir); - } - } - - /// - /// Dumps a copy of the 's files in their decrypted state to the requested . - /// - /// Save Data to dump - /// Path to dump to - public static void Dump(this Player player, string path) - { - foreach (var pair in player) - pair.Dump(path); - } - - /// - /// Dumps a copy of the 's files in their decrypted state to the requested . - /// - /// Save Data to dump - /// Path to dump to - public static void Dump(this EncryptedFilePair pair, string path) - { - Dump(path, pair.Data, pair.NameData); - } - - private static void Dump(string path, byte[] data, string name) - { - Directory.CreateDirectory(path); - var file = Path.Combine(path, name); - File.WriteAllBytes(file, data); - } - - /// - /// Dumps all villager houses to the requested . - /// - /// - /// - /// Path to dump to - public static void DumpPlayerHouses(this IReadOnlyList houses, IReadOnlyList players, string path) - { - for (int i = 0; i < houses.Count; i++) - { - var filename = i < players.Count ? players[i].Personal.PlayerName : $"House {i}"; - houses[i].Dump(filename, path); - } - } - - /// - /// Dumps all villager houses to the requested . - /// - /// Save Data to dump from - /// Path to dump to - public static void DumpPlayerHouses(this HorizonSave sav, string path) - { - var count = Math.Min(sav.Players.Length, MainSaveOffsets.PlayerCount); - for (int i = 0; i < count; i++) - { - var p = sav.Players[i]; - var h = sav.Main.GetPlayerHouse(i); - h.Dump(path, p.Personal); - } - } - - private static void Dump(this IPlayerHouse h, string path, IVillagerOrigin p) => h.Dump(p.PlayerName, path); - - private static void Dump(this IPlayerHouse h, string player, string path) - { - var dest = Path.Combine(path, $"{player}.{h.Extension}"); - var data = h.Write(); - File.WriteAllBytes(dest, data); - } - - /// - /// Dumps all villager houses to the requested . - /// - /// Save Data to dump from - /// Path to dump to - public static void DumpVillagerHouses(this MainSave sav, string path) - { - for (int i = 0; i < MainSaveOffsets.VillagerCount; i++) - { - var v = sav.GetVillager(i); - var h = sav.GetVillagerHouse(i); - h.Dump(path, v); - } - } - - private static void Dump(this IVillagerHouse h, string path, IVillager v) - { - var name = GameInfo.Strings.GetVillager(v.InternalName); - var dest = Path.Combine(path, $"{name}.{h.Extension}"); - var data = h.Write(); - File.WriteAllBytes(dest, data); - } - - /// - /// Dumps all villagers to the requested . - /// - /// Data to dump from - /// Path to dump to - public static void Dump(this IEnumerable villagers, string path) - { - foreach (var v in villagers) - v.Dump(path); - } - - private static void Dump(this IVillager v, string path) - { - var name = GameInfo.Strings.GetVillager(v.InternalName); - var dest = Path.Combine(path, $"{name}.{v.Extension}"); - File.WriteAllBytes(dest, v.Write()); - } - - /// - /// Dumps all designs to the requested . - /// - /// Save Data to dump from - /// Path to dump to - /// Export file names prepended with design index - public static void DumpDesigns(this MainSave sav, string path, bool indexed) - { - for (int i = 0; i < sav.Offsets.PatternCount; i++) - { - var dp = sav.GetDesign(i); - dp.Dump(path, i, indexed); - } - } - - /// - /// Dumps all designs to the requested . - /// - /// Patterns to dump - /// Path to dump to - /// Export file names prepended with design index - public static void Dump(this IReadOnlyList patterns, string path, bool indexed) - { - for (var index = 0; index < patterns.Count; index++) - { - var dp = patterns[index]; - dp.Dump(path, index, indexed); - } - } - - private static void Dump(this DesignPattern dp, string path, int index, bool indexed) - { - var name = dp.DesignName; - string fn = indexed - ? $"{index:00} - {name}.nhd" - : $"{name}.nhd"; - fn = StringUtil.CleanFileName(fn); - var dest = Path.Combine(path, fn); - File.WriteAllBytes(dest, dp.Data); - } - - /// - /// Loads all designs from the requested . - /// - /// Patterns to load - /// Path to load from - /// Change origins of Patterns - public static void Load(this DesignPattern[] patterns, string path, bool changeOrigins) - { - if (patterns.Length == 0) - return; - - var files = Directory.GetFiles(path, "*.nhd", SearchOption.TopDirectoryOnly); - int ctr = 0; - foreach (var f in files) - { - var fi = new FileInfo(f); - if (fi.Length != DesignPattern.SIZE) - continue; - - var data = File.ReadAllBytes(f); - var p = new DesignPattern(data); - if (changeOrigins) - p.ChangeOrigins(patterns[ctr], data); - patterns[ctr] = p; - if (++ctr >= patterns.Length) - break; - } - } - - /// - /// Dumps all designs to the requested . - /// - /// Save Data to dump from - /// Path to dump to - /// Export file names prepended with design index - public static void DumpDesignsPRO(this MainSave sav, string path, bool indexed) - { - for (int i = 0; i < sav.Offsets.PatternCount; i++) - { - var dp = sav.GetDesignPRO(i); - dp.Dump(path, i, indexed); - } - } - - /// - /// Dumps all designs to the requested . - /// - /// Patterns to dump - /// Path to dump to - /// Export file names prepended with design index - public static void Dump(this IReadOnlyList patterns, string path, bool indexed) - { - for (var index = 0; index < patterns.Count; index++) - { - var dp = patterns[index]; - dp.Dump(path, index, indexed); - } - } - - /// - /// Loads all designs from the requested . - /// - /// Patterns to load - /// Path to load from - /// Change origins of Patterns - /// Sort the files by file name instead of depending on the Operating System's return order - public static void Load(this DesignPatternPRO[] patterns, string path, bool changeOrigins, bool sortAlpha = true) - { - if (patterns.Length == 0) - return; - - var files = Directory.GetFiles(path, "*.nhpd", SearchOption.TopDirectoryOnly); - if (sortAlpha) - Array.Sort(files); - int ctr = 0; - foreach (var f in files) - { - var fi = new FileInfo(f); - if (fi.Length != DesignPatternPRO.SIZE) - continue; - - var data = File.ReadAllBytes(f); - var p = new DesignPatternPRO(data); - if (changeOrigins) - p.ChangeOrigins(patterns[ctr], data); - patterns[ctr] = p; - if (++ctr >= patterns.Length) - break; - } - } - - private static void Dump(this DesignPatternPRO dp, string path, int index, bool indexed) - { - var name = dp.DesignName; - string fn = indexed - ? $"{index:00} - {name}.nhpd" - : $"{name}.nhpd"; - fn = StringUtil.CleanFileName(fn); - var dest = Path.Combine(path, fn); - File.WriteAllBytes(dest, dp.Data); + var dir = Path.Combine(path, p.DirectoryName); + p.Dump(dir); } } -} + + /// + /// Dumps a copy of the 's files in their decrypted state to the requested . + /// + /// Save Data to dump + /// Path to dump to + public static void Dump(this Player player, string path) + { + foreach (var pair in player) + pair.Dump(path); + } + + /// + /// Dumps a copy of the 's files in their decrypted state to the requested . + /// + /// Save Data to dump + /// Path to dump to + public static void Dump(this EncryptedFilePair pair, string path) + { + Dump(path, pair.Data, pair.NameData); + } + + private static void Dump(string path, ReadOnlySpan data, string name) + { + Directory.CreateDirectory(path); + var file = Path.Combine(path, name); + File.WriteAllBytes(file, data); + } + + /// + /// Dumps all villager houses to the requested . + /// + /// + /// + /// Path to dump to + public static void DumpPlayerHouses(this IReadOnlyList houses, IReadOnlyList players, string path) + { + for (int i = 0; i < houses.Count; i++) + { + var filename = i < players.Count ? players[i].Personal.PlayerName : $"House {i}"; + houses[i].Dump(filename, path); + } + } + + /// + /// Dumps all villager houses to the requested . + /// + /// Save Data to dump from + /// Path to dump to + public static void DumpPlayerHouses(this HorizonSave sav, string path) + { + var count = Math.Min(sav.Players.Length, MainSaveOffsets.PlayerCount); + for (int i = 0; i < count; i++) + { + var p = sav.Players[i]; + var h = sav.Main.GetPlayerHouse(i); + h.Dump(path, p.Personal); + } + } + + private static void Dump(this IPlayerHouse h, string path, Personal p) => h.Dump(p.PlayerName, path); + + private static void Dump(this IPlayerHouse h, string player, string path) + { + var dest = Path.Combine(path, $"{player}.{h.Extension}"); + var data = h.Write(); + File.WriteAllBytes(dest, data); + } + + /// + /// Dumps all villager houses to the requested . + /// + /// Save Data to dump from + /// Path to dump to + public static void DumpVillagerHouses(this MainSave sav, string path) + { + for (int i = 0; i < MainSaveOffsets.VillagerCount; i++) + { + var v = sav.GetVillager(i); + var h = sav.GetVillagerHouse(i); + h.Dump(path, v); + } + } + + private static void Dump(this IVillagerHouse h, string path, IVillager v) + { + var name = GameInfo.Strings.GetVillager(v.InternalName); + var dest = Path.Combine(path, $"{name}.{h.Extension}"); + var data = h.Write(); + File.WriteAllBytes(dest, data); + } + + /// + /// Dumps all villagers to the requested . + /// + /// Data to dump from + /// Path to dump to + public static void Dump(this IEnumerable villagers, string path) + { + foreach (var v in villagers) + v.Dump(path); + } + + private static void Dump(this IVillager v, string path) + { + var name = GameInfo.Strings.GetVillager(v.InternalName); + var dest = Path.Combine(path, $"{name}.{v.Extension}"); + File.WriteAllBytes(dest, v.Write()); + } + + /// + /// Dumps all designs to the requested . + /// + /// Save Data to dump from + /// Path to dump to + /// Export file names prepended with design index + public static void DumpDesigns(this MainSave sav, string path, bool indexed) + { + for (int i = 0; i < sav.Offsets.PatternCount; i++) + { + var dp = sav.GetDesign(i); + dp.Dump(path, i, indexed); + } + } + + /// + /// Dumps all designs to the requested . + /// + /// Patterns to dump + /// Path to dump to + /// Export file names prepended with design index + public static void Dump(this IReadOnlyList patterns, string path, bool indexed) + { + for (var index = 0; index < patterns.Count; index++) + { + var dp = patterns[index]; + dp.Dump(path, index, indexed); + } + } + + private static void Dump(this DesignPattern dp, string path, int index, bool indexed) + { + var name = dp.DesignName; + string fn = indexed + ? $"{index:00} - {name}.nhd" + : $"{name}.nhd"; + fn = StringUtil.CleanFileName(fn); + var dest = Path.Combine(path, fn); + File.WriteAllBytes(dest, dp.Data); + } + + /// + /// Loads all designs from the requested . + /// + /// Patterns to load + /// Path to load from + /// Change origins of Patterns + public static void Load(this DesignPattern[] patterns, string path, bool changeOrigins) + { + if (patterns.Length == 0) + return; + + var files = Directory.GetFiles(path, "*.nhd", SearchOption.TopDirectoryOnly); + int ctr = 0; + foreach (var f in files) + { + var fi = new FileInfo(f); + if (fi.Length != DesignPattern.SIZE) + continue; + + var data = File.ReadAllBytes(f); + var p = new DesignPattern(data); + if (changeOrigins) + p.ChangeOrigins(patterns[ctr], data); + patterns[ctr] = p; + if (++ctr >= patterns.Length) + break; + } + } + + /// + /// Dumps all designs to the requested . + /// + /// Save Data to dump from + /// Path to dump to + /// Export file names prepended with design index + public static void DumpDesignsPRO(this MainSave sav, string path, bool indexed) + { + for (int i = 0; i < sav.Offsets.PatternCount; i++) + { + var dp = sav.GetDesignPRO(i); + dp.Dump(path, i, indexed); + } + } + + /// + /// Dumps all designs to the requested . + /// + /// Patterns to dump + /// Path to dump to + /// Export file names prepended with design index + public static void Dump(this IReadOnlyList patterns, string path, bool indexed) + { + for (var index = 0; index < patterns.Count; index++) + { + var dp = patterns[index]; + dp.Dump(path, index, indexed); + } + } + + /// + /// Loads all designs from the requested . + /// + /// Patterns to load + /// Path to load from + /// Change origins of Patterns + /// Sort the files by file name instead of depending on the Operating System's return order + public static void Load(this DesignPatternPRO[] patterns, string path, bool changeOrigins, bool sortAlpha = true) + { + if (patterns.Length == 0) + return; + + var files = Directory.GetFiles(path, "*.nhpd", SearchOption.TopDirectoryOnly); + if (sortAlpha) + Array.Sort(files); + int ctr = 0; + foreach (var f in files) + { + var fi = new FileInfo(f); + if (fi.Length != DesignPatternPRO.SIZE) + continue; + + var data = File.ReadAllBytes(f); + var p = new DesignPatternPRO(data); + if (changeOrigins) + p.ChangeOrigins(patterns[ctr], data); + patterns[ctr] = p; + if (++ctr >= patterns.Length) + break; + } + } + + private static void Dump(this DesignPatternPRO dp, string path, int index, bool indexed) + { + var name = dp.DesignName; + string fn = indexed + ? $"{index:00} - {name}.nhpd" + : $"{name}.nhpd"; + fn = StringUtil.CleanFileName(fn); + var dest = Path.Combine(path, fn); + File.WriteAllBytes(dest, dp.Data); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/GameFileLoader.cs b/NHSE.Core/Structures/GameFileLoader.cs index f808d72..a26882a 100644 --- a/NHSE.Core/Structures/GameFileLoader.cs +++ b/NHSE.Core/Structures/GameFileLoader.cs @@ -1,63 +1,63 @@ -using System.IO; +using System; +using System.IO; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Logic for loading decrypted game files. +/// +/// +public static class GameFileLoader { /// - /// Logic for loading decrypted game files. + /// Loads a copy of the 's files in their decrypted state from the requested . /// - /// - public static class GameFileLoader + /// Save Data to load + /// Path to load from + public static void Load(this HorizonSave sav, string path) { - /// - /// Loads a copy of the 's files in their decrypted state from the requested . - /// - /// Save Data to load - /// Path to load from - public static void Load(this HorizonSave sav, string path) + sav.Main.Load(path); + foreach (var p in sav.Players) { - sav.Main.Load(path); - foreach (var p in sav.Players) - { - var dir = Path.Combine(path, p.DirectoryName); - p.Load(dir); - } - } - - /// - /// Loads a copy of the 's files in their decrypted state from the requested . - /// - /// Save Data to load - /// Path to load from - public static void Load(this Player player, string path) - { - foreach (var pair in player) - pair.Load(path); - } - - /// - /// Loads the 's files in their decrypted state from the requested . - /// - /// Save Data to load - /// Path to load from - public static void Load(this EncryptedFilePair pair, string path) - { - Load(path, pair.Data, pair.NameData); - } - - private static void Load(string path, byte[] data, string name) - { - if (!Directory.Exists(path)) - return; - - var file = Path.Combine(path, name); - if (!File.Exists(file)) - return; - - var import = File.ReadAllBytes(file); - if (data.Length != import.Length) - return; - - import.CopyTo(data, 0); + var dir = Path.Combine(path, p.DirectoryName); + p.Load(dir); } } + + /// + /// Loads a copy of the 's files in their decrypted state from the requested . + /// + /// Save Data to load + /// Path to load from + public static void Load(this Player player, string path) + { + foreach (var pair in player) + pair.Load(path); + } + + /// + /// Loads the 's files in their decrypted state from the requested . + /// + /// Save Data to load + /// Path to load from + public static void Load(this EncryptedFilePair pair, string path) + { + Load(path, pair.Data, pair.NameData); + } + + private static void Load(string path, Span data, string name) + { + if (!Directory.Exists(path)) + return; + + var file = Path.Combine(path, name); + if (!File.Exists(file)) + return; + + var import = File.ReadAllBytes(file); + if (data.Length != import.Length) + return; + + import.CopyTo(data); + } } \ No newline at end of file diff --git a/NHSE.Core/Structures/GameLists.cs b/NHSE.Core/Structures/GameLists.cs index 6bcbd24..79ddc4d 100644 --- a/NHSE.Core/Structures/GameLists.cs +++ b/NHSE.Core/Structures/GameLists.cs @@ -1,442 +1,454 @@ -using System.Collections.Generic; +using System; -namespace NHSE.Core +namespace NHSE.Core; + +public static class GameLists { - public static class GameLists - { - public static readonly IReadOnlyList Fruits = new ushort[] - { - 2213, // apple - 2287, // Cherry - 2214, // Orange - 2286, // Peach - 2285, // Pear - }; + public static ReadOnlySpan Fruits => + [ + 2213, // apple + 2287, // Cherry + 2214, // Orange + 2286, // Peach + 2285 // Pear + ]; - public static readonly IReadOnlyList Bugs = new ushort[] - { - 00582, // brown cicada - 00583, // tiger butterfly - 00584, // Rajah Brooke's birdwing - 00585, // red dragonfly - 00586, // Queen Alexandra's birdwing - 00587, // pondskater - 00588, // ant - 00590, // pill bug - 00591, // wharf roach - 00592, // moth - 00594, // diving beetle - 00595, // darner dragonfly - 00596, // goliath beetle - 00597, // fly - 00598, // orchid mantis - 00599, // tiger beetle - 00600, // horned hercules - 00601, // evening cicada - 00602, // cyclommatus stag - 00603, // firefly - 00604, // dung beetle - 00605, // rice grasshopper - 00606, // mosquito - 00607, // mantis - 00608, // stinkbug - 00609, // citrus long-horned beetle - 00610, // peacock butterfly - 00611, // snail - 00612, // horned dynastid - 00613, // grasshopper - 00614, // earth-boring dung beetle - 00615, // horned atlas - 00616, // walking leaf - 00617, // cricket - 00618, // giant cicada - 00619, // spider - 00620, // agrias butterfly - 00621, // robust cicada - 00622, // bagworm - 00623, // honeybee - 00624, // miyama stag - 00625, // yellow butterfly - 00626, // common butterfly - 00627, // emperor butterfly - 00628, // centipede - 00630, // walking stick - 00631, // rainbow stag - 00632, // saw stag - 00633, // flea - 00634, // mole cricket - 00635, // banded dragonfly - 00636, // monarch butterfly - 00637, // giant stag - 00638, // golden stag - 00639, // scarab beetle - 00640, // scorpion - 00641, // cicada shell - 00642, // bell cricket - 00643, // wasp - 00644, // long locust - 00645, // jewel beetle - 00646, // tarantula - 00647, // ladybug - 00648, // migratory locust - 00649, // walker cicada - 00650, // violin beetle - 00651, // hermit crab - 00652, // Atlas moth - 00653, // horned elephant - 03477, // common bluebottle - 03478, // paper kite butterfly - 03479, // great purple emperor - 03480, // drone beetle - 03482, // giraffe stag - 03483, // man-faced stink bug - 03484, // Madagascan sunset moth - 03485, // blue weevil beetle - 03487, // rosalia batesi beetle - 03539, // snowflake - 03540, // large snowflake - 04702, // Wisp spirit piece - 05157, // giant water bug - 05339, // damselfly - 05859, // cherry-blossom petal - 07374, // maple leaf - }; + public static ReadOnlySpan Bugs => + [ + 00582, // brown cicada + 00583, // tiger butterfly + 00584, // Rajah Brooke's birdwing + 00585, // red dragonfly + 00586, // Queen Alexandra's birdwing + 00587, // pondskater + 00588, // ant + 00590, // pill bug + 00591, // wharf roach + 00592, // moth + 00594, // diving beetle + 00595, // darner dragonfly + 00596, // goliath beetle + 00597, // fly + 00598, // orchid mantis + 00599, // tiger beetle + 00600, // horned hercules + 00601, // evening cicada + 00602, // cyclommatus stag + 00603, // firefly + 00604, // dung beetle + 00605, // rice grasshopper + 00606, // mosquito + 00607, // mantis + 00608, // stinkbug + 00609, // citrus long-horned beetle + 00610, // peacock butterfly + 00611, // snail + 00612, // horned dynastid + 00613, // grasshopper + 00614, // earth-boring dung beetle + 00615, // horned atlas + 00616, // walking leaf + 00617, // cricket + 00618, // giant cicada + 00619, // spider + 00620, // agrias butterfly + 00621, // robust cicada + 00622, // bagworm + 00623, // honeybee + 00624, // miyama stag + 00625, // yellow butterfly + 00626, // common butterfly + 00627, // emperor butterfly + 00628, // centipede + 00630, // walking stick + 00631, // rainbow stag + 00632, // saw stag + 00633, // flea + 00634, // mole cricket + 00635, // banded dragonfly + 00636, // monarch butterfly + 00637, // giant stag + 00638, // golden stag + 00639, // scarab beetle + 00640, // scorpion + 00641, // cicada shell + 00642, // bell cricket + 00643, // wasp + 00644, // long locust + 00645, // jewel beetle + 00646, // tarantula + 00647, // ladybug + 00648, // migratory locust + 00649, // walker cicada + 00650, // violin beetle + 00651, // hermit crab + 00652, // Atlas moth + 00653, // horned elephant + 03477, // common bluebottle + 03478, // paper kite butterfly + 03479, // great purple emperor + 03480, // drone beetle + 03482, // giraffe stag + 03483, // man-faced stink bug + 03484, // Madagascan sunset moth + 03485, // blue weevil beetle + 03487, // rosalia batesi beetle + 03539, // snowflake + 03540, // large snowflake + 04702, // Wisp spirit piece + 05157, // giant water bug + 05339, // damselfly + 05859, // cherry-blossom petal + 07374 // maple leaf + ]; - public static readonly IReadOnlyList Fish = new ushort[] - { - 00328, // crucian carp - 00329, // goldfish - 02215, // bitterling - 02216, // pale chub - 02217, // dace - 02219, // carp - 02220, // koi - 02221, // pop-eyed goldfish - 02222, // killifish - 02223, // crawfish - 02224, // soft-shelled turtle - 02225, // tadpole - 02226, // frog - 02227, // freshwater goby - 02228, // loach - 02229, // catfish - 02231, // giant snakehead - 02232, // bluegill - 02233, // yellow perch - 02234, // black bass - 02235, // pike - 02236, // pond smelt - 02237, // sweetfish - 02238, // cherry salmon - 02239, // char - 02241, // stringfish - 02242, // salmon - 02243, // king salmon - 02244, // mitten crab - 02245, // guppy - 02246, // nibble fish - 02247, // angelfish - 02248, // neon tetra - 02249, // piranha - 02250, // arowana - 02251, // dorado - 02252, // gar - 02253, // arapaima - 02254, // saddled bichir - 02255, // sea butterfly - 02256, // sea horse - 02257, // clown fish - 02258, // surgeonfish - 02259, // butterfly fish - 02260, // Napoleonfish - 02261, // zebra turkeyfish - 02262, // blowfish - 02263, // puffer fish - 02264, // horse mackerel - 02265, // barred knifejaw - 02266, // sea bass - 02267, // red snapper - 02268, // dab - 02269, // olive flounder - 02270, // squid - 02271, // moray eel - 02272, // ribbon eel - 02273, // football fish - 02274, // tuna - 02275, // blue marlin - 02276, // giant trevally - 02277, // ray - 02278, // ocean sunfish - 02279, // hammerhead shark - 02280, // great white shark - 02281, // saw shark - 02282, // whale shark - 02283, // oarfish - 02284, // coelacanth - 02502, // stone - 03466, // empty can - 03469, // boot - 03470, // old tire - 04189, // sturgeon - 04190, // tilapia - 04191, // betta - 04192, // snapping turtle - 04193, // golden trout - 04194, // rainbowfish - 04201, // anchovy - 04202, // mahi-mahi - 04203, // suckerfish - 04204, // barreleye - 05254, // ranchu goldfish - 12514, // water egg - }; + public static ReadOnlySpan Fish => + [ + 00328, // crucian carp + 00329, // goldfish + 02215, // bitterling + 02216, // pale chub + 02217, // dace + 02219, // carp + 02220, // koi + 02221, // pop-eyed goldfish + 02222, // killifish + 02223, // crawfish + 02224, // soft-shelled turtle + 02225, // tadpole + 02226, // frog + 02227, // freshwater goby + 02228, // loach + 02229, // catfish + 02231, // giant snakehead + 02232, // bluegill + 02233, // yellow perch + 02234, // black bass + 02235, // pike + 02236, // pond smelt + 02237, // sweetfish + 02238, // cherry salmon + 02239, // char + 02241, // stringfish + 02242, // salmon + 02243, // king salmon + 02244, // mitten crab + 02245, // guppy + 02246, // nibble fish + 02247, // angelfish + 02248, // neon tetra + 02249, // piranha + 02250, // arowana + 02251, // dorado + 02252, // gar + 02253, // arapaima + 02254, // saddled bichir + 02255, // sea butterfly + 02256, // sea horse + 02257, // clown fish + 02258, // surgeonfish + 02259, // butterfly fish + 02260, // Napoleonfish + 02261, // zebra turkeyfish + 02262, // blowfish + 02263, // puffer fish + 02264, // horse mackerel + 02265, // barred knifejaw + 02266, // sea bass + 02267, // red snapper + 02268, // dab + 02269, // olive flounder + 02270, // squid + 02271, // moray eel + 02272, // ribbon eel + 02273, // football fish + 02274, // tuna + 02275, // blue marlin + 02276, // giant trevally + 02277, // ray + 02278, // ocean sunfish + 02279, // hammerhead shark + 02280, // great white shark + 02281, // saw shark + 02282, // whale shark + 02283, // oarfish + 02284, // coelacanth + 02502, // stone + 03466, // empty can + 03469, // boot + 03470, // old tire + 04189, // sturgeon + 04190, // tilapia + 04191, // betta + 04192, // snapping turtle + 04193, // golden trout + 04194, // rainbowfish + 04201, // anchovy + 04202, // mahi-mahi + 04203, // suckerfish + 04204, // barreleye + 05254, // ranchu goldfish + 12514 // water egg + ]; - public static readonly IReadOnlyList Fossils = new ushort[] - { - 00169, // ankylo skull - 00170, // ankylo torso - 00171, // ankylo tail - 00177, // archelon skull - 00178, // archelon tail - 00180, // megacero skull - 00181, // megacero torso - 00182, // megacero tail - 00184, // dimetrodon skull - 00185, // dimetrodon torso - 00188, // iguanodon skull - 00189, // iguanodon torso - 00190, // iguanodon tail - 00192, // ophthalmo skull - 00193, // ophthalmo torso - 00195, // mammoth skull - 00196, // mammoth torso - 00198, // pachy skull - 00199, // pachy tail - 00202, // parasaur skull - 00203, // parasaur torso - 00204, // parasaur tail - 00206, // ptera body - 00207, // right ptera wing - 00208, // left ptera wing - 00210, // deinony torso - 00211, // deinony tail - 00213, // sabertooth skull - 00214, // sabertooth tail - 00216, // diplo skull - 00217, // diplo neck - 00218, // diplo chest - 00219, // diplo pelvis - 00220, // diplo tail - 00222, // spino skull - 00223, // spino torso - 00224, // spino tail - 00226, // stego skull - 00227, // stego torso - 00228, // stego tail - 00234, // plesio skull - 00235, // plesio torso - 00236, // plesio tail - 00238, // T. rex skull - 00239, // T. rex torso - 00240, // T. rex tail - 00242, // tricera skull - 00243, // tricera torso - 00244, // tricera tail - 00294, // amber - 00295, // ammonite - 00296, // coprolite - 00298, // archaeopteryx - 00300, // dinosaur track - 00301, // australopith - 00302, // shark-tooth pattern - 00303, // trilobite - 04651, // anomalocaris - 04658, // right megalo side - 04659, // left megalo side - 04660, // dunkleosteus - 04662, // myllokunmingia - 04663, // eusthenopteron - 04664, // acanthostega - 04665, // juramaia - 04688, // brachio skull - 04689, // brachio chest - 04690, // brachio pelvis - 04691, // brachio tail - 04697, // quetzal torso - 04698, // right quetzal wing - 04699, // left quetzal wing - 07251, // diplo tail tip - }; + public static ReadOnlySpan Fossils => + [ + 00169, // ankylo skull + 00170, // ankylo torso + 00171, // ankylo tail + 00177, // archelon skull + 00178, // archelon tail + 00180, // megacero skull + 00181, // megacero torso + 00182, // megacero tail + 00184, // dimetrodon skull + 00185, // dimetrodon torso + 00188, // iguanodon skull + 00189, // iguanodon torso + 00190, // iguanodon tail + 00192, // ophthalmo skull + 00193, // ophthalmo torso + 00195, // mammoth skull + 00196, // mammoth torso + 00198, // pachy skull + 00199, // pachy tail + 00202, // parasaur skull + 00203, // parasaur torso + 00204, // parasaur tail + 00206, // ptera body + 00207, // right ptera wing + 00208, // left ptera wing + 00210, // deinony torso + 00211, // deinony tail + 00213, // sabertooth skull + 00214, // sabertooth tail + 00216, // diplo skull + 00217, // diplo neck + 00218, // diplo chest + 00219, // diplo pelvis + 00220, // diplo tail + 00222, // spino skull + 00223, // spino torso + 00224, // spino tail + 00226, // stego skull + 00227, // stego torso + 00228, // stego tail + 00234, // plesio skull + 00235, // plesio torso + 00236, // plesio tail + 00238, // T. rex skull + 00239, // T. rex torso + 00240, // T. rex tail + 00242, // tricera skull + 00243, // tricera torso + 00244, // tricera tail + 00294, // amber + 00295, // ammonite + 00296, // coprolite + 00298, // archaeopteryx + 00300, // dinosaur track + 00301, // australopith + 00302, // shark-tooth pattern + 00303, // trilobite + 04651, // anomalocaris + 04658, // right megalo side + 04659, // left megalo side + 04660, // dunkleosteus + 04662, // myllokunmingia + 04663, // eusthenopteron + 04664, // acanthostega + 04665, // juramaia + 04688, // brachio skull + 04689, // brachio chest + 04690, // brachio pelvis + 04691, // brachio tail + 04697, // quetzal torso + 04698, // right quetzal wing + 04699, // left quetzal wing + 07251 // diplo tail tip + ]; - public static readonly IReadOnlyList Art = new ushort[] - { - 00002, // scenic painting - 00005, // graceful painting (forgery) - 00006, // graceful painting - 00009, // quaint painting (forgery) - 00010, // quaint painting - 00013, // basic painting (forgery) - 00014, // basic painting - 00017, // famous painting (forgery) - 00018, // famous painting - 00020, // perfect painting - 00023, // serene painting (forgery) - 00024, // serene painting - 00027, // wistful painting (forgery) - 00028, // wistful painting - 00031, // moving painting (forgery) - 00032, // moving painting - 00034, // warm painting - 00038, // dynamic painting - 00041, // jolly painting (forgery) - 00042, // jolly painting - 00044, // common painting - 00046, // proper painting - 00048, // nice painting - 00050, // flowery painting - 00052, // moody painting - 00055, // amazing painting (forgery) - 00056, // amazing painting - 00065, // scary painting (forgery) - 00066, // scary painting - 00068, // worthy painting - 00071, // solemn painting (forgery) - 00072, // solemn painting - 00075, // wild painting right half (forgery) - 00076, // wild painting right half - 00078, // calm painting - 01331, // motherly statue - 01332, // motherly statue (forgery) - 01333, // gallant statue - 01334, // gallant statue (forgery) - 01335, // robust statue - 01336, // robust statue (forgery) - 01337, // ancient statue - 01338, // ancient statue (forgery) - 01339, // great statue - 01341, // beautiful statue - 01342, // beautiful statue (forgery) - 01343, // mystic statue - 01344, // mystic statue (forgery) - 01345, // valiant statue - 01346, // valiant statue (forgery) - 12533, // rock-head statue - 12534, // rock-head statue (forgery) - 12535, // informative statue - 12536, // informative statue (forgery) - 12537, // tremendous statue - 12538, // tremendous statue (forgery) - 12539, // warrior statue - 12540, // warrior statue (forgery) - 12541, // familiar statue - 12570, // wild painting left half - 12571, // wild painting left half (forgery) - 12618, // twinkling painting - 12619, // academic painting - 12620, // academic painting (forgery) - 12621, // sinking painting - 12622, // detailed painting - 12623, // detailed painting (forgery) - 12624, // glowing painting - 12625, // mysterious painting - 12629, // scenic painting (forgery) - }; + public static ReadOnlySpan Art => + [ + 00002, // scenic painting + 00005, // graceful painting (forgery) + 00006, // graceful painting + 00009, // quaint painting (forgery) + 00010, // quaint painting + 00013, // basic painting (forgery) + 00014, // basic painting + 00017, // famous painting (forgery) + 00018, // famous painting + 00020, // perfect painting + 00023, // serene painting (forgery) + 00024, // serene painting + 00027, // wistful painting (forgery) + 00028, // wistful painting + 00031, // moving painting (forgery) + 00032, // moving painting + 00034, // warm painting + 00038, // dynamic painting + 00041, // jolly painting (forgery) + 00042, // jolly painting + 00044, // common painting + 00046, // proper painting + 00048, // nice painting + 00050, // flowery painting + 00052, // moody painting + 00055, // amazing painting (forgery) + 00056, // amazing painting + 00065, // scary painting (forgery) + 00066, // scary painting + 00068, // worthy painting + 00071, // solemn painting (forgery) + 00072, // solemn painting + 00075, // wild painting right half (forgery) + 00076, // wild painting right half + 00078, // calm painting + 01331, // motherly statue + 01332, // motherly statue (forgery) + 01333, // gallant statue + 01334, // gallant statue (forgery) + 01335, // robust statue + 01336, // robust statue (forgery) + 01337, // ancient statue + 01338, // ancient statue (forgery) + 01339, // great statue + 01341, // beautiful statue + 01342, // beautiful statue (forgery) + 01343, // mystic statue + 01344, // mystic statue (forgery) + 01345, // valiant statue + 01346, // valiant statue (forgery) + 12533, // rock-head statue + 12534, // rock-head statue (forgery) + 12535, // informative statue + 12536, // informative statue (forgery) + 12537, // tremendous statue + 12538, // tremendous statue (forgery) + 12539, // warrior statue + 12540, // warrior statue (forgery) + 12541, // familiar statue + 12570, // wild painting left half + 12571, // wild painting left half (forgery) + 12618, // twinkling painting + 12619, // academic painting + 12620, // academic painting (forgery) + 12621, // sinking painting + 12622, // detailed painting + 12623, // detailed painting (forgery) + 12624, // glowing painting + 12625, // mysterious painting + 12629 // scenic painting (forgery) + ]; - public static readonly IReadOnlyList Dive = new ushort[] - { - 02620, // seaweed - 02830, // sea grapes - 02831, // sea urchin - 02832, // acorn barnacle - 02833, // oyster - 02834, // turban shell - 02835, // abalone - 02838, // pearl oyster - 02839, // scallop - 02840, // sea anemone - 02841, // sea star - 02842, // sea cucumber - 02843, // sea slug - 02844, // flatworm - 02845, // mantis shrimp - 02846, // sweet shrimp - 02847, // tiger prawn - 02848, // spiny lobster - 02849, // lobster - 02850, // snow crab - 02852, // red king crab - 02853, // spider crab - 02854, // octopus - 02855, // spotted garden eel - 02856, // chambered nautilus - 02857, // horseshoe crab - 02858, // giant isopod - 06920, // firefly squid - 07191, // gazami crab - 07203, // vampire squid - 07214, // gigas giant clam - 07228, // sea pineapple - 07245, // moon jellyfish - 07252, // umbrella octopus - 07267, // slate pencil urchin - 07278, // whelk - 07303, // sea pig - 07308, // Dungeness crab - 07318, // Venus' flower basket - 07411, // mussel - }; + public static ReadOnlySpan Dive => + [ + 02620, // seaweed + 02830, // sea grapes + 02831, // sea urchin + 02832, // acorn barnacle + 02833, // oyster + 02834, // turban shell + 02835, // abalone + 02838, // pearl oyster + 02839, // scallop + 02840, // sea anemone + 02841, // sea star + 02842, // sea cucumber + 02843, // sea slug + 02844, // flatworm + 02845, // mantis shrimp + 02846, // sweet shrimp + 02847, // tiger prawn + 02848, // spiny lobster + 02849, // lobster + 02850, // snow crab + 02852, // red king crab + 02853, // spider crab + 02854, // octopus + 02855, // spotted garden eel + 02856, // chambered nautilus + 02857, // horseshoe crab + 02858, // giant isopod + 06920, // firefly squid + 07191, // gazami crab + 07203, // vampire squid + 07214, // gigas giant clam + 07228, // sea pineapple + 07245, // moon jellyfish + 07252, // umbrella octopus + 07267, // slate pencil urchin + 07278, // whelk + 07303, // sea pig + 07308, // Dungeness crab + 07318, // Venus' flower basket + 07411 // mussel + ]; - public static readonly HashSet Shells = new() - { - 1374, // sea snail - 1375, // venus comb - 1376, // conch - // 2 unused 1377, 1378 - 1379, // sand dollar - 1380, // coral - 1381, // giant clam - 1382, // cowrie + public static ReadOnlySpan Shells => + [ + 1374, // sea snail + 1375, // venus comb + 1376, // conch + // 2 unused 1377, 1378 + 1379, // sand dollar + 1380, // coral + 1381, // giant clam + 1382, // cowrie - 5982, // summer shell - 12968, // pearl - }; + 5982, // summer shell + 12968 // pearl + ]; - public static readonly HashSet Terraforming = new() - { - 3075, // path construction permit - 3247, // waterscaping permit - 8773, // stone path permit - 8774, // brick path permit - 8775, // dark dirt path permit - 8776, // arched tile path permit - 8777, // sand path permit - 8778, // terra-cotta tile permit - 8779, // wooden path permit - 8780, // waterscaping permit - 8781, // cliff construction permit - 9771, // custom design path permit - }; + public static ReadOnlySpan Terraforming => + [ + 3075, // path construction permit + 3247, // waterscaping permit + 8773, // stone path permit + 8774, // brick path permit + 8775, // dark dirt path permit + 8776, // arched tile path permit + 8777, // sand path permit + 8778, // terra-cotta tile permit + 8779, // wooden path permit + 8780, // waterscaping permit + 8781, // cliff construction permit + 9771 // custom design path permit + ]; - public static readonly HashSet NoCheckReceived = new(Terraforming) - { - Item.DIYRecipe, + public static ReadOnlySpan NoCheckReceived => + [ + 3075, // path construction permit + 3247, // waterscaping permit + 8773, // stone path permit + 8774, // brick path permit + 8775, // dark dirt path permit + 8776, // arched tile path permit + 8777, // sand path permit + 8778, // terra-cotta tile permit + 8779, // wooden path permit + 8780, // waterscaping permit + 8781, // cliff construction permit + 9771, // custom design path permit - 9046, // Vaulting Pole Recipe - 9047, // Flimsy Shovel Recipe - 9048, // Flimsy Watering Can Recipe - 9049, // Top 8 Pop Hairstyles - 9050, // Top 8 Cool Hairstyles - 9051, // Top 8 Stylish Hair Colors + Item.DIYRecipe, - 9221, // Pretty Good Tools Recipes + 9046, // Vaulting Pole Recipe + 9047, // Flimsy Shovel Recipe + 9048, // Flimsy Watering Can Recipe + 9049, // Top 8 Pop Hairstyles + 9050, // Top 8 Cool Hairstyles + 9051, // Top 8 Stylish Hair Colors - 10309, // Slingshot Recipe + 9221, // Pretty Good Tools Recipes - 11140, // Ultimate Pocket Stuffing + 10309, // Slingshot Recipe - 12294, // Flimsy Axe Recipe + 11140, // Ultimate Pocket Stuffing - 12327, // Ladder Recipe - }; - } -} + 12294, // Flimsy Axe Recipe + + 12327 // Ladder Recipe + ]; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/FieldItem/FieldItemDefinition.cs b/NHSE.Core/Structures/Item/FieldItem/FieldItemDefinition.cs index 3c52710..a5d9888 100644 --- a/NHSE.Core/Structures/Item/FieldItem/FieldItemDefinition.cs +++ b/NHSE.Core/Structures/Item/FieldItem/FieldItemDefinition.cs @@ -1,55 +1,54 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Details for field items -- items with at or above 60,000. +/// +/// +/// These details are extracted from FgMainParam.bcsv +/// +public class FieldItemDefinition : INamedValue { /// - /// Details for field items -- items with at or above 60,000. + /// Item ID + /// + public ushort Index { get; } + + /// + /// Internal Name of the Item + /// + public string Name { get; } + + /// + /// Item ID that the player receives if the item is dug up. + /// + /// Is if it cannot be dug up. + public readonly ushort Dig; + + /// + /// Item ID that the player receives if the item is dug up. + /// + /// Is if it cannot be picked up. + public readonly ushort Pick; + + /// + /// Classification of item. + /// + public readonly FieldItemKind Kind; + + public FieldItemDefinition(ushort id, ushort dig, ushort pick, string name, FieldItemKind kind) + { + Index = id; + Dig = dig; + Pick = pick; + Name = name; + Kind = kind; + } + + /// + /// When the field item is picked up, this is the held item ID. /// /// - /// These details are extracted from FgMainParam.bcsv + /// If the item cannot be picked up, the is returned as a fallback rather than . /// - public class FieldItemDefinition : INamedValue - { - /// - /// Item ID - /// - public ushort Index { get; } - - /// - /// Internal Name of the Item - /// - public string Name { get; } - - /// - /// Item ID that the player receives if the item is dug up. - /// - /// Is if it cannot be dug up. - public readonly ushort Dig; - - /// - /// Item ID that the player receives if the item is dug up. - /// - /// Is if it cannot be picked up. - public readonly ushort Pick; - - /// - /// Classification of item. - /// - public readonly FieldItemKind Kind; - - public FieldItemDefinition(ushort id, ushort dig, ushort pick, string name, FieldItemKind kind) - { - Index = id; - Dig = dig; - Pick = pick; - Name = name; - Kind = kind; - } - - /// - /// When the field item is picked up, this is the held item ID. - /// - /// - /// If the item cannot be picked up, the is returned as a fallback rather than . - /// - public ushort HeldItemId => Pick != Item.NONE ? Pick : Dig != Item.NONE ? Dig : Index; - } -} + public ushort HeldItemId => Pick != Item.NONE ? Pick : Dig != Item.NONE ? Dig : Index; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/FieldItem/FieldItemKind.cs b/NHSE.Core/Structures/Item/FieldItem/FieldItemKind.cs index 586b19f..82ad969 100644 --- a/NHSE.Core/Structures/Item/FieldItem/FieldItemKind.cs +++ b/NHSE.Core/Structures/Item/FieldItem/FieldItemKind.cs @@ -1,108 +1,110 @@ using static NHSE.Core.FieldItemKind; -namespace NHSE.Core +namespace NHSE.Core; + +public enum FieldItemKind : byte { - public enum FieldItemKind : byte - { - FenceBamboo, - FenceBarbedWire, - FenceChinese, - FenceConcreteBlock, - FenceCorrugatedIron, - FenceCrossedBamboo, - FenceDriedStraw, - FenceEasterEgg, - FenceGardenPegRope, - FenceHalloween, - FenceHorizontalLog, - FenceHorizontalWood, - FenceIce, - FenceIkegaki, - FenceIronAndStone, - FenceJapanese, - FenceJuneBride, - FenceLattice, - FenceLatticeBig, - FenceLog, - FenceLogWall, - FenceMermaid, - FencePark, - FencePegRope, - FenceSandProtection, - FenceSharply, - FenceSteel, - FenceStone, - FenceVerticalWood, - FenceWallRenga, - FenceWoodWhite, - LadderKitA, - LadderKitB, - LadderKitC, - LadderKitD, - PltBushAzalea, - PltBushCamellia, - PltBushHibiscus, - PltBushHolly, - PltBushHydrangea, - PltBushOsmanthus, - PltBushPlumeria, - PltFlwAnemone, - PltFlwCosmos, - PltFlwHyacinth, - PltFlwLily, - PltFlwMum, - PltFlwPansy, - PltFlwRose, - PltFlwRoseGold, - PltFlwTulip, - PltFlwYuri, - PltTreeBamboo, - PltTreeCedar, - PltTreeCedarDeco, - PltTreeOak, - PltTreePalm, - PltVgtCarrot, - PltVgtPotato, - PltVgtPumpkin, - PltVgtSugarcane, - PltVgtTomato, - PltVgtWheat, - PltVine, - PltWeedAut0, - PltWeedAut1, - PltWeedAut2, - PltWeedLight, - PltWeedSmr, - PltWeedSpr, - PltWeedWin0, - PltWeedWin1, - StoneA, - StoneB, - StoneC, - StoneD, - StoneE, - UnitIconHole, - } + FenceBamboo, + FenceBarbedWire, + FenceChinese, + FenceConcreteBlock, + FenceCorrugatedIron, + FenceCrossedBamboo, + FenceDriedStraw, + FenceEasterEgg, + FenceGardenPegRope, + FenceHalloween, + FenceHorizontalLog, + FenceHorizontalWood, + FenceIce, + FenceIkegaki, + FenceIronAndStone, + FenceJapanese, + FenceJuneBride, + FenceLattice, + FenceLatticeBig, + FenceLog, + FenceLogWall, + FenceMermaid, + FencePark, + FencePegRope, + FenceSandProtection, + FenceSharply, + FenceSteel, + FenceStone, + FenceVerticalWood, + FenceWallRenga, + FenceWoodWhite, + LadderKitA, + LadderKitB, + LadderKitC, + LadderKitD, + PltBushAzalea, + PltBushCamellia, + PltBushHibiscus, + PltBushHolly, + PltBushHydrangea, + PltBushOsmanthus, + PltBushPlumeria, + PltFlwAnemone, + PltFlwCosmos, + PltFlwHyacinth, + PltFlwLily, + PltFlwMum, + PltFlwPansy, + PltFlwRose, + PltFlwRoseGold, + PltFlwTulip, + PltFlwYuri, + PltTreeBamboo, + PltTreeCedar, + PltTreeCedarDeco, + PltTreeOak, + PltTreePalm, + PltVgtCarrot, + PltVgtPotato, + PltVgtPumpkin, + PltVgtSugarcane, + PltVgtTomato, + PltVgtWheat, + PltVine, + PltWeedAut0, + PltWeedAut1, + PltWeedAut2, + PltWeedLight, + PltWeedSmr, + PltWeedSpr, + PltWeedWin0, + PltWeedWin1, + StoneA, + StoneB, + StoneC, + StoneD, + StoneE, + UnitIconHole, +} - public static class FieldItemKindExtensions +public static class FieldItemKindExtensions +{ + extension(FieldItemKind type) { - public static bool IsWeed(this FieldItemKind type) => type is >= PltWeedAut0 and <= PltWeedWin1; - public static bool IsPlant(this FieldItemKind type) => type is >= PltFlwAnemone and <= PltWeedWin1; - public static bool IsFence(this FieldItemKind type) => type is >= FenceBamboo and <= FenceWoodWhite; - public static bool IsBush(this FieldItemKind type) => type is >= PltBushAzalea and <= PltBushOsmanthus; - public static bool IsFlower(this FieldItemKind type) => type is >= PltFlwAnemone and <= PltFlwYuri; - public static bool IsTree(this FieldItemKind type) => type is >= PltTreeBamboo and <= PltTreePalm; - public static bool IsStone(this FieldItemKind type) => type is >= StoneA and <= StoneE; + public bool IsWeed => type is (>= PltWeedAut0 and <= PltWeedWin1); + public bool IsPlant => type is (>= PltFlwAnemone and <= PltWeedWin1); + public bool IsFence => type is (>= FenceBamboo and <= FenceWoodWhite); + public bool IsBush => type is (>= PltBushAzalea and <= PltBushOsmanthus); + public bool IsFlower => type is (>= PltFlwAnemone and <= PltFlwYuri); + public bool IsTree => type is (>= PltTreeBamboo and <= PltTreePalm); + public bool IsStone => type is (>= StoneA and <= StoneE); - public static ItemKind ToItemKind(this FieldItemKind type) + public ItemKind ToItemKind() { - if (type.IsTree()) + if (type.IsTree) return ItemKind.Kind_Tree; - if (type.IsFlower()) + if (type.IsFlower) return ItemKind.Kind_Flower; - if (type.IsWeed()) + if (type.IsWeed) return ItemKind.Kind_Weed; return ItemKind.Unknown; } } -} +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/FieldItem/FieldItemList.cs b/NHSE.Core/Structures/Item/FieldItem/FieldItemList.cs index 4a1ee98..7ae0aa5 100644 --- a/NHSE.Core/Structures/Item/FieldItem/FieldItemList.cs +++ b/NHSE.Core/Structures/Item/FieldItem/FieldItemList.cs @@ -1,568 +1,567 @@ using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public static class FieldItemList { - public static class FieldItemList + public static ItemKind GetFieldItemKind(ushort id) { - public static ItemKind GetFieldItemKind(ushort id) - { - if (!Items.TryGetValue(id, out var definition)) - return ItemKind.Unknown; + if (!Items.TryGetValue(id, out var definition)) + return ItemKind.Unknown; - var remap = definition.HeldItemId; - if (remap >= 60_000) - return definition.Kind.ToItemKind(); - - var rkind = ItemInfo.GetItemKind(remap); - if (rkind != ItemKind.Unknown) - return rkind; - - // shouldn't reach here, but play it safe + var remap = definition.HeldItemId; + if (remap >= 60_000) return definition.Kind.ToItemKind(); - } - public static readonly IReadOnlyDictionary Items = new Dictionary - { - {0xEA60, new FieldItemDefinition(60000, 2799 , 65534, "PltTreeOak4" , FieldItemKind.PltTreeOak )}, // 広葉樹(成木) - {0xEA61, new FieldItemDefinition(60001, 3360 , 65534, "PltTreeApple" , FieldItemKind.PltTreeOak )}, // リンゴの木(成木) - {0xEA62, new FieldItemDefinition(60002, 3365 , 65534, "PltTreeOrange" , FieldItemKind.PltTreeOak )}, // オレンジの木(成木) - {0xEA65, new FieldItemDefinition(60005, 5152 , 65534, "PltTreeOak0" , FieldItemKind.PltTreeOak )}, // 広葉樹(苗) - {0xEA66, new FieldItemDefinition(60006, 2796 , 65534, "PltTreeOak1" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長1) - {0xEA67, new FieldItemDefinition(60007, 2797 , 65534, "PltTreeOak2" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長2) - {0xEA68, new FieldItemDefinition(60008, 2798 , 65534, "PltTreeOak3" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長3) - {0xEA69, new FieldItemDefinition(60009, 2805 , 65534, "PltTreeCedar4" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成木) - {0xEA6F, new FieldItemDefinition(60015, 2627 , 2627 , "PltFlwCosmos1Red" , FieldItemKind.PltFlwCosmos )}, // コスモス赤(茎) - {0xEA70, new FieldItemDefinition(60016, 2628 , 2628 , "PltFlwCosmos2Red" , FieldItemKind.PltFlwCosmos )}, // コスモス赤(つぼみ) - {0xEA71, new FieldItemDefinition(60017, 3824 , 2304 , "PltFlwCosmos3Red" , FieldItemKind.PltFlwCosmos )}, // コスモス赤(花) - {0xEA72, new FieldItemDefinition(60018, 2630 , 2630 , "PltFlwCosmos1White" , FieldItemKind.PltFlwCosmos )}, // コスモス白(茎) - {0xEA73, new FieldItemDefinition(60019, 2631 , 2631 , "PltFlwCosmos2White" , FieldItemKind.PltFlwCosmos )}, // コスモス白(つぼみ) - {0xEA74, new FieldItemDefinition(60020, 3826 , 2305 , "PltFlwCosmos3White" , FieldItemKind.PltFlwCosmos )}, // コスモス白(花) - {0xEA76, new FieldItemDefinition(60022, 2815 , 65534, "PltTreeBamboo4" , FieldItemKind.PltTreeBamboo )}, // 竹(成木) - {0xEA77, new FieldItemDefinition(60023, 2810 , 65534, "PltTreePalm4" , FieldItemKind.PltTreePalm )}, // ヤシの木(成木) - {0xEA79, new FieldItemDefinition(60025, 65534, 65534, "Hole" , FieldItemKind.UnitIconHole )}, // 穴 - {0xEA7C, new FieldItemDefinition(60028, 12897, 65534, "PltVgtTomato0" , FieldItemKind.PltVgtTomato )}, // トマト(苗) - {0xEA7D, new FieldItemDefinition(60029, 2651 , 65534, "PltVgtTomato1" , FieldItemKind.PltVgtTomato )}, // トマト(成長1) - {0xEA7E, new FieldItemDefinition(60030, 2652 , 65534, "PltVgtTomato2" , FieldItemKind.PltVgtTomato )}, // トマト(成長2) - {0xEA7F, new FieldItemDefinition(60031, 12898, 2570 , "PltVgtTomato3" , FieldItemKind.PltVgtTomato )}, // トマト(成木) - {0xEA81, new FieldItemDefinition(60033, 2624 , 2624 , "PltWeedAut1A" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草01A - {0xEA82, new FieldItemDefinition(60034, 2624 , 2624 , "PltWeedAut1B" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草01B - {0xEA83, new FieldItemDefinition(60035, 2624 , 2624 , "PltWeedAut1C" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草01C - {0xEA86, new FieldItemDefinition(60038, 2624 , 2624 , "PltWeedSmr1A" , FieldItemKind.PltWeedSmr )}, // 夏の雑草1A - {0xEA87, new FieldItemDefinition(60039, 2624 , 2624 , "PltWeedSmr1B" , FieldItemKind.PltWeedSmr )}, // 夏の雑草1B - {0xEA88, new FieldItemDefinition(60040, 2624 , 2624 , "PltWeedSmr1C" , FieldItemKind.PltWeedSmr )}, // 夏の雑草1C - {0xEA89, new FieldItemDefinition(60041, 2865 , 2865 , "PltFlwCosmos1Yellow" , FieldItemKind.PltFlwCosmos )}, // コスモス黄(茎) - {0xEA8A, new FieldItemDefinition(60042, 2866 , 2866 , "PltFlwCosmos2Yellow" , FieldItemKind.PltFlwCosmos )}, // コスモス黄(つぼみ) - {0xEA8B, new FieldItemDefinition(60043, 3828 , 2863 , "PltFlwCosmos3Yellow" , FieldItemKind.PltFlwCosmos )}, // コスモス黄(花) - {0xEA9F, new FieldItemDefinition(60063, 65534, 65534, "PltTreeOak4Stump" , FieldItemKind.PltTreeOak )}, // 広葉樹(成木の切り株) - {0xEAA1, new FieldItemDefinition(60065, 65534, 11711, "FenceWoodWhite" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・白 - {0xEAB4, new FieldItemDefinition(60084, 65534, 65534, "PltTreeCedar4Stump" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成木の切り株) - {0xEAB5, new FieldItemDefinition(60085, 5151 , 65534, "PltTreeCedar0" , FieldItemKind.PltTreeCedar )}, // 針葉樹(苗) - {0xEAB6, new FieldItemDefinition(60086, 2803 , 65534, "PltTreeCedar2" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長2) - {0xEAB7, new FieldItemDefinition(60087, 2802 , 65534, "PltTreeCedar1" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長1) - {0xEAB8, new FieldItemDefinition(60088, 2804 , 65534, "PltTreeCedar3" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長3) - {0xEABE, new FieldItemDefinition(60094, 65534, 65534, "PltTreePalm4Stump" , FieldItemKind.PltTreePalm )}, // ヤシの木(成木の切り株) - {0xEABF, new FieldItemDefinition(60095, 2806 , 65534, "PltTreePalm0" , FieldItemKind.PltTreePalm )}, // ヤシの木(苗) - {0xEAC0, new FieldItemDefinition(60096, 2808 , 65534, "PltTreePalm2" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長2) - {0xEAC1, new FieldItemDefinition(60097, 2807 , 65534, "PltTreePalm1" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長1) - {0xEAC2, new FieldItemDefinition(60098, 2809 , 65534, "PltTreePalm3" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長3) - {0xEAC3, new FieldItemDefinition(60099, 65534, 65534, "PltTreeBamboo4Stump" , FieldItemKind.PltTreeBamboo )}, // 竹(成木の切り株) - {0xEAC4, new FieldItemDefinition(60100, 2811 , 65534, "PltTreeBamboo0" , FieldItemKind.PltTreeBamboo )}, // 竹(苗) - {0xEAC5, new FieldItemDefinition(60101, 2813 , 65534, "PltTreeBamboo2" , FieldItemKind.PltTreeBamboo )}, // 竹(成長2) - {0xEAC6, new FieldItemDefinition(60102, 2812 , 65534, "PltTreeBamboo1" , FieldItemKind.PltTreeBamboo )}, // 竹(成長1) - {0xEAC7, new FieldItemDefinition(60103, 2814 , 65534, "PltTreeBamboo3" , FieldItemKind.PltTreeBamboo )}, // 竹(成長3) - {0xEAC8, new FieldItemDefinition(60104, 3370 , 65534, "PltTreePear" , FieldItemKind.PltTreeOak )}, // ナシの木(成木) - {0xEAC9, new FieldItemDefinition(60105, 3381 , 65534, "PltTreeCherry" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(成木) - {0xEACA, new FieldItemDefinition(60106, 3375 , 65534, "PltTreePeach" , FieldItemKind.PltTreeOak )}, // モモの木(成木) - {0xEACB, new FieldItemDefinition(60107, 2861 , 65534, "PltBushAzalea3White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(成木花) - {0xEACC, new FieldItemDefinition(60108, 12747, 65534, "PltBushAzalea0White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(苗) - {0xEACD, new FieldItemDefinition(60109, 2861 , 65534, "PltBushAzalea2White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(成木つぼみ) - {0xEACF, new FieldItemDefinition(60111, 2861 , 65534, "PltBushAzalea4White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(成木花なし) - {0xEAD0, new FieldItemDefinition(60112, 2860 , 65534, "PltBushAzalea1White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(成長1) - {0xEAD1, new FieldItemDefinition(60113, 3022 , 65534, "PltBushHibiscus3Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(成木花) - {0xEAD2, new FieldItemDefinition(60114, 12752, 65534, "PltBushHibiscus0Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(苗) - {0xEAD3, new FieldItemDefinition(60115, 3022 , 65534, "PltBushHibiscus2Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(成木つぼみ) - {0xEAD4, new FieldItemDefinition(60116, 3022 , 65534, "PltBushHibiscus4Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(成木花なし) - {0xEAD5, new FieldItemDefinition(60117, 3021 , 65534, "PltBushHibiscus1Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(成長1) - {0xEAD6, new FieldItemDefinition(60118, 3027 , 65534, "PltBushHolly3" , FieldItemKind.PltBushHolly )}, // ヒイラギ(成木花) - {0xEAD7, new FieldItemDefinition(60119, 12757, 65534, "PltBushHolly0" , FieldItemKind.PltBushHolly )}, // ヒイラギ(苗) - {0xEAD8, new FieldItemDefinition(60120, 3027 , 65534, "PltBushHolly2" , FieldItemKind.PltBushHolly )}, // ヒイラギ(成木つぼみ) - {0xEAD9, new FieldItemDefinition(60121, 3026 , 65534, "PltBushHolly1" , FieldItemKind.PltBushHolly )}, // ヒイラギ(成長1) - {0xEADA, new FieldItemDefinition(60122, 3027 , 65534, "PltBushHolly4" , FieldItemKind.PltBushHolly )}, // ヒイラギ(成木花なし) - {0xEADC, new FieldItemDefinition(60124, 3033 , 65534, "PltVgtWheat2" , FieldItemKind.PltVgtWheat )}, // 小麦(成長2) - {0xEADD, new FieldItemDefinition(60125, 12899, 3029 , "PltVgtWheat3" , FieldItemKind.PltVgtWheat )}, // 小麦(成木) - {0xEADE, new FieldItemDefinition(60126, 3032 , 65534, "PltVgtWheat1" , FieldItemKind.PltVgtWheat )}, // 小麦(成長1) - {0xEADF, new FieldItemDefinition(60127, 3031 , 65534, "PltVgtWheat0" , FieldItemKind.PltVgtWheat )}, // 小麦(苗) - {0xEAE6, new FieldItemDefinition(60134, 12900, 3034 , "PltVgtSugarCane3" , FieldItemKind.PltVgtSugarcane )}, // サトウキビ(成木) - {0xEAE7, new FieldItemDefinition(60135, 3037 , 65534, "PltVgtSugarCane1" , FieldItemKind.PltVgtSugarcane )}, // サトウキビ(成長1) - {0xEAE8, new FieldItemDefinition(60136, 12901, 65534, "PltVgtSugarCane0" , FieldItemKind.PltVgtSugarcane )}, // サトウキビ(苗) - {0xEAE9, new FieldItemDefinition(60137, 3038 , 65534, "PltVgtSugarCane2" , FieldItemKind.PltVgtSugarcane )}, // サトウキビ(成長2) - {0xEAEA, new FieldItemDefinition(60138, 12902, 3039 , "PltVgtPotato3" , FieldItemKind.PltVgtPotato )}, // ジャガイモ(成木) - {0xEAEB, new FieldItemDefinition(60139, 3042 , 65534, "PltVgtPotato1" , FieldItemKind.PltVgtPotato )}, // ジャガイモ(成長1) - {0xEAEC, new FieldItemDefinition(60140, 12903, 65534, "PltVgtPotato0" , FieldItemKind.PltVgtPotato )}, // ジャガイモ(苗) - {0xEAED, new FieldItemDefinition(60141, 3043 , 65534, "PltVgtPotato2" , FieldItemKind.PltVgtPotato )}, // ジャガイモ(成長2) - {0xEAEE, new FieldItemDefinition(60142, 12905, 3044 , "PltVgtCarrot3" , FieldItemKind.PltVgtCarrot )}, // ニンジン(成木) - {0xEAEF, new FieldItemDefinition(60143, 3047 , 65534, "PltVgtCarrot1" , FieldItemKind.PltVgtCarrot )}, // ニンジン(成長1) - {0xEAF0, new FieldItemDefinition(60144, 3046 , 65534, "PltVgtCarrot0" , FieldItemKind.PltVgtCarrot )}, // ニンジン(苗) - {0xEAF1, new FieldItemDefinition(60145, 3048 , 65534, "PltVgtCarrot2" , FieldItemKind.PltVgtCarrot )}, // ニンジン(成長2) - {0xEAF7, new FieldItemDefinition(60151, 2878 , 2878 , "PltFlwCosmos2Black" , FieldItemKind.PltFlwCosmos )}, // コスモス黒(つぼみ) - {0xEAF8, new FieldItemDefinition(60152, 3832 , 2871 , "PltFlwCosmos3Orange" , FieldItemKind.PltFlwCosmos )}, // コスモスオレンジ(花) - {0xEAF9, new FieldItemDefinition(60153, 3834 , 2875 , "PltFlwCosmos3Black" , FieldItemKind.PltFlwCosmos )}, // コスモス黒(花) - {0xEAFA, new FieldItemDefinition(60154, 3830 , 2867 , "PltFlwCosmos3Pink" , FieldItemKind.PltFlwCosmos )}, // コスモス桃(花) - {0xEAFB, new FieldItemDefinition(60155, 2877 , 2877 , "PltFlwCosmos1Black" , FieldItemKind.PltFlwCosmos )}, // コスモス黒(茎) - {0xEAFC, new FieldItemDefinition(60156, 2873 , 2873 , "PltFlwCosmos1Orange" , FieldItemKind.PltFlwCosmos )}, // コスモスオレンジ(茎) - {0xEAFD, new FieldItemDefinition(60157, 2874 , 2874 , "PltFlwCosmos2Orange" , FieldItemKind.PltFlwCosmos )}, // コスモスオレンジ(つぼみ) - {0xEAFE, new FieldItemDefinition(60158, 2869 , 2869 , "PltFlwCosmos1Pink" , FieldItemKind.PltFlwCosmos )}, // コスモス桃(茎) - {0xEAFF, new FieldItemDefinition(60159, 2870 , 2870 , "PltFlwCosmos2Pink" , FieldItemKind.PltFlwCosmos )}, // コスモス桃(つぼみ) - {0xEB00, new FieldItemDefinition(60160, 65534, 3080 , "FenceWallRenga" , FieldItemKind.FenceWallRenga )}, // レンガの壁 - {0xEB01, new FieldItemDefinition(60161, 2624 , 2624 , "PltWeedSmr3" , FieldItemKind.PltWeedSmr )}, // 夏の雑草3 - {0xEB02, new FieldItemDefinition(60162, 2624 , 2624 , "PltWeedSmr2A" , FieldItemKind.PltWeedSmr )}, // 夏の雑草2A - {0xEB03, new FieldItemDefinition(60163, 2624 , 2624 , "PltWeedSmr2C" , FieldItemKind.PltWeedSmr )}, // 夏の雑草2C - {0xEB04, new FieldItemDefinition(60164, 2624 , 2624 , "PltWeedSmr2B" , FieldItemKind.PltWeedSmr )}, // 夏の雑草2B - {0xEB05, new FieldItemDefinition(60165, 2624 , 2624 , "PltWeedAut3" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草03 - {0xEB12, new FieldItemDefinition(60178, 65534, 65534, "StoneA" , FieldItemKind.StoneA )}, // 岩A - {0xEB13, new FieldItemDefinition(60179, 65534, 65534, "StoneB" , FieldItemKind.StoneB )}, // 岩B - {0xEB14, new FieldItemDefinition(60180, 65534, 65534, "StoneE" , FieldItemKind.StoneE )}, // 岩E - {0xEB15, new FieldItemDefinition(60181, 65534, 65534, "StoneD" , FieldItemKind.StoneD )}, // 岩D - {0xEB16, new FieldItemDefinition(60182, 65534, 65534, "StoneC" , FieldItemKind.StoneC )}, // 岩C - {0xEB17, new FieldItemDefinition(60183, 2624 , 2624 , "PltWeedAut2B" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草02B - {0xEB18, new FieldItemDefinition(60184, 2624 , 2624 , "PltWeedAut2C" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草02C - {0xEB19, new FieldItemDefinition(60185, 2624 , 2624 , "PltWeedAut2A" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草02A - {0xEB28, new FieldItemDefinition(60200, 2624 , 2624 , "PltWeedSpr1A" , FieldItemKind.PltWeedSpr )}, // 春の雑草1A - {0xEB30, new FieldItemDefinition(60208, 2624 , 2624 , "PltWeedSpr1B" , FieldItemKind.PltWeedSpr )}, // 春の雑草1B - {0xEB31, new FieldItemDefinition(60209, 2624 , 2624 , "PltWeedSpr1C" , FieldItemKind.PltWeedSpr )}, // 春の雑草1C - {0xEB32, new FieldItemDefinition(60210, 2624 , 2624 , "PltWeedSpr2A" , FieldItemKind.PltWeedSpr )}, // 春の雑草2A - {0xEB33, new FieldItemDefinition(60211, 2624 , 2624 , "PltWeedSpr2B" , FieldItemKind.PltWeedSpr )}, // 春の雑草2B - {0xEB34, new FieldItemDefinition(60212, 2624 , 2624 , "PltWeedSpr2C" , FieldItemKind.PltWeedSpr )}, // 春の雑草2C - {0xEB35, new FieldItemDefinition(60213, 2624 , 2624 , "PltWeedSpr3" , FieldItemKind.PltWeedSpr )}, // 春の雑草3 - {0xEB36, new FieldItemDefinition(60214, 2624 , 2624 , "PltWeedWin1A" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草01A - {0xEB37, new FieldItemDefinition(60215, 2624 , 2624 , "PltWeedWin1B" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草01B - {0xEB38, new FieldItemDefinition(60216, 2624 , 2624 , "PltWeedWin1C" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草01C - {0xEB39, new FieldItemDefinition(60217, 2624 , 2624 , "PltWeedWin2A" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草02A - {0xEB3A, new FieldItemDefinition(60218, 2624 , 2624 , "PltWeedWin2B" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草02B - {0xEB3B, new FieldItemDefinition(60219, 2624 , 2624 , "PltWeedWin2C" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草02C - {0xEB3C, new FieldItemDefinition(60220, 2624 , 2624 , "PltWeedWin3" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草03 - {0xEB3D, new FieldItemDefinition(60221, 2881 , 2881 , "PltFlwTulip1White" , FieldItemKind.PltFlwTulip )}, // チューリップ白(茎) - {0xEB3E, new FieldItemDefinition(60222, 2882 , 2882 , "PltFlwTulip2White" , FieldItemKind.PltFlwTulip )}, // チューリップ白(つぼみ) - {0xEB3F, new FieldItemDefinition(60223, 3836 , 2879 , "PltFlwTulip3White" , FieldItemKind.PltFlwTulip )}, // チューリップ白(花) - {0xEB40, new FieldItemDefinition(60224, 2885 , 2885 , "PltFlwTulip1Red" , FieldItemKind.PltFlwTulip )}, // チューリップ赤(茎) - {0xEB41, new FieldItemDefinition(60225, 2886 , 2886 , "PltFlwTulip2Red" , FieldItemKind.PltFlwTulip )}, // チューリップ赤(つぼみ) - {0xEB42, new FieldItemDefinition(60226, 3838 , 2883 , "PltFlwTulip3Red" , FieldItemKind.PltFlwTulip )}, // チューリップ赤(花) - {0xEB43, new FieldItemDefinition(60227, 2889 , 2889 , "PltFlwTulip1Yellow" , FieldItemKind.PltFlwTulip )}, // チューリップ黄(茎) - {0xEB44, new FieldItemDefinition(60228, 2890 , 2890 , "PltFlwTulip2Yellow" , FieldItemKind.PltFlwTulip )}, // チューリップ黄(つぼみ) - {0xEB45, new FieldItemDefinition(60229, 3840 , 2887 , "PltFlwTulip3Yellow" , FieldItemKind.PltFlwTulip )}, // チューリップ黄(花) - {0xEB46, new FieldItemDefinition(60230, 2893 , 2893 , "PltFlwTulip1Pink" , FieldItemKind.PltFlwTulip )}, // チューリップ桃(茎) - {0xEB47, new FieldItemDefinition(60231, 2894 , 2894 , "PltFlwTulip2Pink" , FieldItemKind.PltFlwTulip )}, // チューリップ桃(つぼみ) - {0xEB48, new FieldItemDefinition(60232, 3842 , 2891 , "PltFlwTulip3Pink" , FieldItemKind.PltFlwTulip )}, // チューリップ桃(花) - {0xEB49, new FieldItemDefinition(60233, 2897 , 2897 , "PltFlwTulip1Orange" , FieldItemKind.PltFlwTulip )}, // チューリップオレンジ(茎) - {0xEB4A, new FieldItemDefinition(60234, 2898 , 2898 , "PltFlwTulip2Orange" , FieldItemKind.PltFlwTulip )}, // チューリップオレンジ(つぼみ) - {0xEB4B, new FieldItemDefinition(60235, 3844 , 2895 , "PltFlwTulip3Orange" , FieldItemKind.PltFlwTulip )}, // チューリップオレンジ(花) - {0xEB4C, new FieldItemDefinition(60236, 2901 , 2901 , "PltFlwTulip1Purple" , FieldItemKind.PltFlwTulip )}, // チューリップ紫(茎) - {0xEB4D, new FieldItemDefinition(60237, 2902 , 2902 , "PltFlwTulip2Purple" , FieldItemKind.PltFlwTulip )}, // チューリップ紫(つぼみ) - {0xEB4E, new FieldItemDefinition(60238, 3846 , 2899 , "PltFlwTulip3Purple" , FieldItemKind.PltFlwTulip )}, // チューリップ紫(花) - {0xEB4F, new FieldItemDefinition(60239, 2905 , 2905 , "PltFlwTulip1Black" , FieldItemKind.PltFlwTulip )}, // チューリップ黒(茎) - {0xEB50, new FieldItemDefinition(60240, 2906 , 2906 , "PltFlwTulip2Black" , FieldItemKind.PltFlwTulip )}, // チューリップ黒(つぼみ) - {0xEB51, new FieldItemDefinition(60241, 3848 , 2903 , "PltFlwTulip3Black" , FieldItemKind.PltFlwTulip )}, // チューリップ黒(花) - {0xEB52, new FieldItemDefinition(60242, 2909 , 2909 , "PltFlwPansy1White" , FieldItemKind.PltFlwPansy )}, // パンジー白(茎) - {0xEB53, new FieldItemDefinition(60243, 2910 , 2910 , "PltFlwPansy2White" , FieldItemKind.PltFlwPansy )}, // パンジー白(つぼみ) - {0xEB54, new FieldItemDefinition(60244, 3850 , 2907 , "PltFlwPansy3White" , FieldItemKind.PltFlwPansy )}, // パンジー白(花) - {0xEB55, new FieldItemDefinition(60245, 2913 , 2913 , "PltFlwPansy1Red" , FieldItemKind.PltFlwPansy )}, // パンジー赤(茎) - {0xEB56, new FieldItemDefinition(60246, 2914 , 2914 , "PltFlwPansy2Red" , FieldItemKind.PltFlwPansy )}, // パンジー赤(つぼみ) - {0xEB57, new FieldItemDefinition(60247, 3852 , 2911 , "PltFlwPansy3Red" , FieldItemKind.PltFlwPansy )}, // パンジー赤(花) - {0xEB58, new FieldItemDefinition(60248, 2917 , 2917 , "PltFlwPansy1Yellow" , FieldItemKind.PltFlwPansy )}, // パンジー黄(茎) - {0xEB59, new FieldItemDefinition(60249, 2918 , 2918 , "PltFlwPansy2Yellow" , FieldItemKind.PltFlwPansy )}, // パンジー黄(つぼみ) - {0xEB5A, new FieldItemDefinition(60250, 3854 , 2915 , "PltFlwPansy3Yellow" , FieldItemKind.PltFlwPansy )}, // パンジー黄(花) - {0xEB5B, new FieldItemDefinition(60251, 2921 , 2921 , "PltFlwPansy1RedYellow" , FieldItemKind.PltFlwPansy )}, // パンジー赤黄(茎) - {0xEB5C, new FieldItemDefinition(60252, 2922 , 2922 , "PltFlwPansy2RedYellow" , FieldItemKind.PltFlwPansy )}, // パンジー赤黄(つぼみ) - {0xEB5D, new FieldItemDefinition(60253, 3856 , 2919 , "PltFlwPansy3RedYellow" , FieldItemKind.PltFlwPansy )}, // パンジー赤黄(花) - {0xEB5E, new FieldItemDefinition(60254, 2925 , 2925 , "PltFlwPansy1Purple" , FieldItemKind.PltFlwPansy )}, // パンジー紫(茎) - {0xEB5F, new FieldItemDefinition(60255, 2926 , 2926 , "PltFlwPansy2Purple" , FieldItemKind.PltFlwPansy )}, // パンジー紫(つぼみ) - {0xEB60, new FieldItemDefinition(60256, 3858 , 2923 , "PltFlwPansy3Purple" , FieldItemKind.PltFlwPansy )}, // パンジー紫(花) - {0xEB61, new FieldItemDefinition(60257, 2929 , 2929 , "PltFlwPansy1Blue" , FieldItemKind.PltFlwPansy )}, // パンジー青(茎) - {0xEB62, new FieldItemDefinition(60258, 2930 , 2930 , "PltFlwPansy2Blue" , FieldItemKind.PltFlwPansy )}, // パンジー青(つぼみ) - {0xEB63, new FieldItemDefinition(60259, 3860 , 2927 , "PltFlwPansy3Blue" , FieldItemKind.PltFlwPansy )}, // パンジー青(花) - {0xEB64, new FieldItemDefinition(60260, 2933 , 2933 , "PltFlwRose1White" , FieldItemKind.PltFlwRose )}, // バラ白(茎) - {0xEB65, new FieldItemDefinition(60261, 2934 , 2934 , "PltFlwRose2White" , FieldItemKind.PltFlwRose )}, // バラ白(つぼみ) - {0xEB66, new FieldItemDefinition(60262, 3862 , 2931 , "PltFlwRose3White" , FieldItemKind.PltFlwRose )}, // バラ白(花) - {0xEB67, new FieldItemDefinition(60263, 2937 , 2937 , "PltFlwRose1Red" , FieldItemKind.PltFlwRose )}, // バラ赤(茎) - {0xEB68, new FieldItemDefinition(60264, 2938 , 2938 , "PltFlwRose2Red" , FieldItemKind.PltFlwRose )}, // バラ赤(つぼみ) - {0xEB69, new FieldItemDefinition(60265, 3864 , 2935 , "PltFlwRose3Red" , FieldItemKind.PltFlwRose )}, // バラ赤(花) - {0xEB6A, new FieldItemDefinition(60266, 2941 , 2941 , "PltFlwRose1Yellow" , FieldItemKind.PltFlwRose )}, // バラ黄(茎) - {0xEB6B, new FieldItemDefinition(60267, 2942 , 2942 , "PltFlwRose2Yellow" , FieldItemKind.PltFlwRose )}, // バラ黄(つぼみ) - {0xEB6C, new FieldItemDefinition(60268, 3866 , 2939 , "PltFlwRose3Yellow" , FieldItemKind.PltFlwRose )}, // バラ黄(花) - {0xEB6D, new FieldItemDefinition(60269, 2945 , 2945 , "PltFlwRose1Pink" , FieldItemKind.PltFlwRose )}, // バラ桃(茎) - {0xEB6E, new FieldItemDefinition(60270, 2946 , 2946 , "PltFlwRose2Pink" , FieldItemKind.PltFlwRose )}, // バラ桃(つぼみ) - {0xEB6F, new FieldItemDefinition(60271, 3868 , 2943 , "PltFlwRose3Pink" , FieldItemKind.PltFlwRose )}, // バラ桃(花) - {0xEB70, new FieldItemDefinition(60272, 2949 , 2949 , "PltFlwRose1Orange" , FieldItemKind.PltFlwRose )}, // バラオレンジ(茎) - {0xEB71, new FieldItemDefinition(60273, 2950 , 2950 , "PltFlwRose2Orange" , FieldItemKind.PltFlwRose )}, // バラオレンジ(つぼみ) - {0xEB72, new FieldItemDefinition(60274, 3870 , 2947 , "PltFlwRose3Orange" , FieldItemKind.PltFlwRose )}, // バラオレンジ(花) - {0xEB73, new FieldItemDefinition(60275, 2953 , 2953 , "PltFlwRose1Purple" , FieldItemKind.PltFlwRose )}, // バラ紫(茎) - {0xEB74, new FieldItemDefinition(60276, 2954 , 2954 , "PltFlwRose2Purple" , FieldItemKind.PltFlwRose )}, // バラ紫(つぼみ) - {0xEB75, new FieldItemDefinition(60277, 3872 , 2951 , "PltFlwRose3Purple" , FieldItemKind.PltFlwRose )}, // バラ紫(花) - {0xEB76, new FieldItemDefinition(60278, 2957 , 2957 , "PltFlwRose1Black" , FieldItemKind.PltFlwRose )}, // バラ黒(茎) - {0xEB77, new FieldItemDefinition(60279, 2958 , 2958 , "PltFlwRose2Black" , FieldItemKind.PltFlwRose )}, // バラ黒(つぼみ) - {0xEB78, new FieldItemDefinition(60280, 3874 , 2955 , "PltFlwRose3Black" , FieldItemKind.PltFlwRose )}, // バラ黒(花) - {0xEB79, new FieldItemDefinition(60281, 2961 , 2961 , "PltFlwRose1Blue" , FieldItemKind.PltFlwRose )}, // バラ青(茎) - {0xEB7A, new FieldItemDefinition(60282, 2962 , 2962 , "PltFlwRose2Blue" , FieldItemKind.PltFlwRose )}, // バラ青(つぼみ) - {0xEB7B, new FieldItemDefinition(60283, 3876 , 2959 , "PltFlwRose3Blue" , FieldItemKind.PltFlwRose )}, // バラ青(花) - {0xEB7C, new FieldItemDefinition(60284, 2965 , 2965 , "PltFlwRose1Gold" , FieldItemKind.PltFlwRoseGold )}, // バラ金(茎) - {0xEB7D, new FieldItemDefinition(60285, 2966 , 2966 , "PltFlwRose2Gold" , FieldItemKind.PltFlwRoseGold )}, // バラ金(つぼみ) - {0xEB7E, new FieldItemDefinition(60286, 3878 , 2963 , "PltFlwRose3Gold" , FieldItemKind.PltFlwRoseGold )}, // バラ金(花) - {0xEB88, new FieldItemDefinition(60296, 2981 , 2981 , "PltFlwYuri1White" , FieldItemKind.PltFlwYuri )}, // ユリ白(茎) - {0xEB89, new FieldItemDefinition(60297, 2982 , 2982 , "PltFlwYuri2White" , FieldItemKind.PltFlwYuri )}, // ユリ白(つぼみ) - {0xEB8A, new FieldItemDefinition(60298, 3886 , 2979 , "PltFlwYuri3White" , FieldItemKind.PltFlwYuri )}, // ユリ白(花) - {0xEB8B, new FieldItemDefinition(60299, 2985 , 2985 , "PltFlwYuri1Red" , FieldItemKind.PltFlwYuri )}, // ユリ赤(茎) - {0xEB8C, new FieldItemDefinition(60300, 2986 , 2986 , "PltFlwYuri2Red" , FieldItemKind.PltFlwYuri )}, // ユリ赤(つぼみ) - {0xEB8D, new FieldItemDefinition(60301, 3888 , 2983 , "PltFlwYuri3Red" , FieldItemKind.PltFlwYuri )}, // ユリ赤(花) - {0xEB8E, new FieldItemDefinition(60302, 2989 , 2989 , "PltFlwYuri1Yellow" , FieldItemKind.PltFlwYuri )}, // ユリ黄(茎) - {0xEB8F, new FieldItemDefinition(60303, 2990 , 2990 , "PltFlwYuri2Yellow" , FieldItemKind.PltFlwYuri )}, // ユリ黄(つぼみ) - {0xEB90, new FieldItemDefinition(60304, 3890 , 2987 , "PltFlwYuri3Yellow" , FieldItemKind.PltFlwYuri )}, // ユリ黄(花) - {0xEB91, new FieldItemDefinition(60305, 2993 , 2993 , "PltFlwYuri1Pink" , FieldItemKind.PltFlwYuri )}, // ユリ桃(茎) - {0xEB92, new FieldItemDefinition(60306, 2994 , 2994 , "PltFlwYuri2Pink" , FieldItemKind.PltFlwYuri )}, // ユリ桃(つぼみ) - {0xEB93, new FieldItemDefinition(60307, 3892 , 2991 , "PltFlwYuri3Pink" , FieldItemKind.PltFlwYuri )}, // ユリ桃(花) - {0xEB94, new FieldItemDefinition(60308, 2997 , 2997 , "PltFlwYuri1Orange" , FieldItemKind.PltFlwYuri )}, // ユリオレンジ(茎) - {0xEB95, new FieldItemDefinition(60309, 2998 , 2998 , "PltFlwYuri2Orange" , FieldItemKind.PltFlwYuri )}, // ユリオレンジ(つぼみ) - {0xEB96, new FieldItemDefinition(60310, 3894 , 2995 , "PltFlwYuri3Orange" , FieldItemKind.PltFlwYuri )}, // ユリオレンジ(花) - {0xEB97, new FieldItemDefinition(60311, 3001 , 3001 , "PltFlwYuri1Black" , FieldItemKind.PltFlwYuri )}, // ユリ黒(茎) - {0xEB98, new FieldItemDefinition(60312, 3002 , 3002 , "PltFlwYuri2Black" , FieldItemKind.PltFlwYuri )}, // ユリ黒(つぼみ) - {0xEB99, new FieldItemDefinition(60313, 3896 , 2999 , "PltFlwYuri3Black" , FieldItemKind.PltFlwYuri )}, // ユリ黒(花) - {0xEBBA, new FieldItemDefinition(60346, 65534, 3402 , "FenceVerticalWood" , FieldItemKind.FenceVerticalWood )}, // たていたのさく - {0xEBBF, new FieldItemDefinition(60351, 65534, 3403 , "FenceBamboo" , FieldItemKind.FenceBamboo )}, // たけがき - {0xEBC0, new FieldItemDefinition(60352, 3380 , 65534, "PltTreeCherry3" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(成長3) - {0xEBC1, new FieldItemDefinition(60353, 3379 , 65534, "PltTreeCherry2" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(成長2) - {0xEBC2, new FieldItemDefinition(60354, 3377 , 65534, "PltTreeCherry0" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(苗) - {0xEBC3, new FieldItemDefinition(60355, 3378 , 65534, "PltTreeCherry1" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(成長1) - {0xEBC4, new FieldItemDefinition(60356, 3371 , 65534, "PltTreePeach0" , FieldItemKind.PltTreeOak )}, // モモの木(苗) - {0xEBC5, new FieldItemDefinition(60357, 3372 , 65534, "PltTreePeach1" , FieldItemKind.PltTreeOak )}, // モモの木(成長1) - {0xEBC6, new FieldItemDefinition(60358, 3373 , 65534, "PltTreePeach2" , FieldItemKind.PltTreeOak )}, // モモの木(成長2) - {0xEBC7, new FieldItemDefinition(60359, 3374 , 65534, "PltTreePeach3" , FieldItemKind.PltTreeOak )}, // モモの木(成長3) - {0xEBC8, new FieldItemDefinition(60360, 3361 , 65534, "PltTreeOrange0" , FieldItemKind.PltTreeOak )}, // オレンジの木(苗) - {0xEBC9, new FieldItemDefinition(60361, 3362 , 65534, "PltTreeOrange1" , FieldItemKind.PltTreeOak )}, // オレンジの木(成長1) - {0xEBCA, new FieldItemDefinition(60362, 3363 , 65534, "PltTreeOrange2" , FieldItemKind.PltTreeOak )}, // オレンジの木(成長2) - {0xEBCB, new FieldItemDefinition(60363, 3364 , 65534, "PltTreeOrange3" , FieldItemKind.PltTreeOak )}, // オレンジの木(成長3) - {0xEBCC, new FieldItemDefinition(60364, 3366 , 65534, "PltTreePear0" , FieldItemKind.PltTreeOak )}, // ナシの木(苗) - {0xEBCD, new FieldItemDefinition(60365, 3367 , 65534, "PltTreePear1" , FieldItemKind.PltTreeOak )}, // ナシの木(成長1) - {0xEBCE, new FieldItemDefinition(60366, 3368 , 65534, "PltTreePear2" , FieldItemKind.PltTreeOak )}, // ナシの木(成長2) - {0xEBCF, new FieldItemDefinition(60367, 3369 , 65534, "PltTreePear3" , FieldItemKind.PltTreeOak )}, // ナシの木(成長3) - {0xEBD0, new FieldItemDefinition(60368, 3357 , 65534, "PltTreeApple1" , FieldItemKind.PltTreeOak )}, // リンゴの木(成長1) - {0xEBD1, new FieldItemDefinition(60369, 3358 , 65534, "PltTreeApple2" , FieldItemKind.PltTreeOak )}, // リンゴの木(成長2) - {0xEBD2, new FieldItemDefinition(60370, 3359 , 65534, "PltTreeApple3" , FieldItemKind.PltTreeOak )}, // リンゴの木(成長3) - {0xEBD3, new FieldItemDefinition(60371, 3356 , 65534, "PltTreeApple0" , FieldItemKind.PltTreeOak )}, // リンゴの木(苗) - {0xEBD4, new FieldItemDefinition(60372, 65534, 11712, "FenceLattice" , FieldItemKind.FenceLattice )}, // ラティス・青 - {0xEBD5, new FieldItemDefinition(60373, 65534, 4349 , "FenceHorizontalWood" , FieldItemKind.FenceHorizontalWood )}, // よこいたのさく - {0xEBD6, new FieldItemDefinition(60374, 65534, 4350 , "FenceLog" , FieldItemKind.FenceLog )}, // まるたのさく - {0xEBD7, new FieldItemDefinition(60375, 65534, 4351 , "FenceHorizontalLog" , FieldItemKind.FenceHorizontalLog )}, // よこむきのまるたのさく - {0xEBD8, new FieldItemDefinition(60376, 65534, 4352 , "FencePegRope" , FieldItemKind.FencePegRope )}, // ペグとロープ - {0xEBDA, new FieldItemDefinition(60378, 3918 , 3744 , "PltFlwHyacinth3Red" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス赤(花) - {0xEBDB, new FieldItemDefinition(60379, 3906 , 3723 , "PltFlwAnemones3Red" , FieldItemKind.PltFlwAnemone )}, // アネモネ赤(花) - {0xEBDC, new FieldItemDefinition(60380, 3932 , 3768 , "PltFlwMum3Red" , FieldItemKind.PltFlwMum )}, // キク赤(花) - {0xEBDD, new FieldItemDefinition(60381, 3770 , 3770 , "PltFlwMum1Red" , FieldItemKind.PltFlwMum )}, // キク赤(茎) - {0xEBDE, new FieldItemDefinition(60382, 3771 , 3771 , "PltFlwMum2Red" , FieldItemKind.PltFlwMum )}, // キク赤(つぼみ) - {0xEBDF, new FieldItemDefinition(60383, 3725 , 3725 , "PltFlwAnemones1Red" , FieldItemKind.PltFlwAnemone )}, // アネモネ赤(茎) - {0xEBE0, new FieldItemDefinition(60384, 3726 , 3726 , "PltFlwAnemones2Red" , FieldItemKind.PltFlwAnemone )}, // アネモネ赤(つぼみ) - {0xEBE1, new FieldItemDefinition(60385, 3746 , 3746 , "PltFlwHyacinth1Red" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス赤(茎) - {0xEBE2, new FieldItemDefinition(60386, 3747 , 3747 , "PltFlwHyacinth2Red" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス赤(つぼみ) - {0xEBE4, new FieldItemDefinition(60388, 3910 , 3730 , "PltFlwHyacinth3White" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス白(花) - {0xEBE5, new FieldItemDefinition(60389, 3733 , 3733 , "PltFlwHyacinth2White" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス白(つぼみ) - {0xEBE6, new FieldItemDefinition(60390, 3732 , 3732 , "PltFlwHyacinth1White" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス白(茎) - {0xEBE7, new FieldItemDefinition(60391, 3737 , 3737 , "PltFlwHyacinth2Yellow" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス黄(つぼみ) - {0xEBE8, new FieldItemDefinition(60392, 3912 , 3734 , "PltFlwHyacinth3Yellow" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス黄(花) - {0xEBE9, new FieldItemDefinition(60393, 3736 , 3736 , "PltFlwHyacinth1Yellow" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス黄(茎) - {0xEBEA, new FieldItemDefinition(60394, 3920 , 3748 , "PltFlwHyacinth3Blue" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス青(花) - {0xEBEB, new FieldItemDefinition(60395, 3914 , 3738 , "PltFlwHyacinth3Pink" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス桃(花) - {0xEBEC, new FieldItemDefinition(60396, 3916 , 3741 , "PltFlwHyacinth3Orange" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンスオレンジ(花) - {0xEBED, new FieldItemDefinition(60397, 3922 , 3751 , "PltFlwHyacinth3Purple" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス紫(花) - {0xEBEE, new FieldItemDefinition(60398, 3753 , 3753 , "PltFlwHyacinth2Purple" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス紫(つぼみ) - {0xEBEF, new FieldItemDefinition(60399, 3752 , 3752 , "PltFlwHyacinth1Purple" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス紫(茎) - {0xEBF0, new FieldItemDefinition(60400, 3743 , 3743 , "PltFlwHyacinth2Orange" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンスオレンジ(つぼみ) - {0xEBF1, new FieldItemDefinition(60401, 3740 , 3740 , "PltFlwHyacinth2Pink" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス桃(つぼみ) - {0xEBF2, new FieldItemDefinition(60402, 3739 , 3739 , "PltFlwHyacinth1Pink" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス桃(茎) - {0xEBF3, new FieldItemDefinition(60403, 3749 , 3749 , "PltFlwHyacinth1Blue" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス青(茎) - {0xEBF4, new FieldItemDefinition(60404, 3750 , 3750 , "PltFlwHyacinth2Blue" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス青(つぼみ) - {0xEBF5, new FieldItemDefinition(60405, 3742 , 3742 , "PltFlwHyacinth1Orange" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンスオレンジ(茎) - {0xEBF9, new FieldItemDefinition(60409, 12749, 65534, "PltBushHydrangea" , FieldItemKind.PltBushHydrangea )}, // あじさい青(苗) - {0xEBFB, new FieldItemDefinition(60411, 12750, 65534, "PltBushHydrangea0Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(苗) - {0xEBFC, new FieldItemDefinition(60412, 3799 , 65534, "PltBushHydrangea1Blue" , FieldItemKind.PltBushHydrangea )}, // あじさい青(成長1) - {0xEBFD, new FieldItemDefinition(60413, 3800 , 65534, "PltBushHydrangea2Blue" , FieldItemKind.PltBushHydrangea )}, // あじさい青(成木つぼみ) - {0xEBFE, new FieldItemDefinition(60414, 3800 , 65534, "PltBushHydrangea3Blue" , FieldItemKind.PltBushHydrangea )}, // あじさい青(成木花) - {0xEBFF, new FieldItemDefinition(60415, 3800 , 65534, "PltBushHydrangea4Blue" , FieldItemKind.PltBushHydrangea )}, // あじさい青(成木花なし) - {0xEC00, new FieldItemDefinition(60416, 3795 , 65534, "PltBushHydrangea1Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(成長1) - {0xEC01, new FieldItemDefinition(60417, 3796 , 65534, "PltBushHydrangea2Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(成木つぼみ) - {0xEC02, new FieldItemDefinition(60418, 3796 , 65534, "PltBushHydrangea3Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(成木花) - {0xEC03, new FieldItemDefinition(60419, 3796 , 65534, "PltBushHydrangea4Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(成木花なし) - {0xEC04, new FieldItemDefinition(60420, 3756 , 3756 , "PltFlwMum1White" , FieldItemKind.PltFlwMum )}, // キク白(茎) - {0xEC05, new FieldItemDefinition(60421, 3760 , 3760 , "PltFlwMum1Yellow" , FieldItemKind.PltFlwMum )}, // キク黄(茎) - {0xEC06, new FieldItemDefinition(60422, 3763 , 3763 , "PltFlwMum1Purple" , FieldItemKind.PltFlwMum )}, // キク紫(茎) - {0xEC07, new FieldItemDefinition(60423, 3766 , 3766 , "PltFlwMum1Pink" , FieldItemKind.PltFlwMum )}, // キク桃(茎) - {0xEC08, new FieldItemDefinition(60424, 3757 , 3757 , "PltFlwMum2White" , FieldItemKind.PltFlwMum )}, // キク白(つぼみ) - {0xEC09, new FieldItemDefinition(60425, 3924 , 3754 , "PltFlwMum3White" , FieldItemKind.PltFlwMum )}, // キク白(花) - {0xEC0A, new FieldItemDefinition(60426, 3761 , 3761 , "PltFlwMum2Yellow" , FieldItemKind.PltFlwMum )}, // キク黄(つぼみ) - {0xEC0B, new FieldItemDefinition(60427, 3764 , 3764 , "PltFlwMum2Purple" , FieldItemKind.PltFlwMum )}, // キク紫(つぼみ) - {0xEC0C, new FieldItemDefinition(60428, 3767 , 3767 , "PltFlwMum2Pink" , FieldItemKind.PltFlwMum )}, // キク桃(つぼみ) - {0xEC0D, new FieldItemDefinition(60429, 3926 , 3758 , "PltFlwMum3Yellow" , FieldItemKind.PltFlwMum )}, // キク黄(花) - {0xEC0E, new FieldItemDefinition(60430, 3928 , 3762 , "PltFlwMum3Purple" , FieldItemKind.PltFlwMum )}, // キク紫(花) - {0xEC0F, new FieldItemDefinition(60431, 3930 , 3765 , "PltFlwMum3Pink" , FieldItemKind.PltFlwMum )}, // キク桃(花) - {0xEC11, new FieldItemDefinition(60433, 3711 , 3711 , "PltFlwAnemones1White" , FieldItemKind.PltFlwAnemone )}, // アネモネ白(茎) - {0xEC12, new FieldItemDefinition(60434, 3712 , 3712 , "PltFlwAnemones2White" , FieldItemKind.PltFlwAnemone )}, // アネモネ白(つぼみ) - {0xEC13, new FieldItemDefinition(60435, 3898 , 3709 , "PltFlwAnemones3White" , FieldItemKind.PltFlwAnemone )}, // アネモネ白(花) - {0xEC14, new FieldItemDefinition(60436, 3718 , 3718 , "PltFlwAnemones1Blue" , FieldItemKind.PltFlwAnemone )}, // アネモネ青(茎) - {0xEC15, new FieldItemDefinition(60437, 3728 , 3728 , "PltFlwAnemones1Purple" , FieldItemKind.PltFlwAnemone )}, // アネモネ紫(茎) - {0xEC16, new FieldItemDefinition(60438, 3721 , 3721 , "PltFlwAnemones1Pink" , FieldItemKind.PltFlwAnemone )}, // アネモネ桃(茎) - {0xEC17, new FieldItemDefinition(60439, 3715 , 3715 , "PltFlwAnemones1Orange" , FieldItemKind.PltFlwAnemone )}, // アネモネオレンジ(茎) - {0xEC18, new FieldItemDefinition(60440, 3719 , 3719 , "PltFlwAnemones2Blue" , FieldItemKind.PltFlwAnemone )}, // アネモネ青(つぼみ) - {0xEC19, new FieldItemDefinition(60441, 3902 , 3717 , "PltFlwAnemones3Blue" , FieldItemKind.PltFlwAnemone )}, // アネモネ青(花) - {0xEC1A, new FieldItemDefinition(60442, 3729 , 3729 , "PltFlwAnemones2Purple" , FieldItemKind.PltFlwAnemone )}, // アネモネ紫(つぼみ) - {0xEC1B, new FieldItemDefinition(60443, 3908 , 3727 , "PltFlwAnemones3Purple" , FieldItemKind.PltFlwAnemone )}, // アネモネ紫(花) - {0xEC1C, new FieldItemDefinition(60444, 3722 , 3722 , "PltFlwAnemones2Pink" , FieldItemKind.PltFlwAnemone )}, // アネモネ桃(つぼみ) - {0xEC1D, new FieldItemDefinition(60445, 3904 , 3720 , "PltFlwAnemones3Pink" , FieldItemKind.PltFlwAnemone )}, // アネモネ桃(花) - {0xEC1E, new FieldItemDefinition(60446, 3716 , 3716 , "PltFlwAnemones2Orange" , FieldItemKind.PltFlwAnemone )}, // アネモネオレンジ(つぼみ) - {0xEC1F, new FieldItemDefinition(60447, 3900 , 3713 , "PltFlwAnemones3Orange" , FieldItemKind.PltFlwAnemone )}, // アネモネオレンジ(花) - {0xEC20, new FieldItemDefinition(60448, 3787 , 65534, "PltBushAzalea1Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(成長1) - {0xEC21, new FieldItemDefinition(60449, 12748, 65534, "PltBushAzalea0Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(苗) - {0xEC22, new FieldItemDefinition(60450, 3788 , 65534, "PltBushAzalea2Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(成長つぼみ) - {0xEC23, new FieldItemDefinition(60451, 3788 , 65534, "PltBushAzalea3Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(成木花) - {0xEC24, new FieldItemDefinition(60452, 3788 , 65534, "PltBushAzalea4Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(成木花なし) - {0xEC25, new FieldItemDefinition(60453, 12751, 65534, "PltBushHibiscus0Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(苗) - {0xEC26, new FieldItemDefinition(60454, 3791 , 65534, "PltBushHibiscus1Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(成長1) - {0xEC27, new FieldItemDefinition(60455, 3792 , 65534, "PltBushHibiscus2Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(成木つぼみ) - {0xEC28, new FieldItemDefinition(60456, 3792 , 65534, "PltBushHibiscus3Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(成木花) - {0xEC29, new FieldItemDefinition(60457, 3792 , 65534, "PltBushHibiscus4Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(成木花なし) - {0xEC32, new FieldItemDefinition(60466, 3778 , 3778 , "PltFlwMum1Green" , FieldItemKind.PltFlwMum )}, // キク緑(茎) - {0xEC33, new FieldItemDefinition(60467, 3779 , 3779 , "PltFlwMum2Green" , FieldItemKind.PltFlwMum )}, // キク緑(つぼみ) - {0xEC34, new FieldItemDefinition(60468, 3934 , 5175 , "PltFlwMum3Green" , FieldItemKind.PltFlwMum )}, // キク緑(花) - {0xEC38, new FieldItemDefinition(60472, 3909 , 3909 , "PltFlwHyacinth0White" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス白(芽) - {0xEC3A, new FieldItemDefinition(60474, 3925 , 3925 , "PltFlwMum0Yellow" , FieldItemKind.PltFlwMum )}, // キク黄(芽) - {0xEC3B, new FieldItemDefinition(60475, 3911 , 3911 , "PltFlwHyacinth0Yellow" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス黄(芽) - {0xEC3F, new FieldItemDefinition(60479, 3917 , 3917 , "PltFlwHyacinth0Red" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス赤(芽) - {0xEC42, new FieldItemDefinition(60482, 3905 , 3905 , "PltFlwAnemones0Red" , FieldItemKind.PltFlwAnemone )}, // アネモネ赤(芽) - {0xEC43, new FieldItemDefinition(60483, 3897 , 3897 , "PltFlwAnemones0White" , FieldItemKind.PltFlwAnemone )}, // アネモネ白(芽) - {0xEC47, new FieldItemDefinition(60487, 3899 , 3899 , "PltFlwAnemones0Orange" , FieldItemKind.PltFlwAnemone )}, // アネモネオレンジ(芽) - {0xEC48, new FieldItemDefinition(60488, 3931 , 3931 , "PltFlwM0Red" , FieldItemKind.PltFlwMum )}, // キク赤(芽) - {0xEC49, new FieldItemDefinition(60489, 3923 , 3923 , "PltFlwMum0White" , FieldItemKind.PltFlwMum )}, // キク白(芽) - {0xEC4A, new FieldItemDefinition(60490, 3839 , 3839 , "PltFlwTulip0Yellow" , FieldItemKind.PltFlwTulip )}, // チューリップ黄(芽) - {0xEC50, new FieldItemDefinition(60496, 3849 , 3849 , "PltFlwPansy0White" , FieldItemKind.PltFlwPansy )}, // パンジー白(芽) - {0xEC51, new FieldItemDefinition(60497, 3851 , 3851 , "PltFlwPansy0Red" , FieldItemKind.PltFlwPansy )}, // パンジー赤(芽) - {0xEC52, new FieldItemDefinition(60498, 3853 , 3853 , "PltFlwPansy0Yellow" , FieldItemKind.PltFlwPansy )}, // パンジー黄(芽) - {0xEC56, new FieldItemDefinition(60502, 3861 , 3861 , "PltFlwRose0White" , FieldItemKind.PltFlwRose )}, // バラ白(芽) - {0xEC57, new FieldItemDefinition(60503, 3863 , 3863 , "PltFlwRose0Red" , FieldItemKind.PltFlwRose )}, // バラ赤(芽) - {0xEC58, new FieldItemDefinition(60504, 3865 , 3865 , "PltFlwRose0Yellow" , FieldItemKind.PltFlwRose )}, // バラ黄(芽) - {0xEC5B, new FieldItemDefinition(60507, 3889 , 3889 , "PltFlwYuri0Yellow" , FieldItemKind.PltFlwYuri )}, // ユリ黄(芽) - {0xEC60, new FieldItemDefinition(60512, 3885 , 3885 , "PltFlwYuri0White" , FieldItemKind.PltFlwYuri )}, // ユリ白(芽) - {0xEC61, new FieldItemDefinition(60513, 3887 , 3887 , "PltFlwYuri0Red" , FieldItemKind.PltFlwYuri )}, // ユリ赤(芽) - {0xEC62, new FieldItemDefinition(60514, 3823 , 3823 , "PltFlwCosmos0Red" , FieldItemKind.PltFlwCosmos )}, // コスモス赤(芽) - {0xEC63, new FieldItemDefinition(60515, 3837 , 3837 , "PltFlwTulip0Red" , FieldItemKind.PltFlwTulip )}, // チューリップ赤(芽) - {0xEC64, new FieldItemDefinition(60516, 3827 , 3827 , "PltFlwCosmos0Yellow" , FieldItemKind.PltFlwCosmos )}, // コスモス黄(芽) - {0xEC65, new FieldItemDefinition(60517, 3825 , 3825 , "PltFlwCosmos0White" , FieldItemKind.PltFlwCosmos )}, // コスモス白(芽) - {0xEC69, new FieldItemDefinition(60521, 3835 , 3835 , "PltFlwTulip0White" , FieldItemKind.PltFlwTulip )}, // チューリップ白(芽) - {0xEC6B, new FieldItemDefinition(60523, 65534, 65534, "PltTreeOak3Stump" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長3の切り株) - {0xEC6C, new FieldItemDefinition(60524, 65534, 65534, "PltTreeOak2Stump" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長2の切り株) - {0xEC6D, new FieldItemDefinition(60525, 65534, 65534, "PltTreeOak1Stump" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長1の切り株) - {0xEC6E, new FieldItemDefinition(60526, 65534, 65534, "PltTreeCedar3Stump" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長3の切り株) - {0xEC6F, new FieldItemDefinition(60527, 65534, 65534, "PltTreeCedar2Stump" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長2の切り株) - {0xEC70, new FieldItemDefinition(60528, 65534, 65534, "PltTreeCedar1Stump" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長1の切り株) - {0xEC71, new FieldItemDefinition(60529, 65534, 65534, "PltTreeBamboo3Stump" , FieldItemKind.PltTreeBamboo )}, // 竹(成長3の切り株) - {0xEC72, new FieldItemDefinition(60530, 65534, 65534, "PltTreeBamboo2Stump" , FieldItemKind.PltTreeBamboo )}, // 竹(成長2の切り株) - {0xEC73, new FieldItemDefinition(60531, 65534, 65534, "PltTreeBamboo1Stump" , FieldItemKind.PltTreeBamboo )}, // 竹(成長1の切り株) - {0xEC74, new FieldItemDefinition(60532, 65534, 4354 , "FenceChinese" , FieldItemKind.FenceChinese )}, // オリエンタルなさく - {0xEC78, new FieldItemDefinition(60536, 65534, 65534, "PltTreePalm1Stump" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長1の切り株) - {0xEC79, new FieldItemDefinition(60537, 65534, 65534, "PltTreePalm2Stump" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長2の切り株) - {0xEC7A, new FieldItemDefinition(60538, 65534, 65534, "PltTreePalm3Stump" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長3の切り株) - {0xEC7B, new FieldItemDefinition(60539, 65534, 4355 , "FenceConcreteBlock" , FieldItemKind.FenceConcreteBlock )}, // ブロック塀 - {0xEC7C, new FieldItemDefinition(60540, 65534, 4356 , "FenceDriedStraw" , FieldItemKind.FenceDriedStraw )}, // わらぼしのさく - {0xEC7D, new FieldItemDefinition(60541, 65534, 4357 , "FenceSteel" , FieldItemKind.FenceSteel )}, // てつのさく - {0xEC7E, new FieldItemDefinition(60542, 65534, 4358 , "FenceSharply" , FieldItemKind.FenceSharply )}, // トゲトゲのさく - {0xEC7F, new FieldItemDefinition(60543, 2624 , 2624 , "PltWeedAut23" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草23 - {0xEC80, new FieldItemDefinition(60544, 2624 , 2624 , "PltWeedAut22C" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草22C - {0xEC81, new FieldItemDefinition(60545, 2624 , 2624 , "PltWeedAut22A" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草22A - {0xEC82, new FieldItemDefinition(60546, 2624 , 2624 , "PltWeedAut22B" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草22B - {0xEC83, new FieldItemDefinition(60547, 2624 , 2624 , "PltWeedAut21A" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草21A - {0xEC84, new FieldItemDefinition(60548, 2624 , 2624 , "PltWeedAut21B" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草21B - {0xEC85, new FieldItemDefinition(60549, 2624 , 2624 , "PltWeedAut21C" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草21C - {0xEC86, new FieldItemDefinition(60550, 2624 , 2624 , "PltWeedAut11B" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草11B - {0xEC87, new FieldItemDefinition(60551, 2624 , 2624 , "PltWeedAut11C" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草11C - {0xEC88, new FieldItemDefinition(60552, 2624 , 2624 , "PltWeedAut12A" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草12A - {0xEC89, new FieldItemDefinition(60553, 2624 , 2624 , "PltWeedAut12B" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草12B - {0xEC8A, new FieldItemDefinition(60554, 2624 , 2624 , "PltWeedAut12C" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草12C - {0xEC8B, new FieldItemDefinition(60555, 2624 , 2624 , "PltWeedAut13" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草13 - {0xEC8C, new FieldItemDefinition(60556, 2624 , 2624 , "PltWeedAut11A" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草11A - {0xEC8D, new FieldItemDefinition(60557, 2624 , 2624 , "PltWeedWin13" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草13 - {0xEC8E, new FieldItemDefinition(60558, 2624 , 2624 , "PltWeedWin12C" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草12C - {0xEC8F, new FieldItemDefinition(60559, 2624 , 2624 , "PltWeedWin12A" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草12A - {0xEC90, new FieldItemDefinition(60560, 2624 , 2624 , "PltWeedWin12B" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草12B - {0xEC91, new FieldItemDefinition(60561, 2624 , 2624 , "PltWeedWin11A" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草11A - {0xEC92, new FieldItemDefinition(60562, 2624 , 2624 , "PltWeedWin11B" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草11B - {0xEC93, new FieldItemDefinition(60563, 2624 , 2624 , "PltWeedWin11C" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草11C - {0xEC94, new FieldItemDefinition(60564, 65534, 11711, "FenceWoodBlue" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・青 - {0xEC97, new FieldItemDefinition(60567, 2805 , 65534, "PltTreeCedarDecoB" , FieldItemKind.PltTreeCedarDeco )}, // 飾りつき針葉樹B - {0xEC9A, new FieldItemDefinition(60570, 2805 , 65534, "PltTreeCedarDecoA" , FieldItemKind.PltTreeCedarDeco )}, // 飾りつき針葉樹A - {0xEC9B, new FieldItemDefinition(60571, 65534, 5212 , "FenceStone" , FieldItemKind.FenceStone )}, // いしかべ - {0xEC9C, new FieldItemDefinition(60572, 4426 , 65534, "PltTreeMoney4" , FieldItemKind.PltTreeOak )}, // 金のなるの木(成木) - {0xEC9D, new FieldItemDefinition(60573, 4439 , 65534, "PltTreeMoney3" , FieldItemKind.PltTreeOak )}, // 金のなるの木(成長3) - {0xEC9E, new FieldItemDefinition(60574, 4438 , 65534, "PltTreeMoney2" , FieldItemKind.PltTreeOak )}, // 金のなるの木(成長2) - {0xEC9F, new FieldItemDefinition(60575, 4436 , 65534, "PltTreeMoney0" , FieldItemKind.PltTreeOak )}, // 金のなるの木(苗) - {0xECA0, new FieldItemDefinition(60576, 4437 , 65534, "PltTreeMoney1" , FieldItemKind.PltTreeOak )}, // 金のなるの木(成長1) - {0xECA1, new FieldItemDefinition(60577, 4544 , 4528 , "PltVgtSquash3White" , FieldItemKind.PltVgtPumpkin )}, // カボチャ白(成木) - {0xECA2, new FieldItemDefinition(60578, 4543 , 65534, "PltVgtSquash2White" , FieldItemKind.PltVgtPumpkin )}, // カボチャ白(成長2) - {0xECA3, new FieldItemDefinition(60579, 4542 , 65534, "PltVgtSquash1White" , FieldItemKind.PltVgtPumpkin )}, // カボチャ白(成長1) - {0xECA4, new FieldItemDefinition(60580, 4541 , 65534, "PltVgtSquash0White" , FieldItemKind.PltVgtPumpkin )}, // カボチャ白(苗) - {0xECA5, new FieldItemDefinition(60581, 4538 , 65534, "PltVgtSquash1Green" , FieldItemKind.PltVgtPumpkin )}, // カボチャ緑(成長1) - {0xECA6, new FieldItemDefinition(60582, 4539 , 65534, "PltVgtSquash2Green" , FieldItemKind.PltVgtPumpkin )}, // カボチャ緑(成長2) - {0xECA7, new FieldItemDefinition(60583, 4540 , 4527 , "PltVgtSquash3Green" , FieldItemKind.PltVgtPumpkin )}, // カボチャ緑(成木) - {0xECA9, new FieldItemDefinition(60585, 4532 , 4525 , "PltVgtSquash3Orange" , FieldItemKind.PltVgtPumpkin )}, // カボチャオレンジ(成木) - {0xECAA, new FieldItemDefinition(60586, 4533 , 65534, "PltVgtSquash0Yellow" , FieldItemKind.PltVgtPumpkin )}, // カボチャ黄(苗) - {0xECAB, new FieldItemDefinition(60587, 4534 , 65534, "PltVgtSquash1Yellow" , FieldItemKind.PltVgtPumpkin )}, // カボチャ黄(成長1) - {0xECAC, new FieldItemDefinition(60588, 4535 , 65534, "PltVgtSquash2Yellow" , FieldItemKind.PltVgtPumpkin )}, // カボチャ黄(成長2) - {0xECAD, new FieldItemDefinition(60589, 4536 , 4526 , "PltVgtSquash3Yellow" , FieldItemKind.PltVgtPumpkin )}, // カボチャ黄(成木) - {0xECAE, new FieldItemDefinition(60590, 4537 , 65534, "PltVgtSquash0Green" , FieldItemKind.PltVgtPumpkin )}, // カボチャ緑(苗) - {0xECAF, new FieldItemDefinition(60591, 4529 , 65534, "PltVgtSquash0Orange" , FieldItemKind.PltVgtPumpkin )}, // カボチャオレンジ(苗) - {0xECB0, new FieldItemDefinition(60592, 4530 , 65534, "PltVgtSquash1Orange" , FieldItemKind.PltVgtPumpkin )}, // カボチャオレンジ(成長1) - {0xECB1, new FieldItemDefinition(60593, 4531 , 65534, "PltVgtSquash2Orange" , FieldItemKind.PltVgtPumpkin )}, // カボチャオレンジ(成長2) - {0xECB2, new FieldItemDefinition(60594, 65534, 5213 , "FenceBarbedWire" , FieldItemKind.FenceBarbedWire )}, // ゆうしてっせん - {0xECB3, new FieldItemDefinition(60595, 65534, 5210 , "FenceLogWall" , FieldItemKind.FenceLogWall )}, // まるたかべのさく - {0xECB4, new FieldItemDefinition(60596, 65534, 5208 , "FenceLatticeBig" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス - {0xECB5, new FieldItemDefinition(60597, 65534, 11711, "FenceWoodPink" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・ピンク - {0xECB6, new FieldItemDefinition(60598, 65534, 5207 , "FenceJapanese" , FieldItemKind.FenceJapanese )}, // 和風のさく - {0xECB7, new FieldItemDefinition(60599, 65534, 5206 , "FenceIronAndStone" , FieldItemKind.FenceIronAndStone )}, // 洋風のさく - {0xECB8, new FieldItemDefinition(60600, 65534, 3402 , "FenceVerticalWood2" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・黒 - {0xECBA, new FieldItemDefinition(60602, 65534, 11712, "FenceLattice2" , FieldItemKind.FenceLattice )}, // ラティス・白 - {0xECBB, new FieldItemDefinition(60603, 65534, 5208 , "FenceLatticeBig2" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・白 - {0xECBC, new FieldItemDefinition(60604, 65534, 65534, "PltTreeFruitStump1" , FieldItemKind.PltTreeOak )}, // 果物の木(成長1の切り株) - {0xECBD, new FieldItemDefinition(60605, 65534, 65534, "PltTreeFruitStump2" , FieldItemKind.PltTreeOak )}, // 果物の木(成長2の切り株) - {0xECBE, new FieldItemDefinition(60606, 65534, 65534, "PltTreeFruitStump3" , FieldItemKind.PltTreeOak )}, // 果物の木(成長3の切り株) - {0xECBF, new FieldItemDefinition(60607, 65534, 65534, "PltTreeFruitStump4" , FieldItemKind.PltTreeOak )}, // 果物の木(成長4の切り株) - {0xECC1, new FieldItemDefinition(60609, 7651 , 65534, "PltFlwLily3" , FieldItemKind.PltFlwLily )}, // スズラン(花) - {0xECC2, new FieldItemDefinition(60610, 65534, 11711, "FenceWoodNatural" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく - {0xECC3, new FieldItemDefinition(60611, 65534, 11712, "FenceLattice3" , FieldItemKind.FenceLattice )}, // ラティス - {0xECC4, new FieldItemDefinition(60612, 65534, 65534, "FenceCommune" , FieldItemKind.FenceHorizontalLog )}, // コミューン島専用柵 - {0xECC5, new FieldItemDefinition(60613, 65534, 11711, "FenceWoodYellow" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・黒 - {0xECC6, new FieldItemDefinition(60614, 65534, 11711, "FenceWoodOrange" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・オレンジ - {0xECC7, new FieldItemDefinition(60615, 65534, 11711, "FenceWoodPurple" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・紫 - {0xECC8, new FieldItemDefinition(60616, 65534, 11711, "FenceWoodGreen" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・緑 - {0xECC9, new FieldItemDefinition(60617, 65534, 3402 , "FenceVerticalWood6" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・青 - {0xECCA, new FieldItemDefinition(60618, 65534, 3402 , "FenceVerticalWood5" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・緑 - {0xECCB, new FieldItemDefinition(60619, 65534, 3402 , "FenceVerticalWood3" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・ピンク - {0xECCC, new FieldItemDefinition(60620, 65534, 3402 , "FenceVerticalWood4" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・黄 - {0xECCD, new FieldItemDefinition(60621, 65534, 11712, "FenceLattice8" , FieldItemKind.FenceLattice )}, // ラティス・薄紫 - {0xECCE, new FieldItemDefinition(60622, 65534, 11712, "FenceLattice7" , FieldItemKind.FenceLattice )}, // ラティス・黒 - {0xECCF, new FieldItemDefinition(60623, 65534, 11712, "FenceLattice5" , FieldItemKind.FenceLattice )}, // ラティス・黄 - {0xECD0, new FieldItemDefinition(60624, 65534, 11712, "FenceLattice6" , FieldItemKind.FenceLattice )}, // ラティス・緑 - {0xECD1, new FieldItemDefinition(60625, 65534, 11712, "FenceLattice4" , FieldItemKind.FenceLattice )}, // ラティス・ピンク - {0xECD2, new FieldItemDefinition(60626, 65534, 5208 , "FenceLatticeBig8" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・黒 - {0xECD3, new FieldItemDefinition(60627, 65534, 5208 , "FenceLatticeBig7" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・青 - {0xECD4, new FieldItemDefinition(60628, 65534, 5208 , "FenceLatticeBig5" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・緑 - {0xECD5, new FieldItemDefinition(60629, 65534, 5208 , "FenceLatticeBig6" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・紫 - {0xECD6, new FieldItemDefinition(60630, 65534, 5208 , "FenceLatticeBig3" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・赤 - {0xECD7, new FieldItemDefinition(60631, 65534, 5208 , "FenceLatticeBig4" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・オレンジ - {0xECD8, new FieldItemDefinition(60632, 65534, 5207 , "FenceJapanese8" , FieldItemKind.FenceJapanese )}, // 和風のさく・紫 - {0xECD9, new FieldItemDefinition(60633, 65534, 5207 , "FenceJapanese7" , FieldItemKind.FenceJapanese )}, // 和風のさく・緑 - {0xECDA, new FieldItemDefinition(60634, 65534, 5207 , "FenceJapanese5" , FieldItemKind.FenceJapanese )}, // 和風のさく・黄 - {0xECDB, new FieldItemDefinition(60635, 65534, 5207 , "FenceJapanese6" , FieldItemKind.FenceJapanese )}, // 和風のさく・ベージュ - {0xECDC, new FieldItemDefinition(60636, 65534, 5207 , "FenceJapanese2" , FieldItemKind.FenceJapanese )}, // 和風のさく・青 - {0xECDD, new FieldItemDefinition(60637, 65534, 5207 , "FenceJapanese3" , FieldItemKind.FenceJapanese )}, // 和風のさく・赤 - {0xECDE, new FieldItemDefinition(60638, 65534, 5207 , "FenceJapanese4" , FieldItemKind.FenceJapanese )}, // 和風のさく・オレンジ - {0xECDF, new FieldItemDefinition(60639, 65534, 4357 , "FenceSteel2" , FieldItemKind.FenceSteel )}, // てつのさく・赤 - {0xECE0, new FieldItemDefinition(60640, 65534, 4357 , "FenceSteel3" , FieldItemKind.FenceSteel )}, // てつのさく・黄 - {0xECE1, new FieldItemDefinition(60641, 65534, 4357 , "FenceSteel4" , FieldItemKind.FenceSteel )}, // てつのさく・緑 - {0xECE2, new FieldItemDefinition(60642, 65534, 14757, "FenceSandProtection" , FieldItemKind.FenceSandProtection )}, // すだれのさく - {0xECE3, new FieldItemDefinition(60643, 65534, 14755, "FenceCrossedBamboo" , FieldItemKind.FenceCrossedBamboo )}, // あおたけのさく - {0xECE4, new FieldItemDefinition(60644, 65534, 14756, "FenceIce" , FieldItemKind.FenceIce )}, // こおりのさく - {0xECE6, new FieldItemDefinition(60646, 65534, 14756, "FenceIce05" , FieldItemKind.FenceIce )}, // こおりのさく・緑 - {0xECE7, new FieldItemDefinition(60647, 65534, 14756, "FenceIce04" , FieldItemKind.FenceIce )}, // こおりのさく・オレンジ - {0xECE8, new FieldItemDefinition(60648, 65534, 14756, "FenceIce06" , FieldItemKind.FenceIce )}, // こおりのさく・紫 - {0xECE9, new FieldItemDefinition(60649, 65534, 14756, "FenceIce01" , FieldItemKind.FenceIce )}, // こおりのさく・青 - {0xECEA, new FieldItemDefinition(60650, 65534, 14756, "FenceIce02" , FieldItemKind.FenceIce )}, // こおりのさく・ピンク - {0xECEB, new FieldItemDefinition(60651, 65534, 14756, "FenceIce03" , FieldItemKind.FenceIce )}, // こおりのさく・黄 - {0xECF4, new FieldItemDefinition(60660, 12478, 65534, "PltBushOsmathus5Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(成木花なし) - {0xECF5, new FieldItemDefinition(60661, 12478, 65534, "PltBushOsmathus4Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(成木花) - {0xECF6, new FieldItemDefinition(60662, 12477, 65534, "PltBushOsmathus2Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(成長1) - {0xECF7, new FieldItemDefinition(60663, 12478, 65534, "PltBushOsmathus3Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(成木つぼみ) - {0xECF8, new FieldItemDefinition(60664, 12753, 65534, "PltBushOsmathus1Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(苗) - {0xECF9, new FieldItemDefinition(60665, 12482, 65534, "PltBushOsmathus5Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(成木花なし) - {0xECFA, new FieldItemDefinition(60666, 12482, 65534, "PltBushOsmathus4Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(成木花) - {0xECFB, new FieldItemDefinition(60667, 12482, 65534, "PltBushOsmathus3Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(成木つぼみ) - {0xECFC, new FieldItemDefinition(60668, 12754, 65534, "PltBushOsmathus1Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(苗) - {0xECFD, new FieldItemDefinition(60669, 12481, 65534, "PltBushOsmathus2Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(成長1) - {0xECFE, new FieldItemDefinition(60670, 12756, 65534, "PltBushCamellia1Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(苗) - {0xECFF, new FieldItemDefinition(60671, 12491, 65534, "PltBushCamellia2Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(成長1) - {0xED00, new FieldItemDefinition(60672, 12492, 65534, "PltBushCamellia3Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(成木つぼみ) - {0xED01, new FieldItemDefinition(60673, 12492, 65534, "PltBushCamellia4Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(成木花) - {0xED02, new FieldItemDefinition(60674, 12755, 65534, "PltBushCamellia1Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(苗) - {0xED03, new FieldItemDefinition(60675, 12492, 65534, "PltBushCamellia5Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(成木花なし) - {0xED04, new FieldItemDefinition(60676, 12488, 65534, "PltBushCamellia2Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(成長1) - {0xED05, new FieldItemDefinition(60677, 12489, 65534, "PltBushCamellia3Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(成木つぼみ) - {0xED06, new FieldItemDefinition(60678, 12489, 65534, "PltBushCamellia4Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(成木花) - {0xED07, new FieldItemDefinition(60679, 12489, 65534, "PltBushCamellia5Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(成木花なし) - {0xED08, new FieldItemDefinition(60680, 65534, 12758, "FenceIkegaki" , FieldItemKind.FenceIkegaki )}, // いけがき - {0xED09, new FieldItemDefinition(60681, 65534, 12894, "FenceJuneBride4" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・赤 - {0xED0A, new FieldItemDefinition(60682, 65534, 12894, "FenceJuneBride2" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・青 - {0xED0B, new FieldItemDefinition(60683, 65534, 12894, "FenceJuneBride3" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・緑 - {0xED0C, new FieldItemDefinition(60684, 65534, 12630, "FenceEasterEgg" , FieldItemKind.FenceEasterEgg )}, // イースターの柵 - {0xED0D, new FieldItemDefinition(60685, 65534, 12894, "FenceJuneBride" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵 - {0xED0E, new FieldItemDefinition(60686, 65534, 12894, "FenceJuneBride1" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・ピンク - {0xED0F, new FieldItemDefinition(60687, 12550, 12550, "PltWeedLight3" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ3 - {0xED10, new FieldItemDefinition(60688, 12550, 12550, "PltWeedLight2C" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ2C - {0xED11, new FieldItemDefinition(60689, 12550, 12550, "PltWeedLight2B" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ2B - {0xED12, new FieldItemDefinition(60690, 12550, 12550, "PltWeedLight1A" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ1A - {0xED13, new FieldItemDefinition(60691, 12550, 12550, "PltWeedLight2A" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ2A - {0xED14, new FieldItemDefinition(60692, 12550, 12550, "PltWeedLight1B" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ1B - {0xED15, new FieldItemDefinition(60693, 12550, 12550, "PltWeedLight1C" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ1C - {0xED16, new FieldItemDefinition(60694, 2799 , 65534, "PltTreeEasterEgg" , FieldItemKind.PltTreeOak )}, // イースターのタマゴの木 - {0xED17, new FieldItemDefinition(60695, 65534, 12551, "PltVine" , FieldItemKind.PltVine )}, // ツルA - {0xED21, new FieldItemDefinition(60705, 65534, 14278, "FenceMermaid" , FieldItemKind.FenceMermaid )}, // マーメイドな柵 - {0xED25, new FieldItemDefinition(60709, 65534, 13275, "FenceHalloween" , FieldItemKind.FenceHalloween )}, // ハロウィンのさく - {0xED26, new FieldItemDefinition(60710, 13264, 65534, "PltBushPlumeria4Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(成木花なし) - {0xED27, new FieldItemDefinition(60711, 13264, 65534, "PltBushPlumeria3Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(成木花) - {0xED28, new FieldItemDefinition(60712, 13263, 65534, "PltBushPlumeria1Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(成長1) - {0xED29, new FieldItemDefinition(60713, 13264, 65534, "PltBushPlumeria2Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(成長つぼみ) - {0xED2A, new FieldItemDefinition(60714, 13265, 65534, "PltBushPlumeria0Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(苗) - {0xED2B, new FieldItemDefinition(60715, 13350, 65534, "PltBushPlumeria4White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(成木花なし) - {0xED2C, new FieldItemDefinition(60716, 13350, 65534, "PltBushPlumeria3White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(成木花) - {0xED2D, new FieldItemDefinition(60717, 13350, 65534, "PltBushPlumeria2White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(成長つぼみ) - {0xED2E, new FieldItemDefinition(60718, 13351, 65534, "PltBushPlumeria0White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(苗) - {0xED2F, new FieldItemDefinition(60719, 13349, 65534, "PltBushPlumeria1White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(成長1) - {0xED30, new FieldItemDefinition(60720, 65534, 12551, "PltVineC" , FieldItemKind.PltVine )}, // ツルC - {0xED31, new FieldItemDefinition(60721, 65534, 12551, "PltVineB" , FieldItemKind.PltVine )}, // ツルB - {0xED33, new FieldItemDefinition(60723, 65534, 13534, "LadderKitC2" , FieldItemKind.LadderKitC )}, // ハシゴキットC2 - {0xED34, new FieldItemDefinition(60724, 65534, 13534, "LadderKitC0" , FieldItemKind.LadderKitC )}, // ハシゴキットC0 - {0xED35, new FieldItemDefinition(60725, 65534, 13534, "LadderKitC1" , FieldItemKind.LadderKitC )}, // ハシゴキットC1 - {0xED36, new FieldItemDefinition(60726, 65534, 13530, "LadderKitB0" , FieldItemKind.LadderKitB )}, // ハシゴキットB0 - {0xED37, new FieldItemDefinition(60727, 65534, 13530, "LadderKitB1" , FieldItemKind.LadderKitB )}, // ハシゴキットB1 - {0xED38, new FieldItemDefinition(60728, 65534, 13530, "LadderKitB2" , FieldItemKind.LadderKitB )}, // ハシゴキットB2 - {0xED39, new FieldItemDefinition(60729, 65534, 13530, "LadderKitB3" , FieldItemKind.LadderKitB )}, // ハシゴキットB3 - {0xED3A, new FieldItemDefinition(60730, 65534, 13526, "LadderKitA0" , FieldItemKind.LadderKitA )}, // ハシゴキットA0 - {0xED3B, new FieldItemDefinition(60731, 65534, 13526, "LadderKitA1" , FieldItemKind.LadderKitA )}, // ハシゴキットA1 - {0xED3C, new FieldItemDefinition(60732, 65534, 13526, "LadderKitA2" , FieldItemKind.LadderKitA )}, // ハシゴキットA2 - {0xED3F, new FieldItemDefinition(60735, 3052 , 65534, "PltVgtSquash0" , FieldItemKind.PltVgtPumpkin )}, // カボチャ(苗) - {0xED40, new FieldItemDefinition(60736, 3053 , 65534, "PltVgtSquash1" , FieldItemKind.PltVgtPumpkin )}, // カボチャ(成長1) - {0xED41, new FieldItemDefinition(60737, 4362 , 65534, "PltVgtSquash2" , FieldItemKind.PltVgtPumpkin )}, // カボチャ(成長2) - {0xED42, new FieldItemDefinition(60738, 65534, 14470, "LadderKitD" , FieldItemKind.LadderKitD )}, // ハシゴキットD0 - {0xED43, new FieldItemDefinition(60739, 65534, 13530, "LadderKitB4" , FieldItemKind.LadderKitB )}, // ハシゴキットB4 - {0xED44, new FieldItemDefinition(60740, 65534, 13530, "LadderKitB5" , FieldItemKind.LadderKitB )}, // ハシゴキットB5 - {0xED46, new FieldItemDefinition(60742, 65534, 65534, "FenceGardenPegRope" , FieldItemKind.FenceGardenPegRope )}, // 庭専用柵(編集外用) - {0xED47, new FieldItemDefinition(60743, 65534, 14758, "FenceCorrugatedIron" , FieldItemKind.FenceCorrugatedIron )}, // トタンのさく - {0xED48, new FieldItemDefinition(60744, 65534, 14759, "FencePark" , FieldItemKind.FencePark )}, // こうえんのさく・青 - {0xED49, new FieldItemDefinition(60745, 65534, 14759, "FencePark2" , FieldItemKind.FencePark )}, // こうえんのさく・赤 - {0xED4A, new FieldItemDefinition(60746, 65534, 14759, "FencePark5" , FieldItemKind.FencePark )}, // こうえんのさく・ピンク - {0xED4B, new FieldItemDefinition(60747, 65534, 14759, "FencePark4" , FieldItemKind.FencePark )}, // こうえんのさく・緑 - {0xED4C, new FieldItemDefinition(60748, 65534, 14759, "FencePark6" , FieldItemKind.FencePark )}, // こうえんのさく・赤と黄 - {0xED4D, new FieldItemDefinition(60749, 65534, 14759, "FencePark3" , FieldItemKind.FencePark )}, // こうえんのさく・黄 - {0xED4E, new FieldItemDefinition(60750, 65534, 14759, "FencePark8" , FieldItemKind.FencePark )}, // こうえんのさく・青とピンク - {0xED4F, new FieldItemDefinition(60751, 65534, 14759, "FencePark7" , FieldItemKind.FencePark )}, // こうえんのさく・緑とオレンジ - {0xED50, new FieldItemDefinition(60752, 65534, 14758, "FenceCorrugatedIron1" , FieldItemKind.FenceCorrugatedIron )}, // あおいトタンのさく - {0xED51, new FieldItemDefinition(60753, 65534, 14758, "FenceCorrugatedIron2" , FieldItemKind.FenceCorrugatedIron )}, // きいろいトタンのさく - {0xED52, new FieldItemDefinition(60754, 65534, 14758, "FenceCorrugatedIron3" , FieldItemKind.FenceCorrugatedIron )}, // みどりのトタンのさく - {0xED53, new FieldItemDefinition(60755, 65534, 14758, "FenceCorrugatedIron5" , FieldItemKind.FenceCorrugatedIron )}, // さびたトタンのさく - {0xED54, new FieldItemDefinition(60756, 65534, 14758, "FenceCorrugatedIron4" , FieldItemKind.FenceCorrugatedIron )}, // オレンジのトタンのさく - {0xED55, new FieldItemDefinition(60757, 65534, 4357 , "FenceSteel8" , FieldItemKind.FenceSteel )}, // てつのさく・黒 - {0xED56, new FieldItemDefinition(60758, 65534, 4357 , "FenceSteel7" , FieldItemKind.FenceSteel )}, // てつのさく・白 - {0xED57, new FieldItemDefinition(60759, 65534, 4357 , "FenceSteel6" , FieldItemKind.FenceSteel )}, // てつのさく・ネイビー - {0xED58, new FieldItemDefinition(60760, 65534, 4357 , "FenceSteel5" , FieldItemKind.FenceSteel )}, // てつのさく・オレンジ - {0xED59, new FieldItemDefinition(60761, 65534, 14758, "FenceCorrugatedIron6" , FieldItemKind.FenceCorrugatedIron )}, // しろいトタンのさく - {0xED5A, new FieldItemDefinition(60762, 65534, 14758, "FenceCorrugatedIron7" , FieldItemKind.FenceCorrugatedIron )}, // くろいトタンのさく - {0xED5B, new FieldItemDefinition(60763, 65534, 3402 , "FenceVerticalWood8" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・紫 - {0xED5C, new FieldItemDefinition(60764, 65534, 3402 , "FenceVerticalWood7" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・白 - {0xED5D, new FieldItemDefinition(60765, 65534, 12894, "FenceJuneBride7" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・くろ - {0xED5E, new FieldItemDefinition(60766, 65534, 12894, "FenceJuneBride6" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・むらさき - {0xED5F, new FieldItemDefinition(60767, 65534, 12894, "FenceJuneBride5" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・きいろ - }; + var rkind = ItemInfo.GetItemKind(remap); + if (rkind != ItemKind.Unknown) + return rkind; + + // shouldn't reach here, but play it safe + return definition.Kind.ToItemKind(); } -} + + public static readonly IReadOnlyDictionary Items = new Dictionary + { + {0xEA60, new FieldItemDefinition(60000, 2799 , 65534, "PltTreeOak4" , FieldItemKind.PltTreeOak )}, // 広葉樹(成木) + {0xEA61, new FieldItemDefinition(60001, 3360 , 65534, "PltTreeApple" , FieldItemKind.PltTreeOak )}, // リンゴの木(成木) + {0xEA62, new FieldItemDefinition(60002, 3365 , 65534, "PltTreeOrange" , FieldItemKind.PltTreeOak )}, // オレンジの木(成木) + {0xEA65, new FieldItemDefinition(60005, 5152 , 65534, "PltTreeOak0" , FieldItemKind.PltTreeOak )}, // 広葉樹(苗) + {0xEA66, new FieldItemDefinition(60006, 2796 , 65534, "PltTreeOak1" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長1) + {0xEA67, new FieldItemDefinition(60007, 2797 , 65534, "PltTreeOak2" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長2) + {0xEA68, new FieldItemDefinition(60008, 2798 , 65534, "PltTreeOak3" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長3) + {0xEA69, new FieldItemDefinition(60009, 2805 , 65534, "PltTreeCedar4" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成木) + {0xEA6F, new FieldItemDefinition(60015, 2627 , 2627 , "PltFlwCosmos1Red" , FieldItemKind.PltFlwCosmos )}, // コスモス赤(茎) + {0xEA70, new FieldItemDefinition(60016, 2628 , 2628 , "PltFlwCosmos2Red" , FieldItemKind.PltFlwCosmos )}, // コスモス赤(つぼみ) + {0xEA71, new FieldItemDefinition(60017, 3824 , 2304 , "PltFlwCosmos3Red" , FieldItemKind.PltFlwCosmos )}, // コスモス赤(花) + {0xEA72, new FieldItemDefinition(60018, 2630 , 2630 , "PltFlwCosmos1White" , FieldItemKind.PltFlwCosmos )}, // コスモス白(茎) + {0xEA73, new FieldItemDefinition(60019, 2631 , 2631 , "PltFlwCosmos2White" , FieldItemKind.PltFlwCosmos )}, // コスモス白(つぼみ) + {0xEA74, new FieldItemDefinition(60020, 3826 , 2305 , "PltFlwCosmos3White" , FieldItemKind.PltFlwCosmos )}, // コスモス白(花) + {0xEA76, new FieldItemDefinition(60022, 2815 , 65534, "PltTreeBamboo4" , FieldItemKind.PltTreeBamboo )}, // 竹(成木) + {0xEA77, new FieldItemDefinition(60023, 2810 , 65534, "PltTreePalm4" , FieldItemKind.PltTreePalm )}, // ヤシの木(成木) + {0xEA79, new FieldItemDefinition(60025, 65534, 65534, "Hole" , FieldItemKind.UnitIconHole )}, // 穴 + {0xEA7C, new FieldItemDefinition(60028, 12897, 65534, "PltVgtTomato0" , FieldItemKind.PltVgtTomato )}, // トマト(苗) + {0xEA7D, new FieldItemDefinition(60029, 2651 , 65534, "PltVgtTomato1" , FieldItemKind.PltVgtTomato )}, // トマト(成長1) + {0xEA7E, new FieldItemDefinition(60030, 2652 , 65534, "PltVgtTomato2" , FieldItemKind.PltVgtTomato )}, // トマト(成長2) + {0xEA7F, new FieldItemDefinition(60031, 12898, 2570 , "PltVgtTomato3" , FieldItemKind.PltVgtTomato )}, // トマト(成木) + {0xEA81, new FieldItemDefinition(60033, 2624 , 2624 , "PltWeedAut1A" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草01A + {0xEA82, new FieldItemDefinition(60034, 2624 , 2624 , "PltWeedAut1B" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草01B + {0xEA83, new FieldItemDefinition(60035, 2624 , 2624 , "PltWeedAut1C" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草01C + {0xEA86, new FieldItemDefinition(60038, 2624 , 2624 , "PltWeedSmr1A" , FieldItemKind.PltWeedSmr )}, // 夏の雑草1A + {0xEA87, new FieldItemDefinition(60039, 2624 , 2624 , "PltWeedSmr1B" , FieldItemKind.PltWeedSmr )}, // 夏の雑草1B + {0xEA88, new FieldItemDefinition(60040, 2624 , 2624 , "PltWeedSmr1C" , FieldItemKind.PltWeedSmr )}, // 夏の雑草1C + {0xEA89, new FieldItemDefinition(60041, 2865 , 2865 , "PltFlwCosmos1Yellow" , FieldItemKind.PltFlwCosmos )}, // コスモス黄(茎) + {0xEA8A, new FieldItemDefinition(60042, 2866 , 2866 , "PltFlwCosmos2Yellow" , FieldItemKind.PltFlwCosmos )}, // コスモス黄(つぼみ) + {0xEA8B, new FieldItemDefinition(60043, 3828 , 2863 , "PltFlwCosmos3Yellow" , FieldItemKind.PltFlwCosmos )}, // コスモス黄(花) + {0xEA9F, new FieldItemDefinition(60063, 65534, 65534, "PltTreeOak4Stump" , FieldItemKind.PltTreeOak )}, // 広葉樹(成木の切り株) + {0xEAA1, new FieldItemDefinition(60065, 65534, 11711, "FenceWoodWhite" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・白 + {0xEAB4, new FieldItemDefinition(60084, 65534, 65534, "PltTreeCedar4Stump" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成木の切り株) + {0xEAB5, new FieldItemDefinition(60085, 5151 , 65534, "PltTreeCedar0" , FieldItemKind.PltTreeCedar )}, // 針葉樹(苗) + {0xEAB6, new FieldItemDefinition(60086, 2803 , 65534, "PltTreeCedar2" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長2) + {0xEAB7, new FieldItemDefinition(60087, 2802 , 65534, "PltTreeCedar1" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長1) + {0xEAB8, new FieldItemDefinition(60088, 2804 , 65534, "PltTreeCedar3" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長3) + {0xEABE, new FieldItemDefinition(60094, 65534, 65534, "PltTreePalm4Stump" , FieldItemKind.PltTreePalm )}, // ヤシの木(成木の切り株) + {0xEABF, new FieldItemDefinition(60095, 2806 , 65534, "PltTreePalm0" , FieldItemKind.PltTreePalm )}, // ヤシの木(苗) + {0xEAC0, new FieldItemDefinition(60096, 2808 , 65534, "PltTreePalm2" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長2) + {0xEAC1, new FieldItemDefinition(60097, 2807 , 65534, "PltTreePalm1" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長1) + {0xEAC2, new FieldItemDefinition(60098, 2809 , 65534, "PltTreePalm3" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長3) + {0xEAC3, new FieldItemDefinition(60099, 65534, 65534, "PltTreeBamboo4Stump" , FieldItemKind.PltTreeBamboo )}, // 竹(成木の切り株) + {0xEAC4, new FieldItemDefinition(60100, 2811 , 65534, "PltTreeBamboo0" , FieldItemKind.PltTreeBamboo )}, // 竹(苗) + {0xEAC5, new FieldItemDefinition(60101, 2813 , 65534, "PltTreeBamboo2" , FieldItemKind.PltTreeBamboo )}, // 竹(成長2) + {0xEAC6, new FieldItemDefinition(60102, 2812 , 65534, "PltTreeBamboo1" , FieldItemKind.PltTreeBamboo )}, // 竹(成長1) + {0xEAC7, new FieldItemDefinition(60103, 2814 , 65534, "PltTreeBamboo3" , FieldItemKind.PltTreeBamboo )}, // 竹(成長3) + {0xEAC8, new FieldItemDefinition(60104, 3370 , 65534, "PltTreePear" , FieldItemKind.PltTreeOak )}, // ナシの木(成木) + {0xEAC9, new FieldItemDefinition(60105, 3381 , 65534, "PltTreeCherry" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(成木) + {0xEACA, new FieldItemDefinition(60106, 3375 , 65534, "PltTreePeach" , FieldItemKind.PltTreeOak )}, // モモの木(成木) + {0xEACB, new FieldItemDefinition(60107, 2861 , 65534, "PltBushAzalea3White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(成木花) + {0xEACC, new FieldItemDefinition(60108, 12747, 65534, "PltBushAzalea0White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(苗) + {0xEACD, new FieldItemDefinition(60109, 2861 , 65534, "PltBushAzalea2White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(成木つぼみ) + {0xEACF, new FieldItemDefinition(60111, 2861 , 65534, "PltBushAzalea4White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(成木花なし) + {0xEAD0, new FieldItemDefinition(60112, 2860 , 65534, "PltBushAzalea1White" , FieldItemKind.PltBushAzalea )}, // ツツジ白(成長1) + {0xEAD1, new FieldItemDefinition(60113, 3022 , 65534, "PltBushHibiscus3Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(成木花) + {0xEAD2, new FieldItemDefinition(60114, 12752, 65534, "PltBushHibiscus0Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(苗) + {0xEAD3, new FieldItemDefinition(60115, 3022 , 65534, "PltBushHibiscus2Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(成木つぼみ) + {0xEAD4, new FieldItemDefinition(60116, 3022 , 65534, "PltBushHibiscus4Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(成木花なし) + {0xEAD5, new FieldItemDefinition(60117, 3021 , 65534, "PltBushHibiscus1Red" , FieldItemKind.PltBushHibiscus )}, // ハイビスカス赤(成長1) + {0xEAD6, new FieldItemDefinition(60118, 3027 , 65534, "PltBushHolly3" , FieldItemKind.PltBushHolly )}, // ヒイラギ(成木花) + {0xEAD7, new FieldItemDefinition(60119, 12757, 65534, "PltBushHolly0" , FieldItemKind.PltBushHolly )}, // ヒイラギ(苗) + {0xEAD8, new FieldItemDefinition(60120, 3027 , 65534, "PltBushHolly2" , FieldItemKind.PltBushHolly )}, // ヒイラギ(成木つぼみ) + {0xEAD9, new FieldItemDefinition(60121, 3026 , 65534, "PltBushHolly1" , FieldItemKind.PltBushHolly )}, // ヒイラギ(成長1) + {0xEADA, new FieldItemDefinition(60122, 3027 , 65534, "PltBushHolly4" , FieldItemKind.PltBushHolly )}, // ヒイラギ(成木花なし) + {0xEADC, new FieldItemDefinition(60124, 3033 , 65534, "PltVgtWheat2" , FieldItemKind.PltVgtWheat )}, // 小麦(成長2) + {0xEADD, new FieldItemDefinition(60125, 12899, 3029 , "PltVgtWheat3" , FieldItemKind.PltVgtWheat )}, // 小麦(成木) + {0xEADE, new FieldItemDefinition(60126, 3032 , 65534, "PltVgtWheat1" , FieldItemKind.PltVgtWheat )}, // 小麦(成長1) + {0xEADF, new FieldItemDefinition(60127, 3031 , 65534, "PltVgtWheat0" , FieldItemKind.PltVgtWheat )}, // 小麦(苗) + {0xEAE6, new FieldItemDefinition(60134, 12900, 3034 , "PltVgtSugarCane3" , FieldItemKind.PltVgtSugarcane )}, // サトウキビ(成木) + {0xEAE7, new FieldItemDefinition(60135, 3037 , 65534, "PltVgtSugarCane1" , FieldItemKind.PltVgtSugarcane )}, // サトウキビ(成長1) + {0xEAE8, new FieldItemDefinition(60136, 12901, 65534, "PltVgtSugarCane0" , FieldItemKind.PltVgtSugarcane )}, // サトウキビ(苗) + {0xEAE9, new FieldItemDefinition(60137, 3038 , 65534, "PltVgtSugarCane2" , FieldItemKind.PltVgtSugarcane )}, // サトウキビ(成長2) + {0xEAEA, new FieldItemDefinition(60138, 12902, 3039 , "PltVgtPotato3" , FieldItemKind.PltVgtPotato )}, // ジャガイモ(成木) + {0xEAEB, new FieldItemDefinition(60139, 3042 , 65534, "PltVgtPotato1" , FieldItemKind.PltVgtPotato )}, // ジャガイモ(成長1) + {0xEAEC, new FieldItemDefinition(60140, 12903, 65534, "PltVgtPotato0" , FieldItemKind.PltVgtPotato )}, // ジャガイモ(苗) + {0xEAED, new FieldItemDefinition(60141, 3043 , 65534, "PltVgtPotato2" , FieldItemKind.PltVgtPotato )}, // ジャガイモ(成長2) + {0xEAEE, new FieldItemDefinition(60142, 12905, 3044 , "PltVgtCarrot3" , FieldItemKind.PltVgtCarrot )}, // ニンジン(成木) + {0xEAEF, new FieldItemDefinition(60143, 3047 , 65534, "PltVgtCarrot1" , FieldItemKind.PltVgtCarrot )}, // ニンジン(成長1) + {0xEAF0, new FieldItemDefinition(60144, 3046 , 65534, "PltVgtCarrot0" , FieldItemKind.PltVgtCarrot )}, // ニンジン(苗) + {0xEAF1, new FieldItemDefinition(60145, 3048 , 65534, "PltVgtCarrot2" , FieldItemKind.PltVgtCarrot )}, // ニンジン(成長2) + {0xEAF7, new FieldItemDefinition(60151, 2878 , 2878 , "PltFlwCosmos2Black" , FieldItemKind.PltFlwCosmos )}, // コスモス黒(つぼみ) + {0xEAF8, new FieldItemDefinition(60152, 3832 , 2871 , "PltFlwCosmos3Orange" , FieldItemKind.PltFlwCosmos )}, // コスモスオレンジ(花) + {0xEAF9, new FieldItemDefinition(60153, 3834 , 2875 , "PltFlwCosmos3Black" , FieldItemKind.PltFlwCosmos )}, // コスモス黒(花) + {0xEAFA, new FieldItemDefinition(60154, 3830 , 2867 , "PltFlwCosmos3Pink" , FieldItemKind.PltFlwCosmos )}, // コスモス桃(花) + {0xEAFB, new FieldItemDefinition(60155, 2877 , 2877 , "PltFlwCosmos1Black" , FieldItemKind.PltFlwCosmos )}, // コスモス黒(茎) + {0xEAFC, new FieldItemDefinition(60156, 2873 , 2873 , "PltFlwCosmos1Orange" , FieldItemKind.PltFlwCosmos )}, // コスモスオレンジ(茎) + {0xEAFD, new FieldItemDefinition(60157, 2874 , 2874 , "PltFlwCosmos2Orange" , FieldItemKind.PltFlwCosmos )}, // コスモスオレンジ(つぼみ) + {0xEAFE, new FieldItemDefinition(60158, 2869 , 2869 , "PltFlwCosmos1Pink" , FieldItemKind.PltFlwCosmos )}, // コスモス桃(茎) + {0xEAFF, new FieldItemDefinition(60159, 2870 , 2870 , "PltFlwCosmos2Pink" , FieldItemKind.PltFlwCosmos )}, // コスモス桃(つぼみ) + {0xEB00, new FieldItemDefinition(60160, 65534, 3080 , "FenceWallRenga" , FieldItemKind.FenceWallRenga )}, // レンガの壁 + {0xEB01, new FieldItemDefinition(60161, 2624 , 2624 , "PltWeedSmr3" , FieldItemKind.PltWeedSmr )}, // 夏の雑草3 + {0xEB02, new FieldItemDefinition(60162, 2624 , 2624 , "PltWeedSmr2A" , FieldItemKind.PltWeedSmr )}, // 夏の雑草2A + {0xEB03, new FieldItemDefinition(60163, 2624 , 2624 , "PltWeedSmr2C" , FieldItemKind.PltWeedSmr )}, // 夏の雑草2C + {0xEB04, new FieldItemDefinition(60164, 2624 , 2624 , "PltWeedSmr2B" , FieldItemKind.PltWeedSmr )}, // 夏の雑草2B + {0xEB05, new FieldItemDefinition(60165, 2624 , 2624 , "PltWeedAut3" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草03 + {0xEB12, new FieldItemDefinition(60178, 65534, 65534, "StoneA" , FieldItemKind.StoneA )}, // 岩A + {0xEB13, new FieldItemDefinition(60179, 65534, 65534, "StoneB" , FieldItemKind.StoneB )}, // 岩B + {0xEB14, new FieldItemDefinition(60180, 65534, 65534, "StoneE" , FieldItemKind.StoneE )}, // 岩E + {0xEB15, new FieldItemDefinition(60181, 65534, 65534, "StoneD" , FieldItemKind.StoneD )}, // 岩D + {0xEB16, new FieldItemDefinition(60182, 65534, 65534, "StoneC" , FieldItemKind.StoneC )}, // 岩C + {0xEB17, new FieldItemDefinition(60183, 2624 , 2624 , "PltWeedAut2B" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草02B + {0xEB18, new FieldItemDefinition(60184, 2624 , 2624 , "PltWeedAut2C" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草02C + {0xEB19, new FieldItemDefinition(60185, 2624 , 2624 , "PltWeedAut2A" , FieldItemKind.PltWeedAut0 )}, // 秋の雑草02A + {0xEB28, new FieldItemDefinition(60200, 2624 , 2624 , "PltWeedSpr1A" , FieldItemKind.PltWeedSpr )}, // 春の雑草1A + {0xEB30, new FieldItemDefinition(60208, 2624 , 2624 , "PltWeedSpr1B" , FieldItemKind.PltWeedSpr )}, // 春の雑草1B + {0xEB31, new FieldItemDefinition(60209, 2624 , 2624 , "PltWeedSpr1C" , FieldItemKind.PltWeedSpr )}, // 春の雑草1C + {0xEB32, new FieldItemDefinition(60210, 2624 , 2624 , "PltWeedSpr2A" , FieldItemKind.PltWeedSpr )}, // 春の雑草2A + {0xEB33, new FieldItemDefinition(60211, 2624 , 2624 , "PltWeedSpr2B" , FieldItemKind.PltWeedSpr )}, // 春の雑草2B + {0xEB34, new FieldItemDefinition(60212, 2624 , 2624 , "PltWeedSpr2C" , FieldItemKind.PltWeedSpr )}, // 春の雑草2C + {0xEB35, new FieldItemDefinition(60213, 2624 , 2624 , "PltWeedSpr3" , FieldItemKind.PltWeedSpr )}, // 春の雑草3 + {0xEB36, new FieldItemDefinition(60214, 2624 , 2624 , "PltWeedWin1A" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草01A + {0xEB37, new FieldItemDefinition(60215, 2624 , 2624 , "PltWeedWin1B" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草01B + {0xEB38, new FieldItemDefinition(60216, 2624 , 2624 , "PltWeedWin1C" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草01C + {0xEB39, new FieldItemDefinition(60217, 2624 , 2624 , "PltWeedWin2A" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草02A + {0xEB3A, new FieldItemDefinition(60218, 2624 , 2624 , "PltWeedWin2B" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草02B + {0xEB3B, new FieldItemDefinition(60219, 2624 , 2624 , "PltWeedWin2C" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草02C + {0xEB3C, new FieldItemDefinition(60220, 2624 , 2624 , "PltWeedWin3" , FieldItemKind.PltWeedWin0 )}, // 冬の雑草03 + {0xEB3D, new FieldItemDefinition(60221, 2881 , 2881 , "PltFlwTulip1White" , FieldItemKind.PltFlwTulip )}, // チューリップ白(茎) + {0xEB3E, new FieldItemDefinition(60222, 2882 , 2882 , "PltFlwTulip2White" , FieldItemKind.PltFlwTulip )}, // チューリップ白(つぼみ) + {0xEB3F, new FieldItemDefinition(60223, 3836 , 2879 , "PltFlwTulip3White" , FieldItemKind.PltFlwTulip )}, // チューリップ白(花) + {0xEB40, new FieldItemDefinition(60224, 2885 , 2885 , "PltFlwTulip1Red" , FieldItemKind.PltFlwTulip )}, // チューリップ赤(茎) + {0xEB41, new FieldItemDefinition(60225, 2886 , 2886 , "PltFlwTulip2Red" , FieldItemKind.PltFlwTulip )}, // チューリップ赤(つぼみ) + {0xEB42, new FieldItemDefinition(60226, 3838 , 2883 , "PltFlwTulip3Red" , FieldItemKind.PltFlwTulip )}, // チューリップ赤(花) + {0xEB43, new FieldItemDefinition(60227, 2889 , 2889 , "PltFlwTulip1Yellow" , FieldItemKind.PltFlwTulip )}, // チューリップ黄(茎) + {0xEB44, new FieldItemDefinition(60228, 2890 , 2890 , "PltFlwTulip2Yellow" , FieldItemKind.PltFlwTulip )}, // チューリップ黄(つぼみ) + {0xEB45, new FieldItemDefinition(60229, 3840 , 2887 , "PltFlwTulip3Yellow" , FieldItemKind.PltFlwTulip )}, // チューリップ黄(花) + {0xEB46, new FieldItemDefinition(60230, 2893 , 2893 , "PltFlwTulip1Pink" , FieldItemKind.PltFlwTulip )}, // チューリップ桃(茎) + {0xEB47, new FieldItemDefinition(60231, 2894 , 2894 , "PltFlwTulip2Pink" , FieldItemKind.PltFlwTulip )}, // チューリップ桃(つぼみ) + {0xEB48, new FieldItemDefinition(60232, 3842 , 2891 , "PltFlwTulip3Pink" , FieldItemKind.PltFlwTulip )}, // チューリップ桃(花) + {0xEB49, new FieldItemDefinition(60233, 2897 , 2897 , "PltFlwTulip1Orange" , FieldItemKind.PltFlwTulip )}, // チューリップオレンジ(茎) + {0xEB4A, new FieldItemDefinition(60234, 2898 , 2898 , "PltFlwTulip2Orange" , FieldItemKind.PltFlwTulip )}, // チューリップオレンジ(つぼみ) + {0xEB4B, new FieldItemDefinition(60235, 3844 , 2895 , "PltFlwTulip3Orange" , FieldItemKind.PltFlwTulip )}, // チューリップオレンジ(花) + {0xEB4C, new FieldItemDefinition(60236, 2901 , 2901 , "PltFlwTulip1Purple" , FieldItemKind.PltFlwTulip )}, // チューリップ紫(茎) + {0xEB4D, new FieldItemDefinition(60237, 2902 , 2902 , "PltFlwTulip2Purple" , FieldItemKind.PltFlwTulip )}, // チューリップ紫(つぼみ) + {0xEB4E, new FieldItemDefinition(60238, 3846 , 2899 , "PltFlwTulip3Purple" , FieldItemKind.PltFlwTulip )}, // チューリップ紫(花) + {0xEB4F, new FieldItemDefinition(60239, 2905 , 2905 , "PltFlwTulip1Black" , FieldItemKind.PltFlwTulip )}, // チューリップ黒(茎) + {0xEB50, new FieldItemDefinition(60240, 2906 , 2906 , "PltFlwTulip2Black" , FieldItemKind.PltFlwTulip )}, // チューリップ黒(つぼみ) + {0xEB51, new FieldItemDefinition(60241, 3848 , 2903 , "PltFlwTulip3Black" , FieldItemKind.PltFlwTulip )}, // チューリップ黒(花) + {0xEB52, new FieldItemDefinition(60242, 2909 , 2909 , "PltFlwPansy1White" , FieldItemKind.PltFlwPansy )}, // パンジー白(茎) + {0xEB53, new FieldItemDefinition(60243, 2910 , 2910 , "PltFlwPansy2White" , FieldItemKind.PltFlwPansy )}, // パンジー白(つぼみ) + {0xEB54, new FieldItemDefinition(60244, 3850 , 2907 , "PltFlwPansy3White" , FieldItemKind.PltFlwPansy )}, // パンジー白(花) + {0xEB55, new FieldItemDefinition(60245, 2913 , 2913 , "PltFlwPansy1Red" , FieldItemKind.PltFlwPansy )}, // パンジー赤(茎) + {0xEB56, new FieldItemDefinition(60246, 2914 , 2914 , "PltFlwPansy2Red" , FieldItemKind.PltFlwPansy )}, // パンジー赤(つぼみ) + {0xEB57, new FieldItemDefinition(60247, 3852 , 2911 , "PltFlwPansy3Red" , FieldItemKind.PltFlwPansy )}, // パンジー赤(花) + {0xEB58, new FieldItemDefinition(60248, 2917 , 2917 , "PltFlwPansy1Yellow" , FieldItemKind.PltFlwPansy )}, // パンジー黄(茎) + {0xEB59, new FieldItemDefinition(60249, 2918 , 2918 , "PltFlwPansy2Yellow" , FieldItemKind.PltFlwPansy )}, // パンジー黄(つぼみ) + {0xEB5A, new FieldItemDefinition(60250, 3854 , 2915 , "PltFlwPansy3Yellow" , FieldItemKind.PltFlwPansy )}, // パンジー黄(花) + {0xEB5B, new FieldItemDefinition(60251, 2921 , 2921 , "PltFlwPansy1RedYellow" , FieldItemKind.PltFlwPansy )}, // パンジー赤黄(茎) + {0xEB5C, new FieldItemDefinition(60252, 2922 , 2922 , "PltFlwPansy2RedYellow" , FieldItemKind.PltFlwPansy )}, // パンジー赤黄(つぼみ) + {0xEB5D, new FieldItemDefinition(60253, 3856 , 2919 , "PltFlwPansy3RedYellow" , FieldItemKind.PltFlwPansy )}, // パンジー赤黄(花) + {0xEB5E, new FieldItemDefinition(60254, 2925 , 2925 , "PltFlwPansy1Purple" , FieldItemKind.PltFlwPansy )}, // パンジー紫(茎) + {0xEB5F, new FieldItemDefinition(60255, 2926 , 2926 , "PltFlwPansy2Purple" , FieldItemKind.PltFlwPansy )}, // パンジー紫(つぼみ) + {0xEB60, new FieldItemDefinition(60256, 3858 , 2923 , "PltFlwPansy3Purple" , FieldItemKind.PltFlwPansy )}, // パンジー紫(花) + {0xEB61, new FieldItemDefinition(60257, 2929 , 2929 , "PltFlwPansy1Blue" , FieldItemKind.PltFlwPansy )}, // パンジー青(茎) + {0xEB62, new FieldItemDefinition(60258, 2930 , 2930 , "PltFlwPansy2Blue" , FieldItemKind.PltFlwPansy )}, // パンジー青(つぼみ) + {0xEB63, new FieldItemDefinition(60259, 3860 , 2927 , "PltFlwPansy3Blue" , FieldItemKind.PltFlwPansy )}, // パンジー青(花) + {0xEB64, new FieldItemDefinition(60260, 2933 , 2933 , "PltFlwRose1White" , FieldItemKind.PltFlwRose )}, // バラ白(茎) + {0xEB65, new FieldItemDefinition(60261, 2934 , 2934 , "PltFlwRose2White" , FieldItemKind.PltFlwRose )}, // バラ白(つぼみ) + {0xEB66, new FieldItemDefinition(60262, 3862 , 2931 , "PltFlwRose3White" , FieldItemKind.PltFlwRose )}, // バラ白(花) + {0xEB67, new FieldItemDefinition(60263, 2937 , 2937 , "PltFlwRose1Red" , FieldItemKind.PltFlwRose )}, // バラ赤(茎) + {0xEB68, new FieldItemDefinition(60264, 2938 , 2938 , "PltFlwRose2Red" , FieldItemKind.PltFlwRose )}, // バラ赤(つぼみ) + {0xEB69, new FieldItemDefinition(60265, 3864 , 2935 , "PltFlwRose3Red" , FieldItemKind.PltFlwRose )}, // バラ赤(花) + {0xEB6A, new FieldItemDefinition(60266, 2941 , 2941 , "PltFlwRose1Yellow" , FieldItemKind.PltFlwRose )}, // バラ黄(茎) + {0xEB6B, new FieldItemDefinition(60267, 2942 , 2942 , "PltFlwRose2Yellow" , FieldItemKind.PltFlwRose )}, // バラ黄(つぼみ) + {0xEB6C, new FieldItemDefinition(60268, 3866 , 2939 , "PltFlwRose3Yellow" , FieldItemKind.PltFlwRose )}, // バラ黄(花) + {0xEB6D, new FieldItemDefinition(60269, 2945 , 2945 , "PltFlwRose1Pink" , FieldItemKind.PltFlwRose )}, // バラ桃(茎) + {0xEB6E, new FieldItemDefinition(60270, 2946 , 2946 , "PltFlwRose2Pink" , FieldItemKind.PltFlwRose )}, // バラ桃(つぼみ) + {0xEB6F, new FieldItemDefinition(60271, 3868 , 2943 , "PltFlwRose3Pink" , FieldItemKind.PltFlwRose )}, // バラ桃(花) + {0xEB70, new FieldItemDefinition(60272, 2949 , 2949 , "PltFlwRose1Orange" , FieldItemKind.PltFlwRose )}, // バラオレンジ(茎) + {0xEB71, new FieldItemDefinition(60273, 2950 , 2950 , "PltFlwRose2Orange" , FieldItemKind.PltFlwRose )}, // バラオレンジ(つぼみ) + {0xEB72, new FieldItemDefinition(60274, 3870 , 2947 , "PltFlwRose3Orange" , FieldItemKind.PltFlwRose )}, // バラオレンジ(花) + {0xEB73, new FieldItemDefinition(60275, 2953 , 2953 , "PltFlwRose1Purple" , FieldItemKind.PltFlwRose )}, // バラ紫(茎) + {0xEB74, new FieldItemDefinition(60276, 2954 , 2954 , "PltFlwRose2Purple" , FieldItemKind.PltFlwRose )}, // バラ紫(つぼみ) + {0xEB75, new FieldItemDefinition(60277, 3872 , 2951 , "PltFlwRose3Purple" , FieldItemKind.PltFlwRose )}, // バラ紫(花) + {0xEB76, new FieldItemDefinition(60278, 2957 , 2957 , "PltFlwRose1Black" , FieldItemKind.PltFlwRose )}, // バラ黒(茎) + {0xEB77, new FieldItemDefinition(60279, 2958 , 2958 , "PltFlwRose2Black" , FieldItemKind.PltFlwRose )}, // バラ黒(つぼみ) + {0xEB78, new FieldItemDefinition(60280, 3874 , 2955 , "PltFlwRose3Black" , FieldItemKind.PltFlwRose )}, // バラ黒(花) + {0xEB79, new FieldItemDefinition(60281, 2961 , 2961 , "PltFlwRose1Blue" , FieldItemKind.PltFlwRose )}, // バラ青(茎) + {0xEB7A, new FieldItemDefinition(60282, 2962 , 2962 , "PltFlwRose2Blue" , FieldItemKind.PltFlwRose )}, // バラ青(つぼみ) + {0xEB7B, new FieldItemDefinition(60283, 3876 , 2959 , "PltFlwRose3Blue" , FieldItemKind.PltFlwRose )}, // バラ青(花) + {0xEB7C, new FieldItemDefinition(60284, 2965 , 2965 , "PltFlwRose1Gold" , FieldItemKind.PltFlwRoseGold )}, // バラ金(茎) + {0xEB7D, new FieldItemDefinition(60285, 2966 , 2966 , "PltFlwRose2Gold" , FieldItemKind.PltFlwRoseGold )}, // バラ金(つぼみ) + {0xEB7E, new FieldItemDefinition(60286, 3878 , 2963 , "PltFlwRose3Gold" , FieldItemKind.PltFlwRoseGold )}, // バラ金(花) + {0xEB88, new FieldItemDefinition(60296, 2981 , 2981 , "PltFlwYuri1White" , FieldItemKind.PltFlwYuri )}, // ユリ白(茎) + {0xEB89, new FieldItemDefinition(60297, 2982 , 2982 , "PltFlwYuri2White" , FieldItemKind.PltFlwYuri )}, // ユリ白(つぼみ) + {0xEB8A, new FieldItemDefinition(60298, 3886 , 2979 , "PltFlwYuri3White" , FieldItemKind.PltFlwYuri )}, // ユリ白(花) + {0xEB8B, new FieldItemDefinition(60299, 2985 , 2985 , "PltFlwYuri1Red" , FieldItemKind.PltFlwYuri )}, // ユリ赤(茎) + {0xEB8C, new FieldItemDefinition(60300, 2986 , 2986 , "PltFlwYuri2Red" , FieldItemKind.PltFlwYuri )}, // ユリ赤(つぼみ) + {0xEB8D, new FieldItemDefinition(60301, 3888 , 2983 , "PltFlwYuri3Red" , FieldItemKind.PltFlwYuri )}, // ユリ赤(花) + {0xEB8E, new FieldItemDefinition(60302, 2989 , 2989 , "PltFlwYuri1Yellow" , FieldItemKind.PltFlwYuri )}, // ユリ黄(茎) + {0xEB8F, new FieldItemDefinition(60303, 2990 , 2990 , "PltFlwYuri2Yellow" , FieldItemKind.PltFlwYuri )}, // ユリ黄(つぼみ) + {0xEB90, new FieldItemDefinition(60304, 3890 , 2987 , "PltFlwYuri3Yellow" , FieldItemKind.PltFlwYuri )}, // ユリ黄(花) + {0xEB91, new FieldItemDefinition(60305, 2993 , 2993 , "PltFlwYuri1Pink" , FieldItemKind.PltFlwYuri )}, // ユリ桃(茎) + {0xEB92, new FieldItemDefinition(60306, 2994 , 2994 , "PltFlwYuri2Pink" , FieldItemKind.PltFlwYuri )}, // ユリ桃(つぼみ) + {0xEB93, new FieldItemDefinition(60307, 3892 , 2991 , "PltFlwYuri3Pink" , FieldItemKind.PltFlwYuri )}, // ユリ桃(花) + {0xEB94, new FieldItemDefinition(60308, 2997 , 2997 , "PltFlwYuri1Orange" , FieldItemKind.PltFlwYuri )}, // ユリオレンジ(茎) + {0xEB95, new FieldItemDefinition(60309, 2998 , 2998 , "PltFlwYuri2Orange" , FieldItemKind.PltFlwYuri )}, // ユリオレンジ(つぼみ) + {0xEB96, new FieldItemDefinition(60310, 3894 , 2995 , "PltFlwYuri3Orange" , FieldItemKind.PltFlwYuri )}, // ユリオレンジ(花) + {0xEB97, new FieldItemDefinition(60311, 3001 , 3001 , "PltFlwYuri1Black" , FieldItemKind.PltFlwYuri )}, // ユリ黒(茎) + {0xEB98, new FieldItemDefinition(60312, 3002 , 3002 , "PltFlwYuri2Black" , FieldItemKind.PltFlwYuri )}, // ユリ黒(つぼみ) + {0xEB99, new FieldItemDefinition(60313, 3896 , 2999 , "PltFlwYuri3Black" , FieldItemKind.PltFlwYuri )}, // ユリ黒(花) + {0xEBBA, new FieldItemDefinition(60346, 65534, 3402 , "FenceVerticalWood" , FieldItemKind.FenceVerticalWood )}, // たていたのさく + {0xEBBF, new FieldItemDefinition(60351, 65534, 3403 , "FenceBamboo" , FieldItemKind.FenceBamboo )}, // たけがき + {0xEBC0, new FieldItemDefinition(60352, 3380 , 65534, "PltTreeCherry3" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(成長3) + {0xEBC1, new FieldItemDefinition(60353, 3379 , 65534, "PltTreeCherry2" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(成長2) + {0xEBC2, new FieldItemDefinition(60354, 3377 , 65534, "PltTreeCherry0" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(苗) + {0xEBC3, new FieldItemDefinition(60355, 3378 , 65534, "PltTreeCherry1" , FieldItemKind.PltTreeOak )}, // さくらんぼの木(成長1) + {0xEBC4, new FieldItemDefinition(60356, 3371 , 65534, "PltTreePeach0" , FieldItemKind.PltTreeOak )}, // モモの木(苗) + {0xEBC5, new FieldItemDefinition(60357, 3372 , 65534, "PltTreePeach1" , FieldItemKind.PltTreeOak )}, // モモの木(成長1) + {0xEBC6, new FieldItemDefinition(60358, 3373 , 65534, "PltTreePeach2" , FieldItemKind.PltTreeOak )}, // モモの木(成長2) + {0xEBC7, new FieldItemDefinition(60359, 3374 , 65534, "PltTreePeach3" , FieldItemKind.PltTreeOak )}, // モモの木(成長3) + {0xEBC8, new FieldItemDefinition(60360, 3361 , 65534, "PltTreeOrange0" , FieldItemKind.PltTreeOak )}, // オレンジの木(苗) + {0xEBC9, new FieldItemDefinition(60361, 3362 , 65534, "PltTreeOrange1" , FieldItemKind.PltTreeOak )}, // オレンジの木(成長1) + {0xEBCA, new FieldItemDefinition(60362, 3363 , 65534, "PltTreeOrange2" , FieldItemKind.PltTreeOak )}, // オレンジの木(成長2) + {0xEBCB, new FieldItemDefinition(60363, 3364 , 65534, "PltTreeOrange3" , FieldItemKind.PltTreeOak )}, // オレンジの木(成長3) + {0xEBCC, new FieldItemDefinition(60364, 3366 , 65534, "PltTreePear0" , FieldItemKind.PltTreeOak )}, // ナシの木(苗) + {0xEBCD, new FieldItemDefinition(60365, 3367 , 65534, "PltTreePear1" , FieldItemKind.PltTreeOak )}, // ナシの木(成長1) + {0xEBCE, new FieldItemDefinition(60366, 3368 , 65534, "PltTreePear2" , FieldItemKind.PltTreeOak )}, // ナシの木(成長2) + {0xEBCF, new FieldItemDefinition(60367, 3369 , 65534, "PltTreePear3" , FieldItemKind.PltTreeOak )}, // ナシの木(成長3) + {0xEBD0, new FieldItemDefinition(60368, 3357 , 65534, "PltTreeApple1" , FieldItemKind.PltTreeOak )}, // リンゴの木(成長1) + {0xEBD1, new FieldItemDefinition(60369, 3358 , 65534, "PltTreeApple2" , FieldItemKind.PltTreeOak )}, // リンゴの木(成長2) + {0xEBD2, new FieldItemDefinition(60370, 3359 , 65534, "PltTreeApple3" , FieldItemKind.PltTreeOak )}, // リンゴの木(成長3) + {0xEBD3, new FieldItemDefinition(60371, 3356 , 65534, "PltTreeApple0" , FieldItemKind.PltTreeOak )}, // リンゴの木(苗) + {0xEBD4, new FieldItemDefinition(60372, 65534, 11712, "FenceLattice" , FieldItemKind.FenceLattice )}, // ラティス・青 + {0xEBD5, new FieldItemDefinition(60373, 65534, 4349 , "FenceHorizontalWood" , FieldItemKind.FenceHorizontalWood )}, // よこいたのさく + {0xEBD6, new FieldItemDefinition(60374, 65534, 4350 , "FenceLog" , FieldItemKind.FenceLog )}, // まるたのさく + {0xEBD7, new FieldItemDefinition(60375, 65534, 4351 , "FenceHorizontalLog" , FieldItemKind.FenceHorizontalLog )}, // よこむきのまるたのさく + {0xEBD8, new FieldItemDefinition(60376, 65534, 4352 , "FencePegRope" , FieldItemKind.FencePegRope )}, // ペグとロープ + {0xEBDA, new FieldItemDefinition(60378, 3918 , 3744 , "PltFlwHyacinth3Red" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス赤(花) + {0xEBDB, new FieldItemDefinition(60379, 3906 , 3723 , "PltFlwAnemones3Red" , FieldItemKind.PltFlwAnemone )}, // アネモネ赤(花) + {0xEBDC, new FieldItemDefinition(60380, 3932 , 3768 , "PltFlwMum3Red" , FieldItemKind.PltFlwMum )}, // キク赤(花) + {0xEBDD, new FieldItemDefinition(60381, 3770 , 3770 , "PltFlwMum1Red" , FieldItemKind.PltFlwMum )}, // キク赤(茎) + {0xEBDE, new FieldItemDefinition(60382, 3771 , 3771 , "PltFlwMum2Red" , FieldItemKind.PltFlwMum )}, // キク赤(つぼみ) + {0xEBDF, new FieldItemDefinition(60383, 3725 , 3725 , "PltFlwAnemones1Red" , FieldItemKind.PltFlwAnemone )}, // アネモネ赤(茎) + {0xEBE0, new FieldItemDefinition(60384, 3726 , 3726 , "PltFlwAnemones2Red" , FieldItemKind.PltFlwAnemone )}, // アネモネ赤(つぼみ) + {0xEBE1, new FieldItemDefinition(60385, 3746 , 3746 , "PltFlwHyacinth1Red" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス赤(茎) + {0xEBE2, new FieldItemDefinition(60386, 3747 , 3747 , "PltFlwHyacinth2Red" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス赤(つぼみ) + {0xEBE4, new FieldItemDefinition(60388, 3910 , 3730 , "PltFlwHyacinth3White" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス白(花) + {0xEBE5, new FieldItemDefinition(60389, 3733 , 3733 , "PltFlwHyacinth2White" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス白(つぼみ) + {0xEBE6, new FieldItemDefinition(60390, 3732 , 3732 , "PltFlwHyacinth1White" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス白(茎) + {0xEBE7, new FieldItemDefinition(60391, 3737 , 3737 , "PltFlwHyacinth2Yellow" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス黄(つぼみ) + {0xEBE8, new FieldItemDefinition(60392, 3912 , 3734 , "PltFlwHyacinth3Yellow" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス黄(花) + {0xEBE9, new FieldItemDefinition(60393, 3736 , 3736 , "PltFlwHyacinth1Yellow" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス黄(茎) + {0xEBEA, new FieldItemDefinition(60394, 3920 , 3748 , "PltFlwHyacinth3Blue" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス青(花) + {0xEBEB, new FieldItemDefinition(60395, 3914 , 3738 , "PltFlwHyacinth3Pink" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス桃(花) + {0xEBEC, new FieldItemDefinition(60396, 3916 , 3741 , "PltFlwHyacinth3Orange" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンスオレンジ(花) + {0xEBED, new FieldItemDefinition(60397, 3922 , 3751 , "PltFlwHyacinth3Purple" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス紫(花) + {0xEBEE, new FieldItemDefinition(60398, 3753 , 3753 , "PltFlwHyacinth2Purple" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス紫(つぼみ) + {0xEBEF, new FieldItemDefinition(60399, 3752 , 3752 , "PltFlwHyacinth1Purple" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス紫(茎) + {0xEBF0, new FieldItemDefinition(60400, 3743 , 3743 , "PltFlwHyacinth2Orange" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンスオレンジ(つぼみ) + {0xEBF1, new FieldItemDefinition(60401, 3740 , 3740 , "PltFlwHyacinth2Pink" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス桃(つぼみ) + {0xEBF2, new FieldItemDefinition(60402, 3739 , 3739 , "PltFlwHyacinth1Pink" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス桃(茎) + {0xEBF3, new FieldItemDefinition(60403, 3749 , 3749 , "PltFlwHyacinth1Blue" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス青(茎) + {0xEBF4, new FieldItemDefinition(60404, 3750 , 3750 , "PltFlwHyacinth2Blue" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス青(つぼみ) + {0xEBF5, new FieldItemDefinition(60405, 3742 , 3742 , "PltFlwHyacinth1Orange" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンスオレンジ(茎) + {0xEBF9, new FieldItemDefinition(60409, 12749, 65534, "PltBushHydrangea" , FieldItemKind.PltBushHydrangea )}, // あじさい青(苗) + {0xEBFB, new FieldItemDefinition(60411, 12750, 65534, "PltBushHydrangea0Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(苗) + {0xEBFC, new FieldItemDefinition(60412, 3799 , 65534, "PltBushHydrangea1Blue" , FieldItemKind.PltBushHydrangea )}, // あじさい青(成長1) + {0xEBFD, new FieldItemDefinition(60413, 3800 , 65534, "PltBushHydrangea2Blue" , FieldItemKind.PltBushHydrangea )}, // あじさい青(成木つぼみ) + {0xEBFE, new FieldItemDefinition(60414, 3800 , 65534, "PltBushHydrangea3Blue" , FieldItemKind.PltBushHydrangea )}, // あじさい青(成木花) + {0xEBFF, new FieldItemDefinition(60415, 3800 , 65534, "PltBushHydrangea4Blue" , FieldItemKind.PltBushHydrangea )}, // あじさい青(成木花なし) + {0xEC00, new FieldItemDefinition(60416, 3795 , 65534, "PltBushHydrangea1Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(成長1) + {0xEC01, new FieldItemDefinition(60417, 3796 , 65534, "PltBushHydrangea2Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(成木つぼみ) + {0xEC02, new FieldItemDefinition(60418, 3796 , 65534, "PltBushHydrangea3Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(成木花) + {0xEC03, new FieldItemDefinition(60419, 3796 , 65534, "PltBushHydrangea4Pink" , FieldItemKind.PltBushHydrangea )}, // あじさい桃(成木花なし) + {0xEC04, new FieldItemDefinition(60420, 3756 , 3756 , "PltFlwMum1White" , FieldItemKind.PltFlwMum )}, // キク白(茎) + {0xEC05, new FieldItemDefinition(60421, 3760 , 3760 , "PltFlwMum1Yellow" , FieldItemKind.PltFlwMum )}, // キク黄(茎) + {0xEC06, new FieldItemDefinition(60422, 3763 , 3763 , "PltFlwMum1Purple" , FieldItemKind.PltFlwMum )}, // キク紫(茎) + {0xEC07, new FieldItemDefinition(60423, 3766 , 3766 , "PltFlwMum1Pink" , FieldItemKind.PltFlwMum )}, // キク桃(茎) + {0xEC08, new FieldItemDefinition(60424, 3757 , 3757 , "PltFlwMum2White" , FieldItemKind.PltFlwMum )}, // キク白(つぼみ) + {0xEC09, new FieldItemDefinition(60425, 3924 , 3754 , "PltFlwMum3White" , FieldItemKind.PltFlwMum )}, // キク白(花) + {0xEC0A, new FieldItemDefinition(60426, 3761 , 3761 , "PltFlwMum2Yellow" , FieldItemKind.PltFlwMum )}, // キク黄(つぼみ) + {0xEC0B, new FieldItemDefinition(60427, 3764 , 3764 , "PltFlwMum2Purple" , FieldItemKind.PltFlwMum )}, // キク紫(つぼみ) + {0xEC0C, new FieldItemDefinition(60428, 3767 , 3767 , "PltFlwMum2Pink" , FieldItemKind.PltFlwMum )}, // キク桃(つぼみ) + {0xEC0D, new FieldItemDefinition(60429, 3926 , 3758 , "PltFlwMum3Yellow" , FieldItemKind.PltFlwMum )}, // キク黄(花) + {0xEC0E, new FieldItemDefinition(60430, 3928 , 3762 , "PltFlwMum3Purple" , FieldItemKind.PltFlwMum )}, // キク紫(花) + {0xEC0F, new FieldItemDefinition(60431, 3930 , 3765 , "PltFlwMum3Pink" , FieldItemKind.PltFlwMum )}, // キク桃(花) + {0xEC11, new FieldItemDefinition(60433, 3711 , 3711 , "PltFlwAnemones1White" , FieldItemKind.PltFlwAnemone )}, // アネモネ白(茎) + {0xEC12, new FieldItemDefinition(60434, 3712 , 3712 , "PltFlwAnemones2White" , FieldItemKind.PltFlwAnemone )}, // アネモネ白(つぼみ) + {0xEC13, new FieldItemDefinition(60435, 3898 , 3709 , "PltFlwAnemones3White" , FieldItemKind.PltFlwAnemone )}, // アネモネ白(花) + {0xEC14, new FieldItemDefinition(60436, 3718 , 3718 , "PltFlwAnemones1Blue" , FieldItemKind.PltFlwAnemone )}, // アネモネ青(茎) + {0xEC15, new FieldItemDefinition(60437, 3728 , 3728 , "PltFlwAnemones1Purple" , FieldItemKind.PltFlwAnemone )}, // アネモネ紫(茎) + {0xEC16, new FieldItemDefinition(60438, 3721 , 3721 , "PltFlwAnemones1Pink" , FieldItemKind.PltFlwAnemone )}, // アネモネ桃(茎) + {0xEC17, new FieldItemDefinition(60439, 3715 , 3715 , "PltFlwAnemones1Orange" , FieldItemKind.PltFlwAnemone )}, // アネモネオレンジ(茎) + {0xEC18, new FieldItemDefinition(60440, 3719 , 3719 , "PltFlwAnemones2Blue" , FieldItemKind.PltFlwAnemone )}, // アネモネ青(つぼみ) + {0xEC19, new FieldItemDefinition(60441, 3902 , 3717 , "PltFlwAnemones3Blue" , FieldItemKind.PltFlwAnemone )}, // アネモネ青(花) + {0xEC1A, new FieldItemDefinition(60442, 3729 , 3729 , "PltFlwAnemones2Purple" , FieldItemKind.PltFlwAnemone )}, // アネモネ紫(つぼみ) + {0xEC1B, new FieldItemDefinition(60443, 3908 , 3727 , "PltFlwAnemones3Purple" , FieldItemKind.PltFlwAnemone )}, // アネモネ紫(花) + {0xEC1C, new FieldItemDefinition(60444, 3722 , 3722 , "PltFlwAnemones2Pink" , FieldItemKind.PltFlwAnemone )}, // アネモネ桃(つぼみ) + {0xEC1D, new FieldItemDefinition(60445, 3904 , 3720 , "PltFlwAnemones3Pink" , FieldItemKind.PltFlwAnemone )}, // アネモネ桃(花) + {0xEC1E, new FieldItemDefinition(60446, 3716 , 3716 , "PltFlwAnemones2Orange" , FieldItemKind.PltFlwAnemone )}, // アネモネオレンジ(つぼみ) + {0xEC1F, new FieldItemDefinition(60447, 3900 , 3713 , "PltFlwAnemones3Orange" , FieldItemKind.PltFlwAnemone )}, // アネモネオレンジ(花) + {0xEC20, new FieldItemDefinition(60448, 3787 , 65534, "PltBushAzalea1Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(成長1) + {0xEC21, new FieldItemDefinition(60449, 12748, 65534, "PltBushAzalea0Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(苗) + {0xEC22, new FieldItemDefinition(60450, 3788 , 65534, "PltBushAzalea2Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(成長つぼみ) + {0xEC23, new FieldItemDefinition(60451, 3788 , 65534, "PltBushAzalea3Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(成木花) + {0xEC24, new FieldItemDefinition(60452, 3788 , 65534, "PltBushAzalea4Pink" , FieldItemKind.PltBushAzalea )}, // ツツジ桃(成木花なし) + {0xEC25, new FieldItemDefinition(60453, 12751, 65534, "PltBushHibiscus0Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(苗) + {0xEC26, new FieldItemDefinition(60454, 3791 , 65534, "PltBushHibiscus1Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(成長1) + {0xEC27, new FieldItemDefinition(60455, 3792 , 65534, "PltBushHibiscus2Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(成木つぼみ) + {0xEC28, new FieldItemDefinition(60456, 3792 , 65534, "PltBushHibiscus3Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(成木花) + {0xEC29, new FieldItemDefinition(60457, 3792 , 65534, "PltBushHibiscus4Yellow", FieldItemKind.PltBushHibiscus )}, // ハイビスカス黄(成木花なし) + {0xEC32, new FieldItemDefinition(60466, 3778 , 3778 , "PltFlwMum1Green" , FieldItemKind.PltFlwMum )}, // キク緑(茎) + {0xEC33, new FieldItemDefinition(60467, 3779 , 3779 , "PltFlwMum2Green" , FieldItemKind.PltFlwMum )}, // キク緑(つぼみ) + {0xEC34, new FieldItemDefinition(60468, 3934 , 5175 , "PltFlwMum3Green" , FieldItemKind.PltFlwMum )}, // キク緑(花) + {0xEC38, new FieldItemDefinition(60472, 3909 , 3909 , "PltFlwHyacinth0White" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス白(芽) + {0xEC3A, new FieldItemDefinition(60474, 3925 , 3925 , "PltFlwMum0Yellow" , FieldItemKind.PltFlwMum )}, // キク黄(芽) + {0xEC3B, new FieldItemDefinition(60475, 3911 , 3911 , "PltFlwHyacinth0Yellow" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス黄(芽) + {0xEC3F, new FieldItemDefinition(60479, 3917 , 3917 , "PltFlwHyacinth0Red" , FieldItemKind.PltFlwHyacinth )}, // ヒヤシンス赤(芽) + {0xEC42, new FieldItemDefinition(60482, 3905 , 3905 , "PltFlwAnemones0Red" , FieldItemKind.PltFlwAnemone )}, // アネモネ赤(芽) + {0xEC43, new FieldItemDefinition(60483, 3897 , 3897 , "PltFlwAnemones0White" , FieldItemKind.PltFlwAnemone )}, // アネモネ白(芽) + {0xEC47, new FieldItemDefinition(60487, 3899 , 3899 , "PltFlwAnemones0Orange" , FieldItemKind.PltFlwAnemone )}, // アネモネオレンジ(芽) + {0xEC48, new FieldItemDefinition(60488, 3931 , 3931 , "PltFlwM0Red" , FieldItemKind.PltFlwMum )}, // キク赤(芽) + {0xEC49, new FieldItemDefinition(60489, 3923 , 3923 , "PltFlwMum0White" , FieldItemKind.PltFlwMum )}, // キク白(芽) + {0xEC4A, new FieldItemDefinition(60490, 3839 , 3839 , "PltFlwTulip0Yellow" , FieldItemKind.PltFlwTulip )}, // チューリップ黄(芽) + {0xEC50, new FieldItemDefinition(60496, 3849 , 3849 , "PltFlwPansy0White" , FieldItemKind.PltFlwPansy )}, // パンジー白(芽) + {0xEC51, new FieldItemDefinition(60497, 3851 , 3851 , "PltFlwPansy0Red" , FieldItemKind.PltFlwPansy )}, // パンジー赤(芽) + {0xEC52, new FieldItemDefinition(60498, 3853 , 3853 , "PltFlwPansy0Yellow" , FieldItemKind.PltFlwPansy )}, // パンジー黄(芽) + {0xEC56, new FieldItemDefinition(60502, 3861 , 3861 , "PltFlwRose0White" , FieldItemKind.PltFlwRose )}, // バラ白(芽) + {0xEC57, new FieldItemDefinition(60503, 3863 , 3863 , "PltFlwRose0Red" , FieldItemKind.PltFlwRose )}, // バラ赤(芽) + {0xEC58, new FieldItemDefinition(60504, 3865 , 3865 , "PltFlwRose0Yellow" , FieldItemKind.PltFlwRose )}, // バラ黄(芽) + {0xEC5B, new FieldItemDefinition(60507, 3889 , 3889 , "PltFlwYuri0Yellow" , FieldItemKind.PltFlwYuri )}, // ユリ黄(芽) + {0xEC60, new FieldItemDefinition(60512, 3885 , 3885 , "PltFlwYuri0White" , FieldItemKind.PltFlwYuri )}, // ユリ白(芽) + {0xEC61, new FieldItemDefinition(60513, 3887 , 3887 , "PltFlwYuri0Red" , FieldItemKind.PltFlwYuri )}, // ユリ赤(芽) + {0xEC62, new FieldItemDefinition(60514, 3823 , 3823 , "PltFlwCosmos0Red" , FieldItemKind.PltFlwCosmos )}, // コスモス赤(芽) + {0xEC63, new FieldItemDefinition(60515, 3837 , 3837 , "PltFlwTulip0Red" , FieldItemKind.PltFlwTulip )}, // チューリップ赤(芽) + {0xEC64, new FieldItemDefinition(60516, 3827 , 3827 , "PltFlwCosmos0Yellow" , FieldItemKind.PltFlwCosmos )}, // コスモス黄(芽) + {0xEC65, new FieldItemDefinition(60517, 3825 , 3825 , "PltFlwCosmos0White" , FieldItemKind.PltFlwCosmos )}, // コスモス白(芽) + {0xEC69, new FieldItemDefinition(60521, 3835 , 3835 , "PltFlwTulip0White" , FieldItemKind.PltFlwTulip )}, // チューリップ白(芽) + {0xEC6B, new FieldItemDefinition(60523, 65534, 65534, "PltTreeOak3Stump" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長3の切り株) + {0xEC6C, new FieldItemDefinition(60524, 65534, 65534, "PltTreeOak2Stump" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長2の切り株) + {0xEC6D, new FieldItemDefinition(60525, 65534, 65534, "PltTreeOak1Stump" , FieldItemKind.PltTreeOak )}, // 広葉樹(成長1の切り株) + {0xEC6E, new FieldItemDefinition(60526, 65534, 65534, "PltTreeCedar3Stump" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長3の切り株) + {0xEC6F, new FieldItemDefinition(60527, 65534, 65534, "PltTreeCedar2Stump" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長2の切り株) + {0xEC70, new FieldItemDefinition(60528, 65534, 65534, "PltTreeCedar1Stump" , FieldItemKind.PltTreeCedar )}, // 針葉樹(成長1の切り株) + {0xEC71, new FieldItemDefinition(60529, 65534, 65534, "PltTreeBamboo3Stump" , FieldItemKind.PltTreeBamboo )}, // 竹(成長3の切り株) + {0xEC72, new FieldItemDefinition(60530, 65534, 65534, "PltTreeBamboo2Stump" , FieldItemKind.PltTreeBamboo )}, // 竹(成長2の切り株) + {0xEC73, new FieldItemDefinition(60531, 65534, 65534, "PltTreeBamboo1Stump" , FieldItemKind.PltTreeBamboo )}, // 竹(成長1の切り株) + {0xEC74, new FieldItemDefinition(60532, 65534, 4354 , "FenceChinese" , FieldItemKind.FenceChinese )}, // オリエンタルなさく + {0xEC78, new FieldItemDefinition(60536, 65534, 65534, "PltTreePalm1Stump" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長1の切り株) + {0xEC79, new FieldItemDefinition(60537, 65534, 65534, "PltTreePalm2Stump" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長2の切り株) + {0xEC7A, new FieldItemDefinition(60538, 65534, 65534, "PltTreePalm3Stump" , FieldItemKind.PltTreePalm )}, // ヤシの木(成長3の切り株) + {0xEC7B, new FieldItemDefinition(60539, 65534, 4355 , "FenceConcreteBlock" , FieldItemKind.FenceConcreteBlock )}, // ブロック塀 + {0xEC7C, new FieldItemDefinition(60540, 65534, 4356 , "FenceDriedStraw" , FieldItemKind.FenceDriedStraw )}, // わらぼしのさく + {0xEC7D, new FieldItemDefinition(60541, 65534, 4357 , "FenceSteel" , FieldItemKind.FenceSteel )}, // てつのさく + {0xEC7E, new FieldItemDefinition(60542, 65534, 4358 , "FenceSharply" , FieldItemKind.FenceSharply )}, // トゲトゲのさく + {0xEC7F, new FieldItemDefinition(60543, 2624 , 2624 , "PltWeedAut23" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草23 + {0xEC80, new FieldItemDefinition(60544, 2624 , 2624 , "PltWeedAut22C" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草22C + {0xEC81, new FieldItemDefinition(60545, 2624 , 2624 , "PltWeedAut22A" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草22A + {0xEC82, new FieldItemDefinition(60546, 2624 , 2624 , "PltWeedAut22B" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草22B + {0xEC83, new FieldItemDefinition(60547, 2624 , 2624 , "PltWeedAut21A" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草21A + {0xEC84, new FieldItemDefinition(60548, 2624 , 2624 , "PltWeedAut21B" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草21B + {0xEC85, new FieldItemDefinition(60549, 2624 , 2624 , "PltWeedAut21C" , FieldItemKind.PltWeedAut2 )}, // 秋の雑草21C + {0xEC86, new FieldItemDefinition(60550, 2624 , 2624 , "PltWeedAut11B" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草11B + {0xEC87, new FieldItemDefinition(60551, 2624 , 2624 , "PltWeedAut11C" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草11C + {0xEC88, new FieldItemDefinition(60552, 2624 , 2624 , "PltWeedAut12A" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草12A + {0xEC89, new FieldItemDefinition(60553, 2624 , 2624 , "PltWeedAut12B" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草12B + {0xEC8A, new FieldItemDefinition(60554, 2624 , 2624 , "PltWeedAut12C" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草12C + {0xEC8B, new FieldItemDefinition(60555, 2624 , 2624 , "PltWeedAut13" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草13 + {0xEC8C, new FieldItemDefinition(60556, 2624 , 2624 , "PltWeedAut11A" , FieldItemKind.PltWeedAut1 )}, // 秋の雑草11A + {0xEC8D, new FieldItemDefinition(60557, 2624 , 2624 , "PltWeedWin13" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草13 + {0xEC8E, new FieldItemDefinition(60558, 2624 , 2624 , "PltWeedWin12C" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草12C + {0xEC8F, new FieldItemDefinition(60559, 2624 , 2624 , "PltWeedWin12A" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草12A + {0xEC90, new FieldItemDefinition(60560, 2624 , 2624 , "PltWeedWin12B" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草12B + {0xEC91, new FieldItemDefinition(60561, 2624 , 2624 , "PltWeedWin11A" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草11A + {0xEC92, new FieldItemDefinition(60562, 2624 , 2624 , "PltWeedWin11B" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草11B + {0xEC93, new FieldItemDefinition(60563, 2624 , 2624 , "PltWeedWin11C" , FieldItemKind.PltWeedWin1 )}, // 冬の雑草11C + {0xEC94, new FieldItemDefinition(60564, 65534, 11711, "FenceWoodBlue" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・青 + {0xEC97, new FieldItemDefinition(60567, 2805 , 65534, "PltTreeCedarDecoB" , FieldItemKind.PltTreeCedarDeco )}, // 飾りつき針葉樹B + {0xEC9A, new FieldItemDefinition(60570, 2805 , 65534, "PltTreeCedarDecoA" , FieldItemKind.PltTreeCedarDeco )}, // 飾りつき針葉樹A + {0xEC9B, new FieldItemDefinition(60571, 65534, 5212 , "FenceStone" , FieldItemKind.FenceStone )}, // いしかべ + {0xEC9C, new FieldItemDefinition(60572, 4426 , 65534, "PltTreeMoney4" , FieldItemKind.PltTreeOak )}, // 金のなるの木(成木) + {0xEC9D, new FieldItemDefinition(60573, 4439 , 65534, "PltTreeMoney3" , FieldItemKind.PltTreeOak )}, // 金のなるの木(成長3) + {0xEC9E, new FieldItemDefinition(60574, 4438 , 65534, "PltTreeMoney2" , FieldItemKind.PltTreeOak )}, // 金のなるの木(成長2) + {0xEC9F, new FieldItemDefinition(60575, 4436 , 65534, "PltTreeMoney0" , FieldItemKind.PltTreeOak )}, // 金のなるの木(苗) + {0xECA0, new FieldItemDefinition(60576, 4437 , 65534, "PltTreeMoney1" , FieldItemKind.PltTreeOak )}, // 金のなるの木(成長1) + {0xECA1, new FieldItemDefinition(60577, 4544 , 4528 , "PltVgtSquash3White" , FieldItemKind.PltVgtPumpkin )}, // カボチャ白(成木) + {0xECA2, new FieldItemDefinition(60578, 4543 , 65534, "PltVgtSquash2White" , FieldItemKind.PltVgtPumpkin )}, // カボチャ白(成長2) + {0xECA3, new FieldItemDefinition(60579, 4542 , 65534, "PltVgtSquash1White" , FieldItemKind.PltVgtPumpkin )}, // カボチャ白(成長1) + {0xECA4, new FieldItemDefinition(60580, 4541 , 65534, "PltVgtSquash0White" , FieldItemKind.PltVgtPumpkin )}, // カボチャ白(苗) + {0xECA5, new FieldItemDefinition(60581, 4538 , 65534, "PltVgtSquash1Green" , FieldItemKind.PltVgtPumpkin )}, // カボチャ緑(成長1) + {0xECA6, new FieldItemDefinition(60582, 4539 , 65534, "PltVgtSquash2Green" , FieldItemKind.PltVgtPumpkin )}, // カボチャ緑(成長2) + {0xECA7, new FieldItemDefinition(60583, 4540 , 4527 , "PltVgtSquash3Green" , FieldItemKind.PltVgtPumpkin )}, // カボチャ緑(成木) + {0xECA9, new FieldItemDefinition(60585, 4532 , 4525 , "PltVgtSquash3Orange" , FieldItemKind.PltVgtPumpkin )}, // カボチャオレンジ(成木) + {0xECAA, new FieldItemDefinition(60586, 4533 , 65534, "PltVgtSquash0Yellow" , FieldItemKind.PltVgtPumpkin )}, // カボチャ黄(苗) + {0xECAB, new FieldItemDefinition(60587, 4534 , 65534, "PltVgtSquash1Yellow" , FieldItemKind.PltVgtPumpkin )}, // カボチャ黄(成長1) + {0xECAC, new FieldItemDefinition(60588, 4535 , 65534, "PltVgtSquash2Yellow" , FieldItemKind.PltVgtPumpkin )}, // カボチャ黄(成長2) + {0xECAD, new FieldItemDefinition(60589, 4536 , 4526 , "PltVgtSquash3Yellow" , FieldItemKind.PltVgtPumpkin )}, // カボチャ黄(成木) + {0xECAE, new FieldItemDefinition(60590, 4537 , 65534, "PltVgtSquash0Green" , FieldItemKind.PltVgtPumpkin )}, // カボチャ緑(苗) + {0xECAF, new FieldItemDefinition(60591, 4529 , 65534, "PltVgtSquash0Orange" , FieldItemKind.PltVgtPumpkin )}, // カボチャオレンジ(苗) + {0xECB0, new FieldItemDefinition(60592, 4530 , 65534, "PltVgtSquash1Orange" , FieldItemKind.PltVgtPumpkin )}, // カボチャオレンジ(成長1) + {0xECB1, new FieldItemDefinition(60593, 4531 , 65534, "PltVgtSquash2Orange" , FieldItemKind.PltVgtPumpkin )}, // カボチャオレンジ(成長2) + {0xECB2, new FieldItemDefinition(60594, 65534, 5213 , "FenceBarbedWire" , FieldItemKind.FenceBarbedWire )}, // ゆうしてっせん + {0xECB3, new FieldItemDefinition(60595, 65534, 5210 , "FenceLogWall" , FieldItemKind.FenceLogWall )}, // まるたかべのさく + {0xECB4, new FieldItemDefinition(60596, 65534, 5208 , "FenceLatticeBig" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス + {0xECB5, new FieldItemDefinition(60597, 65534, 11711, "FenceWoodPink" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・ピンク + {0xECB6, new FieldItemDefinition(60598, 65534, 5207 , "FenceJapanese" , FieldItemKind.FenceJapanese )}, // 和風のさく + {0xECB7, new FieldItemDefinition(60599, 65534, 5206 , "FenceIronAndStone" , FieldItemKind.FenceIronAndStone )}, // 洋風のさく + {0xECB8, new FieldItemDefinition(60600, 65534, 3402 , "FenceVerticalWood2" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・黒 + {0xECBA, new FieldItemDefinition(60602, 65534, 11712, "FenceLattice2" , FieldItemKind.FenceLattice )}, // ラティス・白 + {0xECBB, new FieldItemDefinition(60603, 65534, 5208 , "FenceLatticeBig2" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・白 + {0xECBC, new FieldItemDefinition(60604, 65534, 65534, "PltTreeFruitStump1" , FieldItemKind.PltTreeOak )}, // 果物の木(成長1の切り株) + {0xECBD, new FieldItemDefinition(60605, 65534, 65534, "PltTreeFruitStump2" , FieldItemKind.PltTreeOak )}, // 果物の木(成長2の切り株) + {0xECBE, new FieldItemDefinition(60606, 65534, 65534, "PltTreeFruitStump3" , FieldItemKind.PltTreeOak )}, // 果物の木(成長3の切り株) + {0xECBF, new FieldItemDefinition(60607, 65534, 65534, "PltTreeFruitStump4" , FieldItemKind.PltTreeOak )}, // 果物の木(成長4の切り株) + {0xECC1, new FieldItemDefinition(60609, 7651 , 65534, "PltFlwLily3" , FieldItemKind.PltFlwLily )}, // スズラン(花) + {0xECC2, new FieldItemDefinition(60610, 65534, 11711, "FenceWoodNatural" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく + {0xECC3, new FieldItemDefinition(60611, 65534, 11712, "FenceLattice3" , FieldItemKind.FenceLattice )}, // ラティス + {0xECC4, new FieldItemDefinition(60612, 65534, 65534, "FenceCommune" , FieldItemKind.FenceHorizontalLog )}, // コミューン島専用柵 + {0xECC5, new FieldItemDefinition(60613, 65534, 11711, "FenceWoodYellow" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・黒 + {0xECC6, new FieldItemDefinition(60614, 65534, 11711, "FenceWoodOrange" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・オレンジ + {0xECC7, new FieldItemDefinition(60615, 65534, 11711, "FenceWoodPurple" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・紫 + {0xECC8, new FieldItemDefinition(60616, 65534, 11711, "FenceWoodGreen" , FieldItemKind.FenceWoodWhite )}, // そぼくなもくせいのさく・緑 + {0xECC9, new FieldItemDefinition(60617, 65534, 3402 , "FenceVerticalWood6" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・青 + {0xECCA, new FieldItemDefinition(60618, 65534, 3402 , "FenceVerticalWood5" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・緑 + {0xECCB, new FieldItemDefinition(60619, 65534, 3402 , "FenceVerticalWood3" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・ピンク + {0xECCC, new FieldItemDefinition(60620, 65534, 3402 , "FenceVerticalWood4" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・黄 + {0xECCD, new FieldItemDefinition(60621, 65534, 11712, "FenceLattice8" , FieldItemKind.FenceLattice )}, // ラティス・薄紫 + {0xECCE, new FieldItemDefinition(60622, 65534, 11712, "FenceLattice7" , FieldItemKind.FenceLattice )}, // ラティス・黒 + {0xECCF, new FieldItemDefinition(60623, 65534, 11712, "FenceLattice5" , FieldItemKind.FenceLattice )}, // ラティス・黄 + {0xECD0, new FieldItemDefinition(60624, 65534, 11712, "FenceLattice6" , FieldItemKind.FenceLattice )}, // ラティス・緑 + {0xECD1, new FieldItemDefinition(60625, 65534, 11712, "FenceLattice4" , FieldItemKind.FenceLattice )}, // ラティス・ピンク + {0xECD2, new FieldItemDefinition(60626, 65534, 5208 , "FenceLatticeBig8" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・黒 + {0xECD3, new FieldItemDefinition(60627, 65534, 5208 , "FenceLatticeBig7" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・青 + {0xECD4, new FieldItemDefinition(60628, 65534, 5208 , "FenceLatticeBig5" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・緑 + {0xECD5, new FieldItemDefinition(60629, 65534, 5208 , "FenceLatticeBig6" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・紫 + {0xECD6, new FieldItemDefinition(60630, 65534, 5208 , "FenceLatticeBig3" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・赤 + {0xECD7, new FieldItemDefinition(60631, 65534, 5208 , "FenceLatticeBig4" , FieldItemKind.FenceLatticeBig )}, // おおきなラティス・オレンジ + {0xECD8, new FieldItemDefinition(60632, 65534, 5207 , "FenceJapanese8" , FieldItemKind.FenceJapanese )}, // 和風のさく・紫 + {0xECD9, new FieldItemDefinition(60633, 65534, 5207 , "FenceJapanese7" , FieldItemKind.FenceJapanese )}, // 和風のさく・緑 + {0xECDA, new FieldItemDefinition(60634, 65534, 5207 , "FenceJapanese5" , FieldItemKind.FenceJapanese )}, // 和風のさく・黄 + {0xECDB, new FieldItemDefinition(60635, 65534, 5207 , "FenceJapanese6" , FieldItemKind.FenceJapanese )}, // 和風のさく・ベージュ + {0xECDC, new FieldItemDefinition(60636, 65534, 5207 , "FenceJapanese2" , FieldItemKind.FenceJapanese )}, // 和風のさく・青 + {0xECDD, new FieldItemDefinition(60637, 65534, 5207 , "FenceJapanese3" , FieldItemKind.FenceJapanese )}, // 和風のさく・赤 + {0xECDE, new FieldItemDefinition(60638, 65534, 5207 , "FenceJapanese4" , FieldItemKind.FenceJapanese )}, // 和風のさく・オレンジ + {0xECDF, new FieldItemDefinition(60639, 65534, 4357 , "FenceSteel2" , FieldItemKind.FenceSteel )}, // てつのさく・赤 + {0xECE0, new FieldItemDefinition(60640, 65534, 4357 , "FenceSteel3" , FieldItemKind.FenceSteel )}, // てつのさく・黄 + {0xECE1, new FieldItemDefinition(60641, 65534, 4357 , "FenceSteel4" , FieldItemKind.FenceSteel )}, // てつのさく・緑 + {0xECE2, new FieldItemDefinition(60642, 65534, 14757, "FenceSandProtection" , FieldItemKind.FenceSandProtection )}, // すだれのさく + {0xECE3, new FieldItemDefinition(60643, 65534, 14755, "FenceCrossedBamboo" , FieldItemKind.FenceCrossedBamboo )}, // あおたけのさく + {0xECE4, new FieldItemDefinition(60644, 65534, 14756, "FenceIce" , FieldItemKind.FenceIce )}, // こおりのさく + {0xECE6, new FieldItemDefinition(60646, 65534, 14756, "FenceIce05" , FieldItemKind.FenceIce )}, // こおりのさく・緑 + {0xECE7, new FieldItemDefinition(60647, 65534, 14756, "FenceIce04" , FieldItemKind.FenceIce )}, // こおりのさく・オレンジ + {0xECE8, new FieldItemDefinition(60648, 65534, 14756, "FenceIce06" , FieldItemKind.FenceIce )}, // こおりのさく・紫 + {0xECE9, new FieldItemDefinition(60649, 65534, 14756, "FenceIce01" , FieldItemKind.FenceIce )}, // こおりのさく・青 + {0xECEA, new FieldItemDefinition(60650, 65534, 14756, "FenceIce02" , FieldItemKind.FenceIce )}, // こおりのさく・ピンク + {0xECEB, new FieldItemDefinition(60651, 65534, 14756, "FenceIce03" , FieldItemKind.FenceIce )}, // こおりのさく・黄 + {0xECF4, new FieldItemDefinition(60660, 12478, 65534, "PltBushOsmathus5Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(成木花なし) + {0xECF5, new FieldItemDefinition(60661, 12478, 65534, "PltBushOsmathus4Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(成木花) + {0xECF6, new FieldItemDefinition(60662, 12477, 65534, "PltBushOsmathus2Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(成長1) + {0xECF7, new FieldItemDefinition(60663, 12478, 65534, "PltBushOsmathus3Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(成木つぼみ) + {0xECF8, new FieldItemDefinition(60664, 12753, 65534, "PltBushOsmathus1Yello" , FieldItemKind.PltBushOsmanthus )}, // キンモクセイ黄(苗) + {0xECF9, new FieldItemDefinition(60665, 12482, 65534, "PltBushOsmathus5Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(成木花なし) + {0xECFA, new FieldItemDefinition(60666, 12482, 65534, "PltBushOsmathus4Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(成木花) + {0xECFB, new FieldItemDefinition(60667, 12482, 65534, "PltBushOsmathus3Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(成木つぼみ) + {0xECFC, new FieldItemDefinition(60668, 12754, 65534, "PltBushOsmathus1Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(苗) + {0xECFD, new FieldItemDefinition(60669, 12481, 65534, "PltBushOsmathus2Orange", FieldItemKind.PltBushOsmanthus )}, // キンモクセイオレンジ(成長1) + {0xECFE, new FieldItemDefinition(60670, 12756, 65534, "PltBushCamellia1Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(苗) + {0xECFF, new FieldItemDefinition(60671, 12491, 65534, "PltBushCamellia2Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(成長1) + {0xED00, new FieldItemDefinition(60672, 12492, 65534, "PltBushCamellia3Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(成木つぼみ) + {0xED01, new FieldItemDefinition(60673, 12492, 65534, "PltBushCamellia4Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(成木花) + {0xED02, new FieldItemDefinition(60674, 12755, 65534, "PltBushCamellia1Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(苗) + {0xED03, new FieldItemDefinition(60675, 12492, 65534, "PltBushCamellia5Pink" , FieldItemKind.PltBushCamellia )}, // ツバキピンク(成木花なし) + {0xED04, new FieldItemDefinition(60676, 12488, 65534, "PltBushCamellia2Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(成長1) + {0xED05, new FieldItemDefinition(60677, 12489, 65534, "PltBushCamellia3Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(成木つぼみ) + {0xED06, new FieldItemDefinition(60678, 12489, 65534, "PltBushCamellia4Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(成木花) + {0xED07, new FieldItemDefinition(60679, 12489, 65534, "PltBushCamellia5Red" , FieldItemKind.PltBushCamellia )}, // ツバキ赤(成木花なし) + {0xED08, new FieldItemDefinition(60680, 65534, 12758, "FenceIkegaki" , FieldItemKind.FenceIkegaki )}, // いけがき + {0xED09, new FieldItemDefinition(60681, 65534, 12894, "FenceJuneBride4" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・赤 + {0xED0A, new FieldItemDefinition(60682, 65534, 12894, "FenceJuneBride2" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・青 + {0xED0B, new FieldItemDefinition(60683, 65534, 12894, "FenceJuneBride3" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・緑 + {0xED0C, new FieldItemDefinition(60684, 65534, 12630, "FenceEasterEgg" , FieldItemKind.FenceEasterEgg )}, // イースターの柵 + {0xED0D, new FieldItemDefinition(60685, 65534, 12894, "FenceJuneBride" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵 + {0xED0E, new FieldItemDefinition(60686, 65534, 12894, "FenceJuneBride1" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・ピンク + {0xED0F, new FieldItemDefinition(60687, 12550, 12550, "PltWeedLight3" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ3 + {0xED10, new FieldItemDefinition(60688, 12550, 12550, "PltWeedLight2C" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ2C + {0xED11, new FieldItemDefinition(60689, 12550, 12550, "PltWeedLight2B" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ2B + {0xED12, new FieldItemDefinition(60690, 12550, 12550, "PltWeedLight1A" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ1A + {0xED13, new FieldItemDefinition(60691, 12550, 12550, "PltWeedLight2A" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ2A + {0xED14, new FieldItemDefinition(60692, 12550, 12550, "PltWeedLight1B" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ1B + {0xED15, new FieldItemDefinition(60693, 12550, 12550, "PltWeedLight1C" , FieldItemKind.PltWeedLight )}, // ヒカリゴケ1C + {0xED16, new FieldItemDefinition(60694, 2799 , 65534, "PltTreeEasterEgg" , FieldItemKind.PltTreeOak )}, // イースターのタマゴの木 + {0xED17, new FieldItemDefinition(60695, 65534, 12551, "PltVine" , FieldItemKind.PltVine )}, // ツルA + {0xED21, new FieldItemDefinition(60705, 65534, 14278, "FenceMermaid" , FieldItemKind.FenceMermaid )}, // マーメイドな柵 + {0xED25, new FieldItemDefinition(60709, 65534, 13275, "FenceHalloween" , FieldItemKind.FenceHalloween )}, // ハロウィンのさく + {0xED26, new FieldItemDefinition(60710, 13264, 65534, "PltBushPlumeria4Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(成木花なし) + {0xED27, new FieldItemDefinition(60711, 13264, 65534, "PltBushPlumeria3Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(成木花) + {0xED28, new FieldItemDefinition(60712, 13263, 65534, "PltBushPlumeria1Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(成長1) + {0xED29, new FieldItemDefinition(60713, 13264, 65534, "PltBushPlumeria2Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(成長つぼみ) + {0xED2A, new FieldItemDefinition(60714, 13265, 65534, "PltBushPlumeria0Pink" , FieldItemKind.PltBushPlumeria )}, // プルメリア桃(苗) + {0xED2B, new FieldItemDefinition(60715, 13350, 65534, "PltBushPlumeria4White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(成木花なし) + {0xED2C, new FieldItemDefinition(60716, 13350, 65534, "PltBushPlumeria3White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(成木花) + {0xED2D, new FieldItemDefinition(60717, 13350, 65534, "PltBushPlumeria2White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(成長つぼみ) + {0xED2E, new FieldItemDefinition(60718, 13351, 65534, "PltBushPlumeria0White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(苗) + {0xED2F, new FieldItemDefinition(60719, 13349, 65534, "PltBushPlumeria1White" , FieldItemKind.PltBushPlumeria )}, // プルメリア白(成長1) + {0xED30, new FieldItemDefinition(60720, 65534, 12551, "PltVineC" , FieldItemKind.PltVine )}, // ツルC + {0xED31, new FieldItemDefinition(60721, 65534, 12551, "PltVineB" , FieldItemKind.PltVine )}, // ツルB + {0xED33, new FieldItemDefinition(60723, 65534, 13534, "LadderKitC2" , FieldItemKind.LadderKitC )}, // ハシゴキットC2 + {0xED34, new FieldItemDefinition(60724, 65534, 13534, "LadderKitC0" , FieldItemKind.LadderKitC )}, // ハシゴキットC0 + {0xED35, new FieldItemDefinition(60725, 65534, 13534, "LadderKitC1" , FieldItemKind.LadderKitC )}, // ハシゴキットC1 + {0xED36, new FieldItemDefinition(60726, 65534, 13530, "LadderKitB0" , FieldItemKind.LadderKitB )}, // ハシゴキットB0 + {0xED37, new FieldItemDefinition(60727, 65534, 13530, "LadderKitB1" , FieldItemKind.LadderKitB )}, // ハシゴキットB1 + {0xED38, new FieldItemDefinition(60728, 65534, 13530, "LadderKitB2" , FieldItemKind.LadderKitB )}, // ハシゴキットB2 + {0xED39, new FieldItemDefinition(60729, 65534, 13530, "LadderKitB3" , FieldItemKind.LadderKitB )}, // ハシゴキットB3 + {0xED3A, new FieldItemDefinition(60730, 65534, 13526, "LadderKitA0" , FieldItemKind.LadderKitA )}, // ハシゴキットA0 + {0xED3B, new FieldItemDefinition(60731, 65534, 13526, "LadderKitA1" , FieldItemKind.LadderKitA )}, // ハシゴキットA1 + {0xED3C, new FieldItemDefinition(60732, 65534, 13526, "LadderKitA2" , FieldItemKind.LadderKitA )}, // ハシゴキットA2 + {0xED3F, new FieldItemDefinition(60735, 3052 , 65534, "PltVgtSquash0" , FieldItemKind.PltVgtPumpkin )}, // カボチャ(苗) + {0xED40, new FieldItemDefinition(60736, 3053 , 65534, "PltVgtSquash1" , FieldItemKind.PltVgtPumpkin )}, // カボチャ(成長1) + {0xED41, new FieldItemDefinition(60737, 4362 , 65534, "PltVgtSquash2" , FieldItemKind.PltVgtPumpkin )}, // カボチャ(成長2) + {0xED42, new FieldItemDefinition(60738, 65534, 14470, "LadderKitD" , FieldItemKind.LadderKitD )}, // ハシゴキットD0 + {0xED43, new FieldItemDefinition(60739, 65534, 13530, "LadderKitB4" , FieldItemKind.LadderKitB )}, // ハシゴキットB4 + {0xED44, new FieldItemDefinition(60740, 65534, 13530, "LadderKitB5" , FieldItemKind.LadderKitB )}, // ハシゴキットB5 + {0xED46, new FieldItemDefinition(60742, 65534, 65534, "FenceGardenPegRope" , FieldItemKind.FenceGardenPegRope )}, // 庭専用柵(編集外用) + {0xED47, new FieldItemDefinition(60743, 65534, 14758, "FenceCorrugatedIron" , FieldItemKind.FenceCorrugatedIron )}, // トタンのさく + {0xED48, new FieldItemDefinition(60744, 65534, 14759, "FencePark" , FieldItemKind.FencePark )}, // こうえんのさく・青 + {0xED49, new FieldItemDefinition(60745, 65534, 14759, "FencePark2" , FieldItemKind.FencePark )}, // こうえんのさく・赤 + {0xED4A, new FieldItemDefinition(60746, 65534, 14759, "FencePark5" , FieldItemKind.FencePark )}, // こうえんのさく・ピンク + {0xED4B, new FieldItemDefinition(60747, 65534, 14759, "FencePark4" , FieldItemKind.FencePark )}, // こうえんのさく・緑 + {0xED4C, new FieldItemDefinition(60748, 65534, 14759, "FencePark6" , FieldItemKind.FencePark )}, // こうえんのさく・赤と黄 + {0xED4D, new FieldItemDefinition(60749, 65534, 14759, "FencePark3" , FieldItemKind.FencePark )}, // こうえんのさく・黄 + {0xED4E, new FieldItemDefinition(60750, 65534, 14759, "FencePark8" , FieldItemKind.FencePark )}, // こうえんのさく・青とピンク + {0xED4F, new FieldItemDefinition(60751, 65534, 14759, "FencePark7" , FieldItemKind.FencePark )}, // こうえんのさく・緑とオレンジ + {0xED50, new FieldItemDefinition(60752, 65534, 14758, "FenceCorrugatedIron1" , FieldItemKind.FenceCorrugatedIron )}, // あおいトタンのさく + {0xED51, new FieldItemDefinition(60753, 65534, 14758, "FenceCorrugatedIron2" , FieldItemKind.FenceCorrugatedIron )}, // きいろいトタンのさく + {0xED52, new FieldItemDefinition(60754, 65534, 14758, "FenceCorrugatedIron3" , FieldItemKind.FenceCorrugatedIron )}, // みどりのトタンのさく + {0xED53, new FieldItemDefinition(60755, 65534, 14758, "FenceCorrugatedIron5" , FieldItemKind.FenceCorrugatedIron )}, // さびたトタンのさく + {0xED54, new FieldItemDefinition(60756, 65534, 14758, "FenceCorrugatedIron4" , FieldItemKind.FenceCorrugatedIron )}, // オレンジのトタンのさく + {0xED55, new FieldItemDefinition(60757, 65534, 4357 , "FenceSteel8" , FieldItemKind.FenceSteel )}, // てつのさく・黒 + {0xED56, new FieldItemDefinition(60758, 65534, 4357 , "FenceSteel7" , FieldItemKind.FenceSteel )}, // てつのさく・白 + {0xED57, new FieldItemDefinition(60759, 65534, 4357 , "FenceSteel6" , FieldItemKind.FenceSteel )}, // てつのさく・ネイビー + {0xED58, new FieldItemDefinition(60760, 65534, 4357 , "FenceSteel5" , FieldItemKind.FenceSteel )}, // てつのさく・オレンジ + {0xED59, new FieldItemDefinition(60761, 65534, 14758, "FenceCorrugatedIron6" , FieldItemKind.FenceCorrugatedIron )}, // しろいトタンのさく + {0xED5A, new FieldItemDefinition(60762, 65534, 14758, "FenceCorrugatedIron7" , FieldItemKind.FenceCorrugatedIron )}, // くろいトタンのさく + {0xED5B, new FieldItemDefinition(60763, 65534, 3402 , "FenceVerticalWood8" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・紫 + {0xED5C, new FieldItemDefinition(60764, 65534, 3402 , "FenceVerticalWood7" , FieldItemKind.FenceVerticalWood )}, // たていたのさく・白 + {0xED5D, new FieldItemDefinition(60765, 65534, 12894, "FenceJuneBride7" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・くろ + {0xED5E, new FieldItemDefinition(60766, 65534, 12894, "FenceJuneBride6" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・むらさき + {0xED5F, new FieldItemDefinition(60767, 65534, 12894, "FenceJuneBride5" , FieldItemKind.FenceJuneBride )}, // ウェディングな柵・きいろ + }; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/FlowerGene.cs b/NHSE.Core/Structures/Item/FlowerGene.cs index 47e11bb..a7234ae 100644 --- a/NHSE.Core/Structures/Item/FlowerGene.cs +++ b/NHSE.Core/Structures/Item/FlowerGene.cs @@ -1,21 +1,20 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Genes that a Flower Item has +/// +[Flags] +public enum FlowerGene : byte { - /// - /// Genes that a Flower Item has - /// - [Flags] - public enum FlowerGene : byte - { - None = 0, - R1 = 1, - R2 = 1 << 1, - Y1 = 1 << 2, - Y2 = 1 << 3, - w1 = 1 << 4, // inverted; both bits on = no gene (not white) - w2 = 1 << 5, // inverted; both bits on = no gene (not white) - S1 = 1 << 6, - S2 = 1 << 7, - } -} + None = 0, + R1 = 1, + R2 = 1 << 1, + Y1 = 1 << 2, + Y2 = 1 << 3, + w1 = 1 << 4, // inverted; both bits on = no gene (not white) + w2 = 1 << 5, // inverted; both bits on = no gene (not white) + S1 = 1 << 6, + S2 = 1 << 7, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ICopyableItem.cs b/NHSE.Core/Structures/Item/ICopyableItem.cs index 9198dc8..2cfd4e0 100644 --- a/NHSE.Core/Structures/Item/ICopyableItem.cs +++ b/NHSE.Core/Structures/Item/ICopyableItem.cs @@ -1,8 +1,7 @@ -namespace NHSE.Core +namespace NHSE.Core; + +public interface ICopyableItem { - public interface ICopyableItem - { - void CopyFrom(T item); - int Size { get; } - } -} + void CopyFrom(T item); + int Size { get; } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/IGridItem.cs b/NHSE.Core/Structures/Item/IGridItem.cs index 8eb11e9..01eec41 100644 --- a/NHSE.Core/Structures/Item/IGridItem.cs +++ b/NHSE.Core/Structures/Item/IGridItem.cs @@ -1,8 +1,7 @@ -namespace NHSE.Core +namespace NHSE.Core; + +public interface IGridItem { - public interface IGridItem - { - int Width { get; } - int Height { get; } - } + int Width { get; } + int Height { get; } } \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/Item.cs b/NHSE.Core/Structures/Item/Item.cs index 08f1c8d..5df3f10 100644 --- a/NHSE.Core/Structures/Item/Item.cs +++ b/NHSE.Core/Structures/Item/Item.cs @@ -2,258 +2,255 @@ using System.Collections.Generic; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] +public class Item : ICopyableItem, IEquatable { - [StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] - public class Item : ICopyableItem, IEquatable + public static readonly Item NO_ITEM = new() {ItemId = NONE}; + public const ushort NONE = 0xFFFE; + public const ushort EXTENSION = 0xFFFD; + public const ushort FieldItemMin = 60_000; + public const ushort LLOYD = 63_005; + + public const ushort MessageBottle = 0x16A1; + public const ushort DIYRecipe = 0x16A2; + public const ushort MessageBottleEgg = 0x3100; + public const int SIZE = 8; + + [field: FieldOffset(0)] public ulong RawValue { get; set; } + + [field: FieldOffset(0)] public ushort ItemId { get; set; } + [field: FieldOffset(2)] public byte SystemParam { get; set; } + [field: FieldOffset(3)] public byte AdditionalParam { get; set; } + [field: FieldOffset(4)] public int FreeParam { get; set; } + + public void ClearFlags() => SystemParam = 0; + public int Rotation { get => SystemParam & 3; set => SystemParam = (byte)((SystemParam & ~3) | (value & 3)); } + public bool IsBuried { get => (SystemParam & 0x04) != 0; set => SystemParam = (byte) ((SystemParam & ~0x04) | (value ? 0x04 : 0)); } + public bool Is_08 { get => (SystemParam & 0x08) != 0; set => SystemParam = (byte) ((SystemParam & ~0x08) | (value ? 0x08 : 0)); } + public bool Is_10 { get => (SystemParam & 0x10) != 0; set => SystemParam = (byte) ((SystemParam & ~0x10) | (value ? 0x10 : 0)); } + public bool IsDropped { get => (SystemParam & 0x20) != 0; set => SystemParam = (byte) ((SystemParam & ~0x20) | (value ? 0x20 : 0)); } + public bool Is_40 { get => (SystemParam & 0x40) != 0; set => SystemParam = (byte) ((SystemParam & ~0x40) | (value ? 0x40 : 0)); } + public bool Is_80 { get => (SystemParam & 0x80) != 0; set => SystemParam = (byte) ((SystemParam & ~0x80) | (value ? 0x80 : 0)); } + + #region Flag1 (Wrapping / Etc) + public bool IsWrapped { - public static readonly Item NO_ITEM = new() {ItemId = NONE}; - public const ushort NONE = 0xFFFE; - public const ushort EXTENSION = 0xFFFD; - public const ushort FieldItemMin = 60_000; - public const ushort LLOYD = 63_005; - - public const ushort MessageBottle = 0x16A1; - public const ushort DIYRecipe = 0x16A2; - public const ushort MessageBottleEgg = 0x3100; - public const int SIZE = 8; - - [field: FieldOffset(0)] public ulong RawValue { get; set; } - - [field: FieldOffset(0)] public ushort ItemId { get; set; } - [field: FieldOffset(2)] public byte SystemParam { get; set; } - [field: FieldOffset(3)] public byte AdditionalParam { get; set; } - [field: FieldOffset(4)] public int FreeParam { get; set; } - - public void ClearFlags() => SystemParam = 0; - public int Rotation { get => SystemParam & 3; set => SystemParam = (byte)((SystemParam & ~3) | (value & 3)); } - public bool IsBuried { get => (SystemParam & 0x04) != 0; set => SystemParam = (byte) ((SystemParam & ~0x04) | (value ? 0x04 : 0)); } - public bool Is_08 { get => (SystemParam & 0x08) != 0; set => SystemParam = (byte) ((SystemParam & ~0x08) | (value ? 0x08 : 0)); } - public bool Is_10 { get => (SystemParam & 0x10) != 0; set => SystemParam = (byte) ((SystemParam & ~0x10) | (value ? 0x10 : 0)); } - public bool IsDropped { get => (SystemParam & 0x20) != 0; set => SystemParam = (byte) ((SystemParam & ~0x20) | (value ? 0x20 : 0)); } - public bool Is_40 { get => (SystemParam & 0x40) != 0; set => SystemParam = (byte) ((SystemParam & ~0x40) | (value ? 0x40 : 0)); } - public bool Is_80 { get => (SystemParam & 0x80) != 0; set => SystemParam = (byte) ((SystemParam & ~0x80) | (value ? 0x80 : 0)); } - - #region Flag1 (Wrapping / Etc) - public bool IsWrapped + get { - get - { - if (AdditionalParam == 0) - return false; - var id = DisplayItemId; - return id != MessageBottle && id != MessageBottleEgg; - } + if (AdditionalParam == 0) + return false; + var id = DisplayItemId; + return id != MessageBottle && id != MessageBottleEgg; } - - public ItemWrapping WrappingType - { - get - { - var value = (ItemWrapping) (AdditionalParam & 3); - if (value is ItemWrapping.Delivery && WrappingPaper is ItemWrappingPaper.Black) - return ItemWrapping.Festive; - return value; - } - set - { - if (value is ItemWrapping.Festive) - { - value = ItemWrapping.Delivery; // 3 (11) - WrappingPaper = ItemWrappingPaper.Black; // 15 (1111) - } - AdditionalParam = (byte) ((AdditionalParam & ~3) | ((byte) value & 3)); - } - } - - public ItemWrappingPaper WrappingPaper - { - get => (ItemWrappingPaper) ((AdditionalParam >> 2) & 0xF); - set => AdditionalParam = (byte)((AdditionalParam & 3) | ((byte)value & 0xF) << 2); - } - - public void SetWrapping(ItemWrapping wrap, ItemWrappingPaper color, bool showItem = false, bool item80 = false) - { - if (wrap is ItemWrapping.Nothing or > ItemWrapping.Festive) - { - AdditionalParam = 0; - return; - } - WrappingPaper = wrap == ItemWrapping.WrappingPaper ? color : 0; - WrappingType = wrap; - WrappingShowItem = showItem; - Wrapping80 = item80; - } - - public bool WrappingShowItem - { - get => (AdditionalParam & 0x40) != 0; - set => AdditionalParam = (byte)((AdditionalParam & ~0x40) | (value ? 1 << 6 : 0)); - } - - public bool Wrapping80 - { - get => (AdditionalParam & 0x80) != 0; - set => AdditionalParam = (byte)((AdditionalParam & ~0x80) | (value ? 1 << 7 : 0)); - } - #endregion - - #region Stackable Items - [field: FieldOffset(4)] public ushort Count { get; set; } - [field: FieldOffset(6)] public ushort UseCount { get; set; } - #endregion - - #region Customizable Items - public int BodyType - { - get => FreeParam & 7; - set => FreeParam = (FreeParam & ~7) | (value & 7); - } - - public int PatternSource // see RemakeDesignSource - { - get => (FreeParam >> 3) & 3; - set => FreeParam = (FreeParam & ~0x18) | ((value & 3) << 3); - } - - public int PatternChoice - { - get => FreeParam >> 5; - set => FreeParam = (FreeParam & 0x1F) | ((value & 0x7FF) << 5); - } - #endregion - - #region Flowers - - // flowers only -- this is really just a packed u32 - [field: FieldOffset(4)] public FlowerGene Genes { get; set; } - [field: FieldOffset(5)] private ushort Watered { get; set; } - // ReSharper disable once UnusedAutoPropertyAccessor.Local - [field: FieldOffset(7)] private byte Watered2 { get; set; } - // offset 7 is unused bits - - public int DaysWatered - { - get => Watered & 0x1F; - set => Watered = (ushort)((Watered & 0xFFE0) | (value & 0x1F)); - } - - public bool GetIsWateredByVisitor(int visitor) - { - if ((uint)visitor >= 10) - throw new ArgumentOutOfRangeException(nameof(visitor)); - - var shift = 5 + visitor; - return (Watered & (1 << shift)) != 0; - } - - public void SetIsWateredByVisitor(int visitor, bool value = true) - { - if ((uint)visitor >= 10) - throw new ArgumentOutOfRangeException(nameof(visitor)); - - var shift = 5 + visitor; - var bit = (1 << shift); - var mask = ~bit; - - Watered = (ushort)((Watered & mask) | (value ? bit : 0)); - } - - public bool IsWatered - { - get => ((Watered >> 15) & 1) == 1; - set => Watered = (ushort)((Watered & 0x7FFF) | (value ? 0x8000 : 0)); - } - - public bool IsWateredGold - { - get => (Watered2 & 1) == 1; - set => Watered2 = (byte)((Watered2 & 0xFE) | (value ? 1 : 0)); - } - - public void Water(bool all = false) - { - if (all) - { - Watered = 0xFFFF; - Watered2 = 1; - return; - } - - DaysWatered = 31; - IsWatered = true; - } - - #endregion - - #region Item Extensions - public ushort DisplayItemId => IsExtension ? ExtensionItemId : ItemId; - public bool IsNone => ItemId == NONE; - public bool IsExtension => ItemId == EXTENSION; - public bool IsRoot => ItemId < EXTENSION; - public bool IsFieldItem => IsRoot && ItemId >= 60_000; - [field: FieldOffset(4)] public ushort ExtensionItemId { get; set; } - [field: FieldOffset(6)] public byte ExtensionX { get; set; } - [field: FieldOffset(7)] public byte ExtensionY { get; set; } - - public void SetAsExtension(Item tile, byte x, byte y) - { - ItemId = EXTENSION; - SystemParam = 0; - AdditionalParam = 0; - ExtensionX = x; - ExtensionY = y; - ExtensionItemId = tile.ItemId; - } - #endregion - - public Item() { } // marshalling - public Item(ulong raw) => RawValue = raw; - public Item(ushort itemId = NONE) => ItemId = itemId; - - public void Delete() => RawValue = NONE; // clears & sets the two lowest byte as ItemID - - public virtual int Size => SIZE; - - public void CopyFrom(Item item) - { - ItemId = item.ItemId; - SystemParam = item.SystemParam; - AdditionalParam = item.AdditionalParam; - FreeParam = item.FreeParam; - } - - public static Item[] GetArray(byte[] data) => data.GetArray(SIZE); - public static byte[] SetArray(IReadOnlyList data) => data.SetArray(SIZE); - - public ushort GetWrappedItemName() - { - return WrappingType switch - { - ItemWrapping.WrappingPaper => (ushort) (0x1E13 + (ushort)WrappingPaper), - ItemWrapping.Present => 0x1180, - ItemWrapping.Delivery => 0x1225, - _ => ItemId, - }; - } - - public bool Equals(Item? other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return RawValue == other.RawValue; - } - - public override bool Equals(object? obj) - { - if (obj is null) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((Item) obj); - } - - public override int GetHashCode() => RawValue.GetHashCode(); - public static bool operator ==(Item? left, Item? right) => Equals(left, right); - public static bool operator !=(Item? left, Item? right) => !Equals(left, right); } -} + + public ItemWrapping WrappingType + { + get + { + var value = (ItemWrapping) (AdditionalParam & 3); + if (value is ItemWrapping.Delivery && WrappingPaper is ItemWrappingPaper.Black) + return ItemWrapping.Festive; + return value; + } + set + { + if (value is ItemWrapping.Festive) + { + value = ItemWrapping.Delivery; // 3 (11) + WrappingPaper = ItemWrappingPaper.Black; // 15 (1111) + } + AdditionalParam = (byte) ((AdditionalParam & ~3) | ((byte) value & 3)); + } + } + + public ItemWrappingPaper WrappingPaper + { + get => (ItemWrappingPaper) ((AdditionalParam >> 2) & 0xF); + set => AdditionalParam = (byte)((AdditionalParam & 3) | ((byte)value & 0xF) << 2); + } + + public void SetWrapping(ItemWrapping wrap, ItemWrappingPaper color, bool showItem = false, bool item80 = false) + { + if (wrap is ItemWrapping.Nothing or > ItemWrapping.Festive) + { + AdditionalParam = 0; + return; + } + WrappingPaper = wrap == ItemWrapping.WrappingPaper ? color : 0; + WrappingType = wrap; + WrappingShowItem = showItem; + Wrapping80 = item80; + } + + public bool WrappingShowItem + { + get => (AdditionalParam & 0x40) != 0; + set => AdditionalParam = (byte)((AdditionalParam & ~0x40) | (value ? 1 << 6 : 0)); + } + + public bool Wrapping80 + { + get => (AdditionalParam & 0x80) != 0; + set => AdditionalParam = (byte)((AdditionalParam & ~0x80) | (value ? 1 << 7 : 0)); + } + #endregion + + #region Stackable Items + [field: FieldOffset(4)] public ushort Count { get; set; } + [field: FieldOffset(6)] public ushort UseCount { get; set; } + #endregion + + #region Customizable Items + public int BodyType + { + get => FreeParam & 7; + set => FreeParam = (FreeParam & ~7) | (value & 7); + } + + public int PatternSource // see RemakeDesignSource + { + get => (FreeParam >> 3) & 3; + set => FreeParam = (FreeParam & ~0x18) | ((value & 3) << 3); + } + + public int PatternChoice + { + get => FreeParam >> 5; + set => FreeParam = (FreeParam & 0x1F) | ((value & 0x7FF) << 5); + } + #endregion + + #region Flowers + + // flowers only -- this is really just a packed u32 + [field: FieldOffset(4)] public FlowerGene Genes { get; set; } + [field: FieldOffset(5)] private ushort Watered { get; set; } + // ReSharper disable once UnusedAutoPropertyAccessor.Local + [field: FieldOffset(7)] private byte Watered2 { get; set; } + // offset 7 is unused bits + + public int DaysWatered + { + get => Watered & 0x1F; + set => Watered = (ushort)((Watered & 0xFFE0) | (value & 0x1F)); + } + + public bool GetIsWateredByVisitor(int visitor) + { + if ((uint)visitor >= 10) + throw new ArgumentOutOfRangeException(nameof(visitor)); + + var shift = 5 + visitor; + return (Watered & (1 << shift)) != 0; + } + + public void SetIsWateredByVisitor(int visitor, bool value = true) + { + if ((uint)visitor >= 10) + throw new ArgumentOutOfRangeException(nameof(visitor)); + + var shift = 5 + visitor; + var bit = (1 << shift); + var mask = ~bit; + + Watered = (ushort)((Watered & mask) | (value ? bit : 0)); + } + + public bool IsWatered + { + get => ((Watered >> 15) & 1) == 1; + set => Watered = (ushort)((Watered & 0x7FFF) | (value ? 0x8000 : 0)); + } + + public bool IsWateredGold + { + get => (Watered2 & 1) == 1; + set => Watered2 = (byte)((Watered2 & 0xFE) | (value ? 1 : 0)); + } + + public void Water(bool all = false) + { + if (all) + { + Watered = 0xFFFF; + Watered2 = 1; + return; + } + + DaysWatered = 31; + IsWatered = true; + } + + #endregion + + #region Item Extensions + public ushort DisplayItemId => IsExtension ? ExtensionItemId : ItemId; + public bool IsNone => ItemId == NONE; + public bool IsExtension => ItemId == EXTENSION; + public bool IsRoot => ItemId < EXTENSION; + public bool IsFieldItem => IsRoot && ItemId >= 60_000; + [field: FieldOffset(4)] public ushort ExtensionItemId { get; set; } + [field: FieldOffset(6)] public byte ExtensionX { get; set; } + [field: FieldOffset(7)] public byte ExtensionY { get; set; } + + public void SetAsExtension(Item tile, byte x, byte y) + { + ItemId = EXTENSION; + SystemParam = 0; + AdditionalParam = 0; + ExtensionX = x; + ExtensionY = y; + ExtensionItemId = tile.ItemId; + } + #endregion + + public Item() { } // marshalling + public Item(ulong raw) => RawValue = raw; + public Item(ushort itemId = NONE) => ItemId = itemId; + + public void Delete() => RawValue = NONE; // clears & sets the two lowest byte as ItemID + + public virtual int Size => SIZE; + + public void CopyFrom(Item item) + { + ItemId = item.ItemId; + SystemParam = item.SystemParam; + AdditionalParam = item.AdditionalParam; + FreeParam = item.FreeParam; + } + + public static Item[] GetArray(ReadOnlySpan data) => data.GetArray(SIZE); + public static byte[] SetArray(IReadOnlyList data) => data.SetArray(SIZE); + + public ushort GetWrappedItemName() => WrappingType switch + { + ItemWrapping.WrappingPaper => (ushort) (0x1E13 + (ushort)WrappingPaper), + ItemWrapping.Present => 0x1180, + ItemWrapping.Delivery => 0x1225, + _ => ItemId, + }; + + public bool Equals(Item? other) + { + if (other is null) return false; + if (ReferenceEquals(this, other)) return true; + return RawValue == other.RawValue; + } + + public override bool Equals(object? obj) + { + if (obj is null) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((Item) obj); + } + + // ReSharper disable once NonReadonlyMemberInGetHashCode + public override int GetHashCode() => RawValue.GetHashCode(); + public static bool operator ==(Item? left, Item? right) => Equals(left, right); + public static bool operator !=(Item? left, Item? right) => !Equals(left, right); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ItemArrayEditor.cs b/NHSE.Core/Structures/Item/ItemArrayEditor.cs index 624e000..0b08a85 100644 --- a/NHSE.Core/Structures/Item/ItemArrayEditor.cs +++ b/NHSE.Core/Structures/Item/ItemArrayEditor.cs @@ -1,62 +1,62 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public class ItemArrayEditor where T : Item, ICopyableItem { - public class ItemArrayEditor where T : Item, ICopyableItem + public readonly IReadOnlyList Items; + public ItemArrayEditor(IReadOnlyList items) => Items = items; + public int ItemSize => Items[0].Size; + public int TotalSize => Items.Count * ItemSize; + + public byte[] Write() => Items.SetArray(ItemSize); + + public void ImportItemDataX(ReadOnlySpan data, bool skipOccupiedSlots, int start = 0) { - public readonly IReadOnlyList Items; - public ItemArrayEditor(IReadOnlyList items) => Items = items; - public int ItemSize => Items[0].Size; - public int TotalSize => Items.Count * ItemSize; + int expect = ItemSize; + var import = data.GetArray(expect); + ImportItems(import, start, skipOccupiedSlots); + } - public byte[] Write() => Items.SetArray(ItemSize); + private void ImportItems(IReadOnlyList import, int start, bool skipOccupiedSlots) + { + if (skipOccupiedSlots) + ImportItemsSkip(import, start); + else + ImportItemsOverwrite(import, start); + } - public void ImportItemDataX(byte[] data, bool skipOccupiedSlots, int start = 0) + private void ImportItemsOverwrite(IReadOnlyList import, int destIndex, int importIndex = 0) + { + while (importIndex < import.Count && destIndex < Items.Count) { - int expect = ItemSize; - var import = data.GetArray(expect); - ImportItems(import, start, skipOccupiedSlots); - } - - private void ImportItems(IReadOnlyList import, int start, bool skipOccupiedSlots) - { - if (skipOccupiedSlots) - ImportItemsSkip(import, start); - else - ImportItemsOverwrite(import, start); - } - - private void ImportItemsOverwrite(IReadOnlyList import, int destIndex, int importIndex = 0) - { - while (importIndex < import.Count && destIndex < Items.Count) - { - Items[destIndex].CopyFrom(import[importIndex]); - destIndex++; importIndex++; - } - } - - private void ImportItemsSkip(IReadOnlyList import, int destIndex, int importIndex = 0) - { - while (importIndex < import.Count && destIndex < Items.Count) - { - var importItem = import[importIndex]; - if (importItem.ItemId == Item.NONE) - { - importIndex++; - continue; - } - - var destItem = Items[destIndex]; - if (destItem.ItemId != Item.NONE) - { - destIndex++; - continue; - } - - destItem.CopyFrom(importItem); - importIndex++; - destIndex++; - } + Items[destIndex].CopyFrom(import[importIndex]); + destIndex++; importIndex++; } } -} + + private void ImportItemsSkip(IReadOnlyList import, int destIndex, int importIndex = 0) + { + while (importIndex < import.Count && destIndex < Items.Count) + { + var importItem = import[importIndex]; + if (importItem.ItemId == Item.NONE) + { + importIndex++; + continue; + } + + var destItem = Items[destIndex]; + if (destItem.ItemId != Item.NONE) + { + destIndex++; + continue; + } + + destItem.CopyFrom(importItem); + importIndex++; + destIndex++; + } + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ItemCheatCode.cs b/NHSE.Core/Structures/Item/ItemCheatCode.cs index 7c70ce6..a21e5ad 100644 --- a/NHSE.Core/Structures/Item/ItemCheatCode.cs +++ b/NHSE.Core/Structures/Item/ItemCheatCode.cs @@ -1,79 +1,80 @@ using System; using System.Collections.Generic; using System.Globalization; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Converts cheat codes to and from +/// +public static class ItemCheatCode { - /// - /// Converts cheat codes to and from - /// - public static class ItemCheatCode + public static byte[] ReadCode(string paste) { - public static byte[] ReadCode(string paste) - { - var lines = paste.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); - return ReadCode(lines); - } + var lines = paste.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries); + return ReadCode(lines); + } - public static byte[] ReadCode(IEnumerable lines) + public static byte[] ReadCode(IEnumerable lines) + { + var result = new List(); + foreach (var line in lines) { - var result = new List(); - foreach (var line in lines) + var l = line.Trim(); + var chunkCount = GetChunkCount(l); + if (chunkCount == 0) + continue; + + // Since the codes are stored BB AA, we need to import them in reverse (AA BB) + int indexOfSpace = l.Length - 1; + for (int i = 0; i < chunkCount; i++) { - var l = line.Trim(); - var chunkCount = GetChunkCount(l); - if (chunkCount == 0) + indexOfSpace = l.LastIndexOf(' ', indexOfSpace); + if (indexOfSpace < 0) continue; - // Since the codes are stored BB AA, we need to import them in reverse (AA BB) - int indexOfSpace = l.Length - 1; - for (int i = 0; i < chunkCount; i++) - { - indexOfSpace = l.LastIndexOf(' ', indexOfSpace); - if (indexOfSpace < 0) - continue; + var length = l.Length - indexOfSpace - 1; + if (length < 8) + continue; - var length = l.Length - indexOfSpace - 1; - if (length < 8) - continue; - - var lastChunk = l.Substring(indexOfSpace + 1, 8); - AddU32Chunk(lastChunk, result); - indexOfSpace -= 2; - } + var lastChunk = l.Substring(indexOfSpace + 1, 8); + AddU32Chunk(lastChunk, result); + indexOfSpace -= 2; } - return result.ToArray(); } + return result.ToArray(); + } - private static int GetChunkCount(string line) + private static int GetChunkCount(string line) + { + if (line.Length < 2) + return 0; + + // 08 or 04 + var second = line[1]; + return second == '8' ? 2 : 1; + } + + private static void AddU32Chunk(string lastChunk, List result) + { + if (!uint.TryParse(lastChunk, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var hex)) + return; + var bytes = new byte[sizeof(uint)]; + WriteUInt32LittleEndian(bytes, hex); + result.AddRange(bytes); + } + + public static IEnumerable WriteCode(IEnumerable items, uint offset) + { + int ctr = 0; + foreach (var item in items) { - if (line.Length < 2) - return 0; - - // 08 or 04 - var second = line[1]; - return second == '8' ? 2 : 1; - } - - private static void AddU32Chunk(string lastChunk, List result) - { - if (!uint.TryParse(lastChunk, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var hex)) - return; - var bytes = BitConverter.GetBytes(hex); - result.AddRange(bytes); - } - - public static IEnumerable WriteCode(IEnumerable items, uint offset) - { - int ctr = 0; - foreach (var item in items) - { - var bytes = item.ToBytesClass(); - var lower = BitConverter.ToUInt32(bytes, 0); - var upper = BitConverter.ToUInt32(bytes, 4); - yield return $"04100000 {offset + (ctr++*4):X8} {lower:X8}"; - yield return $"04100000 {offset + (ctr++*4):X8} {upper:X8}"; - } + var bytes = item.ToBytesClass(); + var lower = ReadUInt32LittleEndian(bytes.AsSpan(0)); + var upper = ReadUInt32LittleEndian(bytes.AsSpan(4)); + yield return $"04100000 {offset + (ctr++*4):X8} {lower:X8}"; + yield return $"04100000 {offset + (ctr++*4):X8} {upper:X8}"; } } -} +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ItemInfo.cs b/NHSE.Core/Structures/Item/ItemInfo.cs index e6ad056..856e151 100644 --- a/NHSE.Core/Structures/Item/ItemInfo.cs +++ b/NHSE.Core/Structures/Item/ItemInfo.cs @@ -2,367 +2,365 @@ using System.Text; using static NHSE.Core.ItemKind; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Fetching metadata about an +/// +public static class ItemInfo { - /// - /// Fetching metadata about an - /// - public static class ItemInfo + // derived from bcsv; only some data is needed for our logic + private static readonly byte[] ItemKinds = ResourceUtil.GetBinaryResource("item_kind.bin"); + private static readonly byte[] ItemSizes = ResourceUtil.GetBinaryResource("item_size.bin"); + private static readonly ushort[] ItemMenuIcons = ResourceUtil.GetBinaryResourceAsUshort("item_menuicon.bin"); + + public static ItemKind GetItemKind(Item item) => GetItemKind(item.DisplayItemId); + + public static ItemKind GetItemKind(ushort id) { - // derived from bcsv; only some data is needed for our logic - private static readonly byte[] ItemKinds = ResourceUtil.GetBinaryResource("item_kind.bin"); - private static readonly byte[] ItemSizes = ResourceUtil.GetBinaryResource("item_size.bin"); - private static readonly ushort[] ItemMenuIcons = ResourceUtil.GetBinaryResourceAsUshort("item_menuicon.bin"); - - public static ItemKind GetItemKind(Item item) => GetItemKind(item.DisplayItemId); - - public static ItemKind GetItemKind(ushort id) - { - if (id > ItemKinds.Length) - return FieldItemList.GetFieldItemKind(id); - return (ItemKind) ItemKinds[id]; - } - - public static ItemSizeType GetItemSize(Item item) - { - if (item.IsBuried || item.IsDropped) - return ItemSizeType.S_1_0x1_0; - - return GetItemSize(item.DisplayItemId); - } - - public static ItemSizeType GetItemSize(ushort id) - { - if (id > ItemSizes.Length) - return ItemSizeType.Unknown; - return (ItemSizeType)ItemSizes[id]; - } - - public static ItemMenuIconType GetMenuIcon(ushort id) - { - if (id > ItemMenuIcons.Length) - return ItemMenuIconType.Unknown; - return (ItemMenuIconType)ItemMenuIcons[id]; - } - - public static bool TryGetMaxStackCount(Item item, out ushort max) => TryGetMaxStackCount(item.DisplayItemId, out max); - - public static bool TryGetMaxStackCount(ushort id, out ushort max) - { - var kind = GetItemKind(id); - if (kind.IsFlowerPicked()) - kind = Kind_Flower; - return MaxCountByKind.TryGetValue(kind, out max); - } - - private static readonly Dictionary MaxCountByKind = new() - { - {Kind_Ftr, 00001}, - {Kind_Dishes, 00001}, - {Kind_Drink, 00001}, - {Kind_CookingMaterial, 00050}, - {Kind_RoomWall, 00001}, - {Kind_RoomFloor, 00001}, - {Kind_Rug, 00001}, - {Kind_RugMyDesign, 00001}, - {Kind_Socks, 00001}, - {Kind_Cap, 00001}, - {Kind_Helmet, 00001}, - {Kind_Accessory, 00001}, - {Kind_Bag, 00001}, - {Kind_Umbrella, 00001}, - {Kind_FtrWall, 00001}, - {Kind_Counter, 00001}, - {Kind_Pillar, 00001}, - {Kind_FishingRod, 00001}, - {Kind_Net, 00001}, - {Kind_Shovel, 00001}, - {Kind_Axe, 00001}, - {Kind_Watering, 00001}, - {Kind_Slingshot, 00001}, - {Kind_ChangeStick, 00001}, - {Kind_WoodenStickTool, 00001}, - {Kind_Ladder, 00001}, - {Kind_GroundMaker, 00001}, - {Kind_RiverMaker, 00001}, - {Kind_CliffMaker, 00001}, - {Kind_HandBag, 00001}, - {Kind_PartyPopper, 00010}, - {Kind_Ocarina, 00001}, - {Kind_Panflute, 00001}, - {Kind_Tambourine, 00001}, - {Kind_MaracasCarnival, 00001}, - {Kind_StickLight, 00001}, - {Kind_StickLightColorful, 00001}, - {Kind_Uchiwa, 00001}, - {Kind_SubToolSensu, 00001}, - {Kind_Windmill, 00001}, - {Kind_Partyhorn, 00001}, - {Kind_BlowBubble, 00010}, - {Kind_FierworkHand, 00010}, - {Kind_Balloon, 00001}, - {Kind_HandheldPennant, 00001}, - {Kind_BigbagPresent, 00001}, - {Kind_JuiceFuzzyapple, 00001}, - {Kind_Megaphone, 00001}, - {Kind_SoySet, 00001}, - {Kind_FlowerShower, 00001}, - {Kind_Candyfloss, 00001}, - {Kind_SubToolDonut, 00001}, - {Kind_SubToolEat, 00001}, - {Kind_SubToolEatRemakeable, 00001}, - {Kind_Tapioca, 00001}, - {Kind_SubToolCan, 00001}, - {Kind_Icecandy, 00001}, - {Kind_SubToolIcecream, 00001}, - {Kind_SubToolIcesoft, 00001}, - {Kind_SubToolEatDrop, 00001}, - {Kind_SubToolGeneric, 00001}, - {Kind_Basket, 00001}, - {Kind_Lantern, 00001}, - {Kind_SubToolRemakeable, 00001}, - {Kind_Timer, 00001}, - {Kind_Gyroid, 00001}, - {Kind_GyroidScrap, 00001}, - {Kind_TreeSeedling, 00010}, - {Kind_Tree, 00001}, - {Kind_BushSeedling, 00010}, - {Kind_Bush, 00001}, - {Kind_VegeSeedling, 00010}, - {Kind_VegeTree, 00001}, - {Kind_Vegetable, 00010}, - {Kind_Weed, 00099}, - {Kind_WeedLight, 00050}, - {Kind_FlowerSeed, 00010}, - {Kind_FlowerBud, 00001}, - {Kind_Flower, 00010}, - {Kind_Fruit, 00010}, - {Kind_Mushroom, 00010}, - {Kind_Turnip, 00010}, - {Kind_TurnipExpired, 00001}, - {Kind_FishBait, 00010}, - {Kind_PitFallSeed, 00010}, - {Kind_Medicine, 00010}, - {Kind_CraftMaterial, 00030}, - {Kind_CraftRemake, 00050}, - {Kind_Ore, 00030}, - {Kind_CraftPhoneCase, 00001}, - {Kind_Honeycomb, 00010}, - {Kind_Trash, 00001}, - {Kind_SnowCrystal, 00010}, - {Kind_AutumnLeaf, 00010}, - {Kind_Sakurapetal, 00010}, - {Kind_XmasDeco, 00010}, - {Kind_StarPiece, 00010}, - {Kind_Insect, 00001}, - {Kind_Fish, 00001}, - {Kind_DiveFish, 00001}, - {Kind_ShellDrift, 00010}, - {Kind_ShellFish, 00001}, - {Kind_FishToy, 00001}, - {Kind_InsectToy, 00001}, - {Kind_Fossil, 00001}, - {Kind_FossilUnknown, 00001}, - {Kind_Music, 00001}, - {Kind_MusicMiss, 00001}, - {Kind_Bromide, 00001}, - {Kind_Poster, 00001}, - {Kind_HousePost, 00001}, - {Kind_DoorDeco, 00001}, - {Kind_Fence, 00050}, - {Kind_DummyRecipe, 00001}, - {Kind_DummyDIYRecipe, 00001}, - {Kind_DummyHowtoBook, 00001}, - {Kind_LicenseItem, 00001}, - {Kind_BridgeItem, 00001}, - {Kind_SlopeItem, 00001}, - {Kind_DIYRecipe, 00001}, - {Kind_MessageBottle, 00001}, - {Kind_WrappingPaper, 00010}, - {Kind_Otoshidama, 00010}, - {Kind_HousingKit, 00001}, - {Kind_HousingKitRcoQuest, 00001}, - {Kind_HousingKitBirdge, 00001}, - {Kind_Money, 00010}, - {Kind_FireworkM, 00001}, - {Kind_BdayCupcake, 00010}, - {Kind_YutaroWisp, 00005}, - {Kind_JohnnyQuest, 00010}, - {Kind_JohnnyQuestDust, 00010}, - {Kind_PirateQuest, 00010}, - {Kind_QuestWrapping, 00001}, - {Kind_QuestChristmasPresentbox, 00001}, - {Kind_LostQuest, 00001}, - {Kind_LostQuestDust, 00001}, - {Kind_TailorTicket, 00010}, - {Kind_TreasureQuest, 00001}, - {Kind_TreasureQuestDust, 00001}, - {Kind_MilePlaneTicket, 00010}, - {Kind_RollanTicket, 00005}, - {Kind_EasterEgg, 00030}, - {Kind_LoveCrystal, 00030}, - {Kind_Candy, 00030}, - {Kind_HarvestDish, 00001}, - {Kind_Feather, 00003}, - {Kind_RainbowFeather, 00001}, - {Kind_Vine, 00030}, - {Kind_SettingLadder, 00001}, - {Kind_SincerityTowel, 00001}, - {Kind_SouvenirChocolate, 00010}, - {Kind_Giftbox, 00001}, - {Kind_PinataStick, 00001}, - {Kind_NpcOutfit, 00001}, - {Kind_PlayerDemoOutfit, 00001}, - {Kind_Picture, 00001}, - {Kind_Sculpture, 00001}, - {Kind_PictureFake, 00001}, - {Kind_SculptureFake, 00001}, - {Kind_SmartPhone, 00001}, - {Kind_DummyFtr, 00001}, - {Kind_SequenceOnly, 00001}, - {Kind_MyDesignObject, 00001}, - {Kind_MyDesignTexture, 00001}, - {Kind_CommonFabricRug, 00001}, - {Kind_CommonFabricObject, 00001}, - {Kind_CommonFabricTexture, 00001}, - {Kind_OneRoomBox, 00001}, - {Kind_DummyWrapping, 00001}, - {Kind_DummyPresentbox, 00001}, - {Kind_DummyCardboard, 00001}, - {Kind_EventObjFtr, 00001}, - {Kind_NnpcRoomMarker, 00001}, - {Kind_PhotoStudioList, 00001}, - {Kind_ShopTorso, 00001}, - {Kind_DummyWrappingOtoshidama, 00001}, - {Kind_GardenEditList, 00001}, - }; - - /// - /// Lists the customization options for the requested - /// - /// Item ID - public static string GetItemInfo(ushort itemID) - { - var remake = ItemRemakeUtil.GetRemakeIndex(itemID); - if (remake < 0) - return string.Empty; - - var info = ItemRemakeInfoData.List[remake]; - return GetItemInfo(info, GameInfo.Strings); - } - - /// - /// Lists the customization options for the requested - /// - /// Item customization possibilities - /// Game strings - public static string GetItemInfo(ItemRemakeInfo info, IRemakeString str) - { - var sb = new StringBuilder(); - var body = info.GetBodySummary(str); - if (body.Length > 0) - sb.AppendLine(body); - - var fabric = info.GetFabricSummary(str); - if (fabric.Length > 0) - sb.AppendLine(fabric); - - return sb.ToString(); - } - - /// - /// Calculates the position the "Drop" option shows up in the item's interaction menu. - /// - /// Item object to drop - /// How many times the down button has to be pressed to reach the "Drop" option. - public static int GetItemDropOption(this Item item) - { - if (Item.DIYRecipe == item.ItemId) - return 1; - if (item.IsWrapped) - return 0; - - var kind = GetItemKind(item); - return kind switch - { - Kind_DIYRecipe => 1, - - Kind_Flower => 2, - _ => 1, - }; - } - - /// - /// Determines if wrapping the is possible. - /// - /// Item object to drop - /// True if can be wrapped - public static bool ShouldWrapItem(this Item item) - { - if (Item.DIYRecipe == item.ItemId) - return false; - - var kind = GetItemKind(item); - return kind switch - { - Kind_DIYRecipe => false, - - Kind_Flower => false, - _ => true, - }; - } - - /// - /// Checks if the is able to be dropped by the player character. - /// - /// Item object to drop - /// True if can be dropped - public static bool IsDroppable(Item item) - { - if (item.IsFieldItem) - return false; - if (item.IsExtension) - return false; - if (item.IsNone) - return false; - if (item.SystemParam > 3) - return false; // buried, dropped, etc - - var kind = GetItemKind(item); - return kind switch - { - Kind_Insect => false, - - Kind_DummyPresentbox => false, - - Kind_Fish => false, - Kind_DiveFish => false, - Kind_FlowerBud => false, - Kind_Bush => false, - Kind_Tree => false, - - _ => true, - }; - } - - /// - /// Checks if the item can be dropped, and sanitizes up any erroneous values if it can be. - /// - /// Requested item to drop. - /// True if can be dropped, false if cannot be dropped. - public static bool IsSaneItemForDrop(Item item) - { - if (!IsDroppable(item)) - return false; - - // Sanitize Values - if (item.ItemId == Item.MessageBottle || item.ItemId == Item.MessageBottleEgg) - { - item.ItemId = Item.DIYRecipe; - item.FreeParam = 0; - } - - return true; - } + if (id > ItemKinds.Length) + return FieldItemList.GetFieldItemKind(id); + return (ItemKind) ItemKinds[id]; } -} + + public static ItemSizeType GetItemSize(Item item) + { + if (item.IsBuried || item.IsDropped) + return ItemSizeType.S_1_0x1_0; + + return GetItemSize(item.DisplayItemId); + } + + public static ItemSizeType GetItemSize(ushort id) + { + if (id > ItemSizes.Length) + return ItemSizeType.Unknown; + return (ItemSizeType)ItemSizes[id]; + } + + public static ItemMenuIconType GetMenuIcon(ushort id) + { + if (id > ItemMenuIcons.Length) + return ItemMenuIconType.Unknown; + return (ItemMenuIconType)ItemMenuIcons[id]; + } + + public static bool TryGetMaxStackCount(Item item, out ushort max) => TryGetMaxStackCount(item.DisplayItemId, out max); + + public static bool TryGetMaxStackCount(ushort id, out ushort max) + { + var kind = GetItemKind(id); + if (kind.IsFlowerPicked) + kind = Kind_Flower; + return MaxCountByKind.TryGetValue(kind, out max); + } + + private static readonly Dictionary MaxCountByKind = new() + { + {Kind_Ftr, 00001}, + {Kind_Dishes, 00001}, + {Kind_Drink, 00001}, + {Kind_CookingMaterial, 00050}, + {Kind_RoomWall, 00001}, + {Kind_RoomFloor, 00001}, + {Kind_Rug, 00001}, + {Kind_RugMyDesign, 00001}, + {Kind_Socks, 00001}, + {Kind_Cap, 00001}, + {Kind_Helmet, 00001}, + {Kind_Accessory, 00001}, + {Kind_Bag, 00001}, + {Kind_Umbrella, 00001}, + {Kind_FtrWall, 00001}, + {Kind_Counter, 00001}, + {Kind_Pillar, 00001}, + {Kind_FishingRod, 00001}, + {Kind_Net, 00001}, + {Kind_Shovel, 00001}, + {Kind_Axe, 00001}, + {Kind_Watering, 00001}, + {Kind_Slingshot, 00001}, + {Kind_ChangeStick, 00001}, + {Kind_WoodenStickTool, 00001}, + {Kind_Ladder, 00001}, + {Kind_GroundMaker, 00001}, + {Kind_RiverMaker, 00001}, + {Kind_CliffMaker, 00001}, + {Kind_HandBag, 00001}, + {Kind_PartyPopper, 00010}, + {Kind_Ocarina, 00001}, + {Kind_Panflute, 00001}, + {Kind_Tambourine, 00001}, + {Kind_MaracasCarnival, 00001}, + {Kind_StickLight, 00001}, + {Kind_StickLightColorful, 00001}, + {Kind_Uchiwa, 00001}, + {Kind_SubToolSensu, 00001}, + {Kind_Windmill, 00001}, + {Kind_Partyhorn, 00001}, + {Kind_BlowBubble, 00010}, + {Kind_FierworkHand, 00010}, + {Kind_Balloon, 00001}, + {Kind_HandheldPennant, 00001}, + {Kind_BigbagPresent, 00001}, + {Kind_JuiceFuzzyapple, 00001}, + {Kind_Megaphone, 00001}, + {Kind_SoySet, 00001}, + {Kind_FlowerShower, 00001}, + {Kind_Candyfloss, 00001}, + {Kind_SubToolDonut, 00001}, + {Kind_SubToolEat, 00001}, + {Kind_SubToolEatRemakeable, 00001}, + {Kind_Tapioca, 00001}, + {Kind_SubToolCan, 00001}, + {Kind_Icecandy, 00001}, + {Kind_SubToolIcecream, 00001}, + {Kind_SubToolIcesoft, 00001}, + {Kind_SubToolEatDrop, 00001}, + {Kind_SubToolGeneric, 00001}, + {Kind_Basket, 00001}, + {Kind_Lantern, 00001}, + {Kind_SubToolRemakeable, 00001}, + {Kind_Timer, 00001}, + {Kind_Gyroid, 00001}, + {Kind_GyroidScrap, 00001}, + {Kind_TreeSeedling, 00010}, + {Kind_Tree, 00001}, + {Kind_BushSeedling, 00010}, + {Kind_Bush, 00001}, + {Kind_VegeSeedling, 00010}, + {Kind_VegeTree, 00001}, + {Kind_Vegetable, 00010}, + {Kind_Weed, 00099}, + {Kind_WeedLight, 00050}, + {Kind_FlowerSeed, 00010}, + {Kind_FlowerBud, 00001}, + {Kind_Flower, 00010}, + {Kind_Fruit, 00010}, + {Kind_Mushroom, 00010}, + {Kind_Turnip, 00010}, + {Kind_TurnipExpired, 00001}, + {Kind_FishBait, 00010}, + {Kind_PitFallSeed, 00010}, + {Kind_Medicine, 00010}, + {Kind_CraftMaterial, 00030}, + {Kind_CraftRemake, 00050}, + {Kind_Ore, 00030}, + {Kind_CraftPhoneCase, 00001}, + {Kind_Honeycomb, 00010}, + {Kind_Trash, 00001}, + {Kind_SnowCrystal, 00010}, + {Kind_AutumnLeaf, 00010}, + {Kind_Sakurapetal, 00010}, + {Kind_XmasDeco, 00010}, + {Kind_StarPiece, 00010}, + {Kind_Insect, 00001}, + {Kind_Fish, 00001}, + {Kind_DiveFish, 00001}, + {Kind_ShellDrift, 00010}, + {Kind_ShellFish, 00001}, + {Kind_FishToy, 00001}, + {Kind_InsectToy, 00001}, + {Kind_Fossil, 00001}, + {Kind_FossilUnknown, 00001}, + {Kind_Music, 00001}, + {Kind_MusicMiss, 00001}, + {Kind_Bromide, 00001}, + {Kind_Poster, 00001}, + {Kind_HousePost, 00001}, + {Kind_DoorDeco, 00001}, + {Kind_Fence, 00050}, + {Kind_DummyRecipe, 00001}, + {Kind_DummyDIYRecipe, 00001}, + {Kind_DummyHowtoBook, 00001}, + {Kind_LicenseItem, 00001}, + {Kind_BridgeItem, 00001}, + {Kind_SlopeItem, 00001}, + {Kind_DIYRecipe, 00001}, + {Kind_MessageBottle, 00001}, + {Kind_WrappingPaper, 00010}, + {Kind_Otoshidama, 00010}, + {Kind_HousingKit, 00001}, + {Kind_HousingKitRcoQuest, 00001}, + {Kind_HousingKitBirdge, 00001}, + {Kind_Money, 00010}, + {Kind_FireworkM, 00001}, + {Kind_BdayCupcake, 00010}, + {Kind_YutaroWisp, 00005}, + {Kind_JohnnyQuest, 00010}, + {Kind_JohnnyQuestDust, 00010}, + {Kind_PirateQuest, 00010}, + {Kind_QuestWrapping, 00001}, + {Kind_QuestChristmasPresentbox, 00001}, + {Kind_LostQuest, 00001}, + {Kind_LostQuestDust, 00001}, + {Kind_TailorTicket, 00010}, + {Kind_TreasureQuest, 00001}, + {Kind_TreasureQuestDust, 00001}, + {Kind_MilePlaneTicket, 00010}, + {Kind_RollanTicket, 00005}, + {Kind_EasterEgg, 00030}, + {Kind_LoveCrystal, 00030}, + {Kind_Candy, 00030}, + {Kind_HarvestDish, 00001}, + {Kind_Feather, 00003}, + {Kind_RainbowFeather, 00001}, + {Kind_Vine, 00030}, + {Kind_SettingLadder, 00001}, + {Kind_SincerityTowel, 00001}, + {Kind_SouvenirChocolate, 00010}, + {Kind_Giftbox, 00001}, + {Kind_PinataStick, 00001}, + {Kind_NpcOutfit, 00001}, + {Kind_PlayerDemoOutfit, 00001}, + {Kind_Picture, 00001}, + {Kind_Sculpture, 00001}, + {Kind_PictureFake, 00001}, + {Kind_SculptureFake, 00001}, + {Kind_SmartPhone, 00001}, + {Kind_DummyFtr, 00001}, + {Kind_SequenceOnly, 00001}, + {Kind_MyDesignObject, 00001}, + {Kind_MyDesignTexture, 00001}, + {Kind_CommonFabricRug, 00001}, + {Kind_CommonFabricObject, 00001}, + {Kind_CommonFabricTexture, 00001}, + {Kind_OneRoomBox, 00001}, + {Kind_DummyWrapping, 00001}, + {Kind_DummyPresentbox, 00001}, + {Kind_DummyCardboard, 00001}, + {Kind_EventObjFtr, 00001}, + {Kind_NnpcRoomMarker, 00001}, + {Kind_PhotoStudioList, 00001}, + {Kind_ShopTorso, 00001}, + {Kind_DummyWrappingOtoshidama, 00001}, + {Kind_GardenEditList, 00001}, + }; + + /// + /// Lists the customization options for the requested + /// + /// Item ID + public static string GetItemInfo(ushort itemID) + { + var remake = ItemRemakeUtil.GetRemakeIndex(itemID); + if (remake < 0) + return string.Empty; + + var info = ItemRemakeInfoData.List[remake]; + return GetItemInfo(info, GameInfo.Strings); + } + + /// + /// Lists the customization options for the requested + /// + /// Item customization possibilities + /// Game strings + public static string GetItemInfo(ItemRemakeInfo info, IRemakeString str) + { + var sb = new StringBuilder(); + var body = info.GetBodySummary(str); + if (body.Length > 0) + sb.AppendLine(body); + + var fabric = info.GetFabricSummary(str); + if (fabric.Length > 0) + sb.AppendLine(fabric); + + return sb.ToString(); + } + + /// + /// Calculates the position the "Drop" option shows up in the item's interaction menu. + /// + /// Item object to drop + /// How many times the down button has to be pressed to reach the "Drop" option. + public static int GetItemDropOption(this Item item) + { + if (Item.DIYRecipe == item.ItemId) + return 1; + if (item.IsWrapped) + return 0; + + var kind = GetItemKind(item); + return kind switch + { + Kind_DIYRecipe => 1, + Kind_Flower => 2, + _ => 1, + }; + } + + /// + /// Determines if wrapping the is possible. + /// + /// Item object to drop + /// True if can be wrapped + public static bool ShouldWrapItem(this Item item) + { + if (Item.DIYRecipe == item.ItemId) + return false; + + var kind = GetItemKind(item); + return kind switch + { + Kind_DIYRecipe => false, + + Kind_Flower => false, + _ => true, + }; + } + + /// + /// Checks if the is able to be dropped by the player character. + /// + /// Item object to drop + /// True if can be dropped + public static bool IsDroppable(Item item) + { + if (item.IsFieldItem) + return false; + if (item.IsExtension) + return false; + if (item.IsNone) + return false; + if (item.SystemParam > 3) + return false; // buried, dropped, etc + + var kind = GetItemKind(item); + return kind switch + { + Kind_Insect => false, + + Kind_DummyPresentbox => false, + + Kind_Fish => false, + Kind_DiveFish => false, + Kind_FlowerBud => false, + Kind_Bush => false, + Kind_Tree => false, + + _ => true, + }; + } + + /// + /// Checks if the item can be dropped, and sanitizes up any erroneous values if it can be. + /// + /// Requested item to drop. + /// True if can be dropped, false if cannot be dropped. + public static bool IsSaneItemForDrop(Item item) + { + if (!IsDroppable(item)) + return false; + + // Sanitize Values + if (item.ItemId is Item.MessageBottle or Item.MessageBottleEgg) + { + item.ItemId = Item.DIYRecipe; + item.FreeParam = 0; + } + + return true; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ItemKind.cs b/NHSE.Core/Structures/Item/ItemKind.cs index 0730d2a..973d183 100644 --- a/NHSE.Core/Structures/Item/ItemKind.cs +++ b/NHSE.Core/Structures/Item/ItemKind.cs @@ -1,200 +1,235 @@ using System.Collections.Generic; using static NHSE.Core.ItemKind; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Kinds of items +/// +public enum ItemKind : byte { - /// - /// Kinds of items - /// - public enum ItemKind : byte - { + Bottoms_Long, + Bottoms_Middle, + Bottoms_Short, + Ftr_1x1_Chair, + Ftr_1x1_Floor, + Ftr_2x1_Bed, + Ftr_2x1_Floor, + Ftr_2x2_Floor, + Kind_Accessory, + Kind_AutumnLeaf, + Kind_Axe, + Kind_Bag, + Kind_Balloon, + Kind_Basket, + Kind_BdayCupcake, + Kind_BigbagPresent, + Kind_BlowBubble, + Kind_BridgeItem, + Kind_Bromide, + Kind_Bush, + Kind_BushSeedling, + Kind_Candy, + Kind_Candyfloss, + Kind_Cap, + Kind_ChangeStick, + Kind_CliffMaker, + Kind_CommonFabricObject, + Kind_CommonFabricRug, + Kind_CommonFabricTexture, + Kind_CookingMaterial, + Kind_Counter, + Kind_CraftMaterial, + Kind_CraftPhoneCase, + Kind_CraftRemake, + Kind_Dishes, + Kind_DiveFish, + Kind_DIYRecipe, + Kind_DoorDeco, + Kind_Drink, + Kind_DummyCardboard, + Kind_DummyDIYRecipe, + Kind_DummyFtr, + Kind_DummyHowtoBook, + Kind_DummyPresentbox, + Kind_DummyRecipe, + Kind_DummyWrapping, + Kind_DummyWrappingOtoshidama, + Kind_EasterEgg, + Kind_EventObjFtr, + Kind_Feather, + Kind_Fence, + Kind_FierworkHand, + Kind_FireworkM, + Kind_Fish, + Kind_FishBait, + Kind_FishingRod, + Kind_FishToy, + Kind_Flower, + Kind_FlowerBud, + Kind_FlowerSeed, + Kind_FlowerShower, + Kind_Fossil, + Kind_FossilUnknown, + Kind_Fruit, + Kind_Ftr, + Kind_FtrWall, + Kind_GardenEditList, + Kind_Giftbox, + Kind_GroundMaker, + Kind_Gyroid, + Kind_GyroidScrap, + Kind_HandBag, + Kind_HandheldPennant, + Kind_HarvestDish, + Kind_Helmet, + Kind_Honeycomb, + Kind_HousePost, + Kind_HousingKit, + Kind_HousingKitBirdge, + Kind_HousingKitRcoQuest, + Kind_Icecandy, + Kind_Insect, + Kind_InsectToy, + Kind_JohnnyQuest, + Kind_JohnnyQuestDust, + Kind_JuiceFuzzyapple, + Kind_Ladder, + Kind_Lantern, + Kind_LicenseItem, + Kind_LostQuest, + Kind_LostQuestDust, + Kind_LoveCrystal, + Kind_MaracasCarnival, + Kind_Medicine, + Kind_Megaphone, + Kind_MessageBottle, + Kind_MilePlaneTicket, + Kind_Money, + Kind_Mushroom, + Kind_Music, + Kind_MusicMiss, + Kind_MyDesignObject, + Kind_MyDesignTexture, + Kind_Net, + Kind_NnpcRoomMarker, + Kind_NpcOutfit, + Kind_Ocarina, + Kind_OneRoomBox, + Kind_Ore, + Kind_Otoshidama, + Kind_Panflute, + Kind_Partyhorn, + Kind_PartyPopper, + Kind_PhotoStudioList, + Kind_Picture, + Kind_PictureFake, + Kind_Pillar, + Kind_PinataStick, + Kind_PirateQuest, + Kind_PitFallSeed, + Kind_PlayerDemoOutfit, + Kind_Poster, + Kind_QuestChristmasPresentbox, + Kind_QuestWrapping, + Kind_RainbowFeather, + Kind_RiverMaker, + Kind_RollanTicket, + Kind_RoomFloor, + Kind_RoomWall, + Kind_Rug, + Kind_RugMyDesign, + Kind_Sakurapetal, + Kind_Sculpture, + Kind_SculptureFake, + Kind_SequenceOnly, + Kind_SettingLadder, + Kind_ShellDrift, + Kind_ShellFish, + Kind_Shoes, + Kind_ShopTorso, + Kind_Shovel, + Kind_SincerityTowel, + Kind_Slingshot, + Kind_SlopeItem, + Kind_SmartPhone, + Kind_SnowCrystal, + Kind_Socks, + Kind_SouvenirChocolate, + Kind_SoySet, + Kind_StarPiece, + Kind_StickLight, + Kind_StickLightColorful, + Kind_SubToolCan, + Kind_SubToolDonut, + Kind_SubToolEat, // manually added? + Kind_SubToolEatDrop, + Kind_SubToolEatRemakeable, + Kind_SubToolGeneric, + Kind_SubToolIcecream, + Kind_SubToolIcesoft, + Kind_SubToolRemakeable, + Kind_SubToolSensu, + Kind_TailorTicket, + Kind_Tambourine, + Kind_Tapioca, + Kind_Timer, + Kind_Trash, + Kind_TreasureQuest, + Kind_TreasureQuestDust, + Kind_Tree, + Kind_TreeSeedling, + Kind_Turnip, + Kind_TurnipExpired, + Kind_Uchiwa, + Kind_Umbrella, + Kind_VegeSeedling, + Kind_Vegetable, + Kind_VegeTree, + Kind_Vine, + Kind_Watering, + Kind_Weed, + Kind_WeedLight, + Kind_Windmill, + Kind_WoodenStickTool, + Kind_WrappingPaper, + Kind_XmasDeco, + Kind_YutaroWisp, + Onepiece_Dress, + Onepiece_Long, + Onepiece_Middle, + Onepiece_Short, + Shoes_Boots, + Shoes_Pumps, + Top_Long, + Top_Middle, + Top_Short, + UnitIcon_FlwAnemone, + UnitIcon_FlwCosmos, + UnitIcon_FlwHyacinth, + UnitIcon_FlwLily, + UnitIcon_FlwMum, + UnitIcon_FlwPansy, + UnitIcon_FlwRose, + UnitIcon_FlwTulip, + + Unknown = byte.MaxValue, +} + +public static class ItemKindExtensions +{ + private static readonly HashSet Clothing = + [ Bottoms_Long, Bottoms_Middle, Bottoms_Short, - Ftr_1x1_Chair, - Ftr_1x1_Floor, - Ftr_2x1_Bed, - Ftr_2x1_Floor, - Ftr_2x2_Floor, Kind_Accessory, - Kind_AutumnLeaf, - Kind_Axe, Kind_Bag, - Kind_Balloon, - Kind_Basket, - Kind_BdayCupcake, - Kind_BigbagPresent, - Kind_BlowBubble, - Kind_BridgeItem, - Kind_Bromide, - Kind_Bush, - Kind_BushSeedling, - Kind_Candy, - Kind_Candyfloss, Kind_Cap, - Kind_ChangeStick, - Kind_CliffMaker, - Kind_CommonFabricObject, - Kind_CommonFabricRug, - Kind_CommonFabricTexture, - Kind_CookingMaterial, - Kind_Counter, - Kind_CraftMaterial, - Kind_CraftPhoneCase, - Kind_CraftRemake, - Kind_Dishes, - Kind_DiveFish, - Kind_DIYRecipe, - Kind_DoorDeco, - Kind_Drink, - Kind_DummyCardboard, - Kind_DummyDIYRecipe, - Kind_DummyFtr, - Kind_DummyHowtoBook, - Kind_DummyPresentbox, - Kind_DummyRecipe, - Kind_DummyWrapping, - Kind_DummyWrappingOtoshidama, - Kind_EasterEgg, - Kind_EventObjFtr, - Kind_Feather, - Kind_Fence, - Kind_FierworkHand, - Kind_FireworkM, - Kind_Fish, - Kind_FishBait, - Kind_FishingRod, - Kind_FishToy, - Kind_Flower, - Kind_FlowerBud, - Kind_FlowerSeed, - Kind_FlowerShower, - Kind_Fossil, - Kind_FossilUnknown, - Kind_Fruit, - Kind_Ftr, - Kind_FtrWall, - Kind_GardenEditList, - Kind_Giftbox, - Kind_GroundMaker, - Kind_Gyroid, - Kind_GyroidScrap, - Kind_HandBag, - Kind_HandheldPennant, - Kind_HarvestDish, Kind_Helmet, - Kind_Honeycomb, - Kind_HousePost, - Kind_HousingKit, - Kind_HousingKitBirdge, - Kind_HousingKitRcoQuest, - Kind_Icecandy, - Kind_Insect, - Kind_InsectToy, - Kind_JohnnyQuest, - Kind_JohnnyQuestDust, - Kind_JuiceFuzzyapple, - Kind_Ladder, - Kind_Lantern, - Kind_LicenseItem, - Kind_LostQuest, - Kind_LostQuestDust, - Kind_LoveCrystal, - Kind_MaracasCarnival, - Kind_Medicine, - Kind_Megaphone, - Kind_MessageBottle, - Kind_MilePlaneTicket, - Kind_Money, - Kind_Mushroom, - Kind_Music, - Kind_MusicMiss, - Kind_MyDesignObject, - Kind_MyDesignTexture, - Kind_Net, - Kind_NnpcRoomMarker, Kind_NpcOutfit, - Kind_Ocarina, - Kind_OneRoomBox, - Kind_Ore, - Kind_Otoshidama, - Kind_Panflute, - Kind_Partyhorn, - Kind_PartyPopper, - Kind_PhotoStudioList, - Kind_Picture, - Kind_PictureFake, - Kind_Pillar, - Kind_PinataStick, - Kind_PirateQuest, - Kind_PitFallSeed, Kind_PlayerDemoOutfit, - Kind_Poster, - Kind_QuestChristmasPresentbox, - Kind_QuestWrapping, - Kind_RainbowFeather, - Kind_RiverMaker, - Kind_RollanTicket, - Kind_RoomFloor, - Kind_RoomWall, - Kind_Rug, - Kind_RugMyDesign, - Kind_Sakurapetal, - Kind_Sculpture, - Kind_SculptureFake, - Kind_SequenceOnly, - Kind_SettingLadder, - Kind_ShellDrift, - Kind_ShellFish, - Kind_Shoes, - Kind_ShopTorso, - Kind_Shovel, - Kind_SincerityTowel, - Kind_Slingshot, - Kind_SlopeItem, - Kind_SmartPhone, - Kind_SnowCrystal, Kind_Socks, - Kind_SouvenirChocolate, - Kind_SoySet, - Kind_StarPiece, - Kind_StickLight, - Kind_StickLightColorful, - Kind_SubToolCan, - Kind_SubToolDonut, - Kind_SubToolEat, // manually added? - Kind_SubToolEatDrop, - Kind_SubToolEatRemakeable, - Kind_SubToolGeneric, - Kind_SubToolIcecream, - Kind_SubToolIcesoft, - Kind_SubToolRemakeable, - Kind_SubToolSensu, - Kind_TailorTicket, - Kind_Tambourine, - Kind_Tapioca, - Kind_Timer, - Kind_Trash, - Kind_TreasureQuest, - Kind_TreasureQuestDust, - Kind_Tree, - Kind_TreeSeedling, - Kind_Turnip, - Kind_TurnipExpired, - Kind_Uchiwa, - Kind_Umbrella, - Kind_VegeSeedling, - Kind_Vegetable, - Kind_VegeTree, - Kind_Vine, - Kind_Watering, - Kind_Weed, - Kind_WeedLight, - Kind_Windmill, - Kind_WoodenStickTool, - Kind_WrappingPaper, - Kind_XmasDeco, - Kind_YutaroWisp, Onepiece_Dress, Onepiece_Long, Onepiece_Middle, @@ -203,61 +238,28 @@ public enum ItemKind : byte Shoes_Pumps, Top_Long, Top_Middle, - Top_Short, - UnitIcon_FlwAnemone, - UnitIcon_FlwCosmos, - UnitIcon_FlwHyacinth, - UnitIcon_FlwLily, - UnitIcon_FlwMum, - UnitIcon_FlwPansy, - UnitIcon_FlwRose, - UnitIcon_FlwTulip, + Top_Short + ]; - Unknown = byte.MaxValue, - } + private static readonly HashSet Furniture = + [ + Ftr_1x1_Chair, + Ftr_1x1_Floor, + Ftr_2x1_Bed, + Ftr_2x1_Floor, + Ftr_2x2_Floor, + Kind_DummyFtr, + Kind_EventObjFtr, + Kind_Ftr + ]; - public static class ItemKindExtensions + extension(ItemKind k) { - private static readonly HashSet Clothing = new() - { - Bottoms_Long, - Bottoms_Middle, - Bottoms_Short, - Kind_Accessory, - Kind_Bag, - Kind_Cap, - Kind_Helmet, - Kind_NpcOutfit, - Kind_PlayerDemoOutfit, - Kind_Socks, - Onepiece_Dress, - Onepiece_Long, - Onepiece_Middle, - Onepiece_Short, - Shoes_Boots, - Shoes_Pumps, - Top_Long, - Top_Middle, - Top_Short, - }; - - private static readonly HashSet Furniture = new() - { - Ftr_1x1_Chair, - Ftr_1x1_Floor, - Ftr_2x1_Bed, - Ftr_2x1_Floor, - Ftr_2x2_Floor, - Kind_DummyFtr, - Kind_EventObjFtr, - Kind_Ftr, - }; - - public static bool IsFlower(this ItemKind k) => (Kind_Flower <= k && k <= Kind_FlowerBud) || (UnitIcon_FlwAnemone <= k && k <= UnitIcon_FlwTulip); - public static bool IsFlowerPicked(this ItemKind k) => k == Kind_Flower || (UnitIcon_FlwAnemone <= k && k <= UnitIcon_FlwTulip); - public static bool IsFlowerGene(this ItemKind k, ushort id) => k.IsFlower() && (id >= 60_000 || !k.IsFlowerPicked()); - public static bool IsClothing(this ItemKind k) => Clothing.Contains(k); - public static bool IsCrafting(this ItemKind k) => k == Kind_Ore || k == Kind_CraftMaterial || k == Kind_CraftPhoneCase || k == Kind_CraftRemake; - public static bool IsFurniture(this ItemKind k) => Furniture.Contains(k); + public bool IsFlower => k is >= Kind_Flower and <= Kind_FlowerBud or >= UnitIcon_FlwAnemone and <= UnitIcon_FlwTulip; + public bool IsFlowerPicked => k is Kind_Flower or >= UnitIcon_FlwAnemone and <= UnitIcon_FlwTulip; + public bool IsFlowerGene(ushort id) => k.IsFlower && (id >= 60_000 || !k.IsFlowerPicked); + public bool IsClothing => Clothing.Contains(k); + public bool IsCrafting => k is Kind_Ore or Kind_CraftMaterial or Kind_CraftPhoneCase or Kind_CraftRemake; + public bool IsFurniture => Furniture.Contains(k); } -} +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ItemMenuIconType.cs b/NHSE.Core/Structures/Item/ItemMenuIconType.cs index 966df66..33d116f 100644 --- a/NHSE.Core/Structures/Item/ItemMenuIconType.cs +++ b/NHSE.Core/Structures/Item/ItemMenuIconType.cs @@ -1,621 +1,620 @@ -namespace NHSE.Core -{ - /// - /// Menu icons (image shown in the inventory) of Items - /// - public enum ItemMenuIconType : ushort - { - Akoyagai, - Amaebi, - Anemone0, - Anemone1, - Anemone2, - Anemone3, - Anemone4, - Anemone5, - Apple, - AutumnLeaf, - Awabi, - Axe, - AxeDull, - BadKabu, - Bag, - Baigai, - Balloon, - BanbooShoot, - BasketHalloween, - BdayCupcake, - BellExchangeTicket, - BlowRollItem, - Book, - BookPlayer, - BookRecipe, - Boots, - BottleRecipe, - Bottoms, - Branch, - Bridge, - CameraAppPro, - Can, - Candy, - Candyfloss, - CannedDrink, - Cap, - Cardboard, - Carpet, - Carrot, - Cherry, - Chinanago, - Chitoseame, - ChristmasOrnamentA, - ChristmasOrnamentB, - ChristmasOrnamentC, - Cinder, - Coconut, - Coffee, - Coin, - Cosmos0, - Cosmos1, - Cosmos2, - Cosmos3, - Cosmos4, - Cosmos5, - Cracker, - Daiougusokumushi, - Dishes, - DIYAcorn, - DIYBamboo, - DIYBambooSpring, - DIYBranch, - DIYPinecone, - DIYRecipePlus, - DIYWoodHard, - DIYWoodNormal, - DIYWoodSoft, - Donut, - DreamBellExchangeTicket, - Drink, - Dumbbell, - DungenessCrab, - Duster, - EggFish, - EggForest, - EggGround, - EggLeaf, - EggRock, - EggSky, - FeatherBlu, - FeatherGrn, - FeatherPpl, - FeatherRainbow, - FeatherRed, - Fence, - Fish54, - FishAji, - FishAngelfish, - FishAntyobi, - FishArowana, - FishAyu, - FishBait, - FishBeta, - FishBlackbass, - FishBlueguill, - FishChouchinankou, - FishChouchouuo, - FishDemekin, - FishDemenigisu, - FishDojou, - FishDokutaafish, - FishDolado, - FishDonko, - FishEi, - FishEndorikerii, - FishFugu, - FishFuna, - FishGa, - FishGoldenTorauto, - FishGuppi, - FishHanahigeutubo, - FishHarisenbon, - FishHirame, - FishIka, - Fishingrod, - FishIshidai, - FishItou, - FishJinbeezame, - FishKaeru, - FishKajiki, - FishKamitsukigame, - FishKarei, - FishKingsalmon, - FishKingyo, - FishKobanzame, - FishKoi, - FishKumanomi, - FishKurione, - FishMaguro, - FishManbou, - FishMedaka, - FishMinokasago, - FishNamazu, - FishNanyouhagi, - FishNaporeonfish, - FishNeontetora, - FishNishikigoi, - FishNokogirizame, - FishOikawa, - FishOoiwana, - FishOtamajakusi, - FishPaiku, - FishPirania, - FishPiraruku, - FishRaigyo, - FishRainbowfish, - FishRouninaji, - FishRyuuguunotukai, - FishSake, - FishSame, - FishShiira, - FishShumokuzame, - FishSirakansu, - FishSuppon, - FishSuzuki, - FishSyanhaigani, - FishTai, - FishTanago, - FishTatsunootoshigo, - FishThirapia, - FishTyouzame, - FishUgui, - FishUtsubo, - FishWakasagi, - FishYamame, - FishYellowparch, - FishZarigani, - FixedLadder, - Floor, - Flour, - FlourSugarbrown, - FlourWheatwhole, - Flowershower, - Fossil, - FossilJ, - Foxtail, - FtrFishRanchu, - FtrInsectTagame, - Fujitsubo, - GAxe, - Gazami, - GFishingrod, - Glasses, - GlowStick, - GNet, - GoldenRose, - GPachinko, - Gscoop, - GWatering, - Hanabi, - HandBag, - Haniwa, - HaniwaPiece, - Helmet, - Hiramushi, - Hitode, - Honeycomb, - Hotaruika, - Hotate, - HowtoBookExpansion, - HowtoBookHair, - Hoya, - Hyacinth0, - Hyacinth1, - Hyacinth2, - Hyacinth3, - Hyacinth4, - Hyacinth5, - Hyacinth6, - Icecandy, - IceCream, - InsAburazemi, - InsAgehacho, - InsAkaeri, - InsAkiakane, - InsAmenbo, - InsAosuji, - InsArekisandora, - InsAri, - InsBaiorinmushi, - InsDangomushi, - InsFunamushi, - InsFunkorogashi, - InsGa, - InsGengorou, - InsGinyanma, - InsGirafanokogiri, - InsGomadarakamikiri, - InsGoraiasu, - InsHachi, - InsHae, - InsHanakamakiri, - InsHanmyou, - InsHerakuresu, - InsHigurashi, - InsHosoakakuwagata, - InsHotaru, - InsHousekizoumushi, - InsInago, - InsJinmenkamemushi, - InsKa, - InsKabutomushi, - InsKamakiri, - InsKamemushi, - InsKanabun, - InsKarasuageha, - InsKatatsumuri, - InsKirigirisu, - InsKohkasasu, - InsKohrogi, - InsKonohamushi, - InsKumazemi, - InsKumo, - InsMiirotateha, - InsMinminzemi, - InsMinomushi, - InsMitsubachi, - InsMiyamakuwagata, - InsMonkicho, - InsMonshirocho, - InsMorufuocho, - InsMukade, - InsNanafushi, - InsNijiirokuwagata, - InsNishikiohtsu, - InsNokogirikuwagata, - InsNomi, - InsOhgomamadara, - InsOhkabamadara, - InsOhkuwagata, - InsOhmurasaki, - InsOhsenchikogane, - InsOkera, - InsOniyanma, - InsOugononikuwa, - InsPurachinakogane, - InsRuriboshikamikiri, - InsSasori, - InsSeminonukegara, - InsShoryobatta, - InsSuzumushi, - InsTamamushi, - InsTaranchura, - InsTentoumushi, - InsTonosamabatta, - InsTsukutsuku, - InsYadokari, - InsYonagunisan, - InsZoukabuto, - Iseebi, - Isogintyaku, - Itotonbo, - JohnnyQuestDust1, - JohnyParts, - JuiceShamrock, - Kabu, - Kabutogani, - Kairoudouketsu, - Kaki, - Koumoridako, - Kurumaebi, - Lantern, - Leaf, - LifeSupport, - Lollipop, - LostQuestMemo, - Love, - Magazine, - MaracasCarnival, - Medicine, - Megaphone, - Mendako, - MessageBottleEgg, - Mizukurage, - MoneyBag010, - MoneyBag039, - MoneyBag069, - Muhrugai, - Mum0, - Mum1, - Mum2, - Mum3, - Mum4, - Mum5, - Mush0, - Mush1, - Mush2, - Mush3, - Mush4, - Music, - MyDesignPro, - Namako, - Net, - Ocarina, - Onepiece, - OneroomCardboard, - Orange, - OreClay, - OreGold, - OreIron, - OreStone, - OtoshidamaOpenCh, - OtoshidamaOpenJp, - OtoshidamaOpenKr, - OtoshidamaSealCh, - OtoshidamaSealJp, - OtoshidamaSealKr, - Oumugai, - Pachinko, - Paipuuni, - Panflute, - Pansi0, - Pansi1, - Pansi2, - Pansi3, - Pansi4, - Pansi5, - PaperRecipe, - Peach, - Pear, - Pearl, - PirateQuest, - PlaneTicket, - PltAnemone0, - PltAnemone1, - PltAnemone2, - PltAnemone3, - PltAnemone4, - PltAnemone5, - PltApple, - PltAzaleaPink, - PltAzaleaWhite, - PltBamboo, - PltBushCamelliaPink, - PltBushCamelliaRed, - PltBushOsmathusOrange, - PltBushOsmathusYellow, - PltBushPlumeriaPink, - PltBushPlumeriaWhite, - PltCarrot, - PltCherry, - PltConifer, - PltCosmos0, - PltCosmos1, - PltCosmos2, - PltCosmos3, - PltCosmos4, - PltCosmos5, - PltGoldenRose, - PltHibiscusRed, - PltHibiscusYellow, - PltHolly, - PltHyacinth0, - PltHyacinth1, - PltHyacinth2, - PltHyacinth3, - PltHyacinth4, - PltHyacinth5, - PltHyacinth6, - PltHydrangeaBlue, - PltHydrangeaPink, - PltMoney, - PltMum0, - PltMum1, - PltMum2, - PltMum3, - PltMum4, - PltMum5, - PltOak, - PltOrange, - PltPalm, - PltPansi0, - PltPansi1, - PltPansi2, - PltPansi3, - PltPansi4, - PltPansi5, - PltPeach, - PltPear, - PltPotato, - PltRose0, - PltRose1, - PltRose2, - PltRose3, - PltRose4, - PltRose5, - PltRose6, - PltRose7, - PltSquashGreen, - PltSquashOrange, - PltSquashWhite, - PltSquashYellow, - PltSugarCane, - PltSuzuran, - PltTomato, - PltTurip0, - PltTurip1, - PltTurip2, - PltTurip3, - PltTurip4, - PltTurip5, - PltTurip6, - PltVine, - PltWeedLight, - PltWheat, - PltYuri0, - PltYuri1, - PltYuri2, - PltYuri3, - PltYuri4, - PltYuri5, - Porch, - Post, - Potato, - Present, - Present2, - Protein, - PutHanabi, - RemakeKit, - RollanTicket, - Rose0, - Rose1, - Rose2, - Rose3, - Rose4, - Rose5, - Rose6, - Rose7, - Sakurapetal, - SantaSack, - Sazae, - Scoop, - Seedling, - SeedlingBush, - SeedlingConifer, - SeedlingVegetable, - SeedPaperbag0, - SeedPaperbag1, - SeedPaperbag2, - SeedPaperbag3, - SeedPitfall, - Senjunamako, - Sensu, - Shako, - Shakogai, - Shell1, - Shell2, - Shell3, - Shell4, - Shell6, - Shell7, - Shell8, - ShellFIshAsari, - ShellSummer, - Shoes, - Slope, - SmartphoneCase, - SmartphoneCaseComp, - SmartphoneCaseOtg, - SnowCrystal, - SnowCrystalLarge, - Socks, - SoftCream, - SouvenirChocolate, - Soy, - SparklingSoda, - SquashGreen, - SquashOrange, - SquashWhite, - SquashYellow, - StarPiece, - StarpieceAquarius, - StarpieceAries, - StarpieceCancer, - StarpieceCapricornus, - StarpieceGemini, - StarpieceLeo, - StarpieceLibra, - StarpiecePisces, - StarPieceRare, - StarpieceSagittarius, - StarpieceScorpio, - StarpieceTaurus, - StarpieceVirgo, - Sugar, - SugarCane, - Syabon, - TailorTicket, - Takaashigani, - Tako, - Tambourine, - Tapioca, - Tarabagani, - Tent, - TentWhite, - Timer, - Tire, - Tomato, - ToolChangeStick, - ToolCliffMaker, - ToolGroundMaker, - ToolLadder, - ToolPennantRcm, - ToolRiverJump, - ToolRiverMaker, - Tops, - Turip0, - Turip1, - Turip2, - Turip3, - Turip4, - Turip5, - Turip6, - Uchiwa, - Umbrella, - Umibudou, - Umiushi, - Uni, - Wakame, - Wall, - WallHighSeries, - Watering, - WBagBlack, - WBagBlue, - WBagBrown, - WBagGary, - WBagGold, - WBagGreen, - WBagLightBlue, - WBagLightGreen, - WBagMint, - WBagNavy, - WBagOrange, - WBagOrnament, - WBagPink, - WBagPurple, - WBagRed, - WBagWhite, - WBagYellow, - Weed, - WetSuit, - Wheat, - Wig, - Windmill, - WPaperBlack, - WPaperBlue, - WPaperBrown, - WPaperGold, - WPaperGray, - WPaperGreen, - WPaperLightBlue, - WPaperLightGreen, - WPaperMint, - WPaperNavy, - WPaperOrange, - WPaperOrnament, - WPaperPink, - WPaperPurple, - WPaperRed, - WPaperWhite, - WPaperYellow, - YellowPaperBag, - Yuri0, - Yuri1, - Yuri2, - Yuri3, - Yuri4, - Yuri5, - YutaroWisp, - Zuwaigani, +namespace NHSE.Core; - Unknown = ushort.MaxValue, - } -} +/// +/// Menu icons (image shown in the inventory) of Items +/// +public enum ItemMenuIconType : ushort +{ + Akoyagai, + Amaebi, + Anemone0, + Anemone1, + Anemone2, + Anemone3, + Anemone4, + Anemone5, + Apple, + AutumnLeaf, + Awabi, + Axe, + AxeDull, + BadKabu, + Bag, + Baigai, + Balloon, + BanbooShoot, + BasketHalloween, + BdayCupcake, + BellExchangeTicket, + BlowRollItem, + Book, + BookPlayer, + BookRecipe, + Boots, + BottleRecipe, + Bottoms, + Branch, + Bridge, + CameraAppPro, + Can, + Candy, + Candyfloss, + CannedDrink, + Cap, + Cardboard, + Carpet, + Carrot, + Cherry, + Chinanago, + Chitoseame, + ChristmasOrnamentA, + ChristmasOrnamentB, + ChristmasOrnamentC, + Cinder, + Coconut, + Coffee, + Coin, + Cosmos0, + Cosmos1, + Cosmos2, + Cosmos3, + Cosmos4, + Cosmos5, + Cracker, + Daiougusokumushi, + Dishes, + DIYAcorn, + DIYBamboo, + DIYBambooSpring, + DIYBranch, + DIYPinecone, + DIYRecipePlus, + DIYWoodHard, + DIYWoodNormal, + DIYWoodSoft, + Donut, + DreamBellExchangeTicket, + Drink, + Dumbbell, + DungenessCrab, + Duster, + EggFish, + EggForest, + EggGround, + EggLeaf, + EggRock, + EggSky, + FeatherBlu, + FeatherGrn, + FeatherPpl, + FeatherRainbow, + FeatherRed, + Fence, + Fish54, + FishAji, + FishAngelfish, + FishAntyobi, + FishArowana, + FishAyu, + FishBait, + FishBeta, + FishBlackbass, + FishBlueguill, + FishChouchinankou, + FishChouchouuo, + FishDemekin, + FishDemenigisu, + FishDojou, + FishDokutaafish, + FishDolado, + FishDonko, + FishEi, + FishEndorikerii, + FishFugu, + FishFuna, + FishGa, + FishGoldenTorauto, + FishGuppi, + FishHanahigeutubo, + FishHarisenbon, + FishHirame, + FishIka, + Fishingrod, + FishIshidai, + FishItou, + FishJinbeezame, + FishKaeru, + FishKajiki, + FishKamitsukigame, + FishKarei, + FishKingsalmon, + FishKingyo, + FishKobanzame, + FishKoi, + FishKumanomi, + FishKurione, + FishMaguro, + FishManbou, + FishMedaka, + FishMinokasago, + FishNamazu, + FishNanyouhagi, + FishNaporeonfish, + FishNeontetora, + FishNishikigoi, + FishNokogirizame, + FishOikawa, + FishOoiwana, + FishOtamajakusi, + FishPaiku, + FishPirania, + FishPiraruku, + FishRaigyo, + FishRainbowfish, + FishRouninaji, + FishRyuuguunotukai, + FishSake, + FishSame, + FishShiira, + FishShumokuzame, + FishSirakansu, + FishSuppon, + FishSuzuki, + FishSyanhaigani, + FishTai, + FishTanago, + FishTatsunootoshigo, + FishThirapia, + FishTyouzame, + FishUgui, + FishUtsubo, + FishWakasagi, + FishYamame, + FishYellowparch, + FishZarigani, + FixedLadder, + Floor, + Flour, + FlourSugarbrown, + FlourWheatwhole, + Flowershower, + Fossil, + FossilJ, + Foxtail, + FtrFishRanchu, + FtrInsectTagame, + Fujitsubo, + GAxe, + Gazami, + GFishingrod, + Glasses, + GlowStick, + GNet, + GoldenRose, + GPachinko, + Gscoop, + GWatering, + Hanabi, + HandBag, + Haniwa, + HaniwaPiece, + Helmet, + Hiramushi, + Hitode, + Honeycomb, + Hotaruika, + Hotate, + HowtoBookExpansion, + HowtoBookHair, + Hoya, + Hyacinth0, + Hyacinth1, + Hyacinth2, + Hyacinth3, + Hyacinth4, + Hyacinth5, + Hyacinth6, + Icecandy, + IceCream, + InsAburazemi, + InsAgehacho, + InsAkaeri, + InsAkiakane, + InsAmenbo, + InsAosuji, + InsArekisandora, + InsAri, + InsBaiorinmushi, + InsDangomushi, + InsFunamushi, + InsFunkorogashi, + InsGa, + InsGengorou, + InsGinyanma, + InsGirafanokogiri, + InsGomadarakamikiri, + InsGoraiasu, + InsHachi, + InsHae, + InsHanakamakiri, + InsHanmyou, + InsHerakuresu, + InsHigurashi, + InsHosoakakuwagata, + InsHotaru, + InsHousekizoumushi, + InsInago, + InsJinmenkamemushi, + InsKa, + InsKabutomushi, + InsKamakiri, + InsKamemushi, + InsKanabun, + InsKarasuageha, + InsKatatsumuri, + InsKirigirisu, + InsKohkasasu, + InsKohrogi, + InsKonohamushi, + InsKumazemi, + InsKumo, + InsMiirotateha, + InsMinminzemi, + InsMinomushi, + InsMitsubachi, + InsMiyamakuwagata, + InsMonkicho, + InsMonshirocho, + InsMorufuocho, + InsMukade, + InsNanafushi, + InsNijiirokuwagata, + InsNishikiohtsu, + InsNokogirikuwagata, + InsNomi, + InsOhgomamadara, + InsOhkabamadara, + InsOhkuwagata, + InsOhmurasaki, + InsOhsenchikogane, + InsOkera, + InsOniyanma, + InsOugononikuwa, + InsPurachinakogane, + InsRuriboshikamikiri, + InsSasori, + InsSeminonukegara, + InsShoryobatta, + InsSuzumushi, + InsTamamushi, + InsTaranchura, + InsTentoumushi, + InsTonosamabatta, + InsTsukutsuku, + InsYadokari, + InsYonagunisan, + InsZoukabuto, + Iseebi, + Isogintyaku, + Itotonbo, + JohnnyQuestDust1, + JohnyParts, + JuiceShamrock, + Kabu, + Kabutogani, + Kairoudouketsu, + Kaki, + Koumoridako, + Kurumaebi, + Lantern, + Leaf, + LifeSupport, + Lollipop, + LostQuestMemo, + Love, + Magazine, + MaracasCarnival, + Medicine, + Megaphone, + Mendako, + MessageBottleEgg, + Mizukurage, + MoneyBag010, + MoneyBag039, + MoneyBag069, + Muhrugai, + Mum0, + Mum1, + Mum2, + Mum3, + Mum4, + Mum5, + Mush0, + Mush1, + Mush2, + Mush3, + Mush4, + Music, + MyDesignPro, + Namako, + Net, + Ocarina, + Onepiece, + OneroomCardboard, + Orange, + OreClay, + OreGold, + OreIron, + OreStone, + OtoshidamaOpenCh, + OtoshidamaOpenJp, + OtoshidamaOpenKr, + OtoshidamaSealCh, + OtoshidamaSealJp, + OtoshidamaSealKr, + Oumugai, + Pachinko, + Paipuuni, + Panflute, + Pansi0, + Pansi1, + Pansi2, + Pansi3, + Pansi4, + Pansi5, + PaperRecipe, + Peach, + Pear, + Pearl, + PirateQuest, + PlaneTicket, + PltAnemone0, + PltAnemone1, + PltAnemone2, + PltAnemone3, + PltAnemone4, + PltAnemone5, + PltApple, + PltAzaleaPink, + PltAzaleaWhite, + PltBamboo, + PltBushCamelliaPink, + PltBushCamelliaRed, + PltBushOsmathusOrange, + PltBushOsmathusYellow, + PltBushPlumeriaPink, + PltBushPlumeriaWhite, + PltCarrot, + PltCherry, + PltConifer, + PltCosmos0, + PltCosmos1, + PltCosmos2, + PltCosmos3, + PltCosmos4, + PltCosmos5, + PltGoldenRose, + PltHibiscusRed, + PltHibiscusYellow, + PltHolly, + PltHyacinth0, + PltHyacinth1, + PltHyacinth2, + PltHyacinth3, + PltHyacinth4, + PltHyacinth5, + PltHyacinth6, + PltHydrangeaBlue, + PltHydrangeaPink, + PltMoney, + PltMum0, + PltMum1, + PltMum2, + PltMum3, + PltMum4, + PltMum5, + PltOak, + PltOrange, + PltPalm, + PltPansi0, + PltPansi1, + PltPansi2, + PltPansi3, + PltPansi4, + PltPansi5, + PltPeach, + PltPear, + PltPotato, + PltRose0, + PltRose1, + PltRose2, + PltRose3, + PltRose4, + PltRose5, + PltRose6, + PltRose7, + PltSquashGreen, + PltSquashOrange, + PltSquashWhite, + PltSquashYellow, + PltSugarCane, + PltSuzuran, + PltTomato, + PltTurip0, + PltTurip1, + PltTurip2, + PltTurip3, + PltTurip4, + PltTurip5, + PltTurip6, + PltVine, + PltWeedLight, + PltWheat, + PltYuri0, + PltYuri1, + PltYuri2, + PltYuri3, + PltYuri4, + PltYuri5, + Porch, + Post, + Potato, + Present, + Present2, + Protein, + PutHanabi, + RemakeKit, + RollanTicket, + Rose0, + Rose1, + Rose2, + Rose3, + Rose4, + Rose5, + Rose6, + Rose7, + Sakurapetal, + SantaSack, + Sazae, + Scoop, + Seedling, + SeedlingBush, + SeedlingConifer, + SeedlingVegetable, + SeedPaperbag0, + SeedPaperbag1, + SeedPaperbag2, + SeedPaperbag3, + SeedPitfall, + Senjunamako, + Sensu, + Shako, + Shakogai, + Shell1, + Shell2, + Shell3, + Shell4, + Shell6, + Shell7, + Shell8, + ShellFIshAsari, + ShellSummer, + Shoes, + Slope, + SmartphoneCase, + SmartphoneCaseComp, + SmartphoneCaseOtg, + SnowCrystal, + SnowCrystalLarge, + Socks, + SoftCream, + SouvenirChocolate, + Soy, + SparklingSoda, + SquashGreen, + SquashOrange, + SquashWhite, + SquashYellow, + StarPiece, + StarpieceAquarius, + StarpieceAries, + StarpieceCancer, + StarpieceCapricornus, + StarpieceGemini, + StarpieceLeo, + StarpieceLibra, + StarpiecePisces, + StarPieceRare, + StarpieceSagittarius, + StarpieceScorpio, + StarpieceTaurus, + StarpieceVirgo, + Sugar, + SugarCane, + Syabon, + TailorTicket, + Takaashigani, + Tako, + Tambourine, + Tapioca, + Tarabagani, + Tent, + TentWhite, + Timer, + Tire, + Tomato, + ToolChangeStick, + ToolCliffMaker, + ToolGroundMaker, + ToolLadder, + ToolPennantRcm, + ToolRiverJump, + ToolRiverMaker, + Tops, + Turip0, + Turip1, + Turip2, + Turip3, + Turip4, + Turip5, + Turip6, + Uchiwa, + Umbrella, + Umibudou, + Umiushi, + Uni, + Wakame, + Wall, + WallHighSeries, + Watering, + WBagBlack, + WBagBlue, + WBagBrown, + WBagGary, + WBagGold, + WBagGreen, + WBagLightBlue, + WBagLightGreen, + WBagMint, + WBagNavy, + WBagOrange, + WBagOrnament, + WBagPink, + WBagPurple, + WBagRed, + WBagWhite, + WBagYellow, + Weed, + WetSuit, + Wheat, + Wig, + Windmill, + WPaperBlack, + WPaperBlue, + WPaperBrown, + WPaperGold, + WPaperGray, + WPaperGreen, + WPaperLightBlue, + WPaperLightGreen, + WPaperMint, + WPaperNavy, + WPaperOrange, + WPaperOrnament, + WPaperPink, + WPaperPurple, + WPaperRed, + WPaperWhite, + WPaperYellow, + YellowPaperBag, + Yuri0, + Yuri1, + Yuri2, + Yuri3, + Yuri4, + Yuri5, + YutaroWisp, + Zuwaigani, + + Unknown = ushort.MaxValue, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ItemSize.cs b/NHSE.Core/Structures/Item/ItemSize.cs index 4ad0f4f..2b7e319 100644 --- a/NHSE.Core/Structures/Item/ItemSize.cs +++ b/NHSE.Core/Structures/Item/ItemSize.cs @@ -1,56 +1,49 @@ using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Detail about an item's dimensions +/// +public readonly record struct ItemSize(int Width, int Height); + +public static class ItemSizeExtensions { - /// - /// Detail about an item's dimensions - /// - public class ItemSize + public const string EnumPrefix = "S_"; + + private static readonly Dictionary Dictionary = new() { - public readonly int Width; - public readonly int Height; + {ItemSizeType.S_1_0x1_0 , new ItemSize( 2, 2)}, // 1x1 + {ItemSizeType.S_2_0x1_0 , new ItemSize( 4, 2)}, // 2x1 + {ItemSizeType.S_2_0x2_0 , new ItemSize( 4, 4)}, // 2x2 + {ItemSizeType.S_3_0x1_0 , new ItemSize( 6, 2)}, // 3x1 + {ItemSizeType.S_3_0x2_0 , new ItemSize( 6, 4)}, // 3x2 + {ItemSizeType.S_3_0x3_0 , new ItemSize( 6, 6)}, // 3x3 + {ItemSizeType.S_1_0x0_5 , new ItemSize( 2, 1)}, // 1x0.5 + {ItemSizeType.S_2_0x0_5 , new ItemSize( 4, 1)}, // 2x0.5 + {ItemSizeType.S_1_5x1_5 , new ItemSize( 3, 3)}, // 1.5x1.5 + {ItemSizeType.S_1_0x0_5_Wall, new ItemSize( 2, 1)}, // 1x0.5(壁) + {ItemSizeType.S_0_5x1_0_Wall, new ItemSize( 1, 2)}, // 0.5x1(壁) + {ItemSizeType.S_1_0x1_0_Wall, new ItemSize( 2, 2)}, // 1x1(壁) + {ItemSizeType.S_1_0x1_5_Wall, new ItemSize( 2, 3)}, // 1x1.5 (壁) + {ItemSizeType.S_1_0x2_0_Wall, new ItemSize( 2, 4)}, // 1x2  (壁) + {ItemSizeType.S_2_0x1_0_Wall, new ItemSize( 4, 2)}, // 2x1(壁) + {ItemSizeType.S_2_0x1_5_Wall, new ItemSize( 4, 3)}, // 2x1.5 (壁) + {ItemSizeType.S_2_0x2_0_Wall, new ItemSize( 4, 4)}, // 2x2(壁) + {ItemSizeType.S_1_0x1_0_Rug , new ItemSize( 2, 2)}, // 1x1(ラグ) + {ItemSizeType.S_2_0x1_0_Rug , new ItemSize( 4, 2)}, // 2x1(ラグ) + {ItemSizeType.S_2_0x2_0_Rug , new ItemSize( 4, 4)}, // 2x2(ラグ) + {ItemSizeType.S_3_0x2_0_Rug , new ItemSize( 6, 4)}, // 3x2(ラグ) + {ItemSizeType.S_3_0x3_0_Rug , new ItemSize( 6, 6)}, // 3x3(ラグ) + {ItemSizeType.S_4_0x3_0_Rug , new ItemSize( 8, 6)}, // 4x3(ラグ) + {ItemSizeType.S_4_0x4_0_Rug , new ItemSize( 8, 8)}, // 4x4(ラグ) + {ItemSizeType.S_5_0x4_0_Rug , new ItemSize(10, 8)}, // 5x4(ラグ) + {ItemSizeType.S_5_0x5_0_Rug , new ItemSize(10, 10)}, // 5x5(ラグ) + }; - public ItemSize(int w, int h) - { - Width = w; Height = h; - } - } - - public static class ItemSizeExtensions + extension(ItemSizeType s) { - public const string EnumPrefix = "S_"; - - private static readonly Dictionary Dictionary = new() - { - {ItemSizeType.S_1_0x1_0 , new ItemSize( 2, 2)}, // 1x1 - {ItemSizeType.S_2_0x1_0 , new ItemSize( 4, 2)}, // 2x1 - {ItemSizeType.S_2_0x2_0 , new ItemSize( 4, 4)}, // 2x2 - {ItemSizeType.S_3_0x1_0 , new ItemSize( 6, 2)}, // 3x1 - {ItemSizeType.S_3_0x2_0 , new ItemSize( 6, 4)}, // 3x2 - {ItemSizeType.S_3_0x3_0 , new ItemSize( 6, 6)}, // 3x3 - {ItemSizeType.S_1_0x0_5 , new ItemSize( 2, 1)}, // 1x0.5 - {ItemSizeType.S_2_0x0_5 , new ItemSize( 4, 1)}, // 2x0.5 - {ItemSizeType.S_1_5x1_5 , new ItemSize( 3, 3)}, // 1.5x1.5 - {ItemSizeType.S_1_0x0_5_Wall, new ItemSize( 2, 1)}, // 1x0.5(壁) - {ItemSizeType.S_0_5x1_0_Wall, new ItemSize( 1, 2)}, // 0.5x1(壁) - {ItemSizeType.S_1_0x1_0_Wall, new ItemSize( 2, 2)}, // 1x1(壁) - {ItemSizeType.S_1_0x1_5_Wall, new ItemSize( 2, 3)}, // 1x1.5 (壁) - {ItemSizeType.S_1_0x2_0_Wall, new ItemSize( 2, 4)}, // 1x2  (壁) - {ItemSizeType.S_2_0x1_0_Wall, new ItemSize( 4, 2)}, // 2x1(壁) - {ItemSizeType.S_2_0x1_5_Wall, new ItemSize( 4, 3)}, // 2x1.5 (壁) - {ItemSizeType.S_2_0x2_0_Wall, new ItemSize( 4, 4)}, // 2x2(壁) - {ItemSizeType.S_1_0x1_0_Rug , new ItemSize( 2, 2)}, // 1x1(ラグ) - {ItemSizeType.S_2_0x1_0_Rug , new ItemSize( 4, 2)}, // 2x1(ラグ) - {ItemSizeType.S_2_0x2_0_Rug , new ItemSize( 4, 4)}, // 2x2(ラグ) - {ItemSizeType.S_3_0x2_0_Rug , new ItemSize( 6, 4)}, // 3x2(ラグ) - {ItemSizeType.S_3_0x3_0_Rug , new ItemSize( 6, 6)}, // 3x3(ラグ) - {ItemSizeType.S_4_0x3_0_Rug , new ItemSize( 8, 6)}, // 4x3(ラグ) - {ItemSizeType.S_4_0x4_0_Rug , new ItemSize( 8, 8)}, // 4x4(ラグ) - {ItemSizeType.S_5_0x4_0_Rug , new ItemSize(10, 8)}, // 5x4(ラグ) - {ItemSizeType.S_5_0x5_0_Rug , new ItemSize(10, 10)}, // 5x5(ラグ) - }; - - public static int GetWidth(this ItemSizeType s) => Dictionary.TryGetValue(s, out var val) ? val.Width : 2; - public static int GetHeight(this ItemSizeType s) => Dictionary.TryGetValue(s, out var val) ? val.Height : 2; + public int Width => Dictionary.TryGetValue(s, out var val) ? val.Width : 2; + public int Height => Dictionary.TryGetValue(s, out var val) ? val.Height : 2; } -} +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ItemSizeType.cs b/NHSE.Core/Structures/Item/ItemSizeType.cs index 99a32a0..8657d38 100644 --- a/NHSE.Core/Structures/Item/ItemSizeType.cs +++ b/NHSE.Core/Structures/Item/ItemSizeType.cs @@ -1,38 +1,37 @@ -namespace NHSE.Core -{ - /// - /// Sizes of Items - /// - public enum ItemSizeType : byte - { - S_0_5x1_0_Wall, - S_0x2B28C88F, - S_1_0x0_5, - S_1_0x0_5_Wall, - S_1_0x1_0, - S_1_0x1_0_Rug, - S_1_0x1_0_Wall, - S_1_0x1_5_Wall, - S_1_0x2_0_Wall, - S_1_5x1_5, - S_2_0x0_5, - S_2_0x1_0, - S_2_0x1_0_Rug, - S_2_0x1_0_Wall, - S_2_0x1_5_Wall, - S_2_0x2_0, - S_2_0x2_0_Rug, - S_2_0x2_0_Wall, - S_3_0x1_0, - S_3_0x2_0, - S_3_0x2_0_Rug, - S_3_0x3_0, - S_3_0x3_0_Rug, - S_4_0x3_0_Rug, - S_4_0x4_0_Rug, - S_5_0x5_0_Rug, +namespace NHSE.Core; - S_5_0x4_0_Rug, // not used by any items; manually added since it's in ItemSize - Unknown = byte.MaxValue, - } -} +/// +/// Sizes of Items +/// +public enum ItemSizeType : byte +{ + S_0_5x1_0_Wall, + S_0x2B28C88F, + S_1_0x0_5, + S_1_0x0_5_Wall, + S_1_0x1_0, + S_1_0x1_0_Rug, + S_1_0x1_0_Wall, + S_1_0x1_5_Wall, + S_1_0x2_0_Wall, + S_1_5x1_5, + S_2_0x0_5, + S_2_0x1_0, + S_2_0x1_0_Rug, + S_2_0x1_0_Wall, + S_2_0x1_5_Wall, + S_2_0x2_0, + S_2_0x2_0_Rug, + S_2_0x2_0_Wall, + S_3_0x1_0, + S_3_0x2_0, + S_3_0x2_0_Rug, + S_3_0x3_0, + S_3_0x3_0_Rug, + S_4_0x3_0_Rug, + S_4_0x4_0_Rug, + S_5_0x5_0_Rug, + + S_5_0x4_0_Rug, // not used by any items; manually added since it's in ItemSize + Unknown = byte.MaxValue, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ItemWrapping.cs b/NHSE.Core/Structures/Item/ItemWrapping.cs index c4b576f..ca0d877 100644 --- a/NHSE.Core/Structures/Item/ItemWrapping.cs +++ b/NHSE.Core/Structures/Item/ItemWrapping.cs @@ -1,16 +1,15 @@ -namespace NHSE.Core -{ - /// - /// Type of wrapping an has - /// - public enum ItemWrapping : byte - { - Nothing = 0, - WrappingPaper = 1, - Present = 2, - Delivery = 3, +namespace NHSE.Core; - // These values are handled with special logic. Only 2 bits are allocated to be stored. - Festive = 4, - } -} +/// +/// Type of wrapping an has +/// +public enum ItemWrapping : byte +{ + Nothing = 0, + WrappingPaper = 1, + Present = 2, + Delivery = 3, + + // These values are handled with special logic. Only 2 bits are allocated to be stored. + Festive = 4, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/ItemWrappingPaper.cs b/NHSE.Core/Structures/Item/ItemWrappingPaper.cs index 68e4dff..1e0a9f7 100644 --- a/NHSE.Core/Structures/Item/ItemWrappingPaper.cs +++ b/NHSE.Core/Structures/Item/ItemWrappingPaper.cs @@ -1,25 +1,24 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Color of wrapping paper when an has . +/// +public enum ItemWrappingPaper : byte { - /// - /// Color of wrapping paper when an has . - /// - public enum ItemWrappingPaper : byte - { - Yellow = 00, - Pink = 01, - Orange = 02, - LightGreen = 03, - Green = 04, - Mint = 05, - LightBlue = 06, - Purple = 07, - Navy = 08, - Blue = 09, - White = 10, - Red = 11, - Gold = 12, - Brown = 13, - Gray = 14, - Black = 15, - } + Yellow = 00, + Pink = 01, + Orange = 02, + LightGreen = 03, + Green = 04, + Mint = 05, + LightBlue = 06, + Purple = 07, + Navy = 08, + Blue = 09, + White = 10, + Red = 11, + Gold = 12, + Brown = 13, + Gray = 14, + Black = 15, } \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/Remake/ItemCustomColor.cs b/NHSE.Core/Structures/Item/Remake/ItemCustomColor.cs index a45088c..c5275b2 100644 --- a/NHSE.Core/Structures/Item/Remake/ItemCustomColor.cs +++ b/NHSE.Core/Structures/Item/Remake/ItemCustomColor.cs @@ -1,24 +1,23 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// General color that a customized item (of a specific value) has +/// +public enum ItemCustomColor : byte { - /// - /// General color that a customized item (of a specific value) has - /// - public enum ItemCustomColor : byte - { - Orange = 0, // オレンジ - Red = 1, // レッド - Pink = 2, // ピンク - Purple = 3, // パープル - Blue = 4, // ブルー - LightBlue = 5, // みずいろ - Green = 6, // グリーン - Yellow = 7, // イエロー - Beige = 8, // ベージュ - Brown = 9, // ブラウン - Black = 10, // ブラック - Gray = 11, // グレー - White = 12, // ホワイト - Colorful = 13, // カラフル - None = 14, // なし - } -} + Orange = 0, // オレンジ + Red = 1, // レッド + Pink = 2, // ピンク + Purple = 3, // パープル + Blue = 4, // ブルー + LightBlue = 5, // みずいろ + Green = 6, // グリーン + Yellow = 7, // イエロー + Beige = 8, // ベージュ + Brown = 9, // ブラウン + Black = 10, // ブラック + Gray = 11, // グレー + White = 12, // ホワイト + Colorful = 13, // カラフル + None = 14, // なし +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/Remake/ItemRemakeCommonPattern.cs b/NHSE.Core/Structures/Item/Remake/ItemRemakeCommonPattern.cs index b8a4112..507ac5c 100644 --- a/NHSE.Core/Structures/Item/Remake/ItemRemakeCommonPattern.cs +++ b/NHSE.Core/Structures/Item/Remake/ItemRemakeCommonPattern.cs @@ -1,222 +1,221 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Customization fabric used for an , sourced from the Able Sisters +/// +public enum ItemRemakeCommonPattern : byte { - /// - /// Customization fabric used for an , sourced from the Able Sisters - /// - public enum ItemRemakeCommonPattern : byte - { - DotSmall00 = 0, - DotSmall01 = 1, - DotSmall02 = 2, - DotSmall03 = 3, - DotMedium00 = 4, - DotMedium01 = 5, - DotMedium02 = 6, - DotMedium03 = 7, - DotStar00 = 8, - DotStar01 = 9, - DotStar02 = 10, - DotStar03 = 11, - DotRandom00 = 12, - DotRandom01 = 13, - DotRandom02 = 14, - DotRandom03 = 15, - DotBig00 = 16, - DotBig01 = 17, - DotBig02 = 18, - DotBig03 = 19, - StripeSingle00 = 20, - StripeSingle01 = 21, - StripeSingle02 = 22, - StripeSingle03 = 23, - StripeSixth00 = 24, - StripeSixth01 = 25, - StripeSixth02 = 26, - StripeSixth03 = 27, - StripeRainbow00 = 28, - StripeRainbow01 = 29, - StripeRainbow02 = 30, - StripeRainbow03 = 31, - BorderMulti00 = 32, - BorderMulti01 = 33, - StripeDiagonal00 = 34, - StripeDiagonal01 = 35, - StripeChevron00 = 36, - StripeChevron01 = 37, - StripeWave00 = 38, - StripeWave01 = 39, - CheckGingham00 = 40, - CheckGingham01 = 41, - CheckGingham02 = 42, - CheckGingham03 = 43, - CheckBuffalo00 = 44, - CheckBuffalo01 = 45, - CheckBuffalo02 = 46, - CheckBuffalo03 = 47, - CheckPunk00 = 48, - CheckPunk01 = 49, - CheckPunk02 = 50, - CheckPunk03 = 51, - CheckGraph00 = 52, - CheckGraph01 = 53, - CheckGraph02 = 54, - CheckGraph03 = 55, - CheckShirt00 = 56, - CheckShirt01 = 57, - CheckShirt02 = 58, - CheckShirt03 = 59, - CheckMadras00 = 60, - CheckMadras01 = 61, - CheckMadras02 = 62, - CheckMadras03 = 63, - CheckDiagonal00 = 64, - CheckDiagonal01 = 65, - CheckTartan00 = 66, - CheckTartan01 = 67, - Damond00 = 68, - Damond01 = 69, - Argyle00 = 70, - Argyle01 = 71, - CheckHouse00 = 72, - CheckHouse01 = 73, - CheckGunclub00 = 74, - CheckGunclub01 = 75, - CheckChidori00 = 76, - CheckChidori01 = 77, - CheckChidori02 = 78, - CheckChidori03 = 79, - Ya00 = 80, - Ya01 = 81, - Karakusa00 = 82, - Karakusa01 = 83, - Koume00 = 84, - Koume01 = 85, - Ume00 = 86, - Ume01 = 87, - China00 = 88, - China01 = 89, - Tonbo00 = 90, - Tonbo01 = 91, - Kamawanu00 = 92, - Kamawanu01 = 93, - Igeta00 = 94, - Igeta01 = 95, - Sashiko00 = 96, - Sashiko01 = 97, - Zyuzi00 = 98, - Zyuzi01 = 99, - Chimayo00 = 100, - Chimayo01 = 101, - Ginkgo00 = 102, - Ginkgo01 = 103, - Snow00 = 104, - Snow01 = 105, - Nordic00 = 106, - Nordic01 = 107, - Swirl00 = 108, - Swirl01 = 109, - Water00 = 110, - Water01 = 111, - Geometry00 = 112, - Geometry01 = 113, - Square00 = 114, - Square01 = 115, - Paisley00 = 116, - Paisley01 = 117, - Tropical00 = 118, - Tropical01 = 119, - LegendFlower00 = 120, - LegendFlower01 = 121, - Jasmine00 = 122, - Jasmine01 = 123, - RetroFlower00 = 124, - RetroFlower01 = 125, - ColorfulFlower00 = 126, - ColorfulFlower01 = 127, - Monogram00 = 128, - Monogram01 = 129, - Psyche00 = 130, - Psyche01 = 131, - Apple00 = 132, - Apple01 = 133, - Himawari00 = 134, - Himawari01 = 135, - Hiyoko00 = 136, - Hiyoko01 = 137, - Retro00 = 138, - Retro01 = 139, - Flower00 = 140, - Flower01 = 141, - Ameba00 = 142, - Ameba01 = 143, - Suzuran00 = 144, - Suzuran01 = 145, - Uroko00 = 146, - Uroko01 = 147, - Clover00 = 148, - Clover01 = 149, - House00 = 150, - House01 = 151, - Rose00 = 152, - Rose01 = 153, - Bird00 = 154, - Bird01 = 155, - Wood00 = 156, - Wood01 = 157, - Yacht00 = 158, - Yacht01 = 159, - Pizza00 = 160, - Pizza01 = 161, - Skull00 = 162, - Skull01 = 163, - Donut00 = 164, - Donut01 = 165, - Space00 = 166, - Space01 = 167, - Sushi00 = 168, - Sushi01 = 169, - Star00 = 170, - Star01 = 171, - Lightning00 = 172, - Lightning01 = 173, - Hibiscus00 = 174, - Hibiscus01 = 175, - Marine00 = 176, - Marine01 = 177, - Puzzle00 = 178, - Puzzle01 = 179, - Tile00 = 180, - Tile01 = 181, - Dazzle00 = 182, - Dazzle01 = 183, - Giraffe00 = 184, - Giraffe01 = 185, - Leopard00 = 186, - Leopard01 = 187, - Zebra00 = 188, - Zebra01 = 189, - Dalmatian00 = 190, - Dalmatian01 = 191, - Python00 = 192, - Python01 = 193, - Camo00 = 194, - Camo01 = 195, - Ganshizin00 = 196, - Ganshizin01 = 197, - Dancer00 = 198, - Dancer01 = 199, - } - - public static class ItemRemakeCommonPatternExtensions - { - // The game is nice and evenly has 20/category, in order. - private const int PatternsPerCategory = 20; - - public static ItemRemakeCommonPatternCategory GetCategory(this ItemRemakeCommonPattern p) - { - var val = (byte) p; - var category = val / PatternsPerCategory; - return (ItemRemakeCommonPatternCategory)category; - } - } + DotSmall00 = 0, + DotSmall01 = 1, + DotSmall02 = 2, + DotSmall03 = 3, + DotMedium00 = 4, + DotMedium01 = 5, + DotMedium02 = 6, + DotMedium03 = 7, + DotStar00 = 8, + DotStar01 = 9, + DotStar02 = 10, + DotStar03 = 11, + DotRandom00 = 12, + DotRandom01 = 13, + DotRandom02 = 14, + DotRandom03 = 15, + DotBig00 = 16, + DotBig01 = 17, + DotBig02 = 18, + DotBig03 = 19, + StripeSingle00 = 20, + StripeSingle01 = 21, + StripeSingle02 = 22, + StripeSingle03 = 23, + StripeSixth00 = 24, + StripeSixth01 = 25, + StripeSixth02 = 26, + StripeSixth03 = 27, + StripeRainbow00 = 28, + StripeRainbow01 = 29, + StripeRainbow02 = 30, + StripeRainbow03 = 31, + BorderMulti00 = 32, + BorderMulti01 = 33, + StripeDiagonal00 = 34, + StripeDiagonal01 = 35, + StripeChevron00 = 36, + StripeChevron01 = 37, + StripeWave00 = 38, + StripeWave01 = 39, + CheckGingham00 = 40, + CheckGingham01 = 41, + CheckGingham02 = 42, + CheckGingham03 = 43, + CheckBuffalo00 = 44, + CheckBuffalo01 = 45, + CheckBuffalo02 = 46, + CheckBuffalo03 = 47, + CheckPunk00 = 48, + CheckPunk01 = 49, + CheckPunk02 = 50, + CheckPunk03 = 51, + CheckGraph00 = 52, + CheckGraph01 = 53, + CheckGraph02 = 54, + CheckGraph03 = 55, + CheckShirt00 = 56, + CheckShirt01 = 57, + CheckShirt02 = 58, + CheckShirt03 = 59, + CheckMadras00 = 60, + CheckMadras01 = 61, + CheckMadras02 = 62, + CheckMadras03 = 63, + CheckDiagonal00 = 64, + CheckDiagonal01 = 65, + CheckTartan00 = 66, + CheckTartan01 = 67, + Damond00 = 68, + Damond01 = 69, + Argyle00 = 70, + Argyle01 = 71, + CheckHouse00 = 72, + CheckHouse01 = 73, + CheckGunclub00 = 74, + CheckGunclub01 = 75, + CheckChidori00 = 76, + CheckChidori01 = 77, + CheckChidori02 = 78, + CheckChidori03 = 79, + Ya00 = 80, + Ya01 = 81, + Karakusa00 = 82, + Karakusa01 = 83, + Koume00 = 84, + Koume01 = 85, + Ume00 = 86, + Ume01 = 87, + China00 = 88, + China01 = 89, + Tonbo00 = 90, + Tonbo01 = 91, + Kamawanu00 = 92, + Kamawanu01 = 93, + Igeta00 = 94, + Igeta01 = 95, + Sashiko00 = 96, + Sashiko01 = 97, + Zyuzi00 = 98, + Zyuzi01 = 99, + Chimayo00 = 100, + Chimayo01 = 101, + Ginkgo00 = 102, + Ginkgo01 = 103, + Snow00 = 104, + Snow01 = 105, + Nordic00 = 106, + Nordic01 = 107, + Swirl00 = 108, + Swirl01 = 109, + Water00 = 110, + Water01 = 111, + Geometry00 = 112, + Geometry01 = 113, + Square00 = 114, + Square01 = 115, + Paisley00 = 116, + Paisley01 = 117, + Tropical00 = 118, + Tropical01 = 119, + LegendFlower00 = 120, + LegendFlower01 = 121, + Jasmine00 = 122, + Jasmine01 = 123, + RetroFlower00 = 124, + RetroFlower01 = 125, + ColorfulFlower00 = 126, + ColorfulFlower01 = 127, + Monogram00 = 128, + Monogram01 = 129, + Psyche00 = 130, + Psyche01 = 131, + Apple00 = 132, + Apple01 = 133, + Himawari00 = 134, + Himawari01 = 135, + Hiyoko00 = 136, + Hiyoko01 = 137, + Retro00 = 138, + Retro01 = 139, + Flower00 = 140, + Flower01 = 141, + Ameba00 = 142, + Ameba01 = 143, + Suzuran00 = 144, + Suzuran01 = 145, + Uroko00 = 146, + Uroko01 = 147, + Clover00 = 148, + Clover01 = 149, + House00 = 150, + House01 = 151, + Rose00 = 152, + Rose01 = 153, + Bird00 = 154, + Bird01 = 155, + Wood00 = 156, + Wood01 = 157, + Yacht00 = 158, + Yacht01 = 159, + Pizza00 = 160, + Pizza01 = 161, + Skull00 = 162, + Skull01 = 163, + Donut00 = 164, + Donut01 = 165, + Space00 = 166, + Space01 = 167, + Sushi00 = 168, + Sushi01 = 169, + Star00 = 170, + Star01 = 171, + Lightning00 = 172, + Lightning01 = 173, + Hibiscus00 = 174, + Hibiscus01 = 175, + Marine00 = 176, + Marine01 = 177, + Puzzle00 = 178, + Puzzle01 = 179, + Tile00 = 180, + Tile01 = 181, + Dazzle00 = 182, + Dazzle01 = 183, + Giraffe00 = 184, + Giraffe01 = 185, + Leopard00 = 186, + Leopard01 = 187, + Zebra00 = 188, + Zebra01 = 189, + Dalmatian00 = 190, + Dalmatian01 = 191, + Python00 = 192, + Python01 = 193, + Camo00 = 194, + Camo01 = 195, + Ganshizin00 = 196, + Ganshizin01 = 197, + Dancer00 = 198, + Dancer01 = 199, } + +public static class ItemRemakeCommonPatternExtensions +{ + // The game is nice and evenly has 20/category, in order. + private const int PatternsPerCategory = 20; + + public static ItemRemakeCommonPatternCategory GetCategory(this ItemRemakeCommonPattern p) + { + var val = (byte) p; + var category = val / PatternsPerCategory; + return (ItemRemakeCommonPatternCategory)category; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/Remake/ItemRemakeCommonPatternCategory.cs b/NHSE.Core/Structures/Item/Remake/ItemRemakeCommonPatternCategory.cs index 859a7d7..5d0d28e 100644 --- a/NHSE.Core/Structures/Item/Remake/ItemRemakeCommonPatternCategory.cs +++ b/NHSE.Core/Structures/Item/Remake/ItemRemakeCommonPatternCategory.cs @@ -1,20 +1,19 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Category of +/// +public enum ItemRemakeCommonPatternCategory : byte { - /// - /// Category of - /// - public enum ItemRemakeCommonPatternCategory : byte - { - None = 0, - Dot = 1, - Stripe = 2, - CheckA = 3, - CheckB = 4, - TraditionalA = 5, - TraditionalB = 6, - Retro = 7, - Natural = 8, - Toy = 9, - Cool = 10, - } -} + None = 0, + Dot = 1, + Stripe = 2, + CheckA = 3, + CheckB = 4, + TraditionalA = 5, + TraditionalB = 6, + Retro = 7, + Natural = 8, + Toy = 9, + Cool = 10, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/Remake/ItemRemakeDesignSource.cs b/NHSE.Core/Structures/Item/Remake/ItemRemakeDesignSource.cs index 4bab7be..19b08d5 100644 --- a/NHSE.Core/Structures/Item/Remake/ItemRemakeDesignSource.cs +++ b/NHSE.Core/Structures/Item/Remake/ItemRemakeDesignSource.cs @@ -1,16 +1,15 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Determines how an item's secondary customization value is used. +/// +[Flags] +public enum ItemRemakeDesignSource { - /// - /// Determines how an item's secondary customization value is used. - /// - [Flags] - public enum ItemRemakeDesignSource - { - None = 0, - Common = 1, - MyDesign = 2, - CommonAndMyDesign = Common | MyDesign, - } -} + None = 0, + Common = 1, + MyDesign = 2, + CommonAndMyDesign = Common | MyDesign, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/Remake/ItemRemakeInfo.cs b/NHSE.Core/Structures/Item/Remake/ItemRemakeInfo.cs index 7047a4e..06da87a 100644 --- a/NHSE.Core/Structures/Item/Remake/ItemRemakeInfo.cs +++ b/NHSE.Core/Structures/Item/Remake/ItemRemakeInfo.cs @@ -1,143 +1,142 @@ using System.Text; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Metadata for an item's customization permissions +/// +public class ItemRemakeInfo { - /// - /// Metadata for an item's customization permissions - /// - public class ItemRemakeInfo + public const int BodyColorCountMax = 8; + public const int NoColor = (int)ItemCustomColor.None; // 14 + + public readonly short Index; + public readonly ushort ItemUniqueID; + public readonly sbyte ReBodyPatternNum; // count of body colors + + public readonly byte[] ReBodyPatternColors0; + public readonly byte[] ReBodyPatternColors1; + + public readonly byte[] ReFabricPatternColors0; + public readonly byte[] ReFabricPatternColors1; + + public readonly bool ReFabricPattern0VisibleOff; + + public ItemRemakeInfo(short index, ushort id, sbyte count, byte[] bc0, byte[] bc1, byte[] fc0, byte[] fc1, bool fp0) { - public const int BodyColorCountMax = 8; - public const int NoColor = (int)ItemCustomColor.None; // 14 + Index = index; + ItemUniqueID = id; + ReBodyPatternNum = count; - public readonly short Index; - public readonly ushort ItemUniqueID; - public readonly sbyte ReBodyPatternNum; // count of body colors + ReBodyPatternColors0 = bc0; + ReBodyPatternColors1 = bc1; - public readonly byte[] ReBodyPatternColors0; - public readonly byte[] ReBodyPatternColors1; + ReFabricPatternColors0 = fc0; + ReFabricPatternColors1 = fc1; - public readonly byte[] ReFabricPatternColors0; - public readonly byte[] ReFabricPatternColors1; - - public readonly bool ReFabricPattern0VisibleOff; - - public ItemRemakeInfo(short index, ushort id, sbyte count, byte[] bc0, byte[] bc1, byte[] fc0, byte[] fc1, bool fp0) - { - Index = index; - ItemUniqueID = id; - ReBodyPatternNum = count; - - ReBodyPatternColors0 = bc0; - ReBodyPatternColors1 = bc1; - - ReFabricPatternColors0 = fc0; - ReFabricPatternColors1 = fc1; - - ReFabricPattern0VisibleOff = fp0; - } - - private const string Invalid = nameof(Invalid); - - public bool HasBodyColor(int variant) => ReBodyPatternColors0[variant] != NoColor || ReBodyPatternColors1[variant] != NoColor; - public bool HasFabricColor(int variant) => ReFabricPatternColors0[variant] != NoColor || ReFabricPatternColors1[variant] != NoColor; - - public string GetBodyDescription(int colorIndex, IRemakeString str) - { - if (str.BodyColor.TryGetValue($"{ItemUniqueID:00000}_{colorIndex}", out var color)) - return $"{color} ({GetBodyDescription(colorIndex)})"; - var c0 = ReBodyPatternColors0[colorIndex]; - var c1 = ReBodyPatternColors1[colorIndex]; - return GetColorText(c0, c1); - } - - public string GetFabricDescription(int colorIndex, IRemakeString str) - { - if (str.FabricColor.TryGetValue($"{ItemUniqueID:00000}_{colorIndex}", out var color)) - return $"{color} ({GetBodyDescription(colorIndex)})"; - var c0 = ReFabricPatternColors0[colorIndex]; - var c1 = ReFabricPatternColors1[colorIndex]; - return GetColorText(c0, c1); - } - - public string GetBodyDescription(int colorIndex) - { - var c0 = ReBodyPatternColors0[colorIndex]; - var c1 = ReBodyPatternColors1[colorIndex]; - return GetColorText(c0, c1); - } - - public string GetFabricDescription(int colorIndex) - { - var c0 = ReFabricPatternColors0[colorIndex]; - var c1 = ReFabricPatternColors1[colorIndex]; - return GetColorText(c0, c1); - } - - private static string GetColorText(byte c0, byte c1) - { - if (c0 == (byte) ItemCustomColor.None) - { - if (c1 == (byte) ItemCustomColor.None) - return Invalid; - return GetColorText(c1); - } - - var s0 = GetColorText(c0); - if (c1 == (byte) ItemCustomColor.None || c0 == c1) - return s0; - - var s1 = GetColorText(c1); - - return $"{s0}-{s1}"; - } - - private static string GetColorText(byte value) => ((ItemCustomColor)value).ToString(); - - public string GetBodySummary(IRemakeString str) - { - var sb = new StringBuilder(); - var item = $"{ItemUniqueID:00000}"; - if (str.BodyParts.TryGetValue(item, out var parts)) - sb.Append(parts).AppendLine(":"); - - for (int i = 0; i < 8; i++) - { - var cd = GetBodyDescription(i); - var name = $"{ItemUniqueID:00000}_{i}"; - var hasBody = str.BodyColor.TryGetValue(name, out var desc); - - if (hasBody && cd != Invalid) - sb.Append(i).Append('=').Append(desc).Append(" (").Append(cd).AppendLine(")"); - else if (hasBody) - sb.Append(i).Append('=').AppendLine(desc); - // else don't add anything - } - return sb.ToString(); - } - - public string GetFabricSummary(IRemakeString str) - { - var sb = new StringBuilder(); - var item = $"{ItemUniqueID:00000}"; - if (str.FabricParts.TryGetValue(item, out var parts)) - sb.Append(parts).AppendLine(":"); - - for (int i = 0; i < 8; i++) - { - var cd = GetFabricDescription(i); - if (cd == Invalid) - continue; - - var shifted = (i << 5); - sb.Append(shifted.ToString("000")).Append('='); - var name = $"{ItemUniqueID:00000}_{i}"; - if (str.FabricColor.TryGetValue(name, out var desc)) - sb.Append(desc).Append(" (").Append(cd).AppendLine(")"); - else - sb.AppendLine(cd); - } - return sb.ToString(); - } + ReFabricPattern0VisibleOff = fp0; } -} + + private const string Invalid = nameof(Invalid); + + public bool HasBodyColor(int variant) => ReBodyPatternColors0[variant] != NoColor || ReBodyPatternColors1[variant] != NoColor; + public bool HasFabricColor(int variant) => ReFabricPatternColors0[variant] != NoColor || ReFabricPatternColors1[variant] != NoColor; + + public string GetBodyDescription(int colorIndex, IRemakeString str) + { + if (str.BodyColor.TryGetValue($"{ItemUniqueID:00000}_{colorIndex}", out var color)) + return $"{color} ({GetBodyDescription(colorIndex)})"; + var c0 = ReBodyPatternColors0[colorIndex]; + var c1 = ReBodyPatternColors1[colorIndex]; + return GetColorText(c0, c1); + } + + public string GetFabricDescription(int colorIndex, IRemakeString str) + { + if (str.FabricColor.TryGetValue($"{ItemUniqueID:00000}_{colorIndex}", out var color)) + return $"{color} ({GetBodyDescription(colorIndex)})"; + var c0 = ReFabricPatternColors0[colorIndex]; + var c1 = ReFabricPatternColors1[colorIndex]; + return GetColorText(c0, c1); + } + + public string GetBodyDescription(int colorIndex) + { + var c0 = ReBodyPatternColors0[colorIndex]; + var c1 = ReBodyPatternColors1[colorIndex]; + return GetColorText(c0, c1); + } + + public string GetFabricDescription(int colorIndex) + { + var c0 = ReFabricPatternColors0[colorIndex]; + var c1 = ReFabricPatternColors1[colorIndex]; + return GetColorText(c0, c1); + } + + private static string GetColorText(byte c0, byte c1) + { + if (c0 == (byte) ItemCustomColor.None) + { + if (c1 == (byte) ItemCustomColor.None) + return Invalid; + return GetColorText(c1); + } + + var s0 = GetColorText(c0); + if (c1 == (byte) ItemCustomColor.None || c0 == c1) + return s0; + + var s1 = GetColorText(c1); + + return $"{s0}-{s1}"; + } + + private static string GetColorText(byte value) => ((ItemCustomColor)value).ToString(); + + public string GetBodySummary(IRemakeString str) + { + var sb = new StringBuilder(); + var item = $"{ItemUniqueID:00000}"; + if (str.BodyParts.TryGetValue(item, out var parts)) + sb.Append(parts).AppendLine(":"); + + for (int i = 0; i < 8; i++) + { + var cd = GetBodyDescription(i); + var name = $"{ItemUniqueID:00000}_{i}"; + var hasBody = str.BodyColor.TryGetValue(name, out var desc); + + if (hasBody && cd != Invalid) + sb.Append(i).Append('=').Append(desc).Append(" (").Append(cd).AppendLine(")"); + else if (hasBody) + sb.Append(i).Append('=').AppendLine(desc); + // else don't add anything + } + return sb.ToString(); + } + + public string GetFabricSummary(IRemakeString str) + { + var sb = new StringBuilder(); + var item = $"{ItemUniqueID:00000}"; + if (str.FabricParts.TryGetValue(item, out var parts)) + sb.Append(parts).AppendLine(":"); + + for (int i = 0; i < 8; i++) + { + var cd = GetFabricDescription(i); + if (cd == Invalid) + continue; + + var shifted = (i << 5); + sb.Append(shifted.ToString("000")).Append('='); + var name = $"{ItemUniqueID:00000}_{i}"; + if (str.FabricColor.TryGetValue(name, out var desc)) + sb.Append(desc).Append(" (").Append(cd).AppendLine(")"); + else + sb.AppendLine(cd); + } + return sb.ToString(); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/Remake/ItemRemakeInfoData.cs b/NHSE.Core/Structures/Item/Remake/ItemRemakeInfoData.cs index 140cf55..3ebc066 100644 --- a/NHSE.Core/Structures/Item/Remake/ItemRemakeInfoData.cs +++ b/NHSE.Core/Structures/Item/Remake/ItemRemakeInfoData.cs @@ -1,1267 +1,1266 @@ using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// this sits in its own class because it's so darn big and has lots of highlighting CPU usage. thanks resharper +/// +public static class ItemRemakeInfoData { - /// - /// this sits in its own class because it's so darn big and has lots of highlighting CPU usage. thanks resharper - /// - public static class ItemRemakeInfoData + public static readonly IReadOnlyDictionary List = new Dictionary { - public static readonly IReadOnlyDictionary List = new Dictionary - { - {0072, new ItemRemakeInfo(0072, 01288, 5, new byte[] {10, 12, 08, 04, 06, 01, 14, 14}, new byte[] {06, 06, 06, 06, 06, 06, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fan palm - {0075, new ItemRemakeInfo(0075, 02587, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 05, 02, 06, 07, 14, 14, 14}, false)}, // hospital screen - {0076, new ItemRemakeInfo(0076, 02605, 7, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {00, 02, 05, 06, 14, 14, 14, 14}, false)}, // wooden simple bed - {0078, new ItemRemakeInfo(0078, 02731, 7, new byte[] {00, 06, 05, 04, 03, 01, 12, 10}, new byte[] {12, 06, 00, 07, 06, 12, 05, 01}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // digital alarm clock - {0081, new ItemRemakeInfo(0081, 01608, 2, new byte[] {10, 12, 04, 14, 14, 14, 14, 14}, new byte[] {11, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 12, 06, 05, 07, 06, 12}, false)}, // vertical banner - {0083, new ItemRemakeInfo(0083, 01850, 6, new byte[] {10, 11, 12, 01, 02, 04, 08, 14}, new byte[] {10, 11, 12, 01, 02, 04, 08, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 12, 13, 13, 13, 13, 14, 14}, false)}, // laptop - {0084, new ItemRemakeInfo(0084, 01557, 4, new byte[] {12, 09, 04, 02, 07, 14, 14, 14}, new byte[] {08, 10, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block bed - {0085, new ItemRemakeInfo(0085, 00833, 6, new byte[] {11, 12, 10, 01, 04, 06, 07, 14}, new byte[] {11, 12, 10, 01, 04, 06, 07, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 10, 02, 13, 02, 14, 14, 14}, true)}, // upright locker - {0086, new ItemRemakeInfo(0086, 00086, 7, new byte[] {04, 02, 01, 05, 07, 12, 11, 10}, new byte[] {07, 02, 05, 12, 00, 02, 02, 00}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // elephant slide - {0087, new ItemRemakeInfo(0087, 01851, 6, new byte[] {05, 01, 07, 05, 03, 06, 02, 14}, new byte[] {06, 12, 00, 02, 04, 07, 02, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rocket lamp - {0089, new ItemRemakeInfo(0089, 01803, 7, new byte[] {00, 10, 12, 09, 04, 01, 06, 11}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 10, 12, 10, 08, 14, 14}, false)}, // drum set - {0090, new ItemRemakeInfo(0090, 01567, 7, new byte[] {06, 04, 05, 00, 07, 01, 06, 09}, new byte[] {12, 12, 12, 12, 10, 01, 06, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // oil barrel - {0095, new ItemRemakeInfo(0095, 02560, 7, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden chest - {0096, new ItemRemakeInfo(0096, 01644, 7, new byte[] {00, 02, 10, 01, 07, 08, 12, 04}, new byte[] {12, 12, 12, 12, 12, 10, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 10, 12, 03, 06, 05, 13, 02}, true)}, // rock guitar - {0097, new ItemRemakeInfo(0097, 03078, 4, new byte[] {06, 04, 12, 11, 10, 14, 14, 14}, new byte[] {06, 04, 12, 11, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tourist telescope - {0098, new ItemRemakeInfo(0098, 01888, 4, new byte[] {12, 11, 09, 01, 10, 14, 14, 14}, new byte[] {11, 12, 09, 01, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rice cooker - {0099, new ItemRemakeInfo(0099, 01929, 2, new byte[] {12, 00, 09, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // toilet - {0100, new ItemRemakeInfo(0100, 03333, 7, new byte[] {10, 12, 11, 01, 07, 04, 02, 05}, new byte[] {10, 12, 11, 01, 07, 04, 02, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // LCD TV (20 in.) - {0101, new ItemRemakeInfo(0101, 03252, 4, new byte[] {10, 12, 11, 01, 04, 14, 14, 14}, new byte[] {10, 12, 11, 01, 04, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // LCD TV (50 in.) - {0102, new ItemRemakeInfo(0102, 00080, 5, new byte[] {08, 07, 01, 10, 07, 02, 14, 14}, new byte[] {09, 13, 07, 01, 05, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // clackercart - {0103, new ItemRemakeInfo(0103, 01875, 3, new byte[] {10, 12, 09, 00, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // grand piano - {0104, new ItemRemakeInfo(0104, 03428, 4, new byte[] {10, 12, 11, 01, 04, 14, 14, 14}, new byte[] {10, 12, 11, 01, 04, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall-mounted TV (50 in.) - {0105, new ItemRemakeInfo(0105, 01558, 4, new byte[] {08, 09, 07, 02, 04, 14, 14, 14}, new byte[] {09, 07, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block bookshelf - {0106, new ItemRemakeInfo(0106, 01559, 4, new byte[] {08, 10, 07, 05, 04, 14, 14, 14}, new byte[] {08, 09, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block bench - {0107, new ItemRemakeInfo(0107, 01561, 4, new byte[] {08, 09, 06, 05, 01, 14, 14, 14}, new byte[] {08, 10, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block chest - {0108, new ItemRemakeInfo(0108, 01565, 4, new byte[] {08, 09, 06, 02, 01, 14, 14, 14}, new byte[] {08, 10, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block table - {0109, new ItemRemakeInfo(0109, 02558, 4, new byte[] {08, 09, 01, 02, 07, 14, 14, 14}, new byte[] {08, 10, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block chair - {0111, new ItemRemakeInfo(0111, 03205, 4, new byte[] {08, 09, 07, 07, 04, 14, 14, 14}, new byte[] {08, 07, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block stereo - {0112, new ItemRemakeInfo(0112, 03206, 4, new byte[] {08, 09, 06, 05, 01, 14, 14, 14}, new byte[] {08, 10, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block toy - {0113, new ItemRemakeInfo(0113, 03208, 4, new byte[] {08, 10, 04, 02, 07, 14, 14, 14}, new byte[] {08, 09, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block wall clock - {0114, new ItemRemakeInfo(0114, 03490, 5, new byte[] {08, 07, 00, 09, 10, 12, 14, 14}, new byte[] {08, 07, 00, 09, 10, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden waste bin - {0115, new ItemRemakeInfo(0115, 02740, 5, new byte[] {12, 01, 04, 06, 07, 10, 14, 14}, new byte[] {12, 12, 12, 12, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // automatic washer - {0117, new ItemRemakeInfo(0117, 01103, 4, new byte[] {08, 00, 09, 12, 10, 14, 14, 14}, new byte[] {08, 00, 09, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rocking chair - {0119, new ItemRemakeInfo(0119, 00088, 3, new byte[] {00, 01, 02, 04, 14, 14, 14, 14}, new byte[] {08, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ringtoss - {0120, new ItemRemakeInfo(0120, 01108, 1, new byte[] {09, 09, 14, 14, 14, 14, 14, 14}, new byte[] {11, 11, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // retro TV - {0121, new ItemRemakeInfo(0121, 02713, 7, new byte[] {12, 01, 02, 07, 04, 09, 10, 11}, new byte[] {12, 01, 02, 07, 04, 09, 10, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 02, 13, 06, 13, 14, 14, 14}, true)}, // refrigerator - {0123, new ItemRemakeInfo(0123, 02736, 2, new byte[] {04, 06, 00, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // retro fan - {0124, new ItemRemakeInfo(0124, 01432, 7, new byte[] {01, 04, 06, 07, 02, 05, 10, 08}, new byte[] {01, 04, 06, 07, 02, 05, 10, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lantern - {0125, new ItemRemakeInfo(0125, 01112, 4, new byte[] {13, 04, 03, 01, 13, 14, 14, 14}, new byte[] {13, 12, 07, 10, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // colorful wheel - {0126, new ItemRemakeInfo(0126, 03446, 4, new byte[] {12, 11, 10, 09, 06, 14, 14, 14}, new byte[] {03, 00, 01, 07, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // western-style stone - {0127, new ItemRemakeInfo(0127, 00787, 3, new byte[] {11, 00, 12, 10, 14, 14, 14, 14}, new byte[] {04, 10, 10, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tape deck - {0128, new ItemRemakeInfo(0128, 03439, 7, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 00, 02, 04, 06, 14, 14, 14}, true)}, // wooden table - {0129, new ItemRemakeInfo(0129, 00083, 5, new byte[] {07, 01, 12, 02, 04, 05, 14, 14}, new byte[] {07, 04, 05, 03, 05, 01, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rocking horse - {0130, new ItemRemakeInfo(0130, 01778, 1, new byte[] {11, 05, 14, 14, 14, 14, 14, 14}, new byte[] {11, 05, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 08, 05, 07, 14, 14, 14, 14}, false)}, // clothesline pole - {0131, new ItemRemakeInfo(0131, 03229, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 08, 04, 01, 06, 14, 14, 14}, false)}, // clothesline - {0132, new ItemRemakeInfo(0132, 01889, 7, new byte[] {01, 04, 06, 12, 05, 09, 10, 02}, new byte[] {05, 05, 01, 02, 07, 06, 10, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ring - {0134, new ItemRemakeInfo(0134, 03449, 7, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 00, 02, 05, 06, 14, 14, 14}, true)}, // wooden stool - {0135, new ItemRemakeInfo(0135, 01913, 7, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden chair - {0137, new ItemRemakeInfo(0137, 01877, 6, new byte[] {02, 04, 06, 12, 09, 10, 02, 14}, new byte[] {02, 04, 06, 12, 09, 10, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // piggy bank - {0138, new ItemRemakeInfo(0138, 02554, 7, new byte[] {01, 07, 06, 04, 12, 00, 09, 10}, new byte[] {01, 07, 06, 04, 12, 00, 09, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // double sofa - {0139, new ItemRemakeInfo(0139, 03230, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 00, 06, 14, 14, 14, 14}, false)}, // futon - {0140, new ItemRemakeInfo(0140, 01058, 3, new byte[] {09, 07, 12, 10, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // music stand - {0142, new ItemRemakeInfo(0142, 01170, 4, new byte[] {08, 07, 12, 01, 09, 14, 14, 14}, new byte[] {08, 07, 12, 01, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // swinging bench - {0143, new ItemRemakeInfo(0143, 02010, 3, new byte[] {00, 12, 12, 07, 14, 14, 14, 14}, new byte[] {10, 10, 12, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ball - {0144, new ItemRemakeInfo(0144, 01712, 7, new byte[] {10, 11, 07, 12, 01, 04, 06, 09}, new byte[] {10, 11, 07, 12, 01, 04, 06, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {08, 05, 13, 13, 03, 08, 04, 11}, false)}, // poster stand - {0145, new ItemRemakeInfo(0145, 01852, 7, new byte[] {05, 02, 00, 04, 07, 02, 12, 10}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // box sofa - {0146, new ItemRemakeInfo(0146, 01853, 7, new byte[] {05, 02, 00, 04, 07, 02, 12, 10}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // box corner sofa - {0147, new ItemRemakeInfo(0147, 03282, 5, new byte[] {12, 07, 05, 06, 01, 11, 14, 14}, new byte[] {00, 00, 00, 00, 00, 00, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pop-up toaster - {0148, new ItemRemakeInfo(0148, 01092, 4, new byte[] {01, 06, 02, 04, 10, 14, 14, 14}, new byte[] {07, 07, 12, 05, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // popcorn machine - {0149, new ItemRemakeInfo(0149, 01881, 4, new byte[] {01, 05, 06, 08, 06, 14, 14, 14}, new byte[] {12, 12, 11, 06, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plastic canister - {0150, new ItemRemakeInfo(0150, 03582, 3, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {01, 04, 07, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // book - {0151, new ItemRemakeInfo(0151, 02614, 5, new byte[] {06, 07, 02, 03, 12, 10, 14, 14}, new byte[] {10, 10, 10, 10, 10, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mountain bike - {0152, new ItemRemakeInfo(0152, 01032, 7, new byte[] {08, 00, 09, 12, 10, 07, 04, 01}, new byte[] {08, 00, 09, 12, 10, 07, 04, 01}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 11, 13, 13, 02, 13, 14}, false)}, // magazine rack - {0153, new ItemRemakeInfo(0153, 01870, 7, new byte[] {12, 07, 01, 04, 06, 02, 05, 10}, new byte[] {12, 07, 01, 04, 06, 02, 05, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 10, 07, 04, 00, 07, 14, 14}, true)}, // mug - {0154, new ItemRemakeInfo(0154, 03305, 6, new byte[] {01, 02, 07, 06, 04, 12, 10, 14}, new byte[] {01, 02, 07, 06, 04, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 00, 13, 13, 14, 14, 14}, false)}, // baby chair - {0155, new ItemRemakeInfo(0155, 02771, 5, new byte[] {12, 10, 01, 06, 00, 05, 14, 14}, new byte[] {12, 10, 01, 06, 00, 05, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // round space heater - {0156, new ItemRemakeInfo(0156, 00144, 4, new byte[] {10, 09, 06, 07, 12, 14, 14, 14}, new byte[] {10, 09, 00, 05, 02, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // manhole cover - {0157, new ItemRemakeInfo(0157, 01050, 7, new byte[] {12, 10, 11, 00, 06, 07, 02, 05}, new byte[] {01, 06, 00, 00, 03, 07, 02, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mixer - {0158, new ItemRemakeInfo(0158, 01128, 6, new byte[] {12, 05, 01, 02, 07, 06, 10, 14}, new byte[] {11, 04, 12, 12, 12, 12, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sewing machine - {0159, new ItemRemakeInfo(0159, 01051, 4, new byte[] {01, 04, 06, 07, 02, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // water bird - {0160, new ItemRemakeInfo(0160, 03588, 7, new byte[] {08, 08, 08, 08, 08, 08, 08, 08}, new byte[] {09, 09, 09, 09, 09, 09, 09, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // signpost - {0161, new ItemRemakeInfo(0161, 03122, 7, new byte[] {08, 00, 09, 11, 07, 06, 04, 02}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mini DIY workbench - {0166, new ItemRemakeInfo(0166, 01042, 4, new byte[] {01, 07, 04, 10, 09, 14, 14, 14}, new byte[] {12, 12, 12, 12, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // metronome - {0167, new ItemRemakeInfo(0167, 01866, 4, new byte[] {00, 09, 12, 05, 01, 14, 14, 14}, new byte[] {06, 06, 06, 06, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // menu chalkboard - {0168, new ItemRemakeInfo(0168, 03436, 7, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden wardrobe - {0169, new ItemRemakeInfo(0169, 03438, 7, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {13, 13, 13, 13, 13, 13, 13, 13}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden end table - {0170, new ItemRemakeInfo(0170, 01072, 7, new byte[] {07, 07, 11, 11, 10, 12, 09, 06}, new byte[] {01, 04, 01, 04, 10, 12, 07, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rope partition - {0171, new ItemRemakeInfo(0171, 00330, 4, new byte[] {01, 07, 06, 12, 10, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // barbecue - {0172, new ItemRemakeInfo(0172, 00146, 7, new byte[] {01, 04, 07, 12, 01, 06, 01, 07}, new byte[] {01, 04, 07, 12, 12, 12, 12, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cone - {0173, new ItemRemakeInfo(0173, 03346, 7, new byte[] {05, 06, 00, 08, 07, 00, 02, 10}, new byte[] {05, 06, 00, 08, 04, 06, 05, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // public bench - {0174, new ItemRemakeInfo(0174, 01348, 4, new byte[] {05, 02, 07, 01, 09, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hamster cage - {0175, new ItemRemakeInfo(0175, 01598, 4, new byte[] {04, 02, 12, 10, 07, 14, 14, 14}, new byte[] {04, 02, 12, 10, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // exercise ball - {0176, new ItemRemakeInfo(0176, 00531, 6, new byte[] {06, 06, 06, 06, 06, 00, 12, 14}, new byte[] {06, 02, 06, 13, 01, 09, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hedge standee - {0177, new ItemRemakeInfo(0177, 00533, 4, new byte[] {06, 02, 06, 00, 12, 14, 14, 14}, new byte[] {09, 09, 09, 09, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tree standee - {0178, new ItemRemakeInfo(0178, 00530, 3, new byte[] {06, 06, 08, 12, 14, 14, 14, 14}, new byte[] {06, 06, 09, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // grass standee - {0179, new ItemRemakeInfo(0179, 00532, 5, new byte[] {06, 02, 06, 10, 00, 12, 14, 14}, new byte[] {06, 02, 06, 01, 09, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mountain standee - {0180, new ItemRemakeInfo(0180, 01620, 6, new byte[] {09, 08, 07, 04, 02, 12, 10, 14}, new byte[] {09, 08, 07, 04, 02, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 06, 05, 12, 14, 14, 14, 14}, false)}, // hammock - {0181, new ItemRemakeInfo(0181, 03468, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {05, 01, 07, 02, 04, 07, 12, 14}, new byte[] {13, 12, 01, 02, 04, 07, 12, 14}, false)}, // beach towel - {0182, new ItemRemakeInfo(0182, 00664, 5, new byte[] {12, 10, 04, 00, 07, 02, 14, 14}, new byte[] {12, 10, 05, 12, 06, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // beach chair - {0183, new ItemRemakeInfo(0183, 01029, 2, new byte[] {08, 09, 00, 14, 14, 14, 14, 14}, new byte[] {08, 09, 00, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 01, 04, 00, 11, 14, 14, 14}, false)}, // low screen - {0184, new ItemRemakeInfo(0184, 01082, 5, new byte[] {09, 00, 01, 09, 08, 11, 14, 14}, new byte[] {01, 04, 07, 06, 05, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // picnic basket - {0185, new ItemRemakeInfo(0185, 01621, 5, new byte[] {05, 13, 02, 13, 06, 10, 14, 14}, new byte[] {12, 12, 12, 12, 06, 00, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lawn chair - {0186, new ItemRemakeInfo(0186, 03348, 5, new byte[] {04, 02, 06, 00, 13, 13, 14, 14}, new byte[] {07, 03, 01, 10, 12, 04, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plastic pool - {0188, new ItemRemakeInfo(0188, 03581, 2, new byte[] {09, 07, 00, 14, 14, 14, 14, 14}, new byte[] {08, 08, 08, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fish-drying rack - {0189, new ItemRemakeInfo(0189, 01624, 7, new byte[] {01, 03, 07, 04, 00, 06, 01, 10}, new byte[] {04, 07, 05, 09, 06, 07, 01, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // garden gnome - {0190, new ItemRemakeInfo(0190, 00865, 4, new byte[] {09, 02, 04, 12, 10, 14, 14, 14}, new byte[] {07, 07, 06, 12, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // birdcage - {0192, new ItemRemakeInfo(0192, 03407, 4, new byte[] {10, 04, 12, 01, 08, 14, 14, 14}, new byte[] {09, 09, 09, 09, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // katana - {0193, new ItemRemakeInfo(0193, 01757, 5, new byte[] {12, 10, 01, 05, 02, 07, 14, 14}, new byte[] {12, 12, 12, 12, 12, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // claw-foot tub - {0194, new ItemRemakeInfo(0194, 01227, 5, new byte[] {12, 10, 04, 01, 07, 02, 14, 14}, new byte[] {12, 10, 04, 01, 07, 02, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // deluxe washer - {0195, new ItemRemakeInfo(0195, 03590, 3, new byte[] {10, 11, 12, 02, 14, 14, 14, 14}, new byte[] {10, 11, 12, 02, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 12, 13, 13, 13, 13, 13, 14}, false)}, // desktop computer - {0196, new ItemRemakeInfo(0196, 02553, 2, new byte[] {01, 11, 10, 14, 14, 14, 14, 14}, new byte[] {10, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron frame - {0197, new ItemRemakeInfo(0197, 00085, 3, new byte[] {06, 06, 00, 12, 14, 14, 14, 14}, new byte[] {09, 09, 09, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // train set - {0198, new ItemRemakeInfo(0198, 01716, 4, new byte[] {11, 12, 10, 09, 08, 14, 14, 14}, new byte[] {11, 12, 10, 09, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // display stand - {0199, new ItemRemakeInfo(0199, 01043, 3, new byte[] {12, 10, 01, 06, 14, 14, 14, 14}, new byte[] {12, 10, 01, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // microwave - {0200, new ItemRemakeInfo(0200, 01185, 7, new byte[] {01, 06, 04, 07, 09, 12, 10, 07}, new byte[] {01, 06, 04, 07, 09, 12, 10, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // phone box - {0201, new ItemRemakeInfo(0201, 02335, 5, new byte[] {01, 12, 12, 12, 07, 09, 14, 14}, new byte[] {12, 10, 05, 12, 07, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lighthouse - {0202, new ItemRemakeInfo(0202, 01797, 6, new byte[] {08, 08, 09, 12, 12, 10, 12, 14}, new byte[] {08, 06, 08, 10, 00, 10, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // decoy duck - {0203, new ItemRemakeInfo(0203, 03443, 5, new byte[] {07, 06, 05, 07, 02, 10, 14, 14}, new byte[] {05, 07, 04, 09, 05, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sewing project - {0204, new ItemRemakeInfo(0204, 03416, 7, new byte[] {12, 03, 00, 05, 06, 13, 13, 13}, new byte[] {08, 08, 08, 08, 08, 08, 08, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // soft-serve lamp - {0205, new ItemRemakeInfo(0205, 03307, 6, new byte[] {12, 10, 01, 04, 07, 06, 09, 14}, new byte[] {12, 10, 01, 04, 07, 06, 09, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 01, 06, 11, 07, 14, 14, 14}, false)}, // digital scale - {0206, new ItemRemakeInfo(0206, 02329, 5, new byte[] {10, 01, 07, 06, 04, 12, 14, 14}, new byte[] {10, 01, 07, 06, 04, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tire toy - {0207, new ItemRemakeInfo(0207, 03583, 3, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {07, 07, 07, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fishing-boat flag - {0208, new ItemRemakeInfo(0208, 03558, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {01, 01, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo wall decoration - {0209, new ItemRemakeInfo(0209, 03554, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {08, 08, 08, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo candleholder - {0210, new ItemRemakeInfo(0210, 03556, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {10, 08, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo stopblock - {0211, new ItemRemakeInfo(0211, 03551, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {12, 03, 02, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo shelf - {0213, new ItemRemakeInfo(0213, 03553, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {12, 12, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo partition - {0215, new ItemRemakeInfo(0215, 03557, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo floor lamp - {0216, new ItemRemakeInfo(0216, 00710, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo bench - {0218, new ItemRemakeInfo(0218, 01708, 7, new byte[] {01, 07, 06, 04, 02, 11, 12, 10}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cassette player - {0219, new ItemRemakeInfo(0219, 01573, 7, new byte[] {01, 04, 06, 02, 10, 12, 07, 01}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dharma - {0220, new ItemRemakeInfo(0220, 02776, 4, new byte[] {12, 07, 02, 05, 10, 14, 14, 14}, new byte[] {12, 07, 02, 05, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tankless toilet - {0221, new ItemRemakeInfo(0221, 00742, 3, new byte[] {00, 09, 08, 12, 14, 14, 14, 14}, new byte[] {09, 09, 08, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fireplace - {0222, new ItemRemakeInfo(0222, 02770, 1, new byte[] {09, 10, 14, 14, 14, 14, 14, 14}, new byte[] {07, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // chessboard - {0223, new ItemRemakeInfo(0223, 01411, 2, new byte[] {05, 07, 04, 14, 14, 14, 14, 14}, new byte[] {00, 09, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // globe - {0224, new ItemRemakeInfo(0224, 00739, 4, new byte[] {09, 09, 00, 07, 09, 14, 14, 14}, new byte[] {09, 09, 00, 07, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tea table - {0225, new ItemRemakeInfo(0225, 00547, 3, new byte[] {11, 12, 04, 02, 14, 14, 14, 14}, new byte[] {11, 12, 10, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // washbasin - {0226, new ItemRemakeInfo(0226, 03467, 3, new byte[] {06, 04, 01, 07, 14, 14, 14, 14}, new byte[] {06, 04, 01, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 04, 01, 11, 14, 14, 14, 14}, false)}, // tea set - {0227, new ItemRemakeInfo(0227, 01229, 2, new byte[] {12, 10, 12, 14, 14, 14, 14, 14}, new byte[] {12, 12, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bathroom sink - {0228, new ItemRemakeInfo(0228, 00907, 4, new byte[] {01, 07, 06, 11, 10, 14, 14, 14}, new byte[] {11, 10, 06, 11, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vacuum cleaner - {0229, new ItemRemakeInfo(0229, 00908, 6, new byte[] {11, 12, 10, 01, 00, 06, 02, 14}, new byte[] {10, 10, 10, 10, 10, 10, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // upright vacuum - {0230, new ItemRemakeInfo(0230, 01892, 3, new byte[] {08, 12, 10, 09, 14, 14, 14, 14}, new byte[] {05, 02, 12, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hourglass - {0231, new ItemRemakeInfo(0231, 01117, 1, new byte[] {00, 11, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sand castle - {0232, new ItemRemakeInfo(0232, 00333, 5, new byte[] {09, 09, 09, 01, 04, 12, 14, 14}, new byte[] {07, 09, 12, 07, 04, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // birdhouse - {0234, new ItemRemakeInfo(0234, 03444, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 06, 08, 13, 14, 14, 14}, false)}, // wheelchair - {0236, new ItemRemakeInfo(0236, 01143, 2, new byte[] {10, 06, 11, 14, 14, 14, 14, 14}, new byte[] {08, 08, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // smoker - {0239, new ItemRemakeInfo(0239, 01845, 6, new byte[] {01, 07, 06, 05, 10, 04, 12, 14}, new byte[] {00, 00, 00, 09, 09, 09, 01, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // simple kettle - {0240, new ItemRemakeInfo(0240, 01319, 2, new byte[] {12, 11, 10, 14, 14, 14, 14, 14}, new byte[] {10, 10, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // microscope - {0241, new ItemRemakeInfo(0241, 03595, 3, new byte[] {10, 11, 12, 09, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // park clock - {0242, new ItemRemakeInfo(0242, 00918, 5, new byte[] {12, 12, 07, 02, 04, 12, 14, 14}, new byte[] {12, 06, 07, 02, 07, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // coffee cup - {0244, new ItemRemakeInfo(0244, 02012, 6, new byte[] {06, 06, 06, 06, 06, 06, 06, 14}, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // chalkboard - {0246, new ItemRemakeInfo(0246, 01849, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 02, 07, 13, 14, 14, 14, 14}, false)}, // kotatsu - {0247, new ItemRemakeInfo(0247, 01745, 1, new byte[] {12, 10, 14, 14, 14, 14, 14, 14}, new byte[] {04, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 12, 14, 14, 14}, false)}, // copy machine - {0248, new ItemRemakeInfo(0248, 01823, 3, new byte[] {10, 12, 04, 07, 14, 14, 14, 14}, new byte[] {10, 12, 04, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // trash bags - {0249, new ItemRemakeInfo(0249, 01783, 2, new byte[] {08, 12, 04, 14, 14, 14, 14, 14}, new byte[] {08, 12, 04, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 06, 14, 14, 14, 14, 14}, false)}, // corkboard - {0250, new ItemRemakeInfo(0250, 01632, 5, new byte[] {01, 06, 02, 13, 09, 11, 14, 14}, new byte[] {01, 06, 02, 13, 09, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // golf bag - {0252, new ItemRemakeInfo(0252, 03442, 5, new byte[] {08, 00, 09, 12, 04, 10, 14, 14}, new byte[] {00, 09, 00, 01, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sturdy sewing box - {0253, new ItemRemakeInfo(0253, 01241, 7, new byte[] {08, 09, 09, 10, 12, 05, 07, 01}, new byte[] {13, 13, 13, 13, 13, 13, 13, 13}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // DIY workbench - {0254, new ItemRemakeInfo(0254, 03586, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 01, 03, 04, 05, 09, 13, 14}, false)}, // magazine - {0255, new ItemRemakeInfo(0255, 01199, 4, new byte[] {00, 01, 04, 06, 12, 14, 14, 14}, new byte[] {01, 02, 06, 07, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tricycle - {0256, new ItemRemakeInfo(0256, 03340, 4, new byte[] {00, 08, 07, 12, 10, 14, 14, 14}, new byte[] {00, 08, 07, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // deer decoration - {0257, new ItemRemakeInfo(0257, 01899, 3, new byte[] {12, 08, 08, 08, 14, 14, 14, 14}, new byte[] {12, 08, 08, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 14, 14, 14, 14, 14, 14}, false)}, // autograph cards - {0258, new ItemRemakeInfo(0258, 00338, 4, new byte[] {01, 00, 04, 07, 06, 14, 14, 14}, new byte[] {12, 10, 12, 11, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lawn mower - {0259, new ItemRemakeInfo(0259, 01802, 5, new byte[] {01, 04, 12, 09, 06, 02, 14, 14}, new byte[] {05, 04, 12, 09, 06, 02, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {00, 05, 06, 12, 14, 14, 14, 14}, false)}, // drink machine - {0262, new ItemRemakeInfo(0262, 00922, 6, new byte[] {07, 01, 06, 04, 10, 12, 11, 14}, new byte[] {07, 01, 06, 04, 10, 12, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 04, 12, 00, 01, 02, 06, 01}, true)}, // stacked bottle crates - {0263, new ItemRemakeInfo(0263, 01434, 7, new byte[] {06, 11, 04, 00, 07, 02, 12, 01}, new byte[] {07, 10, 00, 11, 05, 03, 07, 04}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sleeping bag - {0266, new ItemRemakeInfo(0266, 01868, 5, new byte[] {07, 01, 02, 04, 12, 10, 14, 14}, new byte[] {05, 05, 05, 05, 05, 05, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // desk mirror - {0267, new ItemRemakeInfo(0267, 00997, 5, new byte[] {10, 12, 04, 06, 02, 09, 14, 14}, new byte[] {01, 09, 10, 08, 12, 06, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // incense burner - {0268, new ItemRemakeInfo(0268, 01495, 5, new byte[] {01, 04, 06, 02, 10, 12, 14, 14}, new byte[] {08, 08, 08, 08, 08, 08, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dolly - {0269, new ItemRemakeInfo(0269, 01628, 2, new byte[] {10, 12, 06, 14, 14, 14, 14, 14}, new byte[] {10, 12, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // garden lantern - {0270, new ItemRemakeInfo(0270, 03584, 3, new byte[] {01, 05, 12, 10, 14, 14, 14, 14}, new byte[] {13, 13, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // study poster - {0271, new ItemRemakeInfo(0271, 03445, 3, new byte[] {10, 12, 11, 06, 14, 14, 14, 14}, new byte[] {10, 12, 11, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 06, 04, 13, 14, 14, 14, 14}, false)}, // standard umbrella stand - {0272, new ItemRemakeInfo(0272, 01836, 7, new byte[] {12, 08, 09, 02, 07, 06, 05, 03}, new byte[] {12, 12, 12, 02, 07, 06, 05, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // humidifier - {0273, new ItemRemakeInfo(0273, 01234, 4, new byte[] {05, 01, 04, 06, 11, 14, 14, 14}, new byte[] {12, 12, 12, 12, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // portable toilet - {0274, new ItemRemakeInfo(0274, 01308, 5, new byte[] {07, 09, 00, 12, 11, 08, 14, 14}, new byte[] {11, 12, 10, 01, 04, 06, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // school chair - {0275, new ItemRemakeInfo(0275, 01328, 5, new byte[] {07, 09, 00, 12, 11, 08, 14, 14}, new byte[] {11, 12, 10, 01, 04, 06, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // school desk - {0277, new ItemRemakeInfo(0277, 00957, 4, new byte[] {12, 02, 04, 06, 00, 14, 14, 14}, new byte[] {12, 12, 12, 12, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ventilation fan - {0278, new ItemRemakeInfo(0278, 02575, 6, new byte[] {08, 09, 12, 05, 02, 06, 11, 14}, new byte[] {08, 09, 12, 05, 02, 06, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ranch chair - {0279, new ItemRemakeInfo(0279, 00896, 5, new byte[] {08, 09, 04, 11, 02, 12, 14, 14}, new byte[] {08, 08, 08, 07, 05, 08, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cat tower - {0280, new ItemRemakeInfo(0280, 01019, 1, new byte[] {08, 12, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // first-aid kit - {0281, new ItemRemakeInfo(0281, 00839, 3, new byte[] {11, 12, 10, 07, 14, 14, 14, 14}, new byte[] {11, 11, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // safe - {0282, new ItemRemakeInfo(0282, 03064, 3, new byte[] {04, 01, 07, 06, 14, 14, 14, 14}, new byte[] {12, 12, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cooler box - {0284, new ItemRemakeInfo(0284, 01792, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 01, 13, 05, 14, 14}, new byte[] {12, 13, 06, 01, 13, 13, 14, 14}, false)}, // cushion - {0285, new ItemRemakeInfo(0285, 01499, 5, new byte[] {00, 08, 09, 06, 01, 09, 14, 14}, new byte[] {08, 08, 09, 07, 12, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 07, 14, 14, 14, 14}, true)}, // Papa bear - {0286, new ItemRemakeInfo(0286, 01501, 5, new byte[] {08, 08, 09, 04, 07, 13, 14, 14}, new byte[] {12, 08, 09, 02, 12, 13, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 07, 14, 14, 14, 14}, true)}, // Baby bear - {0287, new ItemRemakeInfo(0287, 01500, 5, new byte[] {02, 08, 09, 12, 11, 11, 14, 14}, new byte[] {08, 08, 09, 02, 12, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 07, 14, 14, 14, 14}, true)}, // Mama bear - {0290, new ItemRemakeInfo(0290, 03562, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {11, 11, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron wall rack - {0291, new ItemRemakeInfo(0291, 03559, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron wall lamp - {0292, new ItemRemakeInfo(0292, 03271, 4, new byte[] {08, 00, 09, 09, 00, 14, 14, 14}, new byte[] {10, 10, 10, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ironwood cupboard - {0293, new ItemRemakeInfo(0293, 03270, 4, new byte[] {08, 00, 09, 09, 00, 14, 14, 14}, new byte[] {11, 11, 11, 11, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ironwood kitchenette - {0294, new ItemRemakeInfo(0294, 03275, 4, new byte[] {08, 00, 09, 09, 00, 14, 14, 14}, new byte[] {10, 10, 10, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ironwood clock - {0296, new ItemRemakeInfo(0296, 03193, 4, new byte[] {08, 00, 09, 09, 00, 14, 14, 14}, new byte[] {10, 10, 10, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ironwood chair - {0297, new ItemRemakeInfo(0297, 03196, 4, new byte[] {08, 00, 09, 09, 00, 14, 14, 14}, new byte[] {10, 10, 10, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ironwood dresser - {0298, new ItemRemakeInfo(0298, 03191, 4, new byte[] {08, 00, 09, 09, 00, 14, 14, 14}, new byte[] {10, 10, 10, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ironwood table - {0299, new ItemRemakeInfo(0299, 03200, 4, new byte[] {08, 00, 09, 09, 09, 14, 14, 14}, new byte[] {08, 00, 09, 09, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 05, 09, 14, 14, 14, 14, 14}, false)}, // ironwood bed - {0300, new ItemRemakeInfo(0300, 03509, 5, new byte[] {08, 09, 08, 08, 09, 12, 14, 14}, new byte[] {10, 06, 10, 01, 11, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // garden bench - {0301, new ItemRemakeInfo(0301, 03194, 4, new byte[] {08, 00, 09, 09, 00, 14, 14, 14}, new byte[] {10, 10, 10, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ironwood low table - {0302, new ItemRemakeInfo(0302, 03195, 4, new byte[] {08, 00, 09, 09, 00, 14, 14, 14}, new byte[] {10, 10, 10, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ironwood cart - {0303, new ItemRemakeInfo(0303, 01626, 4, new byte[] {06, 04, 09, 10, 12, 14, 14, 14}, new byte[] {06, 04, 09, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron garden chair - {0304, new ItemRemakeInfo(0304, 01627, 4, new byte[] {06, 04, 09, 10, 12, 14, 14, 14}, new byte[] {06, 04, 09, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron garden table - {0305, new ItemRemakeInfo(0305, 01625, 4, new byte[] {06, 04, 09, 10, 12, 14, 14, 14}, new byte[] {06, 04, 09, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron garden bench - {0306, new ItemRemakeInfo(0306, 03563, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {11, 09, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron shelf - {0307, new ItemRemakeInfo(0307, 03561, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 02, 14, 14, 14, 14, 14, 14}, false)}, // iron hanger stand - {0308, new ItemRemakeInfo(0308, 03560, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron worktable - {0309, new ItemRemakeInfo(0309, 00998, 6, new byte[] {12, 04, 01, 08, 09, 10, 11, 14}, new byte[] {12, 12, 10, 12, 12, 10, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // kitchen island - {0310, new ItemRemakeInfo(0310, 00383, 6, new byte[] {08, 01, 09, 04, 12, 10, 02, 14}, new byte[] {09, 10, 10, 10, 10, 10, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // acoustic guitar - {0311, new ItemRemakeInfo(0311, 01753, 5, new byte[] {12, 09, 06, 02, 08, 10, 14, 14}, new byte[] {05, 00, 06, 02, 06, 04, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // aroma pot - {0312, new ItemRemakeInfo(0312, 00725, 2, new byte[] {08, 09, 00, 14, 14, 14, 14, 14}, new byte[] {08, 09, 00, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 02, 06, 00, 11, 14, 14, 14}, false)}, // paper lantern - {0313, new ItemRemakeInfo(0313, 01799, 4, new byte[] {09, 06, 04, 01, 10, 14, 14, 14}, new byte[] {09, 09, 09, 12, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // doghouse - {0314, new ItemRemakeInfo(0314, 01631, 4, new byte[] {01, 05, 09, 08, 11, 14, 14, 14}, new byte[] {11, 12, 09, 08, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // garden faucet - {0315, new ItemRemakeInfo(0315, 01493, 4, new byte[] {12, 04, 02, 07, 09, 14, 14, 14}, new byte[] {08, 09, 07, 08, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stroller - {0316, new ItemRemakeInfo(0316, 00929, 5, new byte[] {12, 11, 10, 02, 05, 09, 14, 14}, new byte[] {12, 11, 10, 02, 05, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // air conditioner - {0317, new ItemRemakeInfo(0317, 00928, 2, new byte[] {09, 11, 07, 14, 14, 14, 14, 14}, new byte[] {12, 11, 00, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pot rack - {0318, new ItemRemakeInfo(0318, 03616, 7, new byte[] {12, 01, 04, 07, 10, 09, 08, 12}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // system kitchen - {0320, new ItemRemakeInfo(0320, 03623, 3, new byte[] {06, 02, 04, 11, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // toy box - {0321, new ItemRemakeInfo(0321, 03618, 3, new byte[] {08, 00, 09, 07, 14, 14, 14, 14}, new byte[] {08, 00, 09, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 14, 14, 14, 14, 14}, false)}, // cutting board - {0322, new ItemRemakeInfo(0322, 03622, 3, new byte[] {09, 08, 01, 10, 14, 14, 14, 14}, new byte[] {09, 08, 01, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 07, 02, 04, 14, 14, 14, 14}, false)}, // floor seat - {0323, new ItemRemakeInfo(0323, 03621, 7, new byte[] {08, 01, 12, 10, 04, 00, 05, 02}, new byte[] {08, 01, 12, 10, 04, 00, 05, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 05, 00, 07, 02, 13, 13}, false)}, // loft bed with desk - {0324, new ItemRemakeInfo(0324, 03617, 7, new byte[] {08, 09, 07, 06, 02, 12, 10, 11}, new byte[] {08, 09, 07, 06, 02, 12, 10, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 06, 01, 13, 04, 14, 14, 14}, true)}, // stall - {0325, new ItemRemakeInfo(0325, 01263, 1, new byte[] {06, 07, 14, 14, 14, 14, 14, 14}, new byte[] {08, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pear wardrobe - {0326, new ItemRemakeInfo(0326, 03658, 2, new byte[] {06, 08, 09, 14, 14, 14, 14, 14}, new byte[] {06, 07, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo basket - {0327, new ItemRemakeInfo(0327, 03672, 6, new byte[] {07, 07, 07, 12, 12, 12, 07, 14}, new byte[] {07, 04, 00, 01, 02, 06, 01, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cardboard box - {0328, new ItemRemakeInfo(0328, 01081, 3, new byte[] {10, 12, 09, 08, 14, 14, 14, 14}, new byte[] {12, 10, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // upright piano - {0329, new ItemRemakeInfo(0329, 03675, 2, new byte[] {07, 12, 06, 14, 14, 14, 14, 14}, new byte[] {07, 12, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hay bed - {0334, new ItemRemakeInfo(0334, 03697, 7, new byte[] {12, 07, 01, 02, 04, 05, 06, 10}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // portable radio - {0335, new ItemRemakeInfo(0335, 03699, 6, new byte[] {10, 01, 10, 10, 10, 10, 10, 10}, new byte[] {12, 13, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fish print - {0336, new ItemRemakeInfo(0336, 03702, 3, new byte[] {08, 07, 09, 12, 14, 14, 14, 14}, new byte[] {08, 07, 09, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 04, 02, 14, 14, 14, 14, 14}, false)}, // study chair - {0337, new ItemRemakeInfo(0337, 03701, 3, new byte[] {08, 07, 09, 12, 14, 14, 14, 14}, new byte[] {08, 07, 09, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // study desk - {0340, new ItemRemakeInfo(0340, 00808, 4, new byte[] {09, 12, 06, 01, 07, 14, 14, 14}, new byte[] {08, 12, 12, 08, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mush table - {0342, new ItemRemakeInfo(0342, 01779, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 09, 10, 01, 02, 07, 06, 05}, new byte[] {12, 09, 10, 01, 02, 07, 06, 05}, false)}, // table with cloth - {0343, new ItemRemakeInfo(0343, 03499, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen arch - {0344, new ItemRemakeInfo(0344, 03502, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {09, 12, 11, 09, 14, 14, 14, 14}, false)}, // frozen bed - {0345, new ItemRemakeInfo(0345, 03500, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen pillar - {0346, new ItemRemakeInfo(0346, 03498, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen partition - {0347, new ItemRemakeInfo(0347, 03497, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen table - {0348, new ItemRemakeInfo(0348, 03504, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen tree - {0350, new ItemRemakeInfo(0350, 03505, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen counter - {0351, new ItemRemakeInfo(0351, 03503, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen chair - {0352, new ItemRemakeInfo(0352, 03501, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen sculpture - {0353, new ItemRemakeInfo(0353, 01861, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 13, 13, 14}, new byte[] {06, 01, 11, 13, 13, 02, 13, 14}, false)}, // stacked magazines - {0354, new ItemRemakeInfo(0354, 00832, 6, new byte[] {04, 06, 07, 01, 05, 02, 10, 14}, new byte[] {10, 10, 10, 10, 11, 11, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // modern office chair - {0355, new ItemRemakeInfo(0355, 00840, 3, new byte[] {12, 08, 09, 11, 14, 14, 14, 14}, new byte[] {12, 12, 10, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // office desk - {0356, new ItemRemakeInfo(0356, 03692, 2, new byte[] {08, 12, 09, 14, 14, 14, 14, 14}, new byte[] {08, 12, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 09, 04, 07, 14, 14, 14, 14}, false)}, // plain wooden shop sign - {0357, new ItemRemakeInfo(0357, 01759, 3, new byte[] {13, 13, 13, 08, 14, 14, 14, 14}, new byte[] {12, 12, 12, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stack of books - {0358, new ItemRemakeInfo(0358, 02020, 3, new byte[] {00, 09, 12, 10, 14, 14, 14, 14}, new byte[] {00, 09, 12, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 09, 14, 14, 14, 14, 14}, false)}, // director's chair - {0359, new ItemRemakeInfo(0359, 00955, 3, new byte[] {06, 06, 01, 10, 14, 14, 14, 14}, new byte[] {12, 12, 12, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // exit sign - {0360, new ItemRemakeInfo(0360, 00716, 4, new byte[] {07, 07, 07, 07, 08, 14, 14, 14}, new byte[] {06, 01, 06, 00, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // screen - {0362, new ItemRemakeInfo(0362, 03587, 2, new byte[] {07, 07, 10, 14, 14, 14, 14, 14}, new byte[] {10, 10, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fishing-rod stand - {0363, new ItemRemakeInfo(0363, 03591, 5, new byte[] {13, 13, 13, 13, 13, 13, 14, 14}, new byte[] {13, 02, 04, 06, 00, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // birthday candles - {0364, new ItemRemakeInfo(0364, 03592, 2, new byte[] {12, 09, 02, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // birthday cake - {0365, new ItemRemakeInfo(0365, 03593, 5, new byte[] {12, 02, 05, 06, 00, 11, 14, 14}, new byte[] {13, 13, 13, 13, 13, 13, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // birthday table - {0366, new ItemRemakeInfo(0366, 03594, 5, new byte[] {13, 13, 13, 13, 13, 13, 14, 14}, new byte[] {13, 02, 04, 06, 00, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // birthday sign - {0367, new ItemRemakeInfo(0367, 03596, 2, new byte[] {12, 00, 11, 14, 14, 14, 14, 14}, new byte[] {04, 05, 03, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pool - {0368, new ItemRemakeInfo(0368, 00891, 4, new byte[] {01, 04, 07, 09, 02, 14, 14, 14}, new byte[] {09, 12, 09, 09, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // holiday candle - {0370, new ItemRemakeInfo(0370, 01189, 3, new byte[] {10, 06, 13, 10, 14, 14, 14, 14}, new byte[] {10, 09, 13, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tire stack - {0373, new ItemRemakeInfo(0373, 00682, 4, new byte[] {09, 06, 09, 01, 12, 14, 14, 14}, new byte[] {08, 00, 10, 10, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // boomerang - {0374, new ItemRemakeInfo(0374, 00796, 1, new byte[] {09, 00, 14, 14, 14, 14, 14, 14}, new byte[] {08, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // retro stereo - {0375, new ItemRemakeInfo(0375, 03773, 2, new byte[] {10, 08, 09, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // terrarium - {0376, new ItemRemakeInfo(0376, 03775, 2, new byte[] {10, 09, 09, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hanging terrarium - {0377, new ItemRemakeInfo(0377, 03776, 2, new byte[] {00, 12, 11, 14, 14, 14, 14, 14}, new byte[] {09, 01, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // brick well - {0378, new ItemRemakeInfo(0378, 03785, 3, new byte[] {06, 07, 01, 06, 14, 14, 14, 14}, new byte[] {11, 09, 10, 04, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // potted ivy - {0379, new ItemRemakeInfo(0379, 03784, 5, new byte[] {10, 12, 00, 09, 06, 01, 14, 14}, new byte[] {10, 12, 00, 09, 06, 01, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // den chair - {0380, new ItemRemakeInfo(0380, 03783, 4, new byte[] {09, 00, 09, 08, 12, 14, 14, 14}, new byte[] {09, 00, 09, 08, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // den desk - {0381, new ItemRemakeInfo(0381, 01652, 4, new byte[] {01, 07, 04, 09, 06, 14, 14, 14}, new byte[] {07, 12, 05, 08, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // matryoshka - {0383, new ItemRemakeInfo(0383, 00805, 4, new byte[] {09, 12, 04, 01, 07, 14, 14, 14}, new byte[] {09, 12, 04, 08, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mush lamp - {0385, new ItemRemakeInfo(0385, 03808, 4, new byte[] {09, 09, 09, 09, 09, 14, 14, 14}, new byte[] {09, 12, 03, 01, 00, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mush log - {0387, new ItemRemakeInfo(0387, 03806, 4, new byte[] {09, 12, 06, 01, 00, 14, 14, 14}, new byte[] {08, 12, 06, 08, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mush partition - {0389, new ItemRemakeInfo(0389, 03805, 4, new byte[] {00, 12, 11, 01, 07, 14, 14, 14}, new byte[] {09, 09, 09, 09, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mush parasol - {0391, new ItemRemakeInfo(0391, 03816, 3, new byte[] {06, 09, 12, 10, 14, 14, 14, 14}, new byte[] {06, 09, 12, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // streetlamp - {0392, new ItemRemakeInfo(0392, 03818, 4, new byte[] {00, 08, 06, 04, 13, 14, 14, 14}, new byte[] {04, 01, 12, 12, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pennant - {0393, new ItemRemakeInfo(0393, 03819, 5, new byte[] {11, 06, 07, 01, 12, 09, 14, 14}, new byte[] {11, 06, 07, 01, 12, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // oil-barrel bathtub - {0394, new ItemRemakeInfo(0394, 03820, 3, new byte[] {12, 10, 05, 01, 14, 14, 14, 14}, new byte[] {12, 10, 05, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fan - {0395, new ItemRemakeInfo(0395, 03821, 4, new byte[] {12, 10, 02, 06, 07, 14, 14, 14}, new byte[] {12, 11, 02, 11, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // air circulator - {0396, new ItemRemakeInfo(0396, 00915, 6, new byte[] {08, 06, 04, 07, 01, 12, 10, 14}, new byte[] {08, 09, 09, 08, 09, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cuckoo clock - {0397, new ItemRemakeInfo(0397, 03681, 7, new byte[] {10, 01, 12, 04, 09, 06, 06, 07}, new byte[] {10, 10, 12, 12, 09, 09, 08, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // piano bench - {0398, new ItemRemakeInfo(0398, 03624, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 12, 00, 01, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute bed - {0399, new ItemRemakeInfo(0399, 00331, 3, new byte[] {09, 00, 12, 10, 14, 14, 14, 14}, new byte[] {09, 00, 12, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // birdbath - {0400, new ItemRemakeInfo(0400, 03683, 5, new byte[] {07, 00, 09, 08, 11, 10, 14, 14}, new byte[] {12, 12, 06, 12, 12, 04, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plain sink - {0402, new ItemRemakeInfo(0402, 00849, 6, new byte[] {10, 12, 00, 09, 04, 01, 02, 14}, new byte[] {09, 11, 10, 08, 10, 10, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // amp - {0403, new ItemRemakeInfo(0403, 03431, 7, new byte[] {06, 05, 01, 07, 12, 10, 11, 09}, new byte[] {06, 12, 01, 07, 12, 09, 11, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall fan - {0404, new ItemRemakeInfo(0404, 02014, 2, new byte[] {00, 09, 12, 14, 14, 14, 14, 14}, new byte[] {08, 11, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lecture-hall desk - {0405, new ItemRemakeInfo(0405, 03822, 2, new byte[] {10, 09, 10, 14, 14, 14, 14, 14}, new byte[] {11, 01, 04, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pro tape recorder - {0406, new ItemRemakeInfo(0406, 02013, 1, new byte[] {00, 09, 14, 14, 14, 14, 14, 14}, new byte[] {08, 11, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lecture-hall bench - {0407, new ItemRemakeInfo(0407, 01157, 3, new byte[] {01, 09, 12, 10, 14, 14, 14, 14}, new byte[] {11, 11, 10, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // brick oven - {0408, new ItemRemakeInfo(0408, 01171, 5, new byte[] {10, 01, 04, 07, 11, 09, 14, 14}, new byte[] {12, 12, 12, 12, 12, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // synthesizer - {0409, new ItemRemakeInfo(0409, 01221, 2, new byte[] {10, 11, 01, 14, 14, 14, 14, 14}, new byte[] {10, 12, 01, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // video camera - {0410, new ItemRemakeInfo(0410, 00941, 3, new byte[] {10, 12, 00, 02, 14, 14, 14, 14}, new byte[] {11, 11, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 10, 12, 03, 06, 05, 07, 02}, true)}, // DJ's turntable - {0414, new ItemRemakeInfo(0414, 04116, 6, new byte[] {12, 12, 12, 12, 12, 12, 12, 14}, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // whiteboard - {0415, new ItemRemakeInfo(0415, 04066, 5, new byte[] {06, 02, 05, 00, 12, 13, 14, 14}, new byte[] {01, 02, 05, 00, 12, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // illuminated tree - {0416, new ItemRemakeInfo(0416, 04074, 4, new byte[] {07, 02, 04, 06, 12, 14, 14, 14}, new byte[] {07, 02, 04, 06, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // illuminated reindeer - {0417, new ItemRemakeInfo(0417, 04108, 3, new byte[] {07, 02, 04, 12, 14, 14, 14, 14}, new byte[] {01, 06, 00, 04, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // illuminated present - {0418, new ItemRemakeInfo(0418, 04131, 3, new byte[] {05, 02, 07, 12, 14, 14, 14, 14}, new byte[] {05, 02, 00, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // illuminated snowflakes - {0419, new ItemRemakeInfo(0419, 04099, 2, new byte[] {08, 12, 08, 14, 14, 14, 14, 14}, new byte[] {00, 07, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // formal paper - {0420, new ItemRemakeInfo(0420, 04068, 4, new byte[] {12, 02, 07, 05, 10, 14, 14, 14}, new byte[] {12, 02, 07, 05, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {08, 04, 02, 07, 06, 14, 14, 14}, false)}, // table setting - {0421, new ItemRemakeInfo(0421, 04230, 5, new byte[] {12, 01, 02, 06, 04, 03, 14, 14}, new byte[] {12, 01, 02, 06, 04, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glass holder with candle - {0422, new ItemRemakeInfo(0422, 03995, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 04, 00, 01, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute DIY table - {0423, new ItemRemakeInfo(0423, 03996, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 04, 00, 01, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute wall-mounted clock - {0424, new ItemRemakeInfo(0424, 03997, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 04, 00, 12, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute wardrobe - {0425, new ItemRemakeInfo(0425, 03998, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 04, 00, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute sofa - {0426, new ItemRemakeInfo(0426, 03999, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 04, 00, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute chair - {0427, new ItemRemakeInfo(0427, 04000, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 12, 12, 12, 03, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute tea table - {0428, new ItemRemakeInfo(0428, 04001, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 04, 00, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute vanity - {0429, new ItemRemakeInfo(0429, 04002, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 04, 03, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute floor lamp - {0430, new ItemRemakeInfo(0430, 04003, 4, new byte[] {12, 05, 07, 01, 04, 14, 14, 14}, new byte[] {02, 04, 00, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cute music player - {0431, new ItemRemakeInfo(0431, 02586, 2, new byte[] {08, 00, 12, 14, 14, 14, 14, 14}, new byte[] {10, 06, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // natural garden chair - {0432, new ItemRemakeInfo(0432, 03943, 4, new byte[] {08, 00, 09, 09, 00, 14, 14, 14}, new byte[] {10, 10, 10, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ironwood DIY workbench - {0433, new ItemRemakeInfo(0433, 03946, 4, new byte[] {11, 10, 06, 04, 01, 14, 14, 14}, new byte[] {11, 10, 06, 04, 01, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 06, 04, 00, 08, 09, 14}, false)}, // outdoor table - {0434, new ItemRemakeInfo(0434, 03947, 4, new byte[] {11, 10, 06, 04, 01, 14, 14, 14}, new byte[] {11, 10, 06, 04, 01, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 06, 04, 00, 08, 09, 14}, false)}, // outdoor bench - {0435, new ItemRemakeInfo(0435, 03987, 5, new byte[] {12, 10, 11, 09, 01, 04, 14, 14}, new byte[] {12, 10, 11, 09, 01, 04, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall-mounted phone - {0436, new ItemRemakeInfo(0436, 04009, 6, new byte[] {12, 10, 11, 01, 05, 02, 07, 14}, new byte[] {12, 10, 11, 01, 05, 02, 07, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cordless phone - {0437, new ItemRemakeInfo(0437, 04101, 3, new byte[] {12, 02, 09, 10, 14, 14, 14, 14}, new byte[] {12, 02, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, false)}, // fax machine - {0438, new ItemRemakeInfo(0438, 04279, 5, new byte[] {05, 05, 05, 05, 05, 05, 14, 14}, new byte[] {08, 08, 07, 13, 13, 13, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen-treat set - {0440, new ItemRemakeInfo(0440, 04027, 4, new byte[] {07, 02, 03, 12, 13, 14, 14, 14}, new byte[] {05, 06, 06, 07, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // floral swag - {0441, new ItemRemakeInfo(0441, 03396, 2, new byte[] {08, 00, 12, 14, 14, 14, 14, 14}, new byte[] {10, 06, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // natural garden table - {0442, new ItemRemakeInfo(0442, 04034, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 06, 05, 00, 14, 14, 14, 14}, false)}, // scattered papers - {0443, new ItemRemakeInfo(0443, 04135, 3, new byte[] {12, 10, 08, 11, 14, 14, 14, 14}, new byte[] {12, 10, 08, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // freezer - {0444, new ItemRemakeInfo(0444, 03965, 3, new byte[] {07, 02, 05, 12, 14, 14, 14, 14}, new byte[] {07, 02, 05, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 01, 09, 13, 14, 14, 14, 14}, false)}, // painting set - {0445, new ItemRemakeInfo(0445, 04030, 3, new byte[] {11, 07, 09, 10, 14, 14, 14, 14}, new byte[] {12, 09, 02, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bathroom towel rack - {0446, new ItemRemakeInfo(0446, 03948, 4, new byte[] {12, 02, 10, 09, 05, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // accessories stand - {0448, new ItemRemakeInfo(0448, 04025, 5, new byte[] {00, 12, 04, 06, 12, 12, 14, 14}, new byte[] {12, 09, 08, 09, 05, 04, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // unglazed dish set - {0451, new ItemRemakeInfo(0451, 03991, 5, new byte[] {06, 06, 06, 02, 06, 12, 14, 14}, new byte[] {13, 04, 01, 01, 07, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // festive tree - {0452, new ItemRemakeInfo(0452, 03966, 5, new byte[] {06, 04, 06, 02, 06, 12, 14, 14}, new byte[] {13, 04, 01, 02, 07, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // big festive tree - {0453, new ItemRemakeInfo(0453, 04067, 5, new byte[] {06, 06, 06, 02, 06, 12, 14, 14}, new byte[] {13, 04, 01, 12, 07, 07, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tabletop festive tree - {0454, new ItemRemakeInfo(0454, 03993, 7, new byte[] {01, 07, 06, 04, 02, 07, 05, 11}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // analog kitchen scale - {0455, new ItemRemakeInfo(0455, 03961, 1, new byte[] {05, 03, 14, 14, 14, 14, 14, 14}, new byte[] {03, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fortune-telling set - {0456, new ItemRemakeInfo(0456, 00669, 3, new byte[] {08, 09, 12, 04, 14, 14, 14, 14}, new byte[] {09, 09, 08, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ukulele - {0457, new ItemRemakeInfo(0457, 04006, 3, new byte[] {08, 02, 05, 12, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // climbing wall - {0458, new ItemRemakeInfo(0458, 04119, 3, new byte[] {08, 06, 08, 08, 14, 14, 14, 14}, new byte[] {08, 06, 02, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // macrame tapestry - {0460, new ItemRemakeInfo(0460, 03992, 3, new byte[] {09, 08, 12, 10, 14, 14, 14, 14}, new byte[] {09, 08, 12, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // key holder - {0461, new ItemRemakeInfo(0461, 03967, 3, new byte[] {09, 12, 09, 02, 14, 14, 14, 14}, new byte[] {11, 11, 10, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // broom and dustpan - {0462, new ItemRemakeInfo(0462, 04076, 1, new byte[] {02, 10, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // nail-art set - {0463, new ItemRemakeInfo(0463, 00889, 5, new byte[] {07, 01, 04, 06, 09, 10, 14, 14}, new byte[] {11, 11, 11, 11, 11, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // camp stove - {0465, new ItemRemakeInfo(0465, 04014, 7, new byte[] {10, 12, 07, 01, 04, 05, 11, 11}, new byte[] {10, 12, 07, 01, 04, 05, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // folding floor lamp - {0466, new ItemRemakeInfo(0466, 04338, 6, new byte[] {01, 07, 05, 06, 02, 10, 00, 14}, new byte[] {12, 10, 10, 10, 12, 01, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // portable record player - {0467, new ItemRemakeInfo(0467, 04013, 2, new byte[] {01, 04, 10, 14, 14, 14, 14, 14}, new byte[] {10, 10, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // punching bag - {0468, new ItemRemakeInfo(0468, 04081, 7, new byte[] {06, 07, 01, 04, 11, 06, 12, 05}, new byte[] {06, 07, 01, 04, 10, 09, 12, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // camping cot - {0469, new ItemRemakeInfo(0469, 04075, 1, new byte[] {09, 01, 14, 14, 14, 14, 14, 14}, new byte[] {07, 07, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // gong - {0470, new ItemRemakeInfo(0470, 04052, 5, new byte[] {12, 05, 04, 05, 06, 11, 14, 14}, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan bed - {0471, new ItemRemakeInfo(0471, 04113, 5, new byte[] {11, 07, 01, 06, 04, 10, 14, 14}, new byte[] {05, 06, 04, 08, 05, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hose reel - {0472, new ItemRemakeInfo(0472, 03962, 7, new byte[] {05, 06, 03, 02, 07, 13, 13, 08}, new byte[] {05, 06, 03, 02, 07, 12, 13, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // inflatable sofa - {0474, new ItemRemakeInfo(0474, 04094, 3, new byte[] {09, 04, 12, 10, 14, 14, 14, 14}, new byte[] {06, 06, 06, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // floating-biotope planter - {0475, new ItemRemakeInfo(0475, 04073, 5, new byte[] {08, 12, 05, 00, 07, 11, 14, 14}, new byte[] {08, 12, 05, 00, 01, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // classic pitcher - {0476, new ItemRemakeInfo(0476, 00870, 3, new byte[] {12, 04, 10, 02, 14, 14, 14, 14}, new byte[] {13, 13, 10, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // book stands - {0477, new ItemRemakeInfo(0477, 04379, 6, new byte[] {12, 08, 09, 01, 07, 02, 12, 14}, new byte[] {06, 07, 12, 00, 06, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // springy ride-on - {0478, new ItemRemakeInfo(0478, 03950, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique chair - {0479, new ItemRemakeInfo(0479, 03951, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique console table - {0480, new ItemRemakeInfo(0480, 03952, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique table - {0481, new ItemRemakeInfo(0481, 03953, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {07, 07, 07, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique phone - {0482, new ItemRemakeInfo(0482, 03954, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {07, 07, 07, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique clock - {0483, new ItemRemakeInfo(0483, 03955, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {05, 05, 05, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique vanity - {0484, new ItemRemakeInfo(0484, 03956, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique bureau - {0485, new ItemRemakeInfo(0485, 03957, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique bed - {0486, new ItemRemakeInfo(0486, 03958, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique mini table - {0487, new ItemRemakeInfo(0487, 03959, 2, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {09, 08, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique wardrobe - {0488, new ItemRemakeInfo(0488, 04111, 7, new byte[] {05, 01, 07, 08, 10, 09, 11, 07}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // old-fashioned alarm clock - {0489, new ItemRemakeInfo(0489, 04029, 7, new byte[] {10, 08, 06, 04, 01, 07, 00, 12}, new byte[] {10, 08, 06, 04, 01, 10, 10, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rotary phone - {0490, new ItemRemakeInfo(0490, 01606, 5, new byte[] {08, 09, 12, 12, 01, 10, 14, 14}, new byte[] {08, 09, 12, 11, 10, 07, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // serving cart - {0491, new ItemRemakeInfo(0491, 04392, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // magic kit - {0492, new ItemRemakeInfo(0492, 03960, 5, new byte[] {04, 01, 06, 07, 08, 13, 14, 14}, new byte[] {12, 12, 12, 09, 06, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // handy water cooler - {0493, new ItemRemakeInfo(0493, 03949, 4, new byte[] {01, 01, 01, 02, 12, 14, 14, 14}, new byte[] {06, 06, 06, 06, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // anthurium plant - {0494, new ItemRemakeInfo(0494, 01829, 4, new byte[] {06, 06, 06, 06, 06, 14, 14, 14}, new byte[] {09, 05, 07, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cypress plant - {0497, new ItemRemakeInfo(0497, 04129, 5, new byte[] {10, 09, 01, 07, 04, 12, 14, 14}, new byte[] {06, 06, 06, 06, 06, 06, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // monstera - {0498, new ItemRemakeInfo(0498, 04132, 4, new byte[] {12, 09, 06, 04, 10, 14, 14, 14}, new byte[] {06, 06, 06, 06, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // yucca - {0499, new ItemRemakeInfo(0499, 04080, 6, new byte[] {12, 10, 08, 02, 05, 06, 05, 14}, new byte[] {12, 10, 12, 12, 12, 12, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // long bathtub - {0500, new ItemRemakeInfo(0500, 04078, 3, new byte[] {10, 12, 01, 13, 14, 14, 14, 14}, new byte[] {11, 11, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // barbell - {0501, new ItemRemakeInfo(0501, 01838, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 07, 02, 04, 14, 14, 14, 14}, false)}, // ironing set - {0502, new ItemRemakeInfo(0502, 04412, 2, new byte[] {02, 12, 10, 14, 14, 14, 14, 14}, new byte[] {01, 04, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cotton-candy stall - {0503, new ItemRemakeInfo(0503, 04045, 5, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan waste bin - {0504, new ItemRemakeInfo(0504, 04049, 5, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan wardrobe - {0505, new ItemRemakeInfo(0505, 04046, 5, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan end table - {0506, new ItemRemakeInfo(0506, 04047, 5, new byte[] {12, 05, 04, 05, 06, 11, 14, 14}, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan stool - {0507, new ItemRemakeInfo(0507, 04053, 5, new byte[] {12, 05, 04, 05, 06, 11, 14, 14}, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan armchair - {0508, new ItemRemakeInfo(0508, 04048, 5, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {12, 12, 12, 11, 12, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan towel basket - {0509, new ItemRemakeInfo(0509, 04050, 5, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {09, 09, 09, 12, 10, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan table lamp - {0510, new ItemRemakeInfo(0510, 04051, 5, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan vanity - {0511, new ItemRemakeInfo(0511, 04054, 5, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {09, 00, 07, 12, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattan low table - {0512, new ItemRemakeInfo(0512, 04017, 3, new byte[] {11, 07, 09, 10, 14, 14, 14, 14}, new byte[] {10, 07, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shower set - {0513, new ItemRemakeInfo(0513, 04104, 5, new byte[] {10, 10, 10, 10, 10, 10, 14, 14}, new byte[] {10, 06, 08, 01, 07, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frying pan - {0515, new ItemRemakeInfo(0515, 04137, 6, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {12, 12, 12, 12, 12, 12, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // diner chair - {0516, new ItemRemakeInfo(0516, 04138, 6, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 05, 02, 12, 10, 14}, false)}, // diner counter chair - {0517, new ItemRemakeInfo(0517, 04139, 6, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // diner counter table - {0518, new ItemRemakeInfo(0518, 04140, 5, new byte[] {01, 06, 07, 12, 10, 09, 14, 14}, new byte[] {01, 06, 07, 12, 10, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 06, 07, 14, 14, 14, 14, 14}, false)}, // retro gas pump - {0519, new ItemRemakeInfo(0519, 04141, 6, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {12, 12, 12, 12, 12, 12, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // diner sofa - {0520, new ItemRemakeInfo(0520, 04142, 6, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 05, 02, 12, 10, 14}, false)}, // diner dining table - {0521, new ItemRemakeInfo(0521, 04143, 4, new byte[] {04, 07, 01, 02, 01, 14, 14, 14}, new byte[] {01, 00, 06, 03, 04, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // diner neon sign - {0522, new ItemRemakeInfo(0522, 04144, 6, new byte[] {01, 04, 07, 06, 02, 12, 03, 14}, new byte[] {01, 04, 07, 06, 02, 12, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 04, 10, 14, 14, 14, 14, 14}, false)}, // diner neon clock - {0523, new ItemRemakeInfo(0523, 04441, 6, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 05, 02, 12, 10, 14}, false)}, // diner mini table - {0524, new ItemRemakeInfo(0524, 03406, 4, new byte[] {08, 12, 01, 04, 07, 14, 14, 14}, new byte[] {08, 12, 06, 10, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // beekeeper's hive - {0525, new ItemRemakeInfo(0525, 04023, 2, new byte[] {09, 10, 11, 14, 14, 14, 14, 14}, new byte[] {11, 12, 04, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pants press - {0526, new ItemRemakeInfo(0526, 01161, 3, new byte[] {00, 11, 12, 12, 14, 14, 14, 14}, new byte[] {11, 11, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cream and sugar - {0528, new ItemRemakeInfo(0528, 04445, 3, new byte[] {08, 11, 09, 10, 14, 14, 14, 14}, new byte[] {08, 11, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 10, 12, 09, 14, 14, 14, 14}, false)}, // vintage TV tray - {0529, new ItemRemakeInfo(0529, 03619, 7, new byte[] {07, 12, 09, 00, 01, 06, 00, 12}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // soup kettle - {0530, new ItemRemakeInfo(0530, 04546, 1, new byte[] {06, 07, 14, 14, 14, 14, 14, 14}, new byte[] {08, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pear bed - {0531, new ItemRemakeInfo(0531, 04125, 3, new byte[] {07, 00, 09, 12, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden bookshelf - {0532, new ItemRemakeInfo(0532, 01840, 1, new byte[] {12, 10, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // whirlpool bath - {0543, new ItemRemakeInfo(0543, 04572, 7, new byte[] {07, 04, 01, 06, 06, 02, 03, 12}, new byte[] {11, 11, 11, 11, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shaded floor lamp - {0544, new ItemRemakeInfo(0544, 01744, 4, new byte[] {11, 12, 10, 01, 04, 14, 14, 14}, new byte[] {12, 12, 12, 12, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall clock - {0545, new ItemRemakeInfo(0545, 04133, 5, new byte[] {10, 12, 11, 05, 01, 07, 14, 14}, new byte[] {12, 12, 12, 12, 10, 01, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // double-sided wall clock - {0546, new ItemRemakeInfo(0546, 04035, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 13, 13, 09, 05, 14, 14, 14}, true)}, // log garden lounge - {0547, new ItemRemakeInfo(0547, 04036, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 13, 13, 09, 05, 14, 14, 14}, true)}, // log decorative shelves - {0548, new ItemRemakeInfo(0548, 04037, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {08, 08, 08, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // log wall-mounted clock - {0549, new ItemRemakeInfo(0549, 04038, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {08, 08, 08, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // log stool - {0550, new ItemRemakeInfo(0550, 04039, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 13, 13, 09, 05, 14, 14, 14}, true)}, // log chair - {0551, new ItemRemakeInfo(0551, 04040, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 13, 13, 09, 05, 14, 14, 14}, true)}, // log dining table - {0552, new ItemRemakeInfo(0552, 04041, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 09, 05, 14, 14, 14, 14}, false)}, // log bed - {0553, new ItemRemakeInfo(0553, 04042, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {08, 08, 08, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // log bench - {0554, new ItemRemakeInfo(0554, 04043, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 13, 13, 09, 05, 14, 14, 14}, true)}, // log round table - {0555, new ItemRemakeInfo(0555, 04044, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 13, 13, 09, 05, 14, 14, 14}, true)}, // log extra-long sofa - {0556, new ItemRemakeInfo(0556, 04110, 3, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {10, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // essay set - {0558, new ItemRemakeInfo(0558, 04019, 5, new byte[] {11, 01, 02, 05, 07, 10, 14, 14}, new byte[] {10, 10, 10, 10, 10, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stand mixer - {0559, new ItemRemakeInfo(0559, 01125, 2, new byte[] {09, 00, 11, 14, 14, 14, 14, 14}, new byte[] {12, 13, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // revolving spice rack - {0561, new ItemRemakeInfo(0561, 04109, 3, new byte[] {11, 12, 10, 01, 14, 14, 14, 14}, new byte[] {11, 11, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // double-door refrigerator - {0562, new ItemRemakeInfo(0562, 04114, 5, new byte[] {01, 07, 05, 08, 00, 09, 14, 14}, new byte[] {12, 12, 12, 12, 12, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tissue box - {0563, new ItemRemakeInfo(0563, 04687, 5, new byte[] {01, 06, 04, 00, 05, 02, 14, 14}, new byte[] {11, 08, 12, 10, 00, 02, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // toolbox - {0564, new ItemRemakeInfo(0564, 03970, 3, new byte[] {01, 04, 09, 10, 14, 14, 14, 14}, new byte[] {01, 04, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial decorative shelves - {0565, new ItemRemakeInfo(0565, 03971, 3, new byte[] {01, 04, 09, 10, 14, 14, 14, 14}, new byte[] {01, 04, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial partition - {0566, new ItemRemakeInfo(0566, 03972, 3, new byte[] {01, 04, 09, 10, 14, 14, 14, 14}, new byte[] {07, 11, 07, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial chest - {0567, new ItemRemakeInfo(0567, 03973, 3, new byte[] {01, 04, 09, 10, 14, 14, 14, 14}, new byte[] {01, 04, 07, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial bed - {0568, new ItemRemakeInfo(0568, 03974, 3, new byte[] {01, 04, 09, 10, 14, 14, 14, 14}, new byte[] {01, 04, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial low table - {0569, new ItemRemakeInfo(0569, 04708, 4, new byte[] {09, 12, 09, 01, 07, 14, 14, 14}, new byte[] {08, 12, 09, 08, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mush low stool - {0571, new ItemRemakeInfo(0571, 04719, 4, new byte[] {13, 13, 12, 04, 13, 14, 14, 14}, new byte[] {09, 08, 10, 05, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // celebratory candles - {0572, new ItemRemakeInfo(0572, 00954, 6, new byte[] {11, 01, 07, 04, 06, 12, 10, 14}, new byte[] {11, 12, 12, 10, 09, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // espresso maker - {0573, new ItemRemakeInfo(0573, 04722, 3, new byte[] {09, 04, 01, 10, 14, 14, 14, 14}, new byte[] {09, 04, 01, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // monster statue - {0574, new ItemRemakeInfo(0574, 01509, 7, new byte[] {01, 04, 07, 06, 02, 12, 10, 11}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // robot hero - {0575, new ItemRemakeInfo(0575, 01507, 3, new byte[] {13, 13, 13, 10, 14, 14, 14, 14}, new byte[] {13, 07, 12, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plaza teacup ride - {0576, new ItemRemakeInfo(0576, 04102, 2, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 04, 01, 07, 14, 14, 14}, false)}, // poolside bed - {0577, new ItemRemakeInfo(0577, 03977, 5, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {13, 09, 02, 07, 03, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shell arch - {0578, new ItemRemakeInfo(0578, 03978, 5, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {08, 09, 02, 07, 03, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shell partition - {0579, new ItemRemakeInfo(0579, 03979, 5, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {09, 00, 02, 07, 03, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shell stool - {0580, new ItemRemakeInfo(0580, 03980, 5, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shell table - {0582, new ItemRemakeInfo(0582, 03982, 5, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shell fountain - {0583, new ItemRemakeInfo(0583, 03983, 5, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shell bed - {0584, new ItemRemakeInfo(0584, 03984, 5, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shell lamp - {0585, new ItemRemakeInfo(0585, 04069, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 01, 04, 06, 07, 02, 14}, false)}, // table lamp - {0586, new ItemRemakeInfo(0586, 04754, 2, new byte[] {10, 12, 01, 14, 14, 14, 14, 14}, new byte[] {11, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // throwback gothic mirror - {0587, new ItemRemakeInfo(0587, 04759, 6, new byte[] {01, 04, 07, 02, 06, 12, 10, 14}, new byte[] {10, 10, 10, 10, 10, 10, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // throwback race-car bed - {0588, new ItemRemakeInfo(0588, 04757, 5, new byte[] {12, 01, 10, 08, 06, 11, 14, 14}, new byte[] {02, 02, 02, 02, 02, 02, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // throwback skull radio - {0589, new ItemRemakeInfo(0589, 04756, 6, new byte[] {07, 01, 06, 04, 12, 11, 03, 14}, new byte[] {01, 04, 07, 06, 02, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // throwback wall clock - {0591, new ItemRemakeInfo(0591, 04758, 5, new byte[] {00, 09, 01, 04, 06, 12, 14, 14}, new byte[] {00, 09, 12, 12, 01, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // throwback mitt chair - {0592, new ItemRemakeInfo(0592, 04762, 6, new byte[] {07, 01, 04, 07, 05, 12, 10, 14}, new byte[] {06, 12, 12, 11, 07, 00, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // throwback container - {0593, new ItemRemakeInfo(0593, 04753, 5, new byte[] {01, 04, 06, 02, 10, 07, 14, 14}, new byte[] {08, 08, 08, 08, 08, 08, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // throwback wrestling figure - {0594, new ItemRemakeInfo(0594, 04760, 7, new byte[] {01, 04, 06, 10, 10, 12, 12, 12}, new byte[] {01, 04, 06, 00, 07, 04, 01, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // throwback hat table - {0595, new ItemRemakeInfo(0595, 04761, 5, new byte[] {11, 07, 01, 06, 04, 10, 14, 14}, new byte[] {00, 05, 04, 01, 01, 01, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // throwback rocket - {0596, new ItemRemakeInfo(0596, 04077, 5, new byte[] {13, 13, 05, 00, 06, 10, 14, 14}, new byte[] {13, 13, 12, 10, 01, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // party garland - {0598, new ItemRemakeInfo(0598, 05150, 5, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {12, 09, 02, 07, 03, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shell speaker - {0599, new ItemRemakeInfo(0599, 02326, 3, new byte[] {06, 10, 12, 09, 14, 14, 14, 14}, new byte[] {11, 08, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // water pump - {0600, new ItemRemakeInfo(0600, 05165, 4, new byte[] {07, 11, 09, 10, 12, 14, 14, 14}, new byte[] {12, 12, 12, 12, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall-mounted candle - {0601, new ItemRemakeInfo(0601, 04122, 3, new byte[] {10, 11, 02, 08, 14, 14, 14, 14}, new byte[] {10, 11, 02, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, false)}, // cartoonist's set - {0602, new ItemRemakeInfo(0602, 03986, 7, new byte[] {10, 12, 11, 01, 07, 04, 02, 05}, new byte[] {10, 12, 11, 01, 07, 04, 02, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall-mounted TV (20 in.) - {0603, new ItemRemakeInfo(0603, 04072, 1, new byte[] {10, 01, 14, 14, 14, 14, 14, 14}, new byte[] {12, 05, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // toilet-cleaning set - {0604, new ItemRemakeInfo(0604, 02772, 2, new byte[] {09, 12, 10, 14, 14, 14, 14, 14}, new byte[] {10, 10, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fancy violin - {0605, new ItemRemakeInfo(0605, 03430, 4, new byte[] {13, 12, 01, 04, 05, 14, 14, 14}, new byte[] {13, 10, 07, 05, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // playground gym - {0606, new ItemRemakeInfo(0606, 05337, 3, new byte[] {04, 02, 05, 07, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // three-tiered snowperson - {0607, new ItemRemakeInfo(0607, 05338, 7, new byte[] {11, 10, 12, 00, 08, 09, 11, 07}, new byte[] {11, 10, 12, 00, 08, 09, 11, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {11, 12, 09, 09, 12, 08, 11, 07}, false)}, // simple panel - {0608, new ItemRemakeInfo(0608, 01330, 2, new byte[] {00, 07, 12, 14, 14, 14, 14, 14}, new byte[] {11, 07, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // basic teacher's desk - {0609, new ItemRemakeInfo(0609, 03471, 3, new byte[] {11, 07, 12, 09, 14, 14, 14, 14}, new byte[] {10, 11, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // light switch - {0610, new ItemRemakeInfo(0610, 03400, 5, new byte[] {12, 10, 11, 01, 04, 06, 14, 14}, new byte[] {12, 10, 11, 02, 05, 07, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dish-drying rack - {0611, new ItemRemakeInfo(0611, 04308, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 07, 11, 08, 05, 14, 14, 14}, new byte[] {03, 06, 12, 09, 04, 14, 14, 14}, false)}, // unfinished puzzle - {0612, new ItemRemakeInfo(0612, 04093, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {02, 00, 05, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo drum - {0613, new ItemRemakeInfo(0613, 04015, 3, new byte[] {12, 02, 05, 11, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shower booth - {0616, new ItemRemakeInfo(0616, 04071, 1, new byte[] {06, 10, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // electronics kit - {0617, new ItemRemakeInfo(0617, 03976, 1, new byte[] {00, 01, 14, 14, 14, 14, 14, 14}, new byte[] {00, 01, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // orange wall-mounted clock - {0618, new ItemRemakeInfo(0618, 03975, 1, new byte[] {00, 01, 14, 14, 14, 14, 14, 14}, new byte[] {06, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // orange end table - {0619, new ItemRemakeInfo(0619, 04011, 1, new byte[] {01, 01, 14, 14, 14, 14, 14, 14}, new byte[] {06, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cherry speakers - {0620, new ItemRemakeInfo(0620, 04012, 1, new byte[] {01, 01, 14, 14, 14, 14, 14, 14}, new byte[] {06, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cherry lamp - {0622, new ItemRemakeInfo(0622, 04127, 1, new byte[] {02, 07, 14, 14, 14, 14, 14, 14}, new byte[] {09, 01, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // peach chair - {0623, new ItemRemakeInfo(0623, 04128, 1, new byte[] {02, 07, 14, 14, 14, 14, 14, 14}, new byte[] {06, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // peach surprise box - {0624, new ItemRemakeInfo(0624, 04134, 1, new byte[] {01, 06, 14, 14, 14, 14, 14, 14}, new byte[] {07, 07, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // apple chair - {0625, new ItemRemakeInfo(0625, 02596, 1, new byte[] {01, 06, 14, 14, 14, 14, 14, 14}, new byte[] {07, 07, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // juicy-apple TV - {0626, new ItemRemakeInfo(0626, 04070, 3, new byte[] {00, 04, 07, 09, 14, 14, 14, 14}, new byte[] {09, 09, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // street organ - {0627, new ItemRemakeInfo(0627, 04033, 2, new byte[] {00, 09, 10, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // traditional tea set - {0628, new ItemRemakeInfo(0628, 05543, 4, new byte[] {09, 08, 01, 05, 07, 14, 14, 14}, new byte[] {09, 08, 01, 05, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-block stool - {0629, new ItemRemakeInfo(0629, 03251, 4, new byte[] {11, 12, 01, 04, 10, 14, 14, 14}, new byte[] {01, 08, 00, 05, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // gas range - {0630, new ItemRemakeInfo(0630, 04226, 2, new byte[] {04, 06, 10, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // basketball hoop - {0641, new ItemRemakeInfo(0641, 00863, 2, new byte[] {06, 01, 04, 14, 14, 14, 14, 14}, new byte[] {00, 07, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // billiard table - {0642, new ItemRemakeInfo(0642, 05636, 3, new byte[] {08, 10, 09, 01, 14, 14, 14, 14}, new byte[] {10, 07, 12, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden-plank sign - {0643, new ItemRemakeInfo(0643, 05635, 5, new byte[] {00, 01, 05, 10, 09, 06, 14, 14}, new byte[] {00, 12, 13, 06, 08, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tiny library - {0644, new ItemRemakeInfo(0644, 04124, 2, new byte[] {00, 08, 09, 14, 14, 14, 14, 14}, new byte[] {01, 01, 07, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden fish - {0647, new ItemRemakeInfo(0647, 05931, 2, new byte[] {11, 10, 09, 14, 14, 14, 14, 14}, new byte[] {11, 10, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // jail bars - {0648, new ItemRemakeInfo(0648, 05976, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {04, 03, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo sphere - {0650, new ItemRemakeInfo(0650, 05978, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo lunch box - {0651, new ItemRemakeInfo(0651, 00677, 2, new byte[] {06, 08, 09, 14, 14, 14, 14, 14}, new byte[] {11, 09, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // deer scare - {0652, new ItemRemakeInfo(0652, 06426, 7, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Cyrano's photo - {0653, new ItemRemakeInfo(0653, 02379, 7, new byte[] {04, 00, 06, 01, 03, 02, 12, 10}, new byte[] {04, 00, 06, 01, 03, 02, 12, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // watering can - {0654, new ItemRemakeInfo(0654, 06826, 6, new byte[] {07, 06, 05, 03, 02, 00, 12, 14}, new byte[] {07, 06, 05, 03, 02, 00, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // nova light - {0655, new ItemRemakeInfo(0655, 04118, 2, new byte[] {11, 08, 00, 14, 14, 14, 14, 14}, new byte[] {10, 09, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // magnetic knife rack - {0656, new ItemRemakeInfo(0656, 06832, 1, new byte[] {02, 02, 14, 14, 14, 14, 14, 14}, new byte[] {02, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cherry-blossom clock - {0657, new ItemRemakeInfo(0657, 06831, 1, new byte[] {09, 08, 14, 14, 14, 14, 14, 14}, new byte[] {02, 02, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // blossom-viewing lantern - {0658, new ItemRemakeInfo(0658, 07048, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 04, 01, 06, 05, 01, 07, 14}, new byte[] {04, 04, 02, 06, 13, 01, 03, 14}, false)}, // pile of zen cushions - {0659, new ItemRemakeInfo(0659, 07047, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 04, 01, 06, 05, 01, 07, 14}, new byte[] {04, 05, 02, 06, 13, 01, 03, 14}, false)}, // zen cushion - {0661, new ItemRemakeInfo(0661, 07133, 7, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 00, 02, 04, 06, 14, 14, 14}, true)}, // wooden mini table - {0662, new ItemRemakeInfo(0662, 07134, 7, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden low table - {0663, new ItemRemakeInfo(0663, 07137, 7, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden full-length mirror - {0664, new ItemRemakeInfo(0664, 07132, 7, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {00, 02, 05, 06, 14, 14, 14, 14}, false)}, // wooden double bed - {0665, new ItemRemakeInfo(0665, 07140, 5, new byte[] {13, 12, 13, 13, 13, 13, 14, 14}, new byte[] {12, 12, 12, 12, 12, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's tissue box - {0666, new ItemRemakeInfo(0666, 07138, 5, new byte[] {13, 06, 13, 13, 05, 13, 14, 14}, new byte[] {01, 12, 07, 02, 05, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's tea cozy - {0667, new ItemRemakeInfo(0667, 07141, 5, new byte[] {13, 13, 13, 13, 13, 08, 14, 14}, new byte[] {01, 00, 09, 02, 00, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's pen stand - {0668, new ItemRemakeInfo(0668, 07145, 5, new byte[] {13, 13, 13, 13, 13, 13, 14, 14}, new byte[] {07, 00, 09, 02, 06, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's embroidery - {0669, new ItemRemakeInfo(0669, 07147, 5, new byte[] {12, 11, 09, 02, 06, 04, 14, 14}, new byte[] {06, 07, 00, 07, 07, 13, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's plushie - {0670, new ItemRemakeInfo(0670, 07144, 5, new byte[] {13, 13, 13, 13, 07, 13, 14, 14}, new byte[] {01, 04, 06, 02, 04, 04, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's cushion - {0671, new ItemRemakeInfo(0671, 07143, 5, new byte[] {13, 12, 12, 12, 01, 05, 14, 14}, new byte[] {13, 13, 08, 13, 03, 06, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's candle set - {0672, new ItemRemakeInfo(0672, 07146, 5, new byte[] {13, 01, 13, 12, 13, 09, 14, 14}, new byte[] {12, 12, 12, 02, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's homemade cake - {0673, new ItemRemakeInfo(0673, 07139, 7, new byte[] {13, 13, 12, 13, 13, 13, 13, 13}, new byte[] {09, 08, 10, 07, 07, 12, 07, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's art - {0674, new ItemRemakeInfo(0674, 07135, 7, new byte[] {12, 00, 01, 02, 03, 04, 05, 06}, new byte[] {12, 00, 01, 02, 03, 04, 05, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // floor light - {0675, new ItemRemakeInfo(0675, 07136, 4, new byte[] {12, 10, 01, 05, 02, 14, 14, 14}, new byte[] {06, 06, 06, 06, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cat grass - {0676, new ItemRemakeInfo(0676, 07148, 3, new byte[] {01, 04, 07, 00, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // life ring - {0678, new ItemRemakeInfo(0678, 07154, 7, new byte[] {08, 09, 09, 06, 02, 12, 10, 01}, new byte[] {08, 09, 09, 06, 02, 12, 10, 01}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 08, 12, 07, 02, 12, 13}, true)}, // wooden box - {0680, new ItemRemakeInfo(0680, 07189, 7, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {12, 07, 00, 01, 02, 03, 04, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // studio spotlight - {0681, new ItemRemakeInfo(0681, 07190, 7, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {12, 07, 00, 01, 02, 03, 04, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // studio wall spotlight - {0682, new ItemRemakeInfo(0682, 01645, 6, new byte[] {01, 08, 01, 09, 05, 12, 10, 14}, new byte[] {01, 08, 00, 00, 05, 08, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 10, 12, 03, 06, 05, 13, 02}, true)}, // electric guitar - {0684, new ItemRemakeInfo(0684, 07229, 5, new byte[] {06, 04, 09, 07, 01, 11, 14, 14}, new byte[] {09, 12, 08, 09, 09, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // handcart - {0685, new ItemRemakeInfo(0685, 07237, 2, new byte[] {07, 01, 12, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pansy table - {0686, new ItemRemakeInfo(0686, 07236, 2, new byte[] {12, 02, 07, 14, 14, 14, 14, 14}, new byte[] {06, 12, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lily record player - {0687, new ItemRemakeInfo(0687, 07235, 2, new byte[] {01, 03, 10, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rose bed - {0688, new ItemRemakeInfo(0688, 07234, 2, new byte[] {03, 04, 07, 14, 14, 14, 14, 14}, new byte[] {09, 09, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hyacinth lamp - {0689, new ItemRemakeInfo(0689, 07233, 2, new byte[] {01, 02, 03, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // windflower fan - {0690, new ItemRemakeInfo(0690, 07232, 2, new byte[] {07, 01, 12, 14, 14, 14, 14, 14}, new byte[] {07, 01, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mum cushion - {0691, new ItemRemakeInfo(0691, 07231, 2, new byte[] {01, 12, 07, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tulip surprise box - {0692, new ItemRemakeInfo(0692, 07230, 2, new byte[] {02, 01, 12, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cosmos shower - {0694, new ItemRemakeInfo(0694, 07247, 4, new byte[] {01, 06, 04, 10, 05, 14, 14, 14}, new byte[] {09, 09, 11, 12, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // silo - {0696, new ItemRemakeInfo(0696, 07253, 6, new byte[] {07, 06, 05, 03, 02, 00, 12, 14}, new byte[] {07, 06, 05, 03, 02, 00, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // star clock - {0697, new ItemRemakeInfo(0697, 06080, 1, new byte[] {09, 12, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tree's bounty big tree - {0698, new ItemRemakeInfo(0698, 06079, 1, new byte[] {09, 12, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tree's bounty little tree - {0699, new ItemRemakeInfo(0699, 06081, 1, new byte[] {09, 12, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tree's bounty arch - {0700, new ItemRemakeInfo(0700, 06075, 1, new byte[] {09, 12, 14, 14, 14, 14, 14, 14}, new byte[] {00, 07, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tree's bounty mobile - {0701, new ItemRemakeInfo(0701, 06078, 1, new byte[] {09, 08, 14, 14, 14, 14, 14, 14}, new byte[] {01, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tree's bounty lamp - {0702, new ItemRemakeInfo(0702, 07257, 2, new byte[] {10, 01, 06, 14, 14, 14, 14, 14}, new byte[] {04, 02, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pedal board - {0703, new ItemRemakeInfo(0703, 07258, 6, new byte[] {05, 05, 07, 06, 02, 08, 08, 14}, new byte[] {11, 11, 11, 05, 13, 09, 09, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // modeling clay - {0705, new ItemRemakeInfo(0705, 07260, 4, new byte[] {07, 07, 07, 07, 07, 14, 14, 14}, new byte[] {01, 01, 01, 01, 01, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // floor sign - {0707, new ItemRemakeInfo(0707, 07264, 3, new byte[] {01, 04, 06, 10, 14, 14, 14, 14}, new byte[] {07, 07, 07, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // champion's pennant - {0708, new ItemRemakeInfo(0708, 04309, 5, new byte[] {00, 12, 10, 13, 04, 08, 14, 14}, new byte[] {00, 12, 10, 09, 05, 08, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // destinations signpost - {0709, new ItemRemakeInfo(0709, 00690, 5, new byte[] {13, 13, 13, 13, 13, 13, 14, 14}, new byte[] {06, 01, 02, 05, 07, 08, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hula doll - {0710, new ItemRemakeInfo(0710, 01750, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {05, 10, 01, 10, 14, 14, 14, 14}, false)}, // document stack - {0711, new ItemRemakeInfo(0711, 07284, 1, new byte[] {01, 04, 14, 14, 14, 14, 14, 14}, new byte[] {11, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // nutcracker - {0713, new ItemRemakeInfo(0713, 07280, 4, new byte[] {11, 09, 10, 13, 09, 14, 14, 14}, new byte[] {11, 09, 10, 13, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // gears - {0714, new ItemRemakeInfo(0714, 07281, 3, new byte[] {00, 09, 01, 12, 14, 14, 14, 14}, new byte[] {01, 04, 04, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sleigh - {0715, new ItemRemakeInfo(0715, 07282, 4, new byte[] {06, 09, 02, 05, 03, 14, 14, 14}, new byte[] {06, 09, 02, 05, 03, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 11, 00, 00, 08, 14, 14, 14}, false)}, // hanging scroll - {0717, new ItemRemakeInfo(0717, 07317, 4, new byte[] {11, 11, 10, 09, 06, 14, 14, 14}, new byte[] {11, 11, 10, 09, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // zen-style stone - {0719, new ItemRemakeInfo(0719, 00685, 2, new byte[] {01, 04, 12, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Dala horse - {0721, new ItemRemakeInfo(0721, 07391, 3, new byte[] {09, 07, 10, 12, 14, 14, 14, 14}, new byte[] {06, 06, 06, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tatami bed - {0722, new ItemRemakeInfo(0722, 07392, 3, new byte[] {01, 04, 07, 02, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // candy machine - {0724, new ItemRemakeInfo(0724, 01804, 7, new byte[] {12, 08, 00, 10, 04, 06, 02, 11}, new byte[] {09, 10, 09, 12, 05, 10, 02, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // electric bass - {0725, new ItemRemakeInfo(0725, 06827, 6, new byte[] {07, 06, 05, 03, 02, 00, 12, 14}, new byte[] {07, 06, 05, 03, 02, 00, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // starry garland - {0726, new ItemRemakeInfo(0726, 01111, 3, new byte[] {11, 10, 09, 12, 14, 14, 14, 14}, new byte[] {11, 10, 09, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // outdoor bath - {0727, new ItemRemakeInfo(0727, 07393, 1, new byte[] {11, 06, 14, 14, 14, 14, 14, 14}, new byte[] {11, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pond stone - {0728, new ItemRemakeInfo(0728, 07379, 1, new byte[] {12, 12, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wind turbine - {0731, new ItemRemakeInfo(0731, 01816, 7, new byte[] {12, 07, 00, 09, 10, 04, 02, 05}, new byte[] {12, 07, 00, 09, 10, 04, 02, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 03, 10, 07, 02, 01, 06, 05}, false)}, // changing room - {0733, new ItemRemakeInfo(0733, 01127, 2, new byte[] {00, 09, 07, 14, 14, 14, 14, 14}, new byte[] {10, 06, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // old sewing machine - {0734, new ItemRemakeInfo(0734, 00683, 2, new byte[] {05, 05, 05, 14, 14, 14, 14, 14}, new byte[] {12, 06, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bottled ship - {0735, new ItemRemakeInfo(0735, 07238, 5, new byte[] {10, 11, 09, 12, 04, 09, 14, 14}, new byte[] {08, 08, 08, 08, 12, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // anchor statue - {0736, new ItemRemakeInfo(0736, 02333, 1, new byte[] {04, 10, 14, 14, 14, 14, 14, 14}, new byte[] {04, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // solar panel - {0742, new ItemRemakeInfo(0742, 00950, 5, new byte[] {10, 12, 07, 04, 01, 02, 14, 14}, new byte[] {10, 12, 07, 04, 01, 02, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 12, 03, 06, 05, 01, 02}, false)}, // effects rack - {0743, new ItemRemakeInfo(0743, 00987, 4, new byte[] {09, 08, 09, 12, 10, 14, 14, 14}, new byte[] {08, 08, 00, 08, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // harp - {0744, new ItemRemakeInfo(0744, 07153, 2, new byte[] {08, 07, 09, 14, 14, 14, 14, 14}, new byte[] {08, 07, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cypress bathtub - {0745, new ItemRemakeInfo(0745, 07531, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {05, 02, 07, 06, 11, 14, 14, 14}, false)}, // ironing board - {0746, new ItemRemakeInfo(0746, 07535, 5, new byte[] {10, 01, 04, 07, 06, 02, 14, 14}, new byte[] {10, 11, 11, 11, 11, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // kettlebell - {0747, new ItemRemakeInfo(0747, 01449, 2, new byte[] {09, 12, 10, 14, 14, 14, 14, 14}, new byte[] {09, 12, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cello - {0748, new ItemRemakeInfo(0748, 07045, 5, new byte[] {11, 07, 06, 04, 01, 10, 14, 14}, new byte[] {07, 06, 00, 00, 09, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // recycled-can thumb piano - {0750, new ItemRemakeInfo(0750, 07150, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 01, 04, 10, 07, 14, 14, 14}, false)}, // blue corner - {0752, new ItemRemakeInfo(0752, 07599, 2, new byte[] {06, 00, 12, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // board game - {0755, new ItemRemakeInfo(0755, 07653, 2, new byte[] {01, 04, 10, 14, 14, 14, 14, 14}, new byte[] {10, 12, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // speed bag - {0756, new ItemRemakeInfo(0756, 07654, 5, new byte[] {01, 12, 07, 06, 04, 02, 14, 14}, new byte[] {10, 11, 10, 10, 10, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // electric kick scooter - {0757, new ItemRemakeInfo(0757, 06829, 6, new byte[] {07, 06, 05, 03, 02, 00, 12, 14}, new byte[] {07, 07, 07, 07, 07, 07, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // crescent-moon chair - {0758, new ItemRemakeInfo(0758, 00335, 1, new byte[] {02, 02, 14, 14, 14, 14, 14, 14}, new byte[] {02, 02, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mr. Flamingo - {0759, new ItemRemakeInfo(0759, 00336, 1, new byte[] {02, 02, 14, 14, 14, 14, 14, 14}, new byte[] {02, 02, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mrs. Flamingo - {0762, new ItemRemakeInfo(0762, 07681, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 05, 01, 04, 14, 14, 14, 14}, false)}, // loom - {0763, new ItemRemakeInfo(0763, 07682, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 05, 13, 04, 14, 14, 14, 14}, false)}, // kimono stand - {0766, new ItemRemakeInfo(0766, 07454, 3, new byte[] {08, 09, 13, 06, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden toolbox - {0767, new ItemRemakeInfo(0767, 07453, 1, new byte[] {11, 11, 14, 14, 14, 14, 14, 14}, new byte[] {07, 07, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // aluminum briefcase - {0768, new ItemRemakeInfo(0768, 01087, 4, new byte[] {12, 01, 03, 10, 09, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pinball machine - {0771, new ItemRemakeInfo(0771, 00290, 3, new byte[] {10, 01, 04, 12, 14, 14, 14, 14}, new byte[] {11, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // treadmill - {0772, new ItemRemakeInfo(0772, 01177, 2, new byte[] {00, 09, 04, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // foosball table - {0773, new ItemRemakeInfo(0773, 07525, 3, new byte[] {12, 06, 04, 10, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tool shelf - {0774, new ItemRemakeInfo(0774, 07796, 1, new byte[] {01, 09, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial dining table - {0775, new ItemRemakeInfo(0775, 07797, 1, new byte[] {01, 06, 14, 14, 14, 14, 14, 14}, new byte[] {10, 09, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial dining chair - {0776, new ItemRemakeInfo(0776, 07803, 6, new byte[] {12, 07, 06, 05, 02, 09, 10, 14}, new byte[] {00, 09, 01, 10, 07, 11, 05, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // kitty litter box - {0777, new ItemRemakeInfo(0777, 07800, 3, new byte[] {01, 04, 06, 02, 14, 14, 14, 14}, new byte[] {10, 10, 06, 02, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // protein shaker bottle - {0778, new ItemRemakeInfo(0778, 07801, 4, new byte[] {04, 00, 01, 06, 02, 14, 14, 14}, new byte[] {11, 11, 11, 10, 02, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pet food bowl - {0779, new ItemRemakeInfo(0779, 07802, 2, new byte[] {08, 09, 12, 14, 14, 14, 14, 14}, new byte[] {08, 09, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 06, 05, 01, 06, 14, 14, 14}, false)}, // pet bed - {0780, new ItemRemakeInfo(0780, 07804, 2, new byte[] {08, 11, 10, 14, 14, 14, 14, 14}, new byte[] {10, 10, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // knife block - {0782, new ItemRemakeInfo(0782, 07390, 3, new byte[] {09, 01, 07, 06, 14, 14, 14, 14}, new byte[] {08, 08, 09, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // leaf stool - {0784, new ItemRemakeInfo(0784, 05397, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // - {0785, new ItemRemakeInfo(0785, 07845, 3, new byte[] {10, 01, 07, 04, 14, 14, 14, 14}, new byte[] {11, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pull-up-bar stand - {0787, new ItemRemakeInfo(0787, 07865, 4, new byte[] {01, 05, 03, 02, 06, 14, 14, 14}, new byte[] {10, 12, 10, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // elaborate kimono stand - {0789, new ItemRemakeInfo(0789, 07867, 7, new byte[] {08, 08, 08, 08, 08, 08, 08, 08}, new byte[] {09, 09, 09, 09, 09, 09, 09, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // angled signpost - {0790, new ItemRemakeInfo(0790, 05973, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {08, 08, 08, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // log stakes - {0791, new ItemRemakeInfo(0791, 05972, 3, new byte[] {09, 00, 08, 12, 14, 14, 14, 14}, new byte[] {08, 08, 08, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wild log bench - {0793, new ItemRemakeInfo(0793, 01232, 1, new byte[] {12, 10, 14, 14, 14, 14, 14, 14}, new byte[] {04, 04, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // water cooler - {0794, new ItemRemakeInfo(0794, 01211, 5, new byte[] {10, 04, 09, 06, 07, 12, 14, 14}, new byte[] {07, 11, 07, 11, 11, 05, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // typewriter - {0796, new ItemRemakeInfo(0796, 00704, 5, new byte[] {01, 06, 01, 12, 12, 04, 14, 14}, new byte[] {05, 12, 06, 01, 09, 05, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tapestry - {0799, new ItemRemakeInfo(0799, 07529, 5, new byte[] {04, 06, 01, 09, 10, 12, 14, 14}, new byte[] {11, 11, 11, 11, 11, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // folding chair - {0800, new ItemRemakeInfo(0800, 06818, 5, new byte[] {13, 04, 01, 02, 07, 12, 14, 14}, new byte[] {09, 11, 12, 02, 09, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ornament mobile - {0801, new ItemRemakeInfo(0801, 08178, 7, new byte[] {06, 00, 05, 01, 08, 02, 07, 10}, new byte[] {11, 11, 11, 11, 11, 11, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // outdoorsy net - {0803, new ItemRemakeInfo(0803, 00688, 2, new byte[] {06, 00, 09, 14, 14, 14, 14, 14}, new byte[] {01, 09, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pagoda - {0804, new ItemRemakeInfo(0804, 08298, 6, new byte[] {11, 10, 12, 01, 04, 07, 02, 14}, new byte[] {11, 10, 12, 01, 04, 07, 02, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 04, 02, 05, 07, 14, 14, 14}, false)}, // bunk bed - {0805, new ItemRemakeInfo(0805, 02319, 3, new byte[] {08, 11, 09, 10, 14, 14, 14, 14}, new byte[] {08, 11, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // drinking fountain - {0806, new ItemRemakeInfo(0806, 00546, 2, new byte[] {10, 04, 02, 14, 14, 14, 14, 14}, new byte[] {11, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stadiometer - {0807, new ItemRemakeInfo(0807, 01412, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {10, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // TV camera - {0808, new ItemRemakeInfo(0808, 07527, 6, new byte[] {13, 01, 02, 07, 03, 04, 12, 14}, new byte[] {06, 06, 06, 06, 06, 06, 06, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // flower stand - {0809, new ItemRemakeInfo(0809, 07528, 7, new byte[] {01, 00, 07, 06, 04, 02, 10, 11}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tool cart - {0810, new ItemRemakeInfo(0810, 01243, 2, new byte[] {01, 01, 12, 14, 14, 14, 14, 14}, new byte[] {13, 12, 03, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // flashy-flower sign - {0811, new ItemRemakeInfo(0811, 07789, 3, new byte[] {11, 08, 10, 12, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // drying rack - {0812, new ItemRemakeInfo(0812, 08096, 7, new byte[] {10, 12, 01, 07, 06, 04, 11, 02}, new byte[] {10, 12, 01, 07, 06, 04, 11, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 00, 03, 13, 14, 14, 14, 14}, true)}, // record box - {0813, new ItemRemakeInfo(0813, 07159, 1, new byte[] {08, 12, 14, 14, 14, 14, 14, 14}, new byte[] {08, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cardboard sofa - {0814, new ItemRemakeInfo(0814, 07160, 1, new byte[] {07, 07, 14, 14, 14, 14, 14, 14}, new byte[] {07, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cardboard table - {0815, new ItemRemakeInfo(0815, 07161, 1, new byte[] {07, 07, 14, 14, 14, 14, 14, 14}, new byte[] {07, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cardboard bed - {0816, new ItemRemakeInfo(0816, 07163, 1, new byte[] {08, 08, 14, 14, 14, 14, 14, 14}, new byte[] {08, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cardboard chair - {0817, new ItemRemakeInfo(0817, 07526, 5, new byte[] {01, 04, 07, 05, 10, 12, 14, 14}, new byte[] {11, 10, 10, 10, 00, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // outdoor generator - {0818, new ItemRemakeInfo(0818, 00287, 3, new byte[] {10, 01, 07, 12, 14, 14, 14, 14}, new byte[] {11, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // exercise bike - {0819, new ItemRemakeInfo(0819, 07788, 1, new byte[] {09, 09, 14, 14, 14, 14, 14, 14}, new byte[] {00, 00, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // leaf campfire - {0821, new ItemRemakeInfo(0821, 08419, 3, new byte[] {00, 09, 06, 12, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // garden wagon - {0822, new ItemRemakeInfo(0822, 08418, 4, new byte[] {12, 07, 02, 06, 05, 14, 14, 14}, new byte[] {08, 09, 02, 06, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fragrance diffuser - {0823, new ItemRemakeInfo(0823, 08417, 5, new byte[] {12, 09, 07, 01, 04, 10, 14, 14}, new byte[] {13, 13, 13, 13, 13, 13, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall-mounted tool board - {0824, new ItemRemakeInfo(0824, 07868, 5, new byte[] {12, 01, 08, 10, 04, 09, 14, 14}, new byte[] {12, 10, 13, 05, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // surfboard - {0825, new ItemRemakeInfo(0825, 05784, 7, new byte[] {01, 07, 06, 04, 03, 02, 12, 10}, new byte[] {08, 08, 08, 08, 08, 08, 08, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // net - {0826, new ItemRemakeInfo(0826, 02377, 7, new byte[] {04, 07, 06, 01, 03, 02, 12, 10}, new byte[] {08, 08, 08, 08, 08, 08, 08, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fishing rod - {0827, new ItemRemakeInfo(0827, 02099, 7, new byte[] {01, 07, 06, 04, 03, 02, 12, 10}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shovel - {0828, new ItemRemakeInfo(0828, 08177, 7, new byte[] {07, 01, 00, 02, 06, 03, 12, 11}, new byte[] {00, 07, 04, 07, 04, 02, 04, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // colorful net - {0829, new ItemRemakeInfo(0829, 08176, 7, new byte[] {07, 01, 04, 06, 02, 03, 05, 06}, new byte[] {07, 01, 04, 06, 02, 03, 05, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // star net - {0830, new ItemRemakeInfo(0830, 08415, 3, new byte[] {07, 10, 04, 01, 14, 14, 14, 14}, new byte[] {01, 01, 01, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial dining lantern - {0831, new ItemRemakeInfo(0831, 08760, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // customizable phone case kit - {0832, new ItemRemakeInfo(0832, 08826, 7, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {07, 08, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden table mirror - {0833, new ItemRemakeInfo(0833, 08473, 7, new byte[] {06, 00, 05, 01, 08, 02, 07, 10}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // outdoorsy fishing rod - {0835, new ItemRemakeInfo(0835, 08472, 7, new byte[] {07, 00, 05, 02, 06, 03, 12, 10}, new byte[] {00, 07, 07, 07, 04, 02, 04, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // colorful fishing rod - {0836, new ItemRemakeInfo(0836, 08471, 7, new byte[] {06, 07, 00, 05, 04, 03, 02, 01}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fish fishing rod - {0837, new ItemRemakeInfo(0837, 08297, 2, new byte[] {11, 10, 01, 14, 14, 14, 14, 14}, new byte[] {10, 11, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stovetop espresso maker - {0838, new ItemRemakeInfo(0838, 07795, 2, new byte[] {11, 12, 06, 14, 14, 14, 14, 14}, new byte[] {11, 12, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stone lion-dog - {0840, new ItemRemakeInfo(0840, 05718, 7, new byte[] {08, 09, 09, 08, 08, 10, 04, 01}, new byte[] {02, 02, 01, 07, 01, 12, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // timber doorplate - {0841, new ItemRemakeInfo(0841, 05310, 7, new byte[] {10, 07, 06, 02, 03, 01, 11, 04}, new byte[] {06, 03, 01, 05, 06, 04, 03, 01}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spider doorplate - {0842, new ItemRemakeInfo(0842, 04751, 7, new byte[] {09, 12, 10, 02, 01, 07, 04, 08}, new byte[] {08, 01, 08, 01, 08, 09, 12, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bone doorplate - {0843, new ItemRemakeInfo(0843, 05309, 7, new byte[] {02, 11, 10, 04, 06, 00, 01, 03}, new byte[] {12, 05, 12, 05, 06, 00, 01, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // heart doorplate - {0844, new ItemRemakeInfo(0844, 05716, 7, new byte[] {08, 05, 10, 00, 09, 12, 05, 02}, new byte[] {09, 00, 08, 08, 08, 00, 04, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // paw-print doorplate - {0845, new ItemRemakeInfo(0845, 04738, 1, new byte[] {08, 12, 14, 14, 14, 14, 14, 14}, new byte[] {09, 01, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // skull doorplate - {0846, new ItemRemakeInfo(0846, 05717, 5, new byte[] {11, 07, 11, 01, 11, 13, 14, 14}, new byte[] {10, 11, 04, 12, 06, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // crest doorplate - {0847, new ItemRemakeInfo(0847, 05719, 1, new byte[] {11, 04, 14, 14, 14, 14, 14, 14}, new byte[] {08, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fossil doorplate - {0848, new ItemRemakeInfo(0848, 04764, 7, new byte[] {05, 01, 00, 07, 06, 03, 10, 11}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fish doorplate - {0849, new ItemRemakeInfo(0849, 04752, 7, new byte[] {10, 12, 04, 11, 08, 07, 00, 09}, new byte[] {10, 12, 04, 11, 08, 07, 00, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron doorplate - {0850, new ItemRemakeInfo(0850, 04377, 7, new byte[] {05, 07, 11, 06, 01, 06, 02, 03}, new byte[] {04, 00, 12, 07, 07, 11, 03, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ornament wreath - {0851, new ItemRemakeInfo(0851, 03345, 4, new byte[] {04, 12, 07, 06, 01, 14, 14, 14}, new byte[] {12, 12, 12, 11, 01, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lifeguard chair - {0852, new ItemRemakeInfo(0852, 09502, 5, new byte[] {08, 10, 00, 04, 02, 06, 14, 14}, new byte[] {08, 10, 00, 04, 02, 06, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // clothes closet - {0853, new ItemRemakeInfo(0853, 09565, 4, new byte[] {13, 13, 13, 13, 00, 14, 14, 14}, new byte[] {13, 13, 13, 13, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mobile - {0854, new ItemRemakeInfo(0854, 09568, 4, new byte[] {12, 12, 12, 04, 00, 14, 14, 14}, new byte[] {04, 04, 04, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // construction sign - {0856, new ItemRemakeInfo(0856, 02822, 7, new byte[] {01, 07, 06, 04, 03, 02, 12, 11}, new byte[] {08, 08, 08, 08, 08, 08, 08, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // slingshot - {0857, new ItemRemakeInfo(0857, 08579, 7, new byte[] {06, 00, 05, 01, 08, 02, 07, 10}, new byte[] {11, 11, 11, 11, 11, 11, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // outdoorsy slingshot - {0858, new ItemRemakeInfo(0858, 08580, 7, new byte[] {07, 01, 04, 02, 06, 03, 12, 10}, new byte[] {00, 06, 07, 05, 04, 02, 01, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // colorful slingshot - {0859, new ItemRemakeInfo(0859, 09584, 3, new byte[] {13, 04, 01, 06, 14, 14, 14, 14}, new byte[] {13, 12, 12, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // beach ball - {0860, new ItemRemakeInfo(0860, 08534, 7, new byte[] {07, 01, 04, 02, 06, 03, 12, 10}, new byte[] {04, 06, 00, 05, 07, 06, 00, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // colorful watering can - {0861, new ItemRemakeInfo(0861, 08536, 7, new byte[] {06, 00, 05, 01, 08, 02, 07, 10}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // outdoorsy watering can - {0862, new ItemRemakeInfo(0862, 08577, 7, new byte[] {07, 01, 04, 02, 06, 03, 12, 10}, new byte[] {04, 06, 00, 05, 07, 06, 00, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // colorful shovel - {0863, new ItemRemakeInfo(0863, 08575, 7, new byte[] {06, 00, 05, 01, 08, 02, 07, 10}, new byte[] {11, 11, 11, 11, 11, 11, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // outdoorsy shovel - {0864, new ItemRemakeInfo(0864, 02562, 4, new byte[] {07, 11, 09, 10, 12, 14, 14, 14}, new byte[] {12, 12, 12, 12, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // candle - {0866, new ItemRemakeInfo(0866, 09642, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron closet - {0867, new ItemRemakeInfo(0867, 02559, 4, new byte[] {09, 12, 10, 08, 12, 14, 14, 14}, new byte[] {08, 12, 10, 08, 04, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pot - {0868, new ItemRemakeInfo(0868, 09619, 1, new byte[] {11, 11, 14, 14, 14, 14, 14, 14}, new byte[] {11, 11, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // utility pole - {0869, new ItemRemakeInfo(0869, 01504, 5, new byte[] {07, 08, 09, 07, 03, 03, 14, 14}, new byte[] {08, 08, 09, 13, 12, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 04, 07, 14, 14, 14, 14}, true)}, // giant teddy bear - {0870, new ItemRemakeInfo(0870, 08576, 7, new byte[] {05, 12, 07, 02, 06, 04, 03, 10}, new byte[] {08, 08, 08, 08, 08, 08, 08, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // printed-design shovel - {0871, new ItemRemakeInfo(0871, 09766, 7, new byte[] {12, 01, 02, 07, 04, 09, 10, 11}, new byte[] {12, 01, 02, 07, 04, 09, 10, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mini fridge - {0872, new ItemRemakeInfo(0872, 09767, 6, new byte[] {06, 07, 09, 10, 12, 01, 04, 14}, new byte[] {06, 07, 09, 10, 11, 10, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // garbage bin - {0873, new ItemRemakeInfo(0873, 07805, 1, new byte[] {09, 07, 14, 14, 14, 14, 14, 14}, new byte[] {10, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // butter churn - {0874, new ItemRemakeInfo(0874, 08031, 3, new byte[] {11, 09, 10, 12, 14, 14, 14, 14}, new byte[] {11, 09, 10, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fountain - {0875, new ItemRemakeInfo(0875, 02352, 2, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {12, 01, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // parabolic antenna - {0876, new ItemRemakeInfo(0876, 07151, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 01, 04, 10, 07, 14, 14, 14}, false)}, // red corner - {0877, new ItemRemakeInfo(0877, 07152, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 01, 04, 10, 07, 14, 14, 14}, false)}, // neutral corner - {0878, new ItemRemakeInfo(0878, 08535, 7, new byte[] {11, 06, 04, 02, 01, 07, 05, 10}, new byte[] {11, 06, 04, 02, 01, 07, 05, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // elephant watering can - {0879, new ItemRemakeInfo(0879, 00131, 1, new byte[] {12, 10, 14, 14, 14, 14, 14, 14}, new byte[] {07, 07, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lucky cat - {0880, new ItemRemakeInfo(0880, 10244, 3, new byte[] {06, 04, 09, 11, 14, 14, 14, 14}, new byte[] {08, 08, 08, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fragrance sticks - {0882, new ItemRemakeInfo(0882, 02561, 3, new byte[] {08, 09, 12, 10, 14, 14, 14, 14}, new byte[] {08, 09, 12, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 11, 02, 05, 07, 06, 01, 04}, false)}, // floor lamp - {0883, new ItemRemakeInfo(0883, 10742, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo stool - {0884, new ItemRemakeInfo(0884, 10743, 2, new byte[] {06, 07, 09, 14, 14, 14, 14, 14}, new byte[] {08, 08, 08, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bamboo speaker - {0885, new ItemRemakeInfo(0885, 07588, 4, new byte[] {09, 12, 03, 01, 07, 14, 14, 14}, new byte[] {08, 12, 03, 12, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mushroom wand - {0886, new ItemRemakeInfo(0886, 00971, 3, new byte[] {10, 12, 01, 11, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // snack machine - {0887, new ItemRemakeInfo(0887, 00676, 2, new byte[] {11, 12, 11, 14, 14, 14, 14, 14}, new byte[] {11, 12, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tall lantern - {0889, new ItemRemakeInfo(0889, 11941, 1, new byte[] {11, 11, 14, 14, 14, 14, 14, 14}, new byte[] {11, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stone arch - {0890, new ItemRemakeInfo(0890, 11943, 1, new byte[] {10, 11, 14, 14, 14, 14, 14, 14}, new byte[] {10, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stone tablet - {0891, new ItemRemakeInfo(0891, 12140, 3, new byte[] {04, 07, 00, 06, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // DAL model plane - {0895, new ItemRemakeInfo(0895, 12207, 2, new byte[] {01, 11, 04, 14, 14, 14, 14, 14}, new byte[] {11, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // arcade seat - {0896, new ItemRemakeInfo(0896, 07259, 3, new byte[] {06, 07, 02, 04, 14, 14, 14, 14}, new byte[] {00, 06, 02, 04, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // palm-tree lamp - {0897, new ItemRemakeInfo(0897, 11942, 1, new byte[] {13, 13, 14, 14, 14, 14, 14, 14}, new byte[] {01, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // street piano - {0899, new ItemRemakeInfo(0899, 00667, 1, new byte[] {05, 12, 14, 14, 14, 14, 14, 14}, new byte[] {04, 05, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shaved-ice maker - {0901, new ItemRemakeInfo(0901, 12332, 2, new byte[] {08, 00, 12, 14, 14, 14, 14, 14}, new byte[] {10, 06, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // natural square table - {0902, new ItemRemakeInfo(0902, 12313, 2, new byte[] {02, 01, 05, 14, 14, 14, 14, 14}, new byte[] {12, 01, 05, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // public telephone - {0903, new ItemRemakeInfo(0903, 12312, 3, new byte[] {08, 00, 09, 00, 14, 14, 14, 14}, new byte[] {08, 00, 09, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wood-plank table - {0904, new ItemRemakeInfo(0904, 12314, 2, new byte[] {00, 09, 08, 14, 14, 14, 14, 14}, new byte[] {08, 08, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // zen lowboard - {0905, new ItemRemakeInfo(0905, 12311, 5, new byte[] {01, 06, 05, 12, 10, 00, 14, 14}, new byte[] {10, 10, 10, 10, 09, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cruiser bike - {0906, new ItemRemakeInfo(0906, 01906, 3, new byte[] {01, 10, 12, 08, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // snare drum - {0907, new ItemRemakeInfo(0907, 12308, 3, new byte[] {06, 08, 04, 01, 14, 14, 14, 14}, new byte[] {11, 11, 11, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // reception chair - {0909, new ItemRemakeInfo(0909, 12348, 5, new byte[] {06, 02, 05, 07, 00, 04, 14, 14}, new byte[] {06, 02, 05, 07, 10, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // froggy chair - {0910, new ItemRemakeInfo(0910, 12349, 2, new byte[] {00, 08, 09, 14, 14, 14, 14, 14}, new byte[] {00, 08, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // project table - {0911, new ItemRemakeInfo(0911, 12350, 2, new byte[] {08, 08, 09, 14, 14, 14, 14, 14}, new byte[] {08, 08, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // box-shaped seat - {0912, new ItemRemakeInfo(0912, 12344, 7, new byte[] {00, 09, 01, 04, 06, 07, 04, 12}, new byte[] {01, 08, 09, 05, 08, 10, 04, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // baseball set - {0913, new ItemRemakeInfo(0913, 01141, 4, new byte[] {04, 13, 00, 12, 02, 14, 14, 14}, new byte[] {08, 08, 08, 08, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ski rack - {0914, new ItemRemakeInfo(0914, 12356, 5, new byte[] {08, 06, 09, 04, 10, 12, 14, 14}, new byte[] {08, 06, 09, 04, 10, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // round pillow - {0915, new ItemRemakeInfo(0915, 12358, 3, new byte[] {12, 12, 01, 06, 14, 14, 14, 14}, new byte[] {04, 00, 12, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // retro ice-cream case - {0918, new ItemRemakeInfo(0918, 12365, 7, new byte[] {12, 10, 09, 01, 07, 06, 00, 05}, new byte[] {12, 10, 09, 01, 07, 06, 00, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // garden chair - {0919, new ItemRemakeInfo(0919, 12366, 6, new byte[] {04, 12, 07, 01, 06, 02, 10, 14}, new byte[] {11, 11, 11, 11, 06, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 12, 12, 12, 12, 12, 12}, true)}, // plastic bench - {0920, new ItemRemakeInfo(0920, 12373, 5, new byte[] {01, 06, 11, 13, 00, 10, 14, 14}, new byte[] {12, 07, 11, 12, 00, 01, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Pocket vintage camper - {0921, new ItemRemakeInfo(0921, 12372, 5, new byte[] {07, 01, 06, 13, 11, 00, 14, 14}, new byte[] {01, 10, 06, 13, 13, 13, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Pocket modern camper - {0922, new ItemRemakeInfo(0922, 12402, 2, new byte[] {12, 12, 06, 14, 14, 14, 14, 14}, new byte[] {05, 09, 07, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding arch - {0923, new ItemRemakeInfo(0923, 12401, 2, new byte[] {12, 09, 07, 14, 14, 14, 14, 14}, new byte[] {02, 09, 07, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding bench - {0924, new ItemRemakeInfo(0924, 12410, 2, new byte[] {02, 09, 07, 14, 14, 14, 14, 14}, new byte[] {02, 09, 07, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {02, 12, 14, 14, 14, 14, 14, 14}, false)}, // wedding welcome board - {0925, new ItemRemakeInfo(0925, 12408, 2, new byte[] {02, 08, 12, 14, 14, 14, 14, 14}, new byte[] {12, 07, 07, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding candle set - {0926, new ItemRemakeInfo(0926, 12403, 2, new byte[] {02, 12, 09, 14, 14, 14, 14, 14}, new byte[] {12, 07, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding cake - {0927, new ItemRemakeInfo(0927, 12411, 2, new byte[] {02, 12, 07, 14, 14, 14, 14, 14}, new byte[] {12, 07, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding flower stand - {0928, new ItemRemakeInfo(0928, 12405, 2, new byte[] {12, 09, 07, 14, 14, 14, 14, 14}, new byte[] {02, 08, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding chair - {0929, new ItemRemakeInfo(0929, 12406, 2, new byte[] {02, 12, 06, 14, 14, 14, 14, 14}, new byte[] {12, 08, 07, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding table - {0930, new ItemRemakeInfo(0930, 12409, 2, new byte[] {12, 09, 07, 14, 14, 14, 14, 14}, new byte[] {11, 07, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding pipe organ - {0931, new ItemRemakeInfo(0931, 12407, 2, new byte[] {02, 12, 07, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding decoration - {0932, new ItemRemakeInfo(0932, 12404, 2, new byte[] {02, 08, 06, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding head table - {0933, new ItemRemakeInfo(0933, 12516, 4, new byte[] {08, 04, 07, 06, 09, 14, 14, 14}, new byte[] {11, 10, 02, 10, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sampler - {0934, new ItemRemakeInfo(0934, 12543, 1, new byte[] {10, 10, 14, 14, 14, 14, 14, 14}, new byte[] {13, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Nintendo Switch - {0935, new ItemRemakeInfo(0935, 12599, 3, new byte[] {11, 00, 10, 06, 14, 14, 14, 14}, new byte[] {11, 11, 10, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // office chair - {0940, new ItemRemakeInfo(0940, 12612, 6, new byte[] {05, 01, 06, 07, 06, 02, 10, 14}, new byte[] {13, 13, 13, 13, 13, 13, 13, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // capsule-toy machine - {0941, new ItemRemakeInfo(0941, 12608, 4, new byte[] {11, 06, 01, 12, 10, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // flower display case - {0942, new ItemRemakeInfo(0942, 12610, 2, new byte[] {08, 05, 01, 14, 14, 14, 14, 14}, new byte[] {13, 13, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen-drink machine - {0943, new ItemRemakeInfo(0943, 12614, 6, new byte[] {07, 09, 12, 10, 05, 02, 00, 14}, new byte[] {01, 12, 05, 11, 04, 12, 06, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // peacock chair - {0944, new ItemRemakeInfo(0944, 12613, 5, new byte[] {04, 06, 07, 01, 05, 02, 14, 14}, new byte[] {11, 07, 11, 07, 11, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fancy tea set - {0945, new ItemRemakeInfo(0945, 12606, 3, new byte[] {01, 07, 06, 04, 14, 14, 14, 14}, new byte[] {10, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tractor - {0946, new ItemRemakeInfo(0946, 00967, 3, new byte[] {09, 02, 12, 09, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // flower bed - {0947, new ItemRemakeInfo(0947, 12605, 3, new byte[] {07, 04, 06, 01, 14, 14, 14, 14}, new byte[] {07, 04, 06, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 04, 13, 14, 14, 14, 14, 14}, false)}, // safety barrier - {0948, new ItemRemakeInfo(0948, 12637, 3, new byte[] {06, 12, 10, 08, 14, 14, 14, 14}, new byte[] {11, 11, 10, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 10, 10, 14, 14, 14, 14, 14}, false)}, // examination-room desk - {0949, new ItemRemakeInfo(0949, 00538, 4, new byte[] {12, 05, 02, 06, 07, 14, 14, 14}, new byte[] {11, 11, 11, 11, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // exam table - {0950, new ItemRemakeInfo(0950, 12670, 3, new byte[] {12, 08, 10, 11, 14, 14, 14, 14}, new byte[] {12, 12, 10, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // office cabinet - {0951, new ItemRemakeInfo(0951, 00534, 3, new byte[] {12, 02, 12, 12, 14, 14, 14, 14}, new byte[] {12, 02, 06, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hospital bed - {0952, new ItemRemakeInfo(0952, 12653, 3, new byte[] {05, 02, 08, 09, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // modern hospital bed - {0955, new ItemRemakeInfo(0955, 12673, 2, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tall file cabinet - {0956, new ItemRemakeInfo(0956, 12674, 2, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // short file cabinet - {0957, new ItemRemakeInfo(0957, 12675, 7, new byte[] {12, 09, 08, 10, 09, 08, 11, 00}, new byte[] {06, 06, 06, 06, 06, 06, 06, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plant partition - {0958, new ItemRemakeInfo(0958, 12676, 4, new byte[] {08, 09, 09, 12, 06, 14, 14, 14}, new byte[] {08, 09, 09, 12, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // large magazine rack - {0959, new ItemRemakeInfo(0959, 12677, 3, new byte[] {12, 12, 11, 09, 14, 14, 14, 14}, new byte[] {12, 02, 11, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // medicine chest - {0960, new ItemRemakeInfo(0960, 12669, 2, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 06, 07, 12, 10, 02, 14}, false)}, // donut stool - {0961, new ItemRemakeInfo(0961, 12678, 7, new byte[] {12, 08, 09, 09, 05, 02, 09, 07}, new byte[] {11, 12, 10, 09, 12, 12, 12, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // arched reception counter - {0962, new ItemRemakeInfo(0962, 12679, 7, new byte[] {12, 10, 08, 09, 05, 02, 10, 08}, new byte[] {12, 10, 08, 09, 12, 12, 10, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, false)}, // reception counter - {0964, new ItemRemakeInfo(0964, 12699, 2, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 06, 01, 05, 07, 12, 00, 14}, false)}, // standing electric sign - {0994, new ItemRemakeInfo(0994, 12712, 2, new byte[] {11, 09, 12, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // salad bar - {0995, new ItemRemakeInfo(0995, 12714, 1, new byte[] {12, 10, 14, 14, 14, 14, 14, 14}, new byte[] {11, 11, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // modern cash register - {0996, new ItemRemakeInfo(0996, 12713, 4, new byte[] {07, 11, 09, 10, 12, 14, 14, 14}, new byte[] {07, 11, 09, 10, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique cash register - {0997, new ItemRemakeInfo(0997, 12715, 2, new byte[] {06, 04, 12, 14, 14, 14, 14, 14}, new byte[] {12, 11, 00, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {05, 08, 12, 14, 14, 14, 14, 14}, false)}, // bulletin board - {0998, new ItemRemakeInfo(0998, 12700, 5, new byte[] {11, 06, 11, 09, 12, 00, 14, 14}, new byte[] {11, 11, 11, 09, 12, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sturdy office desk - {0999, new ItemRemakeInfo(0999, 12702, 4, new byte[] {01, 04, 10, 09, 06, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // strapped books - {1000, new ItemRemakeInfo(1000, 12704, 5, new byte[] {04, 10, 01, 06, 07, 09, 14, 14}, new byte[] {11, 11, 11, 11, 11, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // basic school chair - {1001, new ItemRemakeInfo(1001, 12705, 5, new byte[] {11, 11, 11, 11, 11, 11, 14, 14}, new byte[] {11, 12, 00, 01, 12, 00, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stewpot - {1002, new ItemRemakeInfo(1002, 12706, 6, new byte[] {10, 10, 10, 10, 10, 10, 10, 14}, new byte[] {10, 01, 07, 07, 09, 07, 01, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial pot - {1003, new ItemRemakeInfo(1003, 12707, 2, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {11, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cans - {1004, new ItemRemakeInfo(1004, 12708, 1, new byte[] {12, 08, 14, 14, 14, 14, 14, 14}, new byte[] {11, 13, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cooking tools - {1006, new ItemRemakeInfo(1006, 12717, 2, new byte[] {06, 06, 10, 14, 14, 14, 14, 14}, new byte[] {00, 09, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // left chalkboard section - {1007, new ItemRemakeInfo(1007, 12718, 2, new byte[] {06, 06, 10, 14, 14, 14, 14, 14}, new byte[] {00, 09, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // right chalkboard section - {1009, new ItemRemakeInfo(1009, 12720, 1, new byte[] {11, 07, 14, 14, 14, 14, 14, 14}, new byte[] {11, 07, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fancy water pitcher - {1010, new ItemRemakeInfo(1010, 12709, 2, new byte[] {10, 07, 01, 14, 14, 14, 14, 14}, new byte[] {08, 08, 08, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // carp on a cutting board - {1011, new ItemRemakeInfo(1011, 12701, 4, new byte[] {11, 11, 12, 08, 10, 14, 14, 14}, new byte[] {11, 11, 12, 13, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // school locker - {1012, new ItemRemakeInfo(1012, 12741, 1, new byte[] {04, 04, 14, 14, 14, 14, 14, 14}, new byte[] {06, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // world map - {1015, new ItemRemakeInfo(1015, 12745, 7, new byte[] {12, 11, 06, 02, 01, 07, 05, 12}, new byte[] {12, 11, 06, 02, 01, 07, 12, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 05, 10, 00, 06, 01, 03, 09}, false)}, // large covered round table - {1016, new ItemRemakeInfo(1016, 12744, 7, new byte[] {12, 11, 06, 02, 01, 07, 05, 12}, new byte[] {12, 11, 06, 02, 01, 07, 12, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 05, 10, 00, 06, 01, 03, 09}, false)}, // small covered round table - {1017, new ItemRemakeInfo(1017, 12766, 4, new byte[] {09, 08, 09, 12, 10, 14, 14, 14}, new byte[] {11, 11, 11, 10, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // small café table - {1018, new ItemRemakeInfo(1018, 12767, 4, new byte[] {09, 08, 09, 12, 10, 14, 14, 14}, new byte[] {11, 11, 11, 10, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // large café table - {1019, new ItemRemakeInfo(1019, 12768, 7, new byte[] {11, 02, 08, 09, 12, 08, 12, 10}, new byte[] {12, 12, 12, 09, 12, 08, 08, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // checkout counter - {1020, new ItemRemakeInfo(1020, 12769, 3, new byte[] {12, 08, 02, 09, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dessert case - {1021, new ItemRemakeInfo(1021, 12772, 2, new byte[] {05, 02, 12, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ice-cream display - {1022, new ItemRemakeInfo(1022, 12773, 7, new byte[] {00, 09, 12, 10, 01, 06, 04, 02}, new byte[] {12, 10, 11, 11, 11, 11, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // counter chair - {1023, new ItemRemakeInfo(1023, 12774, 3, new byte[] {11, 12, 08, 09, 14, 14, 14, 14}, new byte[] {08, 09, 12, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // busing station - {1024, new ItemRemakeInfo(1024, 12775, 2, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {12, 04, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // afternoon-tea set - {1025, new ItemRemakeInfo(1025, 12776, 7, new byte[] {00, 08, 09, 09, 02, 01, 12, 10}, new byte[] {00, 12, 10, 09, 02, 10, 12, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // counter table - {1026, new ItemRemakeInfo(1026, 12777, 3, new byte[] {09, 08, 12, 02, 14, 14, 14, 14}, new byte[] {09, 08, 08, 02, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // covered counter - {1027, new ItemRemakeInfo(1027, 12778, 1, new byte[] {12, 10, 14, 14, 14, 14, 14, 14}, new byte[] {12, 04, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // touchscreen cash register - {1028, new ItemRemakeInfo(1028, 12779, 7, new byte[] {08, 00, 09, 12, 10, 02, 05, 11}, new byte[] {08, 00, 09, 12, 10, 02, 12, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wood partition - {1029, new ItemRemakeInfo(1029, 12780, 3, new byte[] {09, 11, 07, 11, 14, 14, 14, 14}, new byte[] {13, 13, 13, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall shelf with bottles - {1030, new ItemRemakeInfo(1030, 12782, 3, new byte[] {08, 09, 10, 12, 14, 14, 14, 14}, new byte[] {09, 12, 09, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 04, 06, 01, 09, 08, 02, 05}, false)}, // bistro table - {1031, new ItemRemakeInfo(1031, 01820, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 05, 04, 02, 01, 08, 14, 14}, new byte[] {12, 02, 10, 13, 13, 08, 14, 14}, false)}, // stack of clothes - {1032, new ItemRemakeInfo(1032, 12886, 4, new byte[] {08, 08, 09, 12, 13, 14, 14, 14}, new byte[] {13, 06, 09, 02, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 08, 11, 07, 12, 14, 14, 14}, false)}, // corner clothing rack - {1033, new ItemRemakeInfo(1033, 12891, 4, new byte[] {09, 09, 10, 12, 07, 14, 14, 14}, new byte[] {09, 09, 10, 12, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // full-length mirror - {1034, new ItemRemakeInfo(1034, 12887, 3, new byte[] {12, 08, 09, 02, 14, 14, 14, 14}, new byte[] {12, 12, 08, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glass showcase - {1035, new ItemRemakeInfo(1035, 12882, 2, new byte[] {12, 09, 10, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 12, 01, 07, 04, 14, 14, 14}, false)}, // small mannequin - {1036, new ItemRemakeInfo(1036, 12885, 2, new byte[] {08, 09, 12, 14, 14, 14, 14, 14}, new byte[] {13, 11, 02, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hanging clothing rack - {1037, new ItemRemakeInfo(1037, 12893, 3, new byte[] {09, 10, 13, 13, 14, 14, 14, 14}, new byte[] {12, 09, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stacked shoeboxes - {1038, new ItemRemakeInfo(1038, 12890, 3, new byte[] {12, 10, 01, 08, 14, 14, 14, 14}, new byte[] {12, 10, 01, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 07, 04, 06, 14, 14, 14}, true)}, // merchandise table - {1039, new ItemRemakeInfo(1039, 12879, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 10, 07, 01, 12, 06, 07, 02}, false)}, // tabletop POP display - {1040, new ItemRemakeInfo(1040, 12880, 1, new byte[] {11, 10, 14, 14, 14, 14, 14, 14}, new byte[] {11, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 01, 10, 12, 05, 08, 11, 01}, false)}, // standing shop sign - {1041, new ItemRemakeInfo(1041, 12888, 3, new byte[] {11, 10, 12, 07, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hanger rack - {1042, new ItemRemakeInfo(1042, 12883, 4, new byte[] {08, 08, 09, 12, 13, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 04, 10, 12, 13, 14, 14, 14}, false)}, // midsized clothing rack - {1043, new ItemRemakeInfo(1043, 12884, 4, new byte[] {08, 08, 09, 12, 13, 14, 14, 14}, new byte[] {13, 13, 12, 13, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // small clothing rack - {1044, new ItemRemakeInfo(1044, 12892, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {08, 12, 04, 10, 01, 06, 07, 12}, new byte[] {08, 12, 04, 10, 01, 06, 12, 13}, false)}, // sturdy paper bag - {1045, new ItemRemakeInfo(1045, 12889, 7, new byte[] {12, 09, 10, 01, 07, 06, 04, 02}, new byte[] {12, 09, 09, 09, 09, 09, 09, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // boxy stool - {1046, new ItemRemakeInfo(1046, 12881, 2, new byte[] {12, 09, 10, 14, 14, 14, 14, 14}, new byte[] {12, 09, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 07, 10, 12, 14, 14, 14}, false)}, // dress mannequin - {1047, new ItemRemakeInfo(1047, 01314, 5, new byte[] {08, 11, 11, 12, 02, 05, 14, 14}, new byte[] {08, 11, 11, 09, 12, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // handwashing area - {1048, new ItemRemakeInfo(1048, 12976, 7, new byte[] {01, 04, 06, 02, 10, 12, 07, 01}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mini dharma - {1051, new ItemRemakeInfo(1051, 12604, 3, new byte[] {07, 06, 01, 11, 14, 14, 14, 14}, new byte[] {09, 09, 09, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // jackhammer - {1059, new ItemRemakeInfo(1059, 12996, 7, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {09, 04, 12, 02, 07, 06, 05, 03}, false)}, // simple chair - {1061, new ItemRemakeInfo(1061, 12994, 7, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {09, 04, 12, 02, 07, 06, 05, 03}, false)}, // simple bed - {1062, new ItemRemakeInfo(1062, 12993, 7, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {11, 11, 11, 11, 11, 11, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // simple vanity - {1063, new ItemRemakeInfo(1063, 12998, 7, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 04, 12, 02, 07, 06, 05, 03}, true)}, // simple small dresser - {1064, new ItemRemakeInfo(1064, 12995, 7, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {09, 04, 12, 02, 07, 06, 05, 03}, false)}, // simple sofa - {1065, new ItemRemakeInfo(1065, 12991, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {09, 04, 12, 02, 07, 06, 05, 03}, new byte[] {09, 04, 12, 02, 07, 06, 05, 03}, false)}, // simple stool - {1066, new ItemRemakeInfo(1066, 12997, 7, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // simple wall shelf - {1067, new ItemRemakeInfo(1067, 12999, 7, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {08, 09, 12, 02, 07, 06, 05, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 04, 12, 02, 07, 06, 05, 03}, true)}, // simple table - {1068, new ItemRemakeInfo(1068, 13005, 4, new byte[] {11, 10, 00, 04, 01, 14, 14, 14}, new byte[] {11, 10, 00, 04, 01, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 00, 06, 03, 12, 11, 10}, false)}, // artsy chair - {1069, new ItemRemakeInfo(1069, 13004, 7, new byte[] {01, 04, 00, 06, 12, 10, 09, 07}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // artsy table - {1070, new ItemRemakeInfo(1070, 13006, 2, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 01, 00, 04, 06, 07, 09}, false)}, // cool low table - {1071, new ItemRemakeInfo(1071, 13007, 2, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 01, 00, 04, 06, 07, 09}, false)}, // cool side table - {1072, new ItemRemakeInfo(1072, 13008, 2, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 01, 00, 04, 06, 07, 09}, false)}, // cool chair - {1073, new ItemRemakeInfo(1073, 13009, 2, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 01, 00, 04, 06, 07, 09}, false)}, // cool bed - {1074, new ItemRemakeInfo(1074, 13010, 2, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 01, 00, 04, 06, 07, 09}, false)}, // cool sofa - {1088, new ItemRemakeInfo(1088, 13073, 7, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 06, 05, 00, 02, 13, 06, 13}, false)}, // Nordic chair - {1090, new ItemRemakeInfo(1090, 13075, 7, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 06, 05, 00, 02, 13, 06, 13}, false)}, // Nordic sofa - {1091, new ItemRemakeInfo(1091, 13076, 7, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 07, 06, 05, 00, 02, 13, 06}, true)}, // Nordic low table - {1092, new ItemRemakeInfo(1092, 13077, 7, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 07, 06, 05, 00, 02, 13, 06}, true)}, // Nordic lowboard - {1093, new ItemRemakeInfo(1093, 13078, 7, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 07, 06, 05, 00, 02, 13, 06}, true)}, // Nordic shelves - {1094, new ItemRemakeInfo(1094, 13079, 7, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {08, 00, 09, 12, 01, 05, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 07, 06, 05, 00, 02, 13, 06}, true)}, // Nordic table - {1095, new ItemRemakeInfo(1095, 13080, 6, new byte[] {08, 09, 12, 05, 02, 06, 11, 14}, new byte[] {08, 09, 07, 00, 02, 06, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ranch wardrobe - {1096, new ItemRemakeInfo(1096, 13081, 6, new byte[] {08, 09, 12, 05, 02, 06, 11, 14}, new byte[] {08, 09, 07, 00, 02, 06, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 06, 02, 07, 14, 14}, true)}, // ranch tea table - {1097, new ItemRemakeInfo(1097, 13082, 6, new byte[] {08, 09, 12, 05, 02, 06, 11, 14}, new byte[] {08, 09, 07, 00, 02, 06, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 06, 02, 07, 14, 14}, true)}, // ranch lowboard - {1098, new ItemRemakeInfo(1098, 13083, 7, new byte[] {01, 07, 05, 02, 12, 06, 03, 09}, new byte[] {01, 07, 13, 02, 04, 08, 03, 00}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Moroccan footrest - {1099, new ItemRemakeInfo(1099, 13084, 7, new byte[] {09, 07, 09, 11, 04, 06, 03, 10}, new byte[] {09, 09, 09, 12, 12, 09, 09, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Moroccan tray table - {1100, new ItemRemakeInfo(1100, 13085, 7, new byte[] {01, 07, 05, 02, 12, 06, 03, 09}, new byte[] {08, 08, 08, 12, 12, 09, 09, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Moroccan sofa - {1101, new ItemRemakeInfo(1101, 13108, 7, new byte[] {12, 10, 08, 09, 06, 02, 05, 07}, new byte[] {12, 10, 08, 09, 06, 02, 05, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 08, 03, 00, 12, 05, 13}, false)}, // upright organizer - {1102, new ItemRemakeInfo(1102, 13109, 7, new byte[] {12, 10, 00, 09, 06, 02, 05, 07}, new byte[] {12, 10, 00, 09, 06, 02, 05, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 05, 08, 03, 00, 02, 05, 07}, false)}, // horizontal organizer - {1103, new ItemRemakeInfo(1103, 13110, 7, new byte[] {10, 11, 12, 09, 06, 02, 04, 00}, new byte[] {10, 11, 12, 09, 06, 02, 04, 00}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 10, 07, 09, 06, 13, 13, 13}, false)}, // plastic clothing organizer - {1104, new ItemRemakeInfo(1104, 13111, 5, new byte[] {08, 00, 09, 10, 01, 11, 14, 14}, new byte[] {10, 10, 10, 10, 10, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Japanese dresser - {1105, new ItemRemakeInfo(1105, 13112, 5, new byte[] {08, 00, 09, 10, 01, 11, 14, 14}, new byte[] {08, 00, 09, 10, 01, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // zen low table - {1106, new ItemRemakeInfo(1106, 13113, 7, new byte[] {08, 09, 09, 08, 08, 08, 10, 10}, new byte[] {12, 12, 13, 12, 12, 13, 13, 13}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shoji divider - {1107, new ItemRemakeInfo(1107, 13114, 5, new byte[] {08, 09, 11, 06, 12, 10, 14, 14}, new byte[] {10, 08, 11, 06, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vintage stool - {1108, new ItemRemakeInfo(1108, 13115, 5, new byte[] {08, 09, 11, 06, 12, 10, 14, 14}, new byte[] {10, 08, 11, 06, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vintage desk - {1109, new ItemRemakeInfo(1109, 13116, 5, new byte[] {09, 11, 06, 00, 04, 10, 14, 14}, new byte[] {10, 08, 11, 06, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vintage sofa - {1110, new ItemRemakeInfo(1110, 13117, 5, new byte[] {08, 09, 11, 06, 12, 10, 14, 14}, new byte[] {10, 08, 11, 06, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vintage low table - {1111, new ItemRemakeInfo(1111, 13118, 5, new byte[] {08, 09, 11, 06, 12, 10, 14, 14}, new byte[] {10, 08, 11, 06, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vintage dresser - {1112, new ItemRemakeInfo(1112, 13119, 6, new byte[] {06, 05, 01, 07, 02, 12, 10, 14}, new byte[] {06, 05, 01, 07, 02, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // enamel lamp - {1113, new ItemRemakeInfo(1113, 13120, 2, new byte[] {10, 11, 07, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // round light fixture - {1114, new ItemRemakeInfo(1114, 13121, 6, new byte[] {09, 08, 09, 11, 07, 05, 02, 14}, new byte[] {10, 10, 10, 10, 10, 10, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wood-shade lamp - {1115, new ItemRemakeInfo(1115, 13122, 2, new byte[] {00, 09, 08, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // zen light - {1117, new ItemRemakeInfo(1117, 13138, 7, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 12, 00, 01, 10, 05, 02, 14}, false)}, // elegant chair - {1118, new ItemRemakeInfo(1118, 13139, 7, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 12, 00, 01, 10, 05, 02, 14}, false)}, // elegant bed - {1119, new ItemRemakeInfo(1119, 13140, 7, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 06, 12, 00, 01, 10, 05, 02}, true)}, // elegant console table - {1120, new ItemRemakeInfo(1120, 13141, 7, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 12, 00, 01, 10, 05, 02, 14}, false)}, // elegant sofa - {1121, new ItemRemakeInfo(1121, 13142, 7, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 12, 00, 01, 10, 05, 02, 14}, false)}, // elegant lamp - {1122, new ItemRemakeInfo(1122, 13143, 7, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 06, 12, 00, 01, 10, 05, 02}, true)}, // elegant dresser - {1123, new ItemRemakeInfo(1123, 13144, 6, new byte[] {10, 12, 01, 07, 02, 05, 06, 14}, new byte[] {10, 12, 01, 07, 02, 05, 06, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // simple shaded lamp - {1124, new ItemRemakeInfo(1124, 13145, 7, new byte[] {12, 01, 06, 11, 03, 12, 08, 12}, new byte[] {13, 07, 01, 12, 05, 02, 02, 13}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stained-glass light - {1125, new ItemRemakeInfo(1125, 13146, 4, new byte[] {12, 05, 02, 07, 06, 14, 14, 14}, new byte[] {09, 09, 09, 09, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // milk-glass lamp - {1126, new ItemRemakeInfo(1126, 13147, 2, new byte[] {12, 10, 11, 14, 14, 14, 14, 14}, new byte[] {12, 10, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fluorescent light - {1127, new ItemRemakeInfo(1127, 13148, 7, new byte[] {10, 12, 11, 07, 01, 07, 04, 13}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ceiling spotlight - {1128, new ItemRemakeInfo(1128, 13149, 6, new byte[] {06, 04, 00, 01, 02, 11, 12, 14}, new byte[] {06, 04, 00, 01, 02, 11, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Nordic pendant light - {1129, new ItemRemakeInfo(1129, 13150, 7, new byte[] {11, 07, 09, 12, 04, 06, 03, 10}, new byte[] {11, 07, 09, 12, 04, 06, 03, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Moroccan lights - {1130, new ItemRemakeInfo(1130, 13151, 3, new byte[] {07, 10, 01, 09, 14, 14, 14, 14}, new byte[] {07, 10, 01, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 05, 01, 12, 01, 04, 07, 06}, false)}, // festival lantern - {1131, new ItemRemakeInfo(1131, 13152, 6, new byte[] {12, 02, 07, 01, 06, 04, 12, 14}, new byte[] {10, 10, 10, 01, 06, 04, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // imperial lamp - {1132, new ItemRemakeInfo(1132, 13153, 3, new byte[] {09, 10, 08, 12, 14, 14, 14, 14}, new byte[] {10, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden pendant light - {1133, new ItemRemakeInfo(1133, 13154, 7, new byte[] {07, 11, 12, 01, 05, 06, 02, 03}, new byte[] {12, 12, 07, 01, 05, 07, 12, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // chandelier - {1134, new ItemRemakeInfo(1134, 13155, 2, new byte[] {11, 07, 10, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spiral chandelier - {1135, new ItemRemakeInfo(1135, 13156, 7, new byte[] {12, 10, 11, 07, 06, 01, 07, 00}, new byte[] {12, 10, 11, 07, 06, 01, 07, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ceiling fan - {1136, new ItemRemakeInfo(1136, 13157, 2, new byte[] {10, 12, 11, 14, 14, 14, 14, 14}, new byte[] {10, 12, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 05, 12, 10, 13, 04, 06, 04}, false)}, // dual hanging monitors - {1137, new ItemRemakeInfo(1137, 13158, 7, new byte[] {08, 00, 09, 08, 09, 10, 05, 02}, new byte[] {10, 10, 10, 10, 12, 10, 10, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hanging shelves - {1139, new ItemRemakeInfo(1139, 13161, 7, new byte[] {06, 01, 12, 07, 06, 10, 04, 09}, new byte[] {12, 12, 01, 01, 07, 12, 12, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 13, 13, 04, 00, 12, 02, 06}, true)}, // wooden field sign - {1142, new ItemRemakeInfo(1142, 13164, 5, new byte[] {11, 07, 03, 04, 06, 13, 14, 14}, new byte[] {10, 10, 10, 10, 10, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // disco ball - {1143, new ItemRemakeInfo(1143, 13185, 4, new byte[] {08, 05, 04, 12, 10, 14, 14, 14}, new byte[] {08, 04, 12, 01, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // small vase - {1144, new ItemRemakeInfo(1144, 13186, 3, new byte[] {06, 06, 12, 05, 14, 14, 14, 14}, new byte[] {06, 07, 04, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // porcelain vase - {1145, new ItemRemakeInfo(1145, 13187, 3, new byte[] {01, 06, 08, 04, 14, 14, 14, 14}, new byte[] {12, 07, 09, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fine vase - {1146, new ItemRemakeInfo(1146, 13188, 3, new byte[] {09, 12, 12, 07, 14, 14, 14, 14}, new byte[] {06, 04, 11, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ball catcher - {1147, new ItemRemakeInfo(1147, 13189, 5, new byte[] {08, 00, 09, 10, 01, 08, 14, 14}, new byte[] {08, 00, 09, 10, 01, 08, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stair dresser - {1148, new ItemRemakeInfo(1148, 13190, 4, new byte[] {10, 01, 04, 11, 07, 14, 14, 14}, new byte[] {03, 00, 01, 03, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sword - {1149, new ItemRemakeInfo(1149, 13191, 4, new byte[] {10, 01, 04, 11, 07, 14, 14, 14}, new byte[] {03, 00, 01, 03, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bow - {1150, new ItemRemakeInfo(1150, 13192, 4, new byte[] {10, 01, 04, 03, 11, 14, 14, 14}, new byte[] {01, 10, 10, 10, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // samurai suit - {1152, new ItemRemakeInfo(1152, 13220, 3, new byte[] {07, 10, 01, 09, 14, 14, 14, 14}, new byte[] {07, 10, 01, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 05, 01, 12, 01, 04, 07, 06}, false)}, // festival-lantern set - {1153, new ItemRemakeInfo(1153, 13222, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {03, 13, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky garland - {1154, new ItemRemakeInfo(1154, 13223, 3, new byte[] {03, 05, 08, 11, 14, 14, 14, 14}, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky table setting - {1155, new ItemRemakeInfo(1155, 04083, 3, new byte[] {09, 09, 09, 11, 14, 14, 14, 14}, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky arch - {1156, new ItemRemakeInfo(1156, 04084, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {09, 09, 09, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky scarecrow - {1157, new ItemRemakeInfo(1157, 04086, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {00, 07, 06, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky tower - {1168, new ItemRemakeInfo(1168, 12949, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {09, 09, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky standing lamp - {1190, new ItemRemakeInfo(1190, 04087, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {09, 09, 08, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky carriage - {1191, new ItemRemakeInfo(1191, 04088, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky lantern - {1192, new ItemRemakeInfo(1192, 04089, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {06, 06, 06, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky chair - {1193, new ItemRemakeInfo(1193, 04090, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {06, 06, 00, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky table - {1194, new ItemRemakeInfo(1194, 04092, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {08, 08, 08, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky lantern set - {1195, new ItemRemakeInfo(1195, 12951, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {03, 02, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky candy set - {1196, new ItemRemakeInfo(1196, 13163, 3, new byte[] {08, 09, 09, 12, 14, 14, 14, 14}, new byte[] {08, 09, 09, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 08, 13, 13, 14, 14, 14}, true)}, // study carrel - {1197, new ItemRemakeInfo(1197, 13229, 4, new byte[] {11, 12, 10, 01, 04, 14, 14, 14}, new byte[] {11, 12, 10, 01, 04, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // range hood - {1198, new ItemRemakeInfo(1198, 13243, 7, new byte[] {08, 09, 12, 12, 10, 09, 11, 02}, new byte[] {08, 09, 00, 10, 10, 12, 12, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // puppy plushie - {1199, new ItemRemakeInfo(1199, 13201, 7, new byte[] {12, 07, 01, 09, 05, 02, 06, 03}, new byte[] {12, 07, 01, 09, 05, 02, 06, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 06, 06, 05, 02, 00, 12, 14}, true)}, // bath bucket - {1200, new ItemRemakeInfo(1200, 13251, 4, new byte[] {11, 07, 06, 04, 01, 14, 14, 14}, new byte[] {12, 12, 12, 05, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dinosaur toy - {1201, new ItemRemakeInfo(1201, 13249, 7, new byte[] {12, 02, 04, 05, 07, 04, 09, 01}, new byte[] {08, 05, 10, 12, 06, 07, 06, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // kids' tent - {1204, new ItemRemakeInfo(1204, 13246, 3, new byte[] {04, 01, 00, 02, 14, 14, 14, 14}, new byte[] {05, 02, 06, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pop-up book - {1205, new ItemRemakeInfo(1205, 13252, 6, new byte[] {01, 01, 04, 00, 06, 02, 03, 14}, new byte[] {08, 02, 05, 07, 13, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dollhouse - {1207, new ItemRemakeInfo(1207, 13245, 4, new byte[] {09, 12, 12, 02, 06, 14, 14, 14}, new byte[] {07, 09, 01, 05, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Yule log - {1208, new ItemRemakeInfo(1208, 13247, 7, new byte[] {11, 04, 01, 00, 07, 06, 02, 10}, new byte[] {01, 00, 04, 06, 03, 03, 06, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tin robot - {1209, new ItemRemakeInfo(1209, 13244, 6, new byte[] {01, 13, 02, 05, 04, 00, 06, 14}, new byte[] {06, 13, 12, 06, 11, 09, 08, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // gift pile - {1210, new ItemRemakeInfo(1210, 13250, 3, new byte[] {10, 10, 11, 11, 14, 14, 14, 14}, new byte[] {01, 06, 04, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mini circuit - {1211, new ItemRemakeInfo(1211, 13242, 6, new byte[] {04, 01, 07, 06, 02, 05, 03, 14}, new byte[] {12, 10, 12, 12, 12, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // RC helicopter - {1212, new ItemRemakeInfo(1212, 13202, 7, new byte[] {12, 07, 01, 09, 05, 02, 06, 03}, new byte[] {12, 07, 01, 09, 05, 02, 06, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bath stool - {1213, new ItemRemakeInfo(1213, 13203, 6, new byte[] {05, 12, 02, 06, 11, 09, 11, 14}, new byte[] {04, 04, 04, 04, 04, 04, 06, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // square bathtub - {1214, new ItemRemakeInfo(1214, 13206, 2, new byte[] {08, 09, 12, 14, 14, 14, 14, 14}, new byte[] {01, 08, 08, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shopping bag - {1215, new ItemRemakeInfo(1215, 13210, 7, new byte[] {00, 06, 01, 04, 07, 02, 12, 10}, new byte[] {00, 06, 01, 04, 07, 02, 12, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stacked shopping baskets - {1216, new ItemRemakeInfo(1216, 00079, 7, new byte[] {08, 09, 12, 02, 07, 06, 04, 11}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 08, 02, 07, 06, 05, 10, 14}, false)}, // baby bed - {1217, new ItemRemakeInfo(1217, 01222, 3, new byte[] {11, 10, 01, 04, 14, 14, 14, 14}, new byte[] {11, 10, 01, 04, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 10, 13, 13, 14, 14, 14, 14}, false)}, // TV with VCR - {1218, new ItemRemakeInfo(1218, 13209, 7, new byte[] {10, 12, 09, 01, 07, 06, 05, 02}, new byte[] {10, 12, 10, 10, 12, 10, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 13, 12, 13, 13, 13, 13, 11}, false)}, // tablet device - {1219, new ItemRemakeInfo(1219, 13211, 6, new byte[] {12, 10, 01, 07, 06, 04, 11, 14}, new byte[] {07, 07, 07, 07, 07, 07, 07, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // caged cart - {1220, new ItemRemakeInfo(1220, 13207, 1, new byte[] {10, 11, 14, 14, 14, 14, 14, 14}, new byte[] {11, 11, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 01, 06, 01, 05, 04, 01, 07}, false)}, // small LED display - {1221, new ItemRemakeInfo(1221, 13255, 4, new byte[] {10, 09, 00, 12, 07, 14, 14, 14}, new byte[] {12, 09, 01, 12, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // elaborate display case - {1222, new ItemRemakeInfo(1222, 13214, 7, new byte[] {11, 12, 09, 10, 01, 07, 06, 04}, new byte[] {11, 12, 09, 10, 01, 07, 06, 04}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 11, 11, 11, 11, 11, 11, 14}, true)}, // steel trash can - {1223, new ItemRemakeInfo(1223, 13274, 6, new byte[] {11, 10, 12, 01, 04, 09, 07, 14}, new byte[] {11, 10, 12, 01, 04, 09, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wristwatch - {1224, new ItemRemakeInfo(1224, 13271, 7, new byte[] {11, 12, 10, 08, 01, 07, 04, 06}, new byte[] {11, 12, 10, 08, 01, 07, 04, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // upright speaker - {1225, new ItemRemakeInfo(1225, 13205, 4, new byte[] {12, 10, 11, 08, 09, 14, 14, 14}, new byte[] {12, 10, 11, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, false)}, // store shelf - {1226, new ItemRemakeInfo(1226, 12361, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 12, 10, 14, 14, 14, 14, 14}, false)}, // zen bench - {1227, new ItemRemakeInfo(1227, 13270, 2, new byte[] {09, 00, 10, 14, 14, 14, 14, 14}, new byte[] {09, 00, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // antique radio - {1228, new ItemRemakeInfo(1228, 13266, 3, new byte[] {09, 09, 08, 12, 14, 14, 14, 14}, new byte[] {09, 09, 08, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // owl clock - {1229, new ItemRemakeInfo(1229, 13288, 7, new byte[] {08, 09, 12, 02, 07, 06, 04, 11}, new byte[] {08, 09, 12, 02, 07, 06, 04, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 08, 02, 07, 06, 05, 11, 14}, true)}, // high chair - {1230, new ItemRemakeInfo(1230, 13294, 5, new byte[] {12, 10, 04, 00, 07, 02, 14, 14}, new byte[] {12, 10, 04, 00, 07, 02, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 07, 02, 05, 13, 13, 06}, false)}, // beach chairs with parasol - {1231, new ItemRemakeInfo(1231, 13296, 7, new byte[] {04, 01, 07, 06, 12, 11, 09, 10}, new byte[] {11, 11, 11, 11, 11, 11, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 01, 07, 06, 05, 11, 10}, true)}, // vehicle cabin seat - {1232, new ItemRemakeInfo(1232, 13295, 7, new byte[] {01, 07, 06, 04, 02, 00, 03, 09}, new byte[] {12, 12, 12, 12, 12, 12, 12, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 04, 04, 04, 01, 01, 01, 01}, false)}, // game-show stand - {1233, new ItemRemakeInfo(1233, 13299, 6, new byte[] {06, 05, 09, 04, 06, 02, 12, 14}, new byte[] {06, 05, 09, 04, 06, 02, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 00, 12, 04, 10, 14, 14}, true)}, // decorative bottles - {1234, new ItemRemakeInfo(1234, 13302, 6, new byte[] {00, 01, 12, 10, 11, 11, 09, 14}, new byte[] {08, 10, 12, 10, 11, 10, 09, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // decorative pillar - {1235, new ItemRemakeInfo(1235, 13300, 2, new byte[] {12, 10, 11, 14, 14, 14, 14, 14}, new byte[] {12, 10, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stylish wall spotlight - {1236, new ItemRemakeInfo(1236, 13307, 2, new byte[] {12, 10, 11, 14, 14, 14, 14, 14}, new byte[] {12, 10, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stylish spotlight - {1237, new ItemRemakeInfo(1237, 13304, 5, new byte[] {04, 06, 01, 06, 11, 10, 14, 14}, new byte[] {11, 11, 11, 11, 11, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // winnowing machine - {1238, new ItemRemakeInfo(1238, 13305, 5, new byte[] {11, 12, 10, 07, 04, 06, 14, 14}, new byte[] {10, 10, 10, 10, 10, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // conveyor belt - {1240, new ItemRemakeInfo(1240, 13306, 5, new byte[] {11, 12, 10, 07, 04, 06, 14, 14}, new byte[] {11, 11, 11, 11, 11, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // robot arm - {1241, new ItemRemakeInfo(1241, 13303, 7, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {12, 07, 08, 09, 06, 08, 13, 13}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 08, 10, 14, 14, 14, 14}, true)}, // glass jar - {1244, new ItemRemakeInfo(1244, 13313, 3, new byte[] {10, 12, 09, 06, 14, 14, 14, 14}, new byte[] {10, 12, 09, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // curved streetlight - {1245, new ItemRemakeInfo(1245, 13312, 3, new byte[] {10, 11, 12, 09, 14, 14, 14, 14}, new byte[] {10, 11, 12, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // round streetlight - {1249, new ItemRemakeInfo(1249, 04196, 4, new byte[] {10, 12, 07, 06, 01, 14, 14, 14}, new byte[] {10, 12, 07, 06, 01, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 06, 06, 06, 06, 06, 06, 14}, false)}, // crosswalk signal - {1252, new ItemRemakeInfo(1252, 13268, 4, new byte[] {12, 08, 12, 12, 12, 14, 14, 14}, new byte[] {09, 09, 05, 01, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // covered wagon - {1253, new ItemRemakeInfo(1253, 13269, 6, new byte[] {09, 08, 12, 05, 01, 06, 07, 14}, new byte[] {09, 08, 12, 05, 09, 10, 09, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {08, 08, 14, 14, 14, 14, 14, 14}, false)}, // storefront - {1254, new ItemRemakeInfo(1254, 13273, 1, new byte[] {06, 06, 14, 14, 14, 14, 14, 14}, new byte[] {08, 02, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cactus - {1255, new ItemRemakeInfo(1255, 13340, 7, new byte[] {12, 10, 09, 01, 07, 06, 00, 05}, new byte[] {12, 10, 09, 01, 07, 06, 00, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // garden table - {1256, new ItemRemakeInfo(1256, 13335, 7, new byte[] {08, 12, 01, 07, 05, 02, 09, 10}, new byte[] {08, 12, 01, 07, 05, 02, 09, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bird mobile - {1257, new ItemRemakeInfo(1257, 13336, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 05, 06, 12, 11, 00, 14, 14}, new byte[] {14, 05, 06, 12, 11, 00, 14, 14}, true)}, // construction scaffolding - {1258, new ItemRemakeInfo(1258, 13345, 7, new byte[] {07, 07, 00, 08, 08, 09, 00, 01}, new byte[] {07, 07, 00, 09, 08, 02, 00, 00}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 05, 09, 09, 04, 02, 07, 10}, false)}, // snack - {1259, new ItemRemakeInfo(1259, 13338, 7, new byte[] {08, 09, 09, 12, 11, 05, 02, 09}, new byte[] {11, 13, 11, 13, 13, 13, 13, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sloppy sink - {1260, new ItemRemakeInfo(1260, 13339, 7, new byte[] {08, 11, 04, 07, 06, 05, 02, 09}, new byte[] {08, 11, 04, 07, 06, 05, 02, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 05, 04, 01, 06, 07, 02, 08}, false)}, // sloppy sofa - {1261, new ItemRemakeInfo(1261, 13337, 7, new byte[] {08, 09, 09, 12, 11, 05, 02, 09}, new byte[] {12, 08, 09, 07, 06, 05, 02, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 13, 13, 13, 14}, false)}, // sloppy table - {1262, new ItemRemakeInfo(1262, 13341, 7, new byte[] {12, 11, 04, 08, 12, 05, 02, 11}, new byte[] {08, 09, 09, 12, 11, 05, 02, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {08, 11, 04, 07, 06, 05, 02, 09}, false)}, // sloppy bed - {1263, new ItemRemakeInfo(1263, 13343, 5, new byte[] {02, 05, 06, 07, 12, 10, 14, 14}, new byte[] {03, 04, 07, 00, 13, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dreamy wall rack - {1264, new ItemRemakeInfo(1264, 13344, 5, new byte[] {02, 05, 06, 07, 12, 10, 14, 14}, new byte[] {03, 04, 07, 00, 13, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dreamy shelves - {1265, new ItemRemakeInfo(1265, 13342, 5, new byte[] {02, 05, 06, 07, 12, 10, 14, 14}, new byte[] {03, 04, 07, 00, 13, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dreamy bed - {1266, new ItemRemakeInfo(1266, 13347, 5, new byte[] {12, 04, 01, 07, 09, 11, 14, 14}, new byte[] {05, 00, 11, 11, 06, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 10, 10, 04, 14, 14, 14, 14}, true)}, // yacht - {1267, new ItemRemakeInfo(1267, 13367, 7, new byte[] {12, 08, 09, 11, 10, 12, 02, 05}, new byte[] {12, 08, 08, 12, 10, 12, 02, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bunny garden decoration - {1268, new ItemRemakeInfo(1268, 13368, 7, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {07, 11, 09, 12, 10, 05, 02, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // elegant mirror - {1269, new ItemRemakeInfo(1269, 13363, 5, new byte[] {11, 12, 10, 07, 04, 06, 14, 14}, new byte[] {10, 10, 10, 10, 10, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 13, 06, 01, 14, 14, 14}, false)}, // inspection equipment - {1270, new ItemRemakeInfo(1270, 13362, 4, new byte[] {11, 11, 11, 10, 09, 14, 14, 14}, new byte[] {01, 04, 07, 07, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 00, 14, 14, 14, 14, 14, 14}, true)}, // double-edged sword - {1272, new ItemRemakeInfo(1272, 13366, 5, new byte[] {01, 07, 04, 00, 12, 06, 14, 14}, new byte[] {11, 11, 11, 11, 11, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // chainsaw - {1273, new ItemRemakeInfo(1273, 13365, 7, new byte[] {12, 07, 01, 04, 00, 06, 03, 11}, new byte[] {13, 13, 13, 06, 13, 13, 02, 13}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 10, 01, 04, 14, 14, 14, 14}, true)}, // toothbrush-and-cup set - {1274, new ItemRemakeInfo(1274, 13360, 6, new byte[] {12, 05, 08, 09, 06, 00, 03, 14}, new byte[] {12, 05, 08, 09, 06, 00, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {05, 08, 02, 04, 07, 00, 03, 14}, false)}, // bottled beverage - {1275, new ItemRemakeInfo(1275, 13361, 5, new byte[] {11, 11, 11, 11, 11, 11, 14, 14}, new byte[] {13, 13, 13, 13, 08, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // paint cans - {1276, new ItemRemakeInfo(1276, 13369, 7, new byte[] {11, 09, 12, 06, 04, 01, 10, 11}, new byte[] {11, 09, 12, 06, 04, 01, 10, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 09, 11, 14, 14, 14, 14}, true)}, // milk can - {1277, new ItemRemakeInfo(1277, 13370, 2, new byte[] {00, 08, 06, 14, 14, 14, 14, 14}, new byte[] {00, 08, 06, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wheat field - {1278, new ItemRemakeInfo(1278, 13356, 3, new byte[] {04, 06, 01, 10, 14, 14, 14, 14}, new byte[] {12, 11, 10, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {08, 04, 12, 07, 05, 10, 14, 14}, false)}, // rolling cart - {1279, new ItemRemakeInfo(1279, 13455, 7, new byte[] {00, 06, 01, 04, 07, 02, 12, 10}, new byte[] {00, 06, 01, 04, 07, 02, 12, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shopping basket - {1280, new ItemRemakeInfo(1280, 13454, 2, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {11, 10, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 01, 00, 04, 06, 07, 09}, false)}, // cool dining table - {1283, new ItemRemakeInfo(1283, 13464, 7, new byte[] {01, 07, 06, 04, 02, 05, 12, 10}, new byte[] {08, 09, 12, 06, 07, 09, 09, 01}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // crane game - {1285, new ItemRemakeInfo(1285, 13469, 7, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {12, 07, 00, 01, 02, 03, 04, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stage lights - {1286, new ItemRemakeInfo(1286, 13468, 7, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {12, 07, 00, 01, 02, 03, 04, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hanging stage lights - {1287, new ItemRemakeInfo(1287, 13467, 4, new byte[] {10, 10, 10, 10, 10, 14, 14, 14}, new byte[] {01, 07, 02, 03, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stage flame machine - {1288, new ItemRemakeInfo(1288, 13466, 4, new byte[] {11, 07, 04, 02, 06, 14, 14, 14}, new byte[] {11, 07, 04, 02, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // silver confetti blower - {1290, new ItemRemakeInfo(1290, 13479, 5, new byte[] {10, 11, 01, 07, 05, 09, 14, 14}, new byte[] {11, 10, 11, 10, 11, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // nearly busted radio - {1291, new ItemRemakeInfo(1291, 13474, 5, new byte[] {01, 07, 06, 04, 03, 12, 14, 14}, new byte[] {10, 10, 10, 10, 10, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // siren - {1292, new ItemRemakeInfo(1292, 13450, 1, new byte[] {00, 06, 14, 14, 14, 14, 14, 14}, new byte[] {09, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day chair - {1293, new ItemRemakeInfo(1293, 13449, 1, new byte[] {00, 06, 14, 14, 14, 14, 14, 14}, new byte[] {07, 07, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day decorations - {1295, new ItemRemakeInfo(1295, 13447, 1, new byte[] {12, 11, 14, 14, 14, 14, 14, 14}, new byte[] {12, 11, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day garden stand - {1296, new ItemRemakeInfo(1296, 13448, 1, new byte[] {12, 11, 14, 14, 14, 14, 14, 14}, new byte[] {00, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day hearth - {1297, new ItemRemakeInfo(1297, 13453, 1, new byte[] {09, 08, 14, 14, 14, 14, 14, 14}, new byte[] {12, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day table - {1298, new ItemRemakeInfo(1298, 01206, 1, new byte[] {07, 11, 14, 14, 14, 14, 14, 14}, new byte[] {07, 11, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // trumpet - {1299, new ItemRemakeInfo(1299, 02358, 5, new byte[] {11, 11, 11, 11, 11, 11, 14, 14}, new byte[] {12, 01, 07, 06, 05, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stadium light - {1301, new ItemRemakeInfo(1301, 13472, 5, new byte[] {08, 08, 08, 08, 09, 09, 14, 14}, new byte[] {12, 06, 00, 05, 10, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // windmill - {1302, new ItemRemakeInfo(1302, 13496, 4, new byte[] {11, 08, 12, 10, 06, 14, 14, 14}, new byte[] {11, 08, 09, 09, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stonework kitchen - {1303, new ItemRemakeInfo(1303, 13522, 6, new byte[] {07, 10, 09, 08, 01, 02, 10, 14}, new byte[] {07, 10, 09, 08, 01, 02, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 05, 10, 13, 01, 00, 04, 04}, false)}, // dress-up doll - {1304, new ItemRemakeInfo(1304, 13511, 5, new byte[] {11, 09, 10, 13, 08, 09, 14, 14}, new byte[] {11, 09, 10, 12, 08, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // gear apparatus - {1305, new ItemRemakeInfo(1305, 13509, 5, new byte[] {11, 09, 10, 13, 08, 09, 14, 14}, new byte[] {11, 09, 10, 12, 08, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // gear tower - {1306, new ItemRemakeInfo(1306, 13520, 3, new byte[] {11, 08, 10, 06, 14, 14, 14, 14}, new byte[] {11, 08, 10, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // forbidden altar - {1307, new ItemRemakeInfo(1307, 13510, 3, new byte[] {10, 06, 00, 01, 14, 14, 14, 14}, new byte[] {11, 10, 12, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // crew member's seat - {1308, new ItemRemakeInfo(1308, 13519, 7, new byte[] {10, 10, 10, 10, 10, 12, 02, 05}, new byte[] {01, 00, 06, 04, 11, 10, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // gaming chair - {1309, new ItemRemakeInfo(1309, 13521, 7, new byte[] {10, 10, 10, 10, 10, 12, 02, 05}, new byte[] {01, 00, 06, 04, 11, 10, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {03, 04, 05, 08, 02, 07, 10, 11}, false)}, // gaming desk - {1310, new ItemRemakeInfo(1310, 13508, 3, new byte[] {11, 10, 12, 10, 14, 14, 14, 14}, new byte[] {04, 06, 00, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cold sleep pod - {1311, new ItemRemakeInfo(1311, 13513, 7, new byte[] {05, 07, 06, 00, 11, 12, 01, 04}, new byte[] {11, 10, 08, 11, 01, 04, 09, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 04, 10, 02, 04, 14, 14}, true)}, // fish container - {1312, new ItemRemakeInfo(1312, 13504, 3, new byte[] {11, 10, 12, 10, 14, 14, 14, 14}, new byte[] {05, 06, 00, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // strategic meeting table - {1313, new ItemRemakeInfo(1313, 13518, 7, new byte[] {11, 12, 10, 06, 04, 01, 07, 09}, new byte[] {10, 11, 11, 09, 09, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lab chair - {1314, new ItemRemakeInfo(1314, 13523, 7, new byte[] {10, 07, 05, 02, 01, 03, 12, 10}, new byte[] {01, 06, 02, 07, 12, 00, 01, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 07, 05, 12, 13, 14, 14, 14}, true)}, // skateboard - {1315, new ItemRemakeInfo(1315, 13516, 7, new byte[] {11, 12, 10, 06, 04, 01, 07, 11}, new byte[] {10, 11, 11, 11, 09, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // amazing machine - {1316, new ItemRemakeInfo(1316, 13502, 3, new byte[] {11, 10, 12, 10, 14, 14, 14, 14}, new byte[] {05, 06, 00, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spaceship control panel - {1317, new ItemRemakeInfo(1317, 13515, 7, new byte[] {11, 12, 07, 06, 04, 01, 10, 09}, new byte[] {11, 12, 07, 06, 04, 01, 10, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 05, 13, 07, 01, 10, 10, 14}, true)}, // tank - {1318, new ItemRemakeInfo(1318, 13524, 7, new byte[] {11, 08, 09, 11, 07, 02, 05, 11}, new byte[] {10, 00, 10, 10, 06, 01, 04, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // medieval building side - {1319, new ItemRemakeInfo(1319, 13512, 5, new byte[] {11, 07, 06, 04, 01, 09, 14, 14}, new byte[] {09, 09, 09, 10, 10, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {05, 07, 01, 14, 14, 14, 14, 14}, false)}, // retro transportation stop - {1320, new ItemRemakeInfo(1320, 13505, 5, new byte[] {09, 01, 04, 07, 06, 10, 14, 14}, new byte[] {11, 10, 10, 06, 11, 02, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mining car - {1321, new ItemRemakeInfo(1321, 13506, 3, new byte[] {04, 06, 00, 01, 14, 14, 14, 14}, new byte[] {11, 10, 12, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // science pod - {1322, new ItemRemakeInfo(1322, 13514, 4, new byte[] {12, 02, 10, 03, 08, 14, 14, 14}, new byte[] {09, 12, 11, 10, 01, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // powder-room booth - {1323, new ItemRemakeInfo(1323, 13507, 4, new byte[] {06, 04, 12, 10, 00, 14, 14, 14}, new byte[] {09, 09, 08, 11, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // banker's lamp - {1324, new ItemRemakeInfo(1324, 13503, 4, new byte[] {11, 09, 10, 12, 09, 14, 14, 14}, new byte[] {11, 09, 10, 12, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // meter and pipes - {1325, new ItemRemakeInfo(1325, 13272, 7, new byte[] {06, 06, 06, 06, 06, 06, 06, 06}, new byte[] {00, 12, 07, 09, 05, 06, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // evergreen ash - {1326, new ItemRemakeInfo(1326, 13578, 5, new byte[] {02, 02, 12, 10, 06, 12, 14, 14}, new byte[] {02, 02, 12, 10, 04, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // inflatable bird ring - {1327, new ItemRemakeInfo(1327, 13575, 6, new byte[] {10, 11, 12, 09, 04, 01, 02, 14}, new byte[] {01, 07, 10, 11, 10, 10, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // SLR camera - {1328, new ItemRemakeInfo(1328, 13582, 7, new byte[] {11, 08, 09, 11, 02, 04, 08, 09}, new byte[] {11, 08, 09, 10, 02, 12, 08, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 00, 06, 14, 14, 14}, true)}, // castle tower - {1329, new ItemRemakeInfo(1329, 13581, 7, new byte[] {11, 08, 09, 11, 02, 04, 08, 09}, new byte[] {11, 08, 09, 10, 02, 12, 08, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // castle gate - {1330, new ItemRemakeInfo(1330, 13580, 4, new byte[] {08, 13, 02, 10, 09, 14, 14, 14}, new byte[] {09, 09, 07, 11, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // skateboard wall rack - {1331, new ItemRemakeInfo(1331, 13584, 3, new byte[] {11, 07, 02, 10, 14, 14, 14, 14}, new byte[] {02, 01, 05, 03, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 01, 05, 10, 02, 05, 04, 14}, false)}, // makeup pouch - {1332, new ItemRemakeInfo(1332, 13576, 6, new byte[] {06, 06, 06, 06, 06, 06, 06, 14}, new byte[] {10, 12, 06, 09, 08, 11, 00, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // schefflera - {1333, new ItemRemakeInfo(1333, 13586, 3, new byte[] {11, 12, 10, 09, 14, 14, 14, 14}, new byte[] {11, 11, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 06, 07, 03, 03, 09, 09}, false)}, // transit seat - {1335, new ItemRemakeInfo(1335, 13587, 5, new byte[] {08, 07, 02, 05, 12, 02, 14, 14}, new byte[] {07, 06, 12, 04, 06, 13, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dried-flower garland - {1336, new ItemRemakeInfo(1336, 13579, 1, new byte[] {09, 09, 14, 14, 14, 14, 14, 14}, new byte[] {06, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // baobab - {1337, new ItemRemakeInfo(1337, 13589, 7, new byte[] {10, 11, 12, 09, 01, 00, 06, 04}, new byte[] {10, 10, 12, 09, 01, 00, 06, 04}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 09, 10, 12, 14, 14}, true)}, // professional headphones - {1338, new ItemRemakeInfo(1338, 13577, 5, new byte[] {10, 06, 04, 12, 02, 11, 14, 14}, new byte[] {09, 09, 09, 07, 02, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // potted starter plants - {1339, new ItemRemakeInfo(1339, 13573, 7, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // medium wooden partition - {1340, new ItemRemakeInfo(1340, 13574, 7, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {08, 12, 00, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // small wooden partition - {1341, new ItemRemakeInfo(1341, 13588, 7, new byte[] {08, 12, 00, 09, 08, 06, 04, 02}, new byte[] {08, 12, 00, 09, 08, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tension-pole rack - {1342, new ItemRemakeInfo(1342, 13583, 2, new byte[] {12, 08, 09, 14, 14, 14, 14, 14}, new byte[] {12, 08, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 07, 06, 12, 11, 10, 14}, false)}, // rescue mannequin - {1343, new ItemRemakeInfo(1343, 13590, 7, new byte[] {11, 08, 09, 11, 02, 04, 08, 09}, new byte[] {11, 08, 09, 10, 02, 12, 08, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 00, 06, 14, 14, 14}, true)}, // castle wall - {1344, new ItemRemakeInfo(1344, 13591, 6, new byte[] {12, 12, 04, 12, 07, 11, 02, 14}, new byte[] {10, 08, 12, 09, 06, 10, 02, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fancy bathroom vanity - {1345, new ItemRemakeInfo(1345, 13606, 7, new byte[] {05, 07, 06, 00, 11, 12, 01, 04}, new byte[] {11, 10, 08, 11, 01, 04, 09, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 04, 10, 02, 04, 14, 14}, true)}, // stacked fish containers - {1350, new ItemRemakeInfo(1350, 13719, 5, new byte[] {07, 03, 02, 10, 12, 04, 14, 14}, new byte[] {00, 00, 07, 07, 07, 07, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // toy duck - {1353, new ItemRemakeInfo(1353, 13662, 4, new byte[] {12, 12, 08, 10, 11, 14, 14, 14}, new byte[] {06, 06, 08, 01, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ruined decorated pillar - {1355, new ItemRemakeInfo(1355, 13657, 3, new byte[] {09, 10, 08, 11, 14, 14, 14, 14}, new byte[] {09, 10, 08, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 10, 06, 11, 04, 08, 01, 01}, false)}, // decorative plate - {1357, new ItemRemakeInfo(1357, 13626, 4, new byte[] {12, 08, 01, 07, 05, 14, 14, 14}, new byte[] {07, 09, 09, 08, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ornithopter - {1358, new ItemRemakeInfo(1358, 13666, 1, new byte[] {11, 07, 14, 14, 14, 14, 14, 14}, new byte[] {11, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pile of cash - {1360, new ItemRemakeInfo(1360, 13620, 3, new byte[] {08, 08, 12, 12, 14, 14, 14, 14}, new byte[] {12, 12, 05, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // office materials - {1361, new ItemRemakeInfo(1361, 13637, 3, new byte[] {11, 10, 01, 04, 14, 14, 14, 14}, new byte[] {11, 10, 01, 04, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 07, 01, 04, 00, 10, 07, 02}, false)}, // outdoor folding chair - {1362, new ItemRemakeInfo(1362, 13680, 3, new byte[] {11, 10, 01, 04, 14, 14, 14, 14}, new byte[] {11, 10, 01, 04, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {11, 10, 08, 09, 14, 14, 14, 14}, false)}, // outdoor folding table - {1363, new ItemRemakeInfo(1363, 13630, 2, new byte[] {11, 07, 09, 14, 14, 14, 14, 14}, new byte[] {11, 07, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {08, 04, 01, 06, 02, 05, 10, 12}, false)}, // curtain partition - {1365, new ItemRemakeInfo(1365, 13744, 7, new byte[] {09, 11, 12, 10, 01, 04, 07, 06}, new byte[] {09, 11, 12, 10, 01, 04, 07, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 08, 13, 13, 08, 05, 11, 13}, false)}, // framed poster - {1368, new ItemRemakeInfo(1368, 13691, 5, new byte[] {06, 01, 03, 05, 12, 04, 14, 14}, new byte[] {02, 06, 12, 02, 06, 01, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mounted mountain bike - {1370, new ItemRemakeInfo(1370, 13640, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 01, 06, 01, 05, 04, 01, 07}, false)}, // wall-mounted LED display - {1375, new ItemRemakeInfo(1375, 13614, 3, new byte[] {08, 11, 02, 07, 14, 14, 14, 14}, new byte[] {06, 10, 05, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // key tray - {1377, new ItemRemakeInfo(1377, 13638, 3, new byte[] {10, 11, 01, 06, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 07, 01, 04, 00, 09, 12, 02}, false)}, // utility wagon - {1378, new ItemRemakeInfo(1378, 13656, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 07, 00, 01, 02, 03, 04, 06}, false)}, // cube light - {1379, new ItemRemakeInfo(1379, 13633, 4, new byte[] {07, 11, 12, 10, 01, 14, 14, 14}, new byte[] {07, 11, 12, 10, 01, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 06, 03, 12, 10, 07, 14}, false)}, // throne - {1380, new ItemRemakeInfo(1380, 13717, 3, new byte[] {10, 05, 09, 11, 14, 14, 14, 14}, new byte[] {10, 05, 09, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // metal pot - {1381, new ItemRemakeInfo(1381, 13621, 7, new byte[] {12, 10, 04, 01, 07, 06, 02, 08}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 06, 05, 07, 02, 14, 14}, true)}, // minicar - {1382, new ItemRemakeInfo(1382, 13622, 6, new byte[] {10, 11, 12, 01, 04, 06, 07, 14}, new byte[] {11, 10, 10, 10, 10, 10, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // luxury car - {1385, new ItemRemakeInfo(1385, 13722, 7, new byte[] {11, 08, 05, 02, 01, 04, 05, 09}, new byte[] {11, 09, 12, 12, 13, 13, 13, 00}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // recycled-paper bundle - {1386, new ItemRemakeInfo(1386, 13643, 7, new byte[] {12, 10, 01, 07, 06, 04, 00, 11}, new byte[] {10, 12, 12, 10, 12, 12, 09, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // die - {1387, new ItemRemakeInfo(1387, 13747, 2, new byte[] {10, 11, 12, 14, 14, 14, 14, 14}, new byte[] {10, 11, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 06, 01, 04, 07, 07, 01, 06}, false)}, // backlit sign - {1388, new ItemRemakeInfo(1388, 13678, 3, new byte[] {06, 06, 00, 05, 14, 14, 14, 14}, new byte[] {06, 06, 00, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // triangular topiary - {1392, new ItemRemakeInfo(1392, 13655, 7, new byte[] {08, 09, 12, 10, 07, 11, 02, 05}, new byte[] {08, 09, 12, 10, 07, 11, 02, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 05, 06, 00, 05, 09, 13, 13}, false)}, // framed photo - {1396, new ItemRemakeInfo(1396, 13639, 7, new byte[] {11, 10, 12, 00, 08, 09, 11, 07}, new byte[] {11, 10, 12, 00, 08, 09, 11, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {11, 12, 09, 09, 12, 08, 11, 07}, false)}, // short simple panel - {1397, new ItemRemakeInfo(1397, 13727, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 09, 01, 06, 09, 02, 07, 05}, new byte[] {12, 08, 12, 06, 00, 12, 06, 12}, false)}, // dessert carrier - {1399, new ItemRemakeInfo(1399, 13615, 7, new byte[] {08, 11, 10, 04, 01, 07, 06, 05}, new byte[] {09, 10, 09, 12, 09, 09, 09, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 12, 05, 06, 02, 00, 14, 14}, true)}, // scooter - {1402, new ItemRemakeInfo(1402, 13645, 7, new byte[] {09, 07, 10, 12, 05, 02, 06, 08}, new byte[] {13, 11, 04, 13, 13, 13, 13, 13}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // scrapbook - {1403, new ItemRemakeInfo(1403, 13709, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {11, 00, 10, 07, 05, 06, 14, 14}, false)}, // spray can - {1404, new ItemRemakeInfo(1404, 13634, 6, new byte[] {12, 12, 12, 12, 12, 04, 10, 14}, new byte[] {00, 08, 02, 01, 00, 12, 01, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 07, 14, 14, 14, 14}, true)}, // fresh-food trays - {1407, new ItemRemakeInfo(1407, 13652, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {00, 08, 05, 14, 14, 14, 14, 14}, new byte[] {01, 09, 07, 14, 14, 14, 14, 14}, false)}, // antique map - {1411, new ItemRemakeInfo(1411, 13696, 7, new byte[] {08, 08, 07, 10, 08, 05, 09, 12}, new byte[] {08, 04, 00, 01, 06, 00, 06, 00}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pile of cardboard boxes - {1417, new ItemRemakeInfo(1417, 13642, 7, new byte[] {13, 13, 01, 07, 06, 05, 03, 07}, new byte[] {12, 02, 02, 00, 06, 04, 10, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // paper-chain ceiling garland - {1421, new ItemRemakeInfo(1421, 13624, 2, new byte[] {06, 12, 10, 14, 14, 14, 14, 14}, new byte[] {06, 12, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 12, 10, 13, 14, 14, 14, 14}, false)}, // scoreboard - {1422, new ItemRemakeInfo(1422, 13651, 3, new byte[] {06, 12, 01, 11, 14, 14, 14, 14}, new byte[] {09, 08, 09, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 11, 08, 07, 08, 00, 14, 14}, false)}, // tokonoma - {1423, new ItemRemakeInfo(1423, 13746, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 06, 08, 07, 12, 08, 14}, new byte[] {12, 10, 06, 08, 06, 04, 08, 14}, false)}, // stacked bags - {1426, new ItemRemakeInfo(1426, 13748, 2, new byte[] {04, 01, 06, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cards - {1427, new ItemRemakeInfo(1427, 13712, 2, new byte[] {04, 01, 06, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // card tower - {1428, new ItemRemakeInfo(1428, 13631, 3, new byte[] {01, 11, 08, 06, 14, 14, 14, 14}, new byte[] {10, 11, 08, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 10, 10, 10, 10, 14, 14, 14}, true)}, // torii - {1429, new ItemRemakeInfo(1429, 13701, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 10, 12, 04, 06, 07, 05, 03}, new byte[] {01, 10, 12, 04, 06, 07, 05, 02}, false)}, // drapery - {1436, new ItemRemakeInfo(1436, 13649, 2, new byte[] {06, 07, 00, 14, 14, 14, 14, 14}, new byte[] {12, 12, 08, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lily-pad table - {1437, new ItemRemakeInfo(1437, 13616, 3, new byte[] {10, 11, 07, 00, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hanging lightbulb - {1438, new ItemRemakeInfo(1438, 13729, 7, new byte[] {05, 09, 02, 00, 01, 03, 12, 00}, new byte[] {12, 12, 12, 12, 07, 03, 13, 07}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // carton beverage - {1439, new ItemRemakeInfo(1439, 13618, 7, new byte[] {13, 13, 04, 11, 08, 05, 06, 01}, new byte[] {13, 13, 05, 12, 13, 07, 07, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // patchwork sofa chair - {1440, new ItemRemakeInfo(1440, 13625, 7, new byte[] {13, 13, 04, 11, 08, 05, 06, 01}, new byte[] {13, 13, 05, 12, 13, 07, 07, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // patchwork chair - {1441, new ItemRemakeInfo(1441, 13627, 7, new byte[] {13, 13, 04, 11, 08, 05, 06, 01}, new byte[] {13, 13, 05, 12, 13, 07, 07, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // patchwork low table - {1442, new ItemRemakeInfo(1442, 13629, 7, new byte[] {13, 13, 04, 11, 08, 05, 06, 01}, new byte[] {13, 13, 05, 12, 13, 07, 07, 05}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // patchwork bed - {1448, new ItemRemakeInfo(1448, 13636, 4, new byte[] {11, 12, 10, 09, 08, 14, 14, 14}, new byte[] {11, 12, 10, 09, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 13, 13, 01, 10, 13, 13}, false)}, // wide display stand - {1449, new ItemRemakeInfo(1449, 13647, 7, new byte[] {06, 05, 00, 10, 12, 02, 11, 09}, new byte[] {06, 05, 00, 10, 12, 02, 11, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 07, 13, 04, 13, 08, 13, 14}, true)}, // fence - {1452, new ItemRemakeInfo(1452, 13628, 6, new byte[] {01, 12, 07, 04, 06, 10, 12, 14}, new byte[] {13, 13, 13, 13, 13, 04, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // model kit - {1453, new ItemRemakeInfo(1453, 13740, 6, new byte[] {01, 01, 06, 10, 04, 08, 06, 14}, new byte[] {13, 13, 13, 13, 13, 13, 13, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // model kits - {1456, new ItemRemakeInfo(1456, 13681, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 07, 06, 04, 00, 12, 10, 12}, new byte[] {12, 10, 12, 12, 12, 05, 12, 04}, false)}, // light-bulb sign - {1458, new ItemRemakeInfo(1458, 13632, 5, new byte[] {12, 12, 12, 00, 00, 07, 14, 14}, new byte[] {04, 01, 07, 06, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 06, 07, 13, 08, 13, 02}, false)}, // popcorn snack set - {1460, new ItemRemakeInfo(1460, 13676, 3, new byte[] {06, 06, 00, 05, 14, 14, 14, 14}, new byte[] {06, 06, 00, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // round topiary - {1462, new ItemRemakeInfo(1462, 13690, 3, new byte[] {12, 11, 10, 06, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // futuristic meal - {1465, new ItemRemakeInfo(1465, 13623, 4, new byte[] {06, 00, 12, 08, 11, 14, 14, 14}, new byte[] {08, 08, 10, 08, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dormant volcano - {1467, new ItemRemakeInfo(1467, 13745, 6, new byte[] {12, 09, 06, 04, 09, 02, 04, 14}, new byte[] {07, 06, 00, 06, 07, 00, 07, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // yunomi teacup - {1468, new ItemRemakeInfo(1468, 13692, 5, new byte[] {02, 05, 06, 07, 12, 10, 14, 14}, new byte[] {03, 04, 06, 00, 01, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dreamy hanging decoration - {1469, new ItemRemakeInfo(1469, 13683, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {03, 04, 02, 06, 00, 09, 12, 10}, new byte[] {03, 04, 02, 06, 00, 09, 12, 10}, false)}, // yoga mat - {1470, new ItemRemakeInfo(1470, 13730, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 11, 02, 05, 07, 06, 00, 04}, false)}, // shaded pendant lamp - {1486, new ItemRemakeInfo(1486, 13751, 7, new byte[] {08, 12, 00, 09, 08, 06, 04, 02}, new byte[] {08, 12, 00, 09, 08, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 04, 06, 07, 08, 14, 14, 14}, false)}, // open wooden shelves - {1487, new ItemRemakeInfo(1487, 13756, 6, new byte[] {07, 01, 06, 04, 10, 12, 11, 14}, new byte[] {07, 01, 06, 04, 10, 12, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 04, 12, 00, 01, 02, 06, 01}, true)}, // bottle crate - {1492, new ItemRemakeInfo(1492, 13764, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 07, 00, 01, 02, 03, 04, 06}, false)}, // hanging cube light - {1494, new ItemRemakeInfo(1494, 13765, 3, new byte[] {09, 01, 08, 12, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plain party-lights arch - {1495, new ItemRemakeInfo(1495, 13767, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale garland - {1496, new ItemRemakeInfo(1496, 13776, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale confetti machine - {1497, new ItemRemakeInfo(1497, 13775, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 12, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale stage - {1498, new ItemRemakeInfo(1498, 13774, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {09, 09, 12, 02, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale drum - {1500, new ItemRemakeInfo(1500, 13770, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale parasol - {1501, new ItemRemakeInfo(1501, 13772, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 12, 02, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale balloon lamp - {1504, new ItemRemakeInfo(1504, 13773, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale stall - {1505, new ItemRemakeInfo(1505, 13777, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale lamp - {1506, new ItemRemakeInfo(1506, 13778, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {08, 09, 12, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale flag - {1508, new ItemRemakeInfo(1508, 13820, 1, new byte[] {00, 06, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day table setting - {1509, new ItemRemakeInfo(1509, 13818, 1, new byte[] {12, 06, 14, 14, 14, 14, 14, 14}, new byte[] {00, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day casserole - {1510, new ItemRemakeInfo(1510, 13819, 1, new byte[] {09, 07, 14, 14, 14, 14, 14, 14}, new byte[] {08, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day wheat decor - {1511, new ItemRemakeInfo(1511, 13829, 1, new byte[] {06, 01, 14, 14, 14, 14, 14, 14}, new byte[] {08, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Shell - {1512, new ItemRemakeInfo(1512, 13517, 7, new byte[] {11, 12, 10, 06, 04, 01, 07, 11}, new byte[] {01, 04, 01, 06, 04, 01, 07, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // unknown machine - {1513, new ItemRemakeInfo(1513, 13884, 6, new byte[] {08, 09, 12, 05, 02, 06, 11, 14}, new byte[] {12, 08, 07, 00, 12, 12, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ranch cupboard - {1514, new ItemRemakeInfo(1514, 02606, 6, new byte[] {08, 09, 12, 05, 02, 06, 11, 14}, new byte[] {12, 12, 12, 12, 12, 12, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 01, 04, 06, 02, 07, 14, 14}, false)}, // ranch bed - {1515, new ItemRemakeInfo(1515, 00522, 1, new byte[] {12, 06, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // creepy skeleton - {1516, new ItemRemakeInfo(1516, 13488, 3, new byte[] {09, 10, 12, 02, 14, 14, 14, 14}, new byte[] {01, 07, 04, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // chocolate heart - {1519, new ItemRemakeInfo(1519, 13926, 6, new byte[] {12, 10, 01, 04, 07, 06, 08, 14}, new byte[] {11, 12, 12, 12, 11, 12, 09, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 11, 11, 11, 01, 06, 04, 07}, true)}, // hanging guide sign - {1520, new ItemRemakeInfo(1520, 13925, 2, new byte[] {10, 12, 11, 14, 14, 14, 14, 14}, new byte[] {10, 12, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 10, 11, 05, 06, 04, 04}, false)}, // hanging monitor - {1521, new ItemRemakeInfo(1521, 13927, 3, new byte[] {05, 11, 02, 07, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Nintendo Switch Lite - {1522, new ItemRemakeInfo(1522, 13831, 2, new byte[] {01, 04, 06, 14, 14, 14, 14, 14}, new byte[] {08, 08, 08, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // large Mushroom Platform - {1523, new ItemRemakeInfo(1523, 13832, 2, new byte[] {07, 02, 06, 14, 14, 14, 14, 14}, new byte[] {08, 08, 08, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // small Mushroom Platform - {1524, new ItemRemakeInfo(1524, 13930, 5, new byte[] {13, 02, 04, 11, 01, 11, 14, 14}, new byte[] {13, 12, 05, 04, 12, 08, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // set of stockings - {1542, new ItemRemakeInfo(1542, 14017, 3, new byte[] {09, 11, 10, 06, 14, 14, 14, 14}, new byte[] {06, 06, 09, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cave - {1543, new ItemRemakeInfo(1543, 14018, 4, new byte[] {12, 12, 08, 10, 11, 14, 14, 14}, new byte[] {06, 06, 08, 01, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ruined arch - {1544, new ItemRemakeInfo(1544, 14019, 4, new byte[] {06, 06, 06, 09, 11, 14, 14, 14}, new byte[] {09, 12, 09, 08, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vine hanging chair - {1546, new ItemRemakeInfo(1546, 14029, 5, new byte[] {01, 02, 07, 03, 12, 10, 14, 14}, new byte[] {12, 12, 00, 12, 06, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // heart-shaped bouquet - {1547, new ItemRemakeInfo(1547, 14049, 7, new byte[] {11, 11, 11, 11, 11, 11, 11, 11}, new byte[] {12, 10, 11, 01, 07, 00, 06, 04}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 10, 05, 09, 04, 08, 14, 14}, true)}, // truck - {1548, new ItemRemakeInfo(1548, 14055, 5, new byte[] {12, 08, 01, 06, 04, 10, 14, 14}, new byte[] {06, 12, 00, 08, 11, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // outdoor kitchen - {1549, new ItemRemakeInfo(1549, 14053, 7, new byte[] {06, 06, 06, 06, 06, 06, 06, 06}, new byte[] {08, 12, 10, 11, 01, 07, 05, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall planter - {1550, new ItemRemakeInfo(1550, 14054, 6, new byte[] {08, 09, 12, 05, 02, 06, 11, 14}, new byte[] {12, 12, 07, 00, 12, 12, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ranch kitchen - {1552, new ItemRemakeInfo(1552, 14051, 7, new byte[] {07, 11, 09, 12, 10, 06, 02, 08}, new byte[] {07, 11, 09, 12, 10, 06, 02, 08}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 09, 08, 08, 13, 13, 13, 13}, false)}, // fancy frame - {1553, new ItemRemakeInfo(1553, 14050, 6, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {01, 06, 07, 13, 04, 12, 00, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // deep fryer - {1554, new ItemRemakeInfo(1554, 14106, 7, new byte[] {12, 00, 06, 10, 11, 05, 02, 09}, new byte[] {12, 00, 06, 10, 04, 05, 02, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // gazebo - {1556, new ItemRemakeInfo(1556, 14108, 3, new byte[] {08, 08, 09, 06, 14, 14, 14, 14}, new byte[] {09, 08, 09, 08, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // azumaya gazebo - {1567, new ItemRemakeInfo(1567, 14184, 6, new byte[] {06, 04, 03, 02, 02, 07, 00, 14}, new byte[] {09, 09, 09, 09, 11, 12, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pergola - {1568, new ItemRemakeInfo(1568, 12611, 1, new byte[] {11, 11, 14, 14, 14, 14, 14, 14}, new byte[] {11, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plate armor - {1569, new ItemRemakeInfo(1569, 14192, 4, new byte[] {06, 06, 06, 09, 11, 14, 14, 14}, new byte[] {06, 06, 04, 09, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // giant vine - {1570, new ItemRemakeInfo(1570, 14193, 4, new byte[] {06, 06, 06, 09, 11, 14, 14, 14}, new byte[] {06, 06, 04, 08, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vine bench - {1574, new ItemRemakeInfo(1574, 14206, 4, new byte[] {06, 06, 06, 09, 11, 14, 14, 14}, new byte[] {06, 06, 04, 08, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vine garland - {1575, new ItemRemakeInfo(1575, 14205, 4, new byte[] {06, 06, 06, 09, 11, 14, 14, 14}, new byte[] {09, 12, 09, 08, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vine lamp - {1576, new ItemRemakeInfo(1576, 14207, 7, new byte[] {06, 06, 05, 01, 07, 02, 12, 11}, new byte[] {06, 05, 04, 01, 07, 02, 11, 04}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glowing-moss stool - {1577, new ItemRemakeInfo(1577, 14210, 7, new byte[] {06, 06, 05, 01, 07, 02, 12, 11}, new byte[] {06, 05, 05, 01, 07, 02, 11, 04}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // hanging glowing moss - {1578, new ItemRemakeInfo(1578, 14209, 7, new byte[] {06, 06, 05, 01, 07, 02, 12, 11}, new byte[] {06, 05, 04, 01, 07, 02, 11, 04}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glowing-moss boulder - {1579, new ItemRemakeInfo(1579, 14211, 7, new byte[] {06, 06, 05, 01, 07, 02, 12, 11}, new byte[] {06, 06, 05, 01, 07, 02, 12, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glowing-moss wreath - {1580, new ItemRemakeInfo(1580, 14208, 7, new byte[] {06, 06, 05, 01, 07, 02, 12, 11}, new byte[] {11, 11, 11, 11, 11, 11, 11, 04}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glowing-moss balloon - {1581, new ItemRemakeInfo(1581, 14216, 4, new byte[] {06, 05, 02, 07, 13, 14, 14, 14}, new byte[] {10, 10, 10, 10, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // suspicious cauldron - {1582, new ItemRemakeInfo(1582, 14212, 2, new byte[] {06, 06, 03, 14, 14, 14, 14, 14}, new byte[] {05, 12, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glowing-moss pond - {1583, new ItemRemakeInfo(1583, 14213, 3, new byte[] {11, 08, 10, 06, 14, 14, 14, 14}, new byte[] {11, 08, 10, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glowing-moss statue - {1584, new ItemRemakeInfo(1584, 14215, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {06, 06, 04, 01, 07, 02, 12, 05}, new byte[] {06, 06, 04, 01, 07, 02, 12, 05}, false)}, // glow-in-the-dark stickers - {1585, new ItemRemakeInfo(1585, 14214, 3, new byte[] {11, 10, 12, 09, 14, 14, 14, 14}, new byte[] {06, 06, 07, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glowing-moss-jar shelves - {1591, new ItemRemakeInfo(1591, 12343, 4, new byte[] {11, 10, 01, 04, 07, 14, 14, 14}, new byte[] {06, 11, 10, 01, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stepladder - {1593, new ItemRemakeInfo(1593, 13902, 2, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tall wooden island counter - {1595, new ItemRemakeInfo(1595, 14313, 2, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // low wooden island counter - {1599, new ItemRemakeInfo(1599, 14308, 7, new byte[] {12, 02, 05, 07, 01, 04, 11, 10}, new byte[] {12, 02, 05, 07, 01, 04, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // low simple island counter - {1602, new ItemRemakeInfo(1602, 14310, 7, new byte[] {12, 02, 05, 07, 01, 04, 11, 10}, new byte[] {12, 02, 05, 07, 01, 04, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tall simple island counter - {1605, new ItemRemakeInfo(1605, 13897, 2, new byte[] {01, 12, 11, 14, 14, 14, 14, 14}, new byte[] {09, 09, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tall brick island counter - {1607, new ItemRemakeInfo(1607, 13901, 2, new byte[] {01, 12, 11, 14, 14, 14, 14, 14}, new byte[] {09, 09, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // low brick island counter - {1615, new ItemRemakeInfo(1615, 14340, 2, new byte[] {01, 06, 07, 14, 14, 14, 14, 14}, new byte[] {11, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // whoopee cushion - {1620, new ItemRemakeInfo(1620, 14346, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 06, 10, 07, 02, 05, 08, 14}, new byte[] {01, 12, 12, 10, 02, 05, 08, 14}, false)}, // hanging sign - {1622, new ItemRemakeInfo(1622, 14353, 5, new byte[] {04, 05, 07, 00, 01, 03, 14, 14}, new byte[] {04, 05, 07, 00, 01, 03, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dreamy rabbit toy - {1623, new ItemRemakeInfo(1623, 14352, 5, new byte[] {03, 04, 06, 07, 02, 10, 14, 14}, new byte[] {03, 04, 06, 07, 02, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dreamy bear toy - {1624, new ItemRemakeInfo(1624, 14354, 5, new byte[] {02, 05, 12, 07, 00, 03, 14, 14}, new byte[] {05, 03, 05, 06, 01, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dreamy unicorn toy - {1629, new ItemRemakeInfo(1629, 14530, 3, new byte[] {12, 00, 09, 11, 14, 14, 14, 14}, new byte[] {10, 12, 10, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // meeting-room table - {1630, new ItemRemakeInfo(1630, 14534, 5, new byte[] {01, 05, 00, 06, 03, 01, 14, 14}, new byte[] {12, 07, 09, 07, 13, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // instant noodles - {1631, new ItemRemakeInfo(1631, 14520, 7, new byte[] {05, 06, 07, 01, 02, 03, 04, 12}, new byte[] {05, 06, 07, 01, 02, 03, 04, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wall-mounted neon lamps - {1632, new ItemRemakeInfo(1632, 14523, 3, new byte[] {10, 11, 04, 03, 14, 14, 14, 14}, new byte[] {11, 01, 01, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tangled cords - {1633, new ItemRemakeInfo(1633, 14528, 7, new byte[] {04, 01, 07, 06, 10, 12, 11, 11}, new byte[] {04, 01, 07, 06, 10, 12, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // steel fence - {1634, new ItemRemakeInfo(1634, 14527, 6, new byte[] {04, 10, 01, 07, 06, 12, 09, 14}, new byte[] {04, 10, 01, 07, 06, 12, 09, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 10, 12, 12, 12}, false)}, // clipboard - {1635, new ItemRemakeInfo(1635, 14531, 2, new byte[] {00, 09, 12, 14, 14, 14, 14, 14}, new byte[] {11, 10, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // long folding table - {1636, new ItemRemakeInfo(1636, 14525, 6, new byte[] {12, 09, 06, 04, 02, 03, 11, 14}, new byte[] {12, 09, 06, 04, 02, 10, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 08, 11, 02, 14, 14, 14, 14}, true)}, // dispenser - {1637, new ItemRemakeInfo(1637, 14524, 5, new byte[] {12, 05, 02, 03, 07, 08, 14, 14}, new byte[] {07, 11, 12, 10, 06, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // floral sconce - {1639, new ItemRemakeInfo(1639, 14526, 2, new byte[] {07, 00, 09, 14, 14, 14, 14, 14}, new byte[] {07, 00, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden locker - {1640, new ItemRemakeInfo(1640, 14476, 2, new byte[] {12, 04, 09, 14, 14, 14, 14, 14}, new byte[] {02, 05, 01, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // nuptial bell - {1641, new ItemRemakeInfo(1641, 14477, 2, new byte[] {12, 05, 01, 14, 14, 14, 14, 14}, new byte[] {02, 04, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // nuptial ring pillow - {1642, new ItemRemakeInfo(1642, 14475, 2, new byte[] {02, 05, 01, 14, 14, 14, 14, 14}, new byte[] {12, 04, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 12, 14, 14, 14, 14, 14}, false)}, // nuptial doorplate - {1645, new ItemRemakeInfo(1645, 14550, 3, new byte[] {09, 09, 09, 11, 14, 14, 14, 14}, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky tree - {1647, new ItemRemakeInfo(1647, 14551, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky trick lamp - {1648, new ItemRemakeInfo(1648, 14561, 6, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {11, 01, 08, 13, 01, 08, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // chafing dish - {1649, new ItemRemakeInfo(1649, 14592, 7, new byte[] {08, 12, 01, 09, 10, 06, 04, 02}, new byte[] {08, 12, 01, 09, 10, 06, 04, 02}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 00, 04, 07, 12, 00, 07, 12}, true)}, // wooden music box - {1651, new ItemRemakeInfo(1651, 14601, 2, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden pillar - {1652, new ItemRemakeInfo(1652, 14598, 7, new byte[] {12, 02, 05, 07, 01, 04, 11, 10}, new byte[] {12, 02, 05, 07, 01, 04, 11, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // simple pillar - {1653, new ItemRemakeInfo(1653, 14596, 2, new byte[] {01, 12, 11, 14, 14, 14, 14, 14}, new byte[] {09, 08, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // brick pillar - {1654, new ItemRemakeInfo(1654, 14549, 3, new byte[] {09, 09, 12, 09, 14, 14, 14, 14}, new byte[] {11, 09, 12, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // decayed tree - {1655, new ItemRemakeInfo(1655, 14046, 4, new byte[] {07, 05, 02, 12, 09, 14, 14, 14}, new byte[] {03, 07, 06, 07, 04, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // xylophoid - {1656, new ItemRemakeInfo(1656, 14047, 5, new byte[] {05, 02, 06, 03, 09, 12, 14, 14}, new byte[] {12, 02, 12, 02, 08, 13, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // babbloid - {1657, new ItemRemakeInfo(1657, 14092, 4, new byte[] {00, 09, 06, 02, 12, 14, 14, 14}, new byte[] {09, 01, 06, 03, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // scatteroid - {1658, new ItemRemakeInfo(1658, 14074, 3, new byte[] {11, 09, 04, 10, 14, 14, 14, 14}, new byte[] {11, 09, 05, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // aluminoid - {1659, new ItemRemakeInfo(1659, 14597, 2, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // marble pillar - {1660, new ItemRemakeInfo(1660, 14332, 2, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tall marble island counter - {1662, new ItemRemakeInfo(1662, 14337, 2, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {11, 12, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // low marble island counter - {1663, new ItemRemakeInfo(1663, 14604, 7, new byte[] {06, 06, 05, 01, 07, 02, 12, 11}, new byte[] {11, 11, 11, 11, 11, 11, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // glowing-moss jar - {1664, new ItemRemakeInfo(1664, 14080, 3, new byte[] {02, 08, 06, 11, 14, 14, 14, 14}, new byte[] {06, 00, 09, 06, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // thwopoid - {1665, new ItemRemakeInfo(1665, 14081, 6, new byte[] {03, 07, 06, 02, 05, 12, 11, 14}, new byte[] {03, 07, 06, 02, 04, 00, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rumbloid - {1666, new ItemRemakeInfo(1666, 14082, 5, new byte[] {00, 08, 06, 09, 05, 11, 14, 14}, new byte[] {07, 09, 06, 01, 12, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bendoid - {1667, new ItemRemakeInfo(1667, 14083, 5, new byte[] {09, 07, 06, 04, 03, 10, 14, 14}, new byte[] {09, 09, 09, 05, 02, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // boomoid - {1670, new ItemRemakeInfo(1670, 14098, 5, new byte[] {08, 06, 05, 03, 10, 09, 14, 14}, new byte[] {09, 06, 08, 02, 11, 08, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // boioingoid - {1671, new ItemRemakeInfo(1671, 14099, 4, new byte[] {06, 07, 04, 12, 10, 14, 14, 14}, new byte[] {06, 07, 05, 05, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // stelloid - {1672, new ItemRemakeInfo(1672, 14100, 4, new byte[] {03, 07, 02, 11, 05, 14, 14, 14}, new byte[] {03, 07, 02, 11, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // jingloid - {1673, new ItemRemakeInfo(1673, 14101, 5, new byte[] {01, 09, 12, 05, 06, 10, 14, 14}, new byte[] {00, 09, 02, 12, 06, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // rattloid - {1676, new ItemRemakeInfo(1676, 14086, 3, new byte[] {05, 00, 07, 03, 14, 14, 14, 14}, new byte[] {04, 01, 06, 03, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bloopoid - {1677, new ItemRemakeInfo(1677, 14087, 3, new byte[] {08, 06, 01, 04, 14, 14, 14, 14}, new byte[] {09, 06, 01, 04, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sproingoid - {1678, new ItemRemakeInfo(1678, 14088, 5, new byte[] {07, 09, 05, 02, 06, 10, 14, 14}, new byte[] {00, 09, 04, 01, 06, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // crumploid - {1679, new ItemRemakeInfo(1679, 14089, 4, new byte[] {08, 08, 07, 02, 12, 14, 14, 14}, new byte[] {13, 09, 04, 13, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // clatteroid - {1682, new ItemRemakeInfo(1682, 14075, 5, new byte[] {08, 09, 06, 05, 12, 10, 14, 14}, new byte[] {08, 09, 04, 02, 02, 01, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wallopoid - {1683, new ItemRemakeInfo(1683, 14076, 4, new byte[] {04, 06, 09, 03, 10, 14, 14, 14}, new byte[] {07, 00, 05, 02, 11, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // drummoid - {1684, new ItemRemakeInfo(1684, 14077, 6, new byte[] {11, 09, 06, 02, 04, 12, 10, 14}, new byte[] {11, 08, 06, 02, 04, 08, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dootoid - {1685, new ItemRemakeInfo(1685, 14078, 3, new byte[] {05, 01, 07, 11, 14, 14, 14, 14}, new byte[] {11, 11, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // whirroid - {1688, new ItemRemakeInfo(1688, 14093, 6, new byte[] {06, 00, 09, 06, 04, 07, 11, 14}, new byte[] {07, 06, 09, 00, 05, 03, 09, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spikenoid - {1689, new ItemRemakeInfo(1689, 14094, 5, new byte[] {08, 07, 02, 05, 12, 10, 14, 14}, new byte[] {08, 07, 02, 05, 12, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // squeezoid - {1690, new ItemRemakeInfo(1690, 14095, 4, new byte[] {00, 07, 06, 02, 03, 14, 14, 14}, new byte[] {03, 12, 06, 02, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // flutteroid - {1693, new ItemRemakeInfo(1693, 14056, 4, new byte[] {07, 09, 06, 02, 05, 14, 14, 14}, new byte[] {00, 09, 06, 02, 04, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // arfoid - {1694, new ItemRemakeInfo(1694, 14057, 5, new byte[] {05, 09, 07, 06, 02, 12, 14, 14}, new byte[] {05, 09, 07, 06, 02, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // whistloid - {1695, new ItemRemakeInfo(1695, 14058, 3, new byte[] {09, 07, 06, 05, 14, 14, 14, 14}, new byte[] {04, 06, 09, 03, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bwongoid - {1696, new ItemRemakeInfo(1696, 14059, 4, new byte[] {09, 07, 06, 04, 10, 14, 14, 14}, new byte[] {01, 09, 09, 10, 07, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // twangoid - {1697, new ItemRemakeInfo(1697, 14060, 4, new byte[] {06, 07, 02, 05, 11, 14, 14, 14}, new byte[] {02, 00, 02, 02, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // laseroid - {1698, new ItemRemakeInfo(1698, 14061, 4, new byte[] {07, 12, 08, 02, 05, 14, 14, 14}, new byte[] {13, 13, 06, 07, 04, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // squeakoid - {1699, new ItemRemakeInfo(1699, 14062, 4, new byte[] {08, 08, 07, 02, 11, 14, 14, 14}, new byte[] {01, 09, 04, 03, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tockoid - {1700, new ItemRemakeInfo(1700, 14063, 5, new byte[] {01, 07, 06, 05, 03, 12, 14, 14}, new byte[] {04, 08, 12, 02, 07, 05, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ringoid - {1701, new ItemRemakeInfo(1701, 14064, 5, new byte[] {08, 09, 07, 05, 02, 10, 14, 14}, new byte[] {03, 04, 09, 06, 01, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // oinkoid - {1702, new ItemRemakeInfo(1702, 14065, 4, new byte[] {05, 07, 06, 03, 12, 14, 14, 14}, new byte[] {04, 09, 12, 03, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tremoloid - {1703, new ItemRemakeInfo(1703, 14066, 4, new byte[] {09, 06, 02, 03, 12, 14, 14, 14}, new byte[] {09, 06, 02, 03, 05, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bubbloid - {1704, new ItemRemakeInfo(1704, 14067, 6, new byte[] {06, 09, 07, 05, 02, 03, 12, 14}, new byte[] {07, 08, 03, 07, 07, 06, 08, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // petaloid - {1742, new ItemRemakeInfo(1742, 12693, 5, new byte[] {06, 09, 12, 10, 04, 02, 14, 14}, new byte[] {06, 09, 12, 10, 04, 02, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {07, 01, 06, 05, 10, 14, 14, 14}, false)}, // street lamp with banners - {1743, new ItemRemakeInfo(1743, 06830, 4, new byte[] {12, 10, 02, 07, 03, 14, 14, 14}, new byte[] {12, 04, 02, 07, 03, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shell music box - {1747, new ItemRemakeInfo(1747, 14619, 2, new byte[] {09, 10, 12, 14, 14, 14, 14, 14}, new byte[] {09, 10, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 01, 04, 06, 07, 09, 03, 10}, false)}, // vertical split curtains - {1748, new ItemRemakeInfo(1748, 14620, 2, new byte[] {09, 10, 12, 14, 14, 14, 14, 14}, new byte[] {09, 10, 12, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 01, 04, 06, 07, 09, 03, 10}, false)}, // horizontal split curtains - {1749, new ItemRemakeInfo(1749, 14621, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {12, 04, 12, 12, 12, 12, 00, 14}, new byte[] {05, 13, 13, 13, 05, 13, 13, 14}, false)}, // unfolded reference sheet - {1750, new ItemRemakeInfo(1750, 14542, 3, new byte[] {00, 07, 06, 12, 14, 14, 14, 14}, new byte[] {10, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // spooky treats basket - {1751, new ItemRemakeInfo(1751, 14575, 4, new byte[] {11, 04, 07, 01, 06, 14, 14, 14}, new byte[] {11, 05, 11, 12, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ABD - {1752, new ItemRemakeInfo(1752, 14714, 2, new byte[] {08, 12, 09, 14, 14, 14, 14, 14}, new byte[] {08, 12, 09, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 06, 02, 07, 14, 14, 14, 14}, true)}, // donation box - {1754, new ItemRemakeInfo(1754, 14414, 5, new byte[] {10, 10, 13, 07, 07, 07, 14, 14}, new byte[] {07, 07, 00, 00, 12, 06, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // handheld lantern - {1755, new ItemRemakeInfo(1755, 14639, 4, new byte[] {04, 03, 06, 05, 09, 14, 14, 14}, new byte[] {12, 13, 13, 13, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pocketbook - {1756, new ItemRemakeInfo(1756, 14640, 3, new byte[] {05, 04, 11, 00, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pocket magazine - {1757, new ItemRemakeInfo(1757, 14735, 1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // - {1758, new ItemRemakeInfo(1758, 14539, 5, new byte[] {10, 12, 01, 07, 07, 11, 14, 14}, new byte[] {11, 11, 11, 11, 07, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // dumbbell - {1759, new ItemRemakeInfo(1759, 05208, 7, new byte[] {08, 12, 00, 10, 04, 01, 06, 03}, new byte[] {08, 12, 00, 10, 04, 01, 06, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // large lattice fence - {1760, new ItemRemakeInfo(1760, 14756, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen fence - {1761, new ItemRemakeInfo(1761, 14594, 4, new byte[] {01, 06, 04, 02, 03, 14, 14, 14}, new byte[] {07, 09, 12, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // giant ornament - {1762, new ItemRemakeInfo(1762, 14591, 4, new byte[] {01, 06, 04, 02, 03, 14, 14, 14}, new byte[] {07, 09, 12, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ornament table lamp - {1763, new ItemRemakeInfo(1763, 14728, 4, new byte[] {01, 06, 04, 02, 03, 14, 14, 14}, new byte[] {07, 09, 12, 12, 10, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ornament tree - {1764, new ItemRemakeInfo(1764, 14593, 4, new byte[] {07, 09, 12, 12, 10, 14, 14, 14}, new byte[] {01, 06, 04, 02, 03, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ornament garland - {1765, new ItemRemakeInfo(1765, 12600, 3, new byte[] {07, 05, 01, 11, 14, 14, 14, 14}, new byte[] {10, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bulldozer - {1766, new ItemRemakeInfo(1766, 12603, 3, new byte[] {07, 06, 01, 11, 14, 14, 14, 14}, new byte[] {10, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // steamroller - {1767, new ItemRemakeInfo(1767, 12601, 3, new byte[] {07, 04, 01, 11, 14, 14, 14, 14}, new byte[] {10, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cement mixer - {1768, new ItemRemakeInfo(1768, 12602, 3, new byte[] {07, 05, 01, 11, 14, 14, 14, 14}, new byte[] {10, 10, 10, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // excavator - {1769, new ItemRemakeInfo(1769, 12345, 2, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {11, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // metal-and-wood table - {1770, new ItemRemakeInfo(1770, 12346, 2, new byte[] {08, 00, 09, 14, 14, 14, 14, 14}, new byte[] {11, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // metal-and-wood chair - {1771, new ItemRemakeInfo(1771, 00537, 3, new byte[] {11, 05, 02, 06, 14, 14, 14, 14}, new byte[] {05, 05, 02, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // IV drip - {1772, new ItemRemakeInfo(1772, 14538, 3, new byte[] {01, 04, 06, 02, 14, 14, 14, 14}, new byte[] {08, 08, 09, 02, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // protein shake - {1774, new ItemRemakeInfo(1774, 14758, 7, new byte[] {11, 07, 06, 04, 01, 12, 10, 09}, new byte[] {11, 07, 06, 04, 01, 12, 10, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // corrugated iron fence - {1775, new ItemRemakeInfo(1775, 14759, 7, new byte[] {04, 01, 07, 06, 02, 01, 02, 00}, new byte[] {04, 01, 07, 06, 02, 07, 05, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // park fence - {1776, new ItemRemakeInfo(1776, 14574, 4, new byte[] {11, 01, 06, 04, 10, 14, 14, 14}, new byte[] {09, 08, 08, 12, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // coffee beans - {1777, new ItemRemakeInfo(1777, 12305, 4, new byte[] {12, 02, 01, 07, 03, 14, 14, 14}, new byte[] {06, 06, 06, 06, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Casablanca lilies - {1778, new ItemRemakeInfo(1778, 12341, 3, new byte[] {04, 06, 00, 08, 14, 14, 14, 14}, new byte[] {11, 11, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // gurney - {1779, new ItemRemakeInfo(1779, 14556, 3, new byte[] {01, 01, 01, 01, 14, 14, 14, 14}, new byte[] {10, 13, 12, 09, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // osechi - {1781, new ItemRemakeInfo(1781, 14572, 7, new byte[] {05, 04, 06, 01, 08, 10, 02, 12}, new byte[] {10, 10, 10, 10, 09, 10, 11, 00}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 01, 04, 07, 00, 13, 13, 12}, true)}, // storage shed - {1782, new ItemRemakeInfo(1782, 14821, 7, new byte[] {12, 07, 00, 01, 02, 03, 04, 06}, new byte[] {10, 10, 10, 10, 02, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ring light - {1783, new ItemRemakeInfo(1783, 13475, 4, new byte[] {10, 12, 11, 07, 09, 14, 14, 14}, new byte[] {12, 12, 12, 12, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // candle chandelier - {1784, new ItemRemakeInfo(1784, 14826, 4, new byte[] {11, 12, 10, 09, 08, 14, 14, 14}, new byte[] {11, 12, 10, 09, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lighted display stand - {1785, new ItemRemakeInfo(1785, 14831, 7, new byte[] {09, 12, 06, 05, 01, 09, 11, 10}, new byte[] {06, 09, 10, 09, 06, 10, 05, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden storage shed - {1786, new ItemRemakeInfo(1786, 13465, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // bubble machine - {1787, new ItemRemakeInfo(1787, 01235, 6, new byte[] {12, 11, 08, 09, 05, 02, 10, 14}, new byte[] {11, 11, 08, 09, 05, 02, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 13, 13, 13, 13, 14, 14, 14}, true)}, // bathroom stall - {1788, new ItemRemakeInfo(1788, 12340, 4, new byte[] {12, 12, 12, 12, 12, 14, 14, 14}, new byte[] {01, 06, 10, 04, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // volleyball net - {1789, new ItemRemakeInfo(1789, 03402, 7, new byte[] {08, 12, 10, 06, 04, 02, 07, 03}, new byte[] {08, 12, 10, 06, 04, 02, 07, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vertical-board fence - {1795, new ItemRemakeInfo(1795, 04357, 7, new byte[] {04, 01, 06, 07, 04, 00, 12, 10}, new byte[] {04, 01, 06, 07, 04, 00, 12, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron fence - {1796, new ItemRemakeInfo(1796, 05207, 7, new byte[] {10, 04, 01, 00, 07, 08, 06, 03}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // zen fence - {1797, new ItemRemakeInfo(1797, 11711, 7, new byte[] {08, 12, 00, 10, 06, 04, 02, 03}, new byte[] {08, 12, 00, 10, 06, 04, 02, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // simple wooden fence - {1798, new ItemRemakeInfo(1798, 11712, 7, new byte[] {08, 12, 10, 04, 02, 05, 07, 03}, new byte[] {08, 12, 10, 04, 02, 05, 07, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // lattice fence - {1799, new ItemRemakeInfo(1799, 12894, 7, new byte[] {12, 02, 06, 01, 05, 07, 03, 10}, new byte[] {08, 12, 08, 08, 12, 08, 03, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wedding fence - {1800, new ItemRemakeInfo(1800, 13530, 5, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // wooden ladder set-up kit - {1801, new ItemRemakeInfo(1801, 13526, 2, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // vine ladder set-up kit - {1802, new ItemRemakeInfo(1802, 13534, 2, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron ladder set-up kit - {1803, new ItemRemakeInfo(1803, 14882, 4, new byte[] {12, 12, 08, 10, 11, 14, 14, 14}, new byte[] {06, 06, 08, 01, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ruined seat - {1804, new ItemRemakeInfo(1804, 14887, 4, new byte[] {12, 12, 08, 10, 11, 14, 14, 14}, new byte[] {06, 06, 08, 01, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // ruined broken pillar - {1805, new ItemRemakeInfo(1805, 12689, 3, new byte[] {12, 06, 12, 10, 14, 14, 14, 14}, new byte[] {04, 00, 02, 03, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plaza arch - {1806, new ItemRemakeInfo(1806, 12685, 3, new byte[] {04, 07, 02, 03, 14, 14, 14, 14}, new byte[] {06, 06, 06, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // inflatable plaza toy - {1807, new ItemRemakeInfo(1807, 12683, 3, new byte[] {01, 06, 02, 10, 14, 14, 14, 14}, new byte[] {07, 00, 05, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plaza ferris wheel - {1808, new ItemRemakeInfo(1808, 12803, 3, new byte[] {04, 06, 02, 10, 14, 14, 14, 14}, new byte[] {06, 00, 05, 03, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plaza train - {1809, new ItemRemakeInfo(1809, 12690, 3, new byte[] {01, 06, 02, 10, 14, 14, 14, 14}, new byte[] {12, 07, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plaza game stand - {1810, new ItemRemakeInfo(1810, 12692, 3, new byte[] {12, 06, 12, 10, 14, 14, 14, 14}, new byte[] {01, 09, 02, 01, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plaza clock - {1811, new ItemRemakeInfo(1811, 12691, 3, new byte[] {04, 06, 05, 10, 14, 14, 14, 14}, new byte[] {13, 13, 13, 13, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plaza balloon wagon - {1812, new ItemRemakeInfo(1812, 12688, 3, new byte[] {01, 06, 05, 10, 14, 14, 14, 14}, new byte[] {04, 09, 02, 07, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plaza bench - {1813, new ItemRemakeInfo(1813, 12684, 3, new byte[] {04, 06, 02, 10, 14, 14, 14, 14}, new byte[] {12, 07, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // plaza merry-go-round - {1815, new ItemRemakeInfo(1815, 00963, 6, new byte[] {01, 07, 06, 10, 04, 12, 09, 14}, new byte[] {01, 07, 06, 10, 04, 12, 09, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fire hydrant - {1816, new ItemRemakeInfo(1816, 12781, 2, new byte[] {10, 11, 08, 14, 14, 14, 14, 14}, new byte[] {10, 11, 08, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // sample case - {1817, new ItemRemakeInfo(1817, 03465, 1, new byte[] {10, 12, 14, 14, 14, 14, 14, 14}, new byte[] {12, 10, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // projection screen - {1818, new ItemRemakeInfo(1818, 12703, 5, new byte[] {05, 06, 10, 07, 01, 12, 14, 14}, new byte[] {12, 12, 12, 12, 12, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // mop - {1819, new ItemRemakeInfo(1819, 03063, 1, new byte[] {09, 08, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // theremin - {1820, new ItemRemakeInfo(1820, 13478, 7, new byte[] {11, 10, 12, 01, 04, 07, 02, 09}, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // tabletop record player - {1821, new ItemRemakeInfo(1821, 00735, 2, new byte[] {08, 09, 12, 14, 14, 14, 14, 14}, new byte[] {11, 10, 10, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // low folding table - {1822, new ItemRemakeInfo(1822, 00741, 5, new byte[] {08, 09, 07, 06, 10, 11, 14, 14}, new byte[] {12, 10, 11, 06, 10, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // safety railing - {1823, new ItemRemakeInfo(1823, 14799, 7, new byte[] {01, 05, 07, 06, 03, 02, 12, 10}, new byte[] {11, 11, 11, 11, 11, 11, 11, 11}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // flower tabletop mirror - {1824, new ItemRemakeInfo(1824, 00743, 6, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {05, 04, 02, 07, 00, 06, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frozen mini snowperson - {1825, new ItemRemakeInfo(1825, 00744, 7, new byte[] {08, 09, 10, 12, 02, 05, 06, 04}, new byte[] {12, 11, 11, 12, 02, 12, 08, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // compact kitchen - {1826, new ItemRemakeInfo(1826, 01133, -1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {04, 01, 07, 06, 14, 14, 14, 14}, false)}, // shopping cart - }; - } -} + {0072, new(0072, 01288, 5, [10, 12, 08, 04, 06, 01, 14, 14], [06, 06, 06, 06, 06, 06, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fan palm + {0075, new(0075, 02587, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 05, 02, 06, 07, 14, 14, 14], false)}, // hospital screen + {0076, new(0076, 02605, 7, [08, 12, 00, 09, 10, 06, 04, 02], [08, 12, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [00, 02, 05, 06, 14, 14, 14, 14], false)}, // wooden simple bed + {0078, new(0078, 02731, 7, [00, 06, 05, 04, 03, 01, 12, 10], [12, 06, 00, 07, 06, 12, 05, 01], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // digital alarm clock + {0081, new(0081, 01608, 2, [10, 12, 04, 14, 14, 14, 14, 14], [11, 11, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 01, 12, 06, 05, 07, 06, 12], false)}, // vertical banner + {0083, new(0083, 01850, 6, [10, 11, 12, 01, 02, 04, 08, 14], [10, 11, 12, 01, 02, 04, 08, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 12, 13, 13, 13, 13, 14, 14], false)}, // laptop + {0084, new(0084, 01557, 4, [12, 09, 04, 02, 07, 14, 14, 14], [08, 10, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block bed + {0085, new(0085, 00833, 6, [11, 12, 10, 01, 04, 06, 07, 14], [11, 12, 10, 01, 04, 06, 07, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 10, 02, 13, 02, 14, 14, 14], true)}, // upright locker + {0086, new(0086, 00086, 7, [04, 02, 01, 05, 07, 12, 11, 10], [07, 02, 05, 12, 00, 02, 02, 00], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // elephant slide + {0087, new(0087, 01851, 6, [05, 01, 07, 05, 03, 06, 02, 14], [06, 12, 00, 02, 04, 07, 02, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rocket lamp + {0089, new(0089, 01803, 7, [00, 10, 12, 09, 04, 01, 06, 11], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [12, 10, 10, 12, 10, 08, 14, 14], false)}, // drum set + {0090, new(0090, 01567, 7, [06, 04, 05, 00, 07, 01, 06, 09], [12, 12, 12, 12, 10, 01, 06, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // oil barrel + {0095, new(0095, 02560, 7, [07, 08, 00, 09, 10, 06, 04, 02], [07, 08, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden chest + {0096, new(0096, 01644, 7, [00, 02, 10, 01, 07, 08, 12, 04], [12, 12, 12, 12, 12, 10, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 10, 12, 03, 06, 05, 13, 02], true)}, // rock guitar + {0097, new(0097, 03078, 4, [06, 04, 12, 11, 10, 14, 14, 14], [06, 04, 12, 11, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tourist telescope + {0098, new(0098, 01888, 4, [12, 11, 09, 01, 10, 14, 14, 14], [11, 12, 09, 01, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rice cooker + {0099, new(0099, 01929, 2, [12, 00, 09, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // toilet + {0100, new(0100, 03333, 7, [10, 12, 11, 01, 07, 04, 02, 05], [10, 12, 11, 01, 07, 04, 02, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // LCD TV (20 in.) + {0101, new(0101, 03252, 4, [10, 12, 11, 01, 04, 14, 14, 14], [10, 12, 11, 01, 04, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // LCD TV (50 in.) + {0102, new(0102, 00080, 5, [08, 07, 01, 10, 07, 02, 14, 14], [09, 13, 07, 01, 05, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // clackercart + {0103, new(0103, 01875, 3, [10, 12, 09, 00, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // grand piano + {0104, new(0104, 03428, 4, [10, 12, 11, 01, 04, 14, 14, 14], [10, 12, 11, 01, 04, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall-mounted TV (50 in.) + {0105, new(0105, 01558, 4, [08, 09, 07, 02, 04, 14, 14, 14], [09, 07, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block bookshelf + {0106, new(0106, 01559, 4, [08, 10, 07, 05, 04, 14, 14, 14], [08, 09, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block bench + {0107, new(0107, 01561, 4, [08, 09, 06, 05, 01, 14, 14, 14], [08, 10, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block chest + {0108, new(0108, 01565, 4, [08, 09, 06, 02, 01, 14, 14, 14], [08, 10, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block table + {0109, new(0109, 02558, 4, [08, 09, 01, 02, 07, 14, 14, 14], [08, 10, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block chair + {0111, new(0111, 03205, 4, [08, 09, 07, 07, 04, 14, 14, 14], [08, 07, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block stereo + {0112, new(0112, 03206, 4, [08, 09, 06, 05, 01, 14, 14, 14], [08, 10, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block toy + {0113, new(0113, 03208, 4, [08, 10, 04, 02, 07, 14, 14, 14], [08, 09, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block wall clock + {0114, new(0114, 03490, 5, [08, 07, 00, 09, 10, 12, 14, 14], [08, 07, 00, 09, 10, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden waste bin + {0115, new(0115, 02740, 5, [12, 01, 04, 06, 07, 10, 14, 14], [12, 12, 12, 12, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // automatic washer + {0117, new(0117, 01103, 4, [08, 00, 09, 12, 10, 14, 14, 14], [08, 00, 09, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rocking chair + {0119, new(0119, 00088, 3, [00, 01, 02, 04, 14, 14, 14, 14], [08, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ringtoss + {0120, new(0120, 01108, 1, [09, 09, 14, 14, 14, 14, 14, 14], [11, 11, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // retro TV + {0121, new(0121, 02713, 7, [12, 01, 02, 07, 04, 09, 10, 11], [12, 01, 02, 07, 04, 09, 10, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 02, 13, 06, 13, 14, 14, 14], true)}, // refrigerator + {0123, new(0123, 02736, 2, [04, 06, 00, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // retro fan + {0124, new(0124, 01432, 7, [01, 04, 06, 07, 02, 05, 10, 08], [01, 04, 06, 07, 02, 05, 10, 08], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lantern + {0125, new(0125, 01112, 4, [13, 04, 03, 01, 13, 14, 14, 14], [13, 12, 07, 10, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // colorful wheel + {0126, new(0126, 03446, 4, [12, 11, 10, 09, 06, 14, 14, 14], [03, 00, 01, 07, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // western-style stone + {0127, new(0127, 00787, 3, [11, 00, 12, 10, 14, 14, 14, 14], [04, 10, 10, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tape deck + {0128, new(0128, 03439, 7, [08, 12, 00, 09, 10, 06, 04, 02], [08, 12, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 00, 02, 04, 06, 14, 14, 14], true)}, // wooden table + {0129, new(0129, 00083, 5, [07, 01, 12, 02, 04, 05, 14, 14], [07, 04, 05, 03, 05, 01, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rocking horse + {0130, new(0130, 01778, 1, [11, 05, 14, 14, 14, 14, 14, 14], [11, 05, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 08, 05, 07, 14, 14, 14, 14], false)}, // clothesline pole + {0131, new(0131, 03229, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 08, 04, 01, 06, 14, 14, 14], false)}, // clothesline + {0132, new(0132, 01889, 7, [01, 04, 06, 12, 05, 09, 10, 02], [05, 05, 01, 02, 07, 06, 10, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ring + {0134, new(0134, 03449, 7, [08, 12, 00, 09, 10, 06, 04, 02], [08, 12, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 00, 02, 05, 06, 14, 14, 14], true)}, // wooden stool + {0135, new(0135, 01913, 7, [07, 08, 00, 09, 10, 06, 04, 02], [07, 08, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden chair + {0137, new(0137, 01877, 6, [02, 04, 06, 12, 09, 10, 02, 14], [02, 04, 06, 12, 09, 10, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // piggy bank + {0138, new(0138, 02554, 7, [01, 07, 06, 04, 12, 00, 09, 10], [01, 07, 06, 04, 12, 00, 09, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // double sofa + {0139, new(0139, 03230, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 00, 06, 14, 14, 14, 14], false)}, // futon + {0140, new(0140, 01058, 3, [09, 07, 12, 10, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // music stand + {0142, new(0142, 01170, 4, [08, 07, 12, 01, 09, 14, 14, 14], [08, 07, 12, 01, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // swinging bench + {0143, new(0143, 02010, 3, [00, 12, 12, 07, 14, 14, 14, 14], [10, 10, 12, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ball + {0144, new(0144, 01712, 7, [10, 11, 07, 12, 01, 04, 06, 09], [10, 11, 07, 12, 01, 04, 06, 09], [14, 14, 14, 14, 14, 14, 14, 14], [08, 05, 13, 13, 03, 08, 04, 11], false)}, // poster stand + {0145, new(0145, 01852, 7, [05, 02, 00, 04, 07, 02, 12, 10], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // box sofa + {0146, new(0146, 01853, 7, [05, 02, 00, 04, 07, 02, 12, 10], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // box corner sofa + {0147, new(0147, 03282, 5, [12, 07, 05, 06, 01, 11, 14, 14], [00, 00, 00, 00, 00, 00, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pop-up toaster + {0148, new(0148, 01092, 4, [01, 06, 02, 04, 10, 14, 14, 14], [07, 07, 12, 05, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // popcorn machine + {0149, new(0149, 01881, 4, [01, 05, 06, 08, 06, 14, 14, 14], [12, 12, 11, 06, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plastic canister + {0150, new(0150, 03582, 3, [12, 12, 12, 12, 14, 14, 14, 14], [01, 04, 07, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // book + {0151, new(0151, 02614, 5, [06, 07, 02, 03, 12, 10, 14, 14], [10, 10, 10, 10, 10, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mountain bike + {0152, new(0152, 01032, 7, [08, 00, 09, 12, 10, 07, 04, 01], [08, 00, 09, 12, 10, 07, 04, 01], [14, 14, 14, 14, 14, 14, 14, 14], [04, 01, 11, 13, 13, 02, 13, 14], false)}, // magazine rack + {0153, new(0153, 01870, 7, [12, 07, 01, 04, 06, 02, 05, 10], [12, 07, 01, 04, 06, 02, 05, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 10, 07, 04, 00, 07, 14, 14], true)}, // mug + {0154, new(0154, 03305, 6, [01, 02, 07, 06, 04, 12, 10, 14], [01, 02, 07, 06, 04, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [13, 13, 00, 13, 13, 14, 14, 14], false)}, // baby chair + {0155, new(0155, 02771, 5, [12, 10, 01, 06, 00, 05, 14, 14], [12, 10, 01, 06, 00, 05, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // round space heater + {0156, new(0156, 00144, 4, [10, 09, 06, 07, 12, 14, 14, 14], [10, 09, 00, 05, 02, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // manhole cover + {0157, new(0157, 01050, 7, [12, 10, 11, 00, 06, 07, 02, 05], [01, 06, 00, 00, 03, 07, 02, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mixer + {0158, new(0158, 01128, 6, [12, 05, 01, 02, 07, 06, 10, 14], [11, 04, 12, 12, 12, 12, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sewing machine + {0159, new(0159, 01051, 4, [01, 04, 06, 07, 02, 14, 14, 14], [13, 13, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // water bird + {0160, new(0160, 03588, 7, [08, 08, 08, 08, 08, 08, 08, 08], [09, 09, 09, 09, 09, 09, 09, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // signpost + {0161, new(0161, 03122, 7, [08, 00, 09, 11, 07, 06, 04, 02], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mini DIY workbench + {0166, new(0166, 01042, 4, [01, 07, 04, 10, 09, 14, 14, 14], [12, 12, 12, 12, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // metronome + {0167, new(0167, 01866, 4, [00, 09, 12, 05, 01, 14, 14, 14], [06, 06, 06, 06, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // menu chalkboard + {0168, new(0168, 03436, 7, [07, 08, 00, 09, 10, 06, 04, 02], [07, 08, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden wardrobe + {0169, new(0169, 03438, 7, [07, 08, 00, 09, 10, 06, 04, 02], [13, 13, 13, 13, 13, 13, 13, 13], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden end table + {0170, new(0170, 01072, 7, [07, 07, 11, 11, 10, 12, 09, 06], [01, 04, 01, 04, 10, 12, 07, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rope partition + {0171, new(0171, 00330, 4, [01, 07, 06, 12, 10, 14, 14, 14], [13, 13, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // barbecue + {0172, new(0172, 00146, 7, [01, 04, 07, 12, 01, 06, 01, 07], [01, 04, 07, 12, 12, 12, 12, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cone + {0173, new(0173, 03346, 7, [05, 06, 00, 08, 07, 00, 02, 10], [05, 06, 00, 08, 04, 06, 05, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // public bench + {0174, new(0174, 01348, 4, [05, 02, 07, 01, 09, 14, 14, 14], [13, 13, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hamster cage + {0175, new(0175, 01598, 4, [04, 02, 12, 10, 07, 14, 14, 14], [04, 02, 12, 10, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // exercise ball + {0176, new(0176, 00531, 6, [06, 06, 06, 06, 06, 00, 12, 14], [06, 02, 06, 13, 01, 09, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hedge standee + {0177, new(0177, 00533, 4, [06, 02, 06, 00, 12, 14, 14, 14], [09, 09, 09, 09, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tree standee + {0178, new(0178, 00530, 3, [06, 06, 08, 12, 14, 14, 14, 14], [06, 06, 09, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // grass standee + {0179, new(0179, 00532, 5, [06, 02, 06, 10, 00, 12, 14, 14], [06, 02, 06, 01, 09, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mountain standee + {0180, new(0180, 01620, 6, [09, 08, 07, 04, 02, 12, 10, 14], [09, 08, 07, 04, 02, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [13, 06, 05, 12, 14, 14, 14, 14], false)}, // hammock + {0181, new(0181, 03468, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [05, 01, 07, 02, 04, 07, 12, 14], [13, 12, 01, 02, 04, 07, 12, 14], false)}, // beach towel + {0182, new(0182, 00664, 5, [12, 10, 04, 00, 07, 02, 14, 14], [12, 10, 05, 12, 06, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // beach chair + {0183, new(0183, 01029, 2, [08, 09, 00, 14, 14, 14, 14, 14], [08, 09, 00, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 01, 04, 00, 11, 14, 14, 14], false)}, // low screen + {0184, new(0184, 01082, 5, [09, 00, 01, 09, 08, 11, 14, 14], [01, 04, 07, 06, 05, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // picnic basket + {0185, new(0185, 01621, 5, [05, 13, 02, 13, 06, 10, 14, 14], [12, 12, 12, 12, 06, 00, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lawn chair + {0186, new(0186, 03348, 5, [04, 02, 06, 00, 13, 13, 14, 14], [07, 03, 01, 10, 12, 04, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plastic pool + {0188, new(0188, 03581, 2, [09, 07, 00, 14, 14, 14, 14, 14], [08, 08, 08, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fish-drying rack + {0189, new(0189, 01624, 7, [01, 03, 07, 04, 00, 06, 01, 10], [04, 07, 05, 09, 06, 07, 01, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // garden gnome + {0190, new(0190, 00865, 4, [09, 02, 04, 12, 10, 14, 14, 14], [07, 07, 06, 12, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // birdcage + {0192, new(0192, 03407, 4, [10, 04, 12, 01, 08, 14, 14, 14], [09, 09, 09, 09, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // katana + {0193, new(0193, 01757, 5, [12, 10, 01, 05, 02, 07, 14, 14], [12, 12, 12, 12, 12, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // claw-foot tub + {0194, new(0194, 01227, 5, [12, 10, 04, 01, 07, 02, 14, 14], [12, 10, 04, 01, 07, 02, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // deluxe washer + {0195, new(0195, 03590, 3, [10, 11, 12, 02, 14, 14, 14, 14], [10, 11, 12, 02, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 12, 13, 13, 13, 13, 13, 14], false)}, // desktop computer + {0196, new(0196, 02553, 2, [01, 11, 10, 14, 14, 14, 14, 14], [10, 11, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron frame + {0197, new(0197, 00085, 3, [06, 06, 00, 12, 14, 14, 14, 14], [09, 09, 09, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // train set + {0198, new(0198, 01716, 4, [11, 12, 10, 09, 08, 14, 14, 14], [11, 12, 10, 09, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // display stand + {0199, new(0199, 01043, 3, [12, 10, 01, 06, 14, 14, 14, 14], [12, 10, 01, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // microwave + {0200, new(0200, 01185, 7, [01, 06, 04, 07, 09, 12, 10, 07], [01, 06, 04, 07, 09, 12, 10, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // phone box + {0201, new(0201, 02335, 5, [01, 12, 12, 12, 07, 09, 14, 14], [12, 10, 05, 12, 07, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lighthouse + {0202, new(0202, 01797, 6, [08, 08, 09, 12, 12, 10, 12, 14], [08, 06, 08, 10, 00, 10, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // decoy duck + {0203, new(0203, 03443, 5, [07, 06, 05, 07, 02, 10, 14, 14], [05, 07, 04, 09, 05, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sewing project + {0204, new(0204, 03416, 7, [12, 03, 00, 05, 06, 13, 13, 13], [08, 08, 08, 08, 08, 08, 08, 08], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // soft-serve lamp + {0205, new(0205, 03307, 6, [12, 10, 01, 04, 07, 06, 09, 14], [12, 10, 01, 04, 07, 06, 09, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 01, 06, 11, 07, 14, 14, 14], false)}, // digital scale + {0206, new(0206, 02329, 5, [10, 01, 07, 06, 04, 12, 14, 14], [10, 01, 07, 06, 04, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tire toy + {0207, new(0207, 03583, 3, [13, 13, 13, 13, 14, 14, 14, 14], [07, 07, 07, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fishing-boat flag + {0208, new(0208, 03558, 2, [06, 07, 09, 14, 14, 14, 14, 14], [01, 01, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo wall decoration + {0209, new(0209, 03554, 2, [06, 07, 09, 14, 14, 14, 14, 14], [08, 08, 08, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo candleholder + {0210, new(0210, 03556, 2, [06, 07, 09, 14, 14, 14, 14, 14], [10, 08, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo stopblock + {0211, new(0211, 03551, 2, [06, 07, 09, 14, 14, 14, 14, 14], [12, 03, 02, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo shelf + {0213, new(0213, 03553, 2, [06, 07, 09, 14, 14, 14, 14, 14], [12, 12, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo partition + {0215, new(0215, 03557, 2, [06, 07, 09, 14, 14, 14, 14, 14], [06, 07, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo floor lamp + {0216, new(0216, 00710, 2, [06, 07, 09, 14, 14, 14, 14, 14], [06, 07, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo bench + {0218, new(0218, 01708, 7, [01, 07, 06, 04, 02, 11, 12, 10], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cassette player + {0219, new(0219, 01573, 7, [01, 04, 06, 02, 10, 12, 07, 01], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dharma + {0220, new(0220, 02776, 4, [12, 07, 02, 05, 10, 14, 14, 14], [12, 07, 02, 05, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tankless toilet + {0221, new(0221, 00742, 3, [00, 09, 08, 12, 14, 14, 14, 14], [09, 09, 08, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fireplace + {0222, new(0222, 02770, 1, [09, 10, 14, 14, 14, 14, 14, 14], [07, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // chessboard + {0223, new(0223, 01411, 2, [05, 07, 04, 14, 14, 14, 14, 14], [00, 09, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // globe + {0224, new(0224, 00739, 4, [09, 09, 00, 07, 09, 14, 14, 14], [09, 09, 00, 07, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tea table + {0225, new(0225, 00547, 3, [11, 12, 04, 02, 14, 14, 14, 14], [11, 12, 10, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // washbasin + {0226, new(0226, 03467, 3, [06, 04, 01, 07, 14, 14, 14, 14], [06, 04, 01, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [07, 04, 01, 11, 14, 14, 14, 14], false)}, // tea set + {0227, new(0227, 01229, 2, [12, 10, 12, 14, 14, 14, 14, 14], [12, 12, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bathroom sink + {0228, new(0228, 00907, 4, [01, 07, 06, 11, 10, 14, 14, 14], [11, 10, 06, 11, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vacuum cleaner + {0229, new(0229, 00908, 6, [11, 12, 10, 01, 00, 06, 02, 14], [10, 10, 10, 10, 10, 10, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // upright vacuum + {0230, new(0230, 01892, 3, [08, 12, 10, 09, 14, 14, 14, 14], [05, 02, 12, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hourglass + {0231, new(0231, 01117, 1, [00, 11, 14, 14, 14, 14, 14, 14], [01, 04, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sand castle + {0232, new(0232, 00333, 5, [09, 09, 09, 01, 04, 12, 14, 14], [07, 09, 12, 07, 04, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // birdhouse + {0234, new(0234, 03444, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 01, 06, 08, 13, 14, 14, 14], false)}, // wheelchair + {0236, new(0236, 01143, 2, [10, 06, 11, 14, 14, 14, 14, 14], [08, 08, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // smoker + {0239, new(0239, 01845, 6, [01, 07, 06, 05, 10, 04, 12, 14], [00, 00, 00, 09, 09, 09, 01, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // simple kettle + {0240, new(0240, 01319, 2, [12, 11, 10, 14, 14, 14, 14, 14], [10, 10, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // microscope + {0241, new(0241, 03595, 3, [10, 11, 12, 09, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // park clock + {0242, new(0242, 00918, 5, [12, 12, 07, 02, 04, 12, 14, 14], [12, 06, 07, 02, 07, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // coffee cup + {0244, new(0244, 02012, 6, [06, 06, 06, 06, 06, 06, 06, 14], [11, 11, 11, 11, 11, 11, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // chalkboard + {0246, new(0246, 01849, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 02, 07, 13, 14, 14, 14, 14], false)}, // kotatsu + {0247, new(0247, 01745, 1, [12, 10, 14, 14, 14, 14, 14, 14], [04, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 12, 12, 12, 12, 14, 14, 14], false)}, // copy machine + {0248, new(0248, 01823, 3, [10, 12, 04, 07, 14, 14, 14, 14], [10, 12, 04, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // trash bags + {0249, new(0249, 01783, 2, [08, 12, 04, 14, 14, 14, 14, 14], [08, 12, 04, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 06, 14, 14, 14, 14, 14], false)}, // corkboard + {0250, new(0250, 01632, 5, [01, 06, 02, 13, 09, 11, 14, 14], [01, 06, 02, 13, 09, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // golf bag + {0252, new(0252, 03442, 5, [08, 00, 09, 12, 04, 10, 14, 14], [00, 09, 00, 01, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sturdy sewing box + {0253, new(0253, 01241, 7, [08, 09, 09, 10, 12, 05, 07, 01], [13, 13, 13, 13, 13, 13, 13, 13], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // DIY workbench + {0254, new(0254, 03586, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [07, 01, 03, 04, 05, 09, 13, 14], false)}, // magazine + {0255, new(0255, 01199, 4, [00, 01, 04, 06, 12, 14, 14, 14], [01, 02, 06, 07, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tricycle + {0256, new(0256, 03340, 4, [00, 08, 07, 12, 10, 14, 14, 14], [00, 08, 07, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // deer decoration + {0257, new(0257, 01899, 3, [12, 08, 08, 08, 14, 14, 14, 14], [12, 08, 08, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 12, 14, 14, 14, 14, 14, 14], false)}, // autograph cards + {0258, new(0258, 00338, 4, [01, 00, 04, 07, 06, 14, 14, 14], [12, 10, 12, 11, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lawn mower + {0259, new(0259, 01802, 5, [01, 04, 12, 09, 06, 02, 14, 14], [05, 04, 12, 09, 06, 02, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [00, 05, 06, 12, 14, 14, 14, 14], false)}, // drink machine + {0262, new(0262, 00922, 6, [07, 01, 06, 04, 10, 12, 11, 14], [07, 01, 06, 04, 10, 12, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 04, 12, 00, 01, 02, 06, 01], true)}, // stacked bottle crates + {0263, new(0263, 01434, 7, [06, 11, 04, 00, 07, 02, 12, 01], [07, 10, 00, 11, 05, 03, 07, 04], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sleeping bag + {0266, new(0266, 01868, 5, [07, 01, 02, 04, 12, 10, 14, 14], [05, 05, 05, 05, 05, 05, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // desk mirror + {0267, new(0267, 00997, 5, [10, 12, 04, 06, 02, 09, 14, 14], [01, 09, 10, 08, 12, 06, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // incense burner + {0268, new(0268, 01495, 5, [01, 04, 06, 02, 10, 12, 14, 14], [08, 08, 08, 08, 08, 08, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dolly + {0269, new(0269, 01628, 2, [10, 12, 06, 14, 14, 14, 14, 14], [10, 12, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // garden lantern + {0270, new(0270, 03584, 3, [01, 05, 12, 10, 14, 14, 14, 14], [13, 13, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // study poster + {0271, new(0271, 03445, 3, [10, 12, 11, 06, 14, 14, 14, 14], [10, 12, 11, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [13, 06, 04, 13, 14, 14, 14, 14], false)}, // standard umbrella stand + {0272, new(0272, 01836, 7, [12, 08, 09, 02, 07, 06, 05, 03], [12, 12, 12, 02, 07, 06, 05, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // humidifier + {0273, new(0273, 01234, 4, [05, 01, 04, 06, 11, 14, 14, 14], [12, 12, 12, 12, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // portable toilet + {0274, new(0274, 01308, 5, [07, 09, 00, 12, 11, 08, 14, 14], [11, 12, 10, 01, 04, 06, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // school chair + {0275, new(0275, 01328, 5, [07, 09, 00, 12, 11, 08, 14, 14], [11, 12, 10, 01, 04, 06, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // school desk + {0277, new(0277, 00957, 4, [12, 02, 04, 06, 00, 14, 14, 14], [12, 12, 12, 12, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ventilation fan + {0278, new(0278, 02575, 6, [08, 09, 12, 05, 02, 06, 11, 14], [08, 09, 12, 05, 02, 06, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ranch chair + {0279, new(0279, 00896, 5, [08, 09, 04, 11, 02, 12, 14, 14], [08, 08, 08, 07, 05, 08, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cat tower + {0280, new(0280, 01019, 1, [08, 12, 14, 14, 14, 14, 14, 14], [12, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // first-aid kit + {0281, new(0281, 00839, 3, [11, 12, 10, 07, 14, 14, 14, 14], [11, 11, 11, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // safe + {0282, new(0282, 03064, 3, [04, 01, 07, 06, 14, 14, 14, 14], [12, 12, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cooler box + {0284, new(0284, 01792, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 12, 12, 01, 13, 05, 14, 14], [12, 13, 06, 01, 13, 13, 14, 14], false)}, // cushion + {0285, new(0285, 01499, 5, [00, 08, 09, 06, 01, 09, 14, 14], [08, 08, 09, 07, 12, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 07, 14, 14, 14, 14], true)}, // Papa bear + {0286, new(0286, 01501, 5, [08, 08, 09, 04, 07, 13, 14, 14], [12, 08, 09, 02, 12, 13, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 07, 14, 14, 14, 14], true)}, // Baby bear + {0287, new(0287, 01500, 5, [02, 08, 09, 12, 11, 11, 14, 14], [08, 08, 09, 02, 12, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 07, 14, 14, 14, 14], true)}, // Mama bear + {0290, new(0290, 03562, 1, [10, 12, 14, 14, 14, 14, 14, 14], [11, 11, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron wall rack + {0291, new(0291, 03559, 1, [10, 12, 14, 14, 14, 14, 14, 14], [10, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron wall lamp + {0292, new(0292, 03271, 4, [08, 00, 09, 09, 00, 14, 14, 14], [10, 10, 10, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ironwood cupboard + {0293, new(0293, 03270, 4, [08, 00, 09, 09, 00, 14, 14, 14], [11, 11, 11, 11, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ironwood kitchenette + {0294, new(0294, 03275, 4, [08, 00, 09, 09, 00, 14, 14, 14], [10, 10, 10, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ironwood clock + {0296, new(0296, 03193, 4, [08, 00, 09, 09, 00, 14, 14, 14], [10, 10, 10, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ironwood chair + {0297, new(0297, 03196, 4, [08, 00, 09, 09, 00, 14, 14, 14], [10, 10, 10, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ironwood dresser + {0298, new(0298, 03191, 4, [08, 00, 09, 09, 00, 14, 14, 14], [10, 10, 10, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ironwood table + {0299, new(0299, 03200, 4, [08, 00, 09, 09, 09, 14, 14, 14], [08, 00, 09, 09, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 05, 09, 14, 14, 14, 14, 14], false)}, // ironwood bed + {0300, new(0300, 03509, 5, [08, 09, 08, 08, 09, 12, 14, 14], [10, 06, 10, 01, 11, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // garden bench + {0301, new(0301, 03194, 4, [08, 00, 09, 09, 00, 14, 14, 14], [10, 10, 10, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ironwood low table + {0302, new(0302, 03195, 4, [08, 00, 09, 09, 00, 14, 14, 14], [10, 10, 10, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ironwood cart + {0303, new(0303, 01626, 4, [06, 04, 09, 10, 12, 14, 14, 14], [06, 04, 09, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron garden chair + {0304, new(0304, 01627, 4, [06, 04, 09, 10, 12, 14, 14, 14], [06, 04, 09, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron garden table + {0305, new(0305, 01625, 4, [06, 04, 09, 10, 12, 14, 14, 14], [06, 04, 09, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron garden bench + {0306, new(0306, 03563, 1, [10, 12, 14, 14, 14, 14, 14, 14], [11, 09, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron shelf + {0307, new(0307, 03561, 1, [10, 12, 14, 14, 14, 14, 14, 14], [10, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 02, 14, 14, 14, 14, 14, 14], false)}, // iron hanger stand + {0308, new(0308, 03560, 1, [10, 12, 14, 14, 14, 14, 14, 14], [10, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron worktable + {0309, new(0309, 00998, 6, [12, 04, 01, 08, 09, 10, 11, 14], [12, 12, 10, 12, 12, 10, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // kitchen island + {0310, new(0310, 00383, 6, [08, 01, 09, 04, 12, 10, 02, 14], [09, 10, 10, 10, 10, 10, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // acoustic guitar + {0311, new(0311, 01753, 5, [12, 09, 06, 02, 08, 10, 14, 14], [05, 00, 06, 02, 06, 04, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // aroma pot + {0312, new(0312, 00725, 2, [08, 09, 00, 14, 14, 14, 14, 14], [08, 09, 00, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 02, 06, 00, 11, 14, 14, 14], false)}, // paper lantern + {0313, new(0313, 01799, 4, [09, 06, 04, 01, 10, 14, 14, 14], [09, 09, 09, 12, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // doghouse + {0314, new(0314, 01631, 4, [01, 05, 09, 08, 11, 14, 14, 14], [11, 12, 09, 08, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // garden faucet + {0315, new(0315, 01493, 4, [12, 04, 02, 07, 09, 14, 14, 14], [08, 09, 07, 08, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stroller + {0316, new(0316, 00929, 5, [12, 11, 10, 02, 05, 09, 14, 14], [12, 11, 10, 02, 05, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // air conditioner + {0317, new(0317, 00928, 2, [09, 11, 07, 14, 14, 14, 14, 14], [12, 11, 00, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pot rack + {0318, new(0318, 03616, 7, [12, 01, 04, 07, 10, 09, 08, 12], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // system kitchen + {0320, new(0320, 03623, 3, [06, 02, 04, 11, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // toy box + {0321, new(0321, 03618, 3, [08, 00, 09, 07, 14, 14, 14, 14], [08, 00, 09, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 07, 14, 14, 14, 14, 14], false)}, // cutting board + {0322, new(0322, 03622, 3, [09, 08, 01, 10, 14, 14, 14, 14], [09, 08, 01, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 07, 02, 04, 14, 14, 14, 14], false)}, // floor seat + {0323, new(0323, 03621, 7, [08, 01, 12, 10, 04, 00, 05, 02], [08, 01, 12, 10, 04, 00, 05, 02], [14, 14, 14, 14, 14, 14, 14, 14], [12, 10, 05, 00, 07, 02, 13, 13], false)}, // loft bed with desk + {0324, new(0324, 03617, 7, [08, 09, 07, 06, 02, 12, 10, 11], [08, 09, 07, 06, 02, 12, 10, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 06, 01, 13, 04, 14, 14, 14], true)}, // stall + {0325, new(0325, 01263, 1, [06, 07, 14, 14, 14, 14, 14, 14], [08, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pear wardrobe + {0326, new(0326, 03658, 2, [06, 08, 09, 14, 14, 14, 14, 14], [06, 07, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo basket + {0327, new(0327, 03672, 6, [07, 07, 07, 12, 12, 12, 07, 14], [07, 04, 00, 01, 02, 06, 01, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cardboard box + {0328, new(0328, 01081, 3, [10, 12, 09, 08, 14, 14, 14, 14], [12, 10, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // upright piano + {0329, new(0329, 03675, 2, [07, 12, 06, 14, 14, 14, 14, 14], [07, 12, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hay bed + {0334, new(0334, 03697, 7, [12, 07, 01, 02, 04, 05, 06, 10], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // portable radio + {0335, new(0335, 03699, 6, [10, 01, 10, 10, 10, 10, 10, 10], [12, 13, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fish print + {0336, new(0336, 03702, 3, [08, 07, 09, 12, 14, 14, 14, 14], [08, 07, 09, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [07, 04, 02, 14, 14, 14, 14, 14], false)}, // study chair + {0337, new(0337, 03701, 3, [08, 07, 09, 12, 14, 14, 14, 14], [08, 07, 09, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // study desk + {0340, new(0340, 00808, 4, [09, 12, 06, 01, 07, 14, 14, 14], [08, 12, 12, 08, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mush table + {0342, new(0342, 01779, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 09, 10, 01, 02, 07, 06, 05], [12, 09, 10, 01, 02, 07, 06, 05], false)}, // table with cloth + {0343, new(0343, 03499, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen arch + {0344, new(0344, 03502, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [09, 12, 11, 09, 14, 14, 14, 14], false)}, // frozen bed + {0345, new(0345, 03500, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen pillar + {0346, new(0346, 03498, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen partition + {0347, new(0347, 03497, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen table + {0348, new(0348, 03504, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen tree + {0350, new(0350, 03505, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen counter + {0351, new(0351, 03503, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen chair + {0352, new(0352, 03501, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen sculpture + {0353, new(0353, 01861, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [13, 13, 13, 13, 13, 13, 13, 14], [06, 01, 11, 13, 13, 02, 13, 14], false)}, // stacked magazines + {0354, new(0354, 00832, 6, [04, 06, 07, 01, 05, 02, 10, 14], [10, 10, 10, 10, 11, 11, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // modern office chair + {0355, new(0355, 00840, 3, [12, 08, 09, 11, 14, 14, 14, 14], [12, 12, 10, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // office desk + {0356, new(0356, 03692, 2, [08, 12, 09, 14, 14, 14, 14, 14], [08, 12, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 09, 04, 07, 14, 14, 14, 14], false)}, // plain wooden shop sign + {0357, new(0357, 01759, 3, [13, 13, 13, 08, 14, 14, 14, 14], [12, 12, 12, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stack of books + {0358, new(0358, 02020, 3, [00, 09, 12, 10, 14, 14, 14, 14], [00, 09, 12, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 10, 09, 14, 14, 14, 14, 14], false)}, // director's chair + {0359, new(0359, 00955, 3, [06, 06, 01, 10, 14, 14, 14, 14], [12, 12, 12, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // exit sign + {0360, new(0360, 00716, 4, [07, 07, 07, 07, 08, 14, 14, 14], [06, 01, 06, 00, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // screen + {0362, new(0362, 03587, 2, [07, 07, 10, 14, 14, 14, 14, 14], [10, 10, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fishing-rod stand + {0363, new(0363, 03591, 5, [13, 13, 13, 13, 13, 13, 14, 14], [13, 02, 04, 06, 00, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // birthday candles + {0364, new(0364, 03592, 2, [12, 09, 02, 14, 14, 14, 14, 14], [13, 13, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // birthday cake + {0365, new(0365, 03593, 5, [12, 02, 05, 06, 00, 11, 14, 14], [13, 13, 13, 13, 13, 13, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // birthday table + {0366, new(0366, 03594, 5, [13, 13, 13, 13, 13, 13, 14, 14], [13, 02, 04, 06, 00, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // birthday sign + {0367, new(0367, 03596, 2, [12, 00, 11, 14, 14, 14, 14, 14], [04, 05, 03, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pool + {0368, new(0368, 00891, 4, [01, 04, 07, 09, 02, 14, 14, 14], [09, 12, 09, 09, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // holiday candle + {0370, new(0370, 01189, 3, [10, 06, 13, 10, 14, 14, 14, 14], [10, 09, 13, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tire stack + {0373, new(0373, 00682, 4, [09, 06, 09, 01, 12, 14, 14, 14], [08, 00, 10, 10, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // boomerang + {0374, new(0374, 00796, 1, [09, 00, 14, 14, 14, 14, 14, 14], [08, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // retro stereo + {0375, new(0375, 03773, 2, [10, 08, 09, 14, 14, 14, 14, 14], [06, 06, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // terrarium + {0376, new(0376, 03775, 2, [10, 09, 09, 14, 14, 14, 14, 14], [06, 06, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hanging terrarium + {0377, new(0377, 03776, 2, [00, 12, 11, 14, 14, 14, 14, 14], [09, 01, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // brick well + {0378, new(0378, 03785, 3, [06, 07, 01, 06, 14, 14, 14, 14], [11, 09, 10, 04, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // potted ivy + {0379, new(0379, 03784, 5, [10, 12, 00, 09, 06, 01, 14, 14], [10, 12, 00, 09, 06, 01, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // den chair + {0380, new(0380, 03783, 4, [09, 00, 09, 08, 12, 14, 14, 14], [09, 00, 09, 08, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // den desk + {0381, new(0381, 01652, 4, [01, 07, 04, 09, 06, 14, 14, 14], [07, 12, 05, 08, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // matryoshka + {0383, new(0383, 00805, 4, [09, 12, 04, 01, 07, 14, 14, 14], [09, 12, 04, 08, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mush lamp + {0385, new(0385, 03808, 4, [09, 09, 09, 09, 09, 14, 14, 14], [09, 12, 03, 01, 00, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mush log + {0387, new(0387, 03806, 4, [09, 12, 06, 01, 00, 14, 14, 14], [08, 12, 06, 08, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mush partition + {0389, new(0389, 03805, 4, [00, 12, 11, 01, 07, 14, 14, 14], [09, 09, 09, 09, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mush parasol + {0391, new(0391, 03816, 3, [06, 09, 12, 10, 14, 14, 14, 14], [06, 09, 12, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // streetlamp + {0392, new(0392, 03818, 4, [00, 08, 06, 04, 13, 14, 14, 14], [04, 01, 12, 12, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pennant + {0393, new(0393, 03819, 5, [11, 06, 07, 01, 12, 09, 14, 14], [11, 06, 07, 01, 12, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // oil-barrel bathtub + {0394, new(0394, 03820, 3, [12, 10, 05, 01, 14, 14, 14, 14], [12, 10, 05, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fan + {0395, new(0395, 03821, 4, [12, 10, 02, 06, 07, 14, 14, 14], [12, 11, 02, 11, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // air circulator + {0396, new(0396, 00915, 6, [08, 06, 04, 07, 01, 12, 10, 14], [08, 09, 09, 08, 09, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cuckoo clock + {0397, new(0397, 03681, 7, [10, 01, 12, 04, 09, 06, 06, 07], [10, 10, 12, 12, 09, 09, 08, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // piano bench + {0398, new(0398, 03624, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 12, 00, 01, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute bed + {0399, new(0399, 00331, 3, [09, 00, 12, 10, 14, 14, 14, 14], [09, 00, 12, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // birdbath + {0400, new(0400, 03683, 5, [07, 00, 09, 08, 11, 10, 14, 14], [12, 12, 06, 12, 12, 04, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plain sink + {0402, new(0402, 00849, 6, [10, 12, 00, 09, 04, 01, 02, 14], [09, 11, 10, 08, 10, 10, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // amp + {0403, new(0403, 03431, 7, [06, 05, 01, 07, 12, 10, 11, 09], [06, 12, 01, 07, 12, 09, 11, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall fan + {0404, new(0404, 02014, 2, [00, 09, 12, 14, 14, 14, 14, 14], [08, 11, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lecture-hall desk + {0405, new(0405, 03822, 2, [10, 09, 10, 14, 14, 14, 14, 14], [11, 01, 04, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pro tape recorder + {0406, new(0406, 02013, 1, [00, 09, 14, 14, 14, 14, 14, 14], [08, 11, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lecture-hall bench + {0407, new(0407, 01157, 3, [01, 09, 12, 10, 14, 14, 14, 14], [11, 11, 10, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // brick oven + {0408, new(0408, 01171, 5, [10, 01, 04, 07, 11, 09, 14, 14], [12, 12, 12, 12, 12, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // synthesizer + {0409, new(0409, 01221, 2, [10, 11, 01, 14, 14, 14, 14, 14], [10, 12, 01, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // video camera + {0410, new(0410, 00941, 3, [10, 12, 00, 02, 14, 14, 14, 14], [11, 11, 11, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 10, 12, 03, 06, 05, 07, 02], true)}, // DJ's turntable + {0414, new(0414, 04116, 6, [12, 12, 12, 12, 12, 12, 12, 14], [11, 11, 11, 11, 11, 11, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // whiteboard + {0415, new(0415, 04066, 5, [06, 02, 05, 00, 12, 13, 14, 14], [01, 02, 05, 00, 12, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // illuminated tree + {0416, new(0416, 04074, 4, [07, 02, 04, 06, 12, 14, 14, 14], [07, 02, 04, 06, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // illuminated reindeer + {0417, new(0417, 04108, 3, [07, 02, 04, 12, 14, 14, 14, 14], [01, 06, 00, 04, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // illuminated present + {0418, new(0418, 04131, 3, [05, 02, 07, 12, 14, 14, 14, 14], [05, 02, 00, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // illuminated snowflakes + {0419, new(0419, 04099, 2, [08, 12, 08, 14, 14, 14, 14, 14], [00, 07, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // formal paper + {0420, new(0420, 04068, 4, [12, 02, 07, 05, 10, 14, 14, 14], [12, 02, 07, 05, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [08, 04, 02, 07, 06, 14, 14, 14], false)}, // table setting + {0421, new(0421, 04230, 5, [12, 01, 02, 06, 04, 03, 14, 14], [12, 01, 02, 06, 04, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glass holder with candle + {0422, new(0422, 03995, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 04, 00, 01, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute DIY table + {0423, new(0423, 03996, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 04, 00, 01, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute wall-mounted clock + {0424, new(0424, 03997, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 04, 00, 12, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute wardrobe + {0425, new(0425, 03998, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 04, 00, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute sofa + {0426, new(0426, 03999, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 04, 00, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute chair + {0427, new(0427, 04000, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 12, 12, 12, 03, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute tea table + {0428, new(0428, 04001, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 04, 00, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute vanity + {0429, new(0429, 04002, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 04, 03, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute floor lamp + {0430, new(0430, 04003, 4, [12, 05, 07, 01, 04, 14, 14, 14], [02, 04, 00, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cute music player + {0431, new(0431, 02586, 2, [08, 00, 12, 14, 14, 14, 14, 14], [10, 06, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // natural garden chair + {0432, new(0432, 03943, 4, [08, 00, 09, 09, 00, 14, 14, 14], [10, 10, 10, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ironwood DIY workbench + {0433, new(0433, 03946, 4, [11, 10, 06, 04, 01, 14, 14, 14], [11, 10, 06, 04, 01, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 10, 06, 04, 00, 08, 09, 14], false)}, // outdoor table + {0434, new(0434, 03947, 4, [11, 10, 06, 04, 01, 14, 14, 14], [11, 10, 06, 04, 01, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 10, 06, 04, 00, 08, 09, 14], false)}, // outdoor bench + {0435, new(0435, 03987, 5, [12, 10, 11, 09, 01, 04, 14, 14], [12, 10, 11, 09, 01, 04, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall-mounted phone + {0436, new(0436, 04009, 6, [12, 10, 11, 01, 05, 02, 07, 14], [12, 10, 11, 01, 05, 02, 07, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cordless phone + {0437, new(0437, 04101, 3, [12, 02, 09, 10, 14, 14, 14, 14], [12, 02, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], false)}, // fax machine + {0438, new(0438, 04279, 5, [05, 05, 05, 05, 05, 05, 14, 14], [08, 08, 07, 13, 13, 13, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen-treat set + {0440, new(0440, 04027, 4, [07, 02, 03, 12, 13, 14, 14, 14], [05, 06, 06, 07, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // floral swag + {0441, new(0441, 03396, 2, [08, 00, 12, 14, 14, 14, 14, 14], [10, 06, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // natural garden table + {0442, new(0442, 04034, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 06, 05, 00, 14, 14, 14, 14], false)}, // scattered papers + {0443, new(0443, 04135, 3, [12, 10, 08, 11, 14, 14, 14, 14], [12, 10, 08, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // freezer + {0444, new(0444, 03965, 3, [07, 02, 05, 12, 14, 14, 14, 14], [07, 02, 05, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 01, 09, 13, 14, 14, 14, 14], false)}, // painting set + {0445, new(0445, 04030, 3, [11, 07, 09, 10, 14, 14, 14, 14], [12, 09, 02, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bathroom towel rack + {0446, new(0446, 03948, 4, [12, 02, 10, 09, 05, 14, 14, 14], [13, 13, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // accessories stand + {0448, new(0448, 04025, 5, [00, 12, 04, 06, 12, 12, 14, 14], [12, 09, 08, 09, 05, 04, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // unglazed dish set + {0451, new(0451, 03991, 5, [06, 06, 06, 02, 06, 12, 14, 14], [13, 04, 01, 01, 07, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // festive tree + {0452, new(0452, 03966, 5, [06, 04, 06, 02, 06, 12, 14, 14], [13, 04, 01, 02, 07, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // big festive tree + {0453, new(0453, 04067, 5, [06, 06, 06, 02, 06, 12, 14, 14], [13, 04, 01, 12, 07, 07, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tabletop festive tree + {0454, new(0454, 03993, 7, [01, 07, 06, 04, 02, 07, 05, 11], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // analog kitchen scale + {0455, new(0455, 03961, 1, [05, 03, 14, 14, 14, 14, 14, 14], [03, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fortune-telling set + {0456, new(0456, 00669, 3, [08, 09, 12, 04, 14, 14, 14, 14], [09, 09, 08, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ukulele + {0457, new(0457, 04006, 3, [08, 02, 05, 12, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // climbing wall + {0458, new(0458, 04119, 3, [08, 06, 08, 08, 14, 14, 14, 14], [08, 06, 02, 05, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // macrame tapestry + {0460, new(0460, 03992, 3, [09, 08, 12, 10, 14, 14, 14, 14], [09, 08, 12, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // key holder + {0461, new(0461, 03967, 3, [09, 12, 09, 02, 14, 14, 14, 14], [11, 11, 10, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // broom and dustpan + {0462, new(0462, 04076, 1, [02, 10, 14, 14, 14, 14, 14, 14], [13, 13, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // nail-art set + {0463, new(0463, 00889, 5, [07, 01, 04, 06, 09, 10, 14, 14], [11, 11, 11, 11, 11, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // camp stove + {0465, new(0465, 04014, 7, [10, 12, 07, 01, 04, 05, 11, 11], [10, 12, 07, 01, 04, 05, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // folding floor lamp + {0466, new(0466, 04338, 6, [01, 07, 05, 06, 02, 10, 00, 14], [12, 10, 10, 10, 12, 01, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // portable record player + {0467, new(0467, 04013, 2, [01, 04, 10, 14, 14, 14, 14, 14], [10, 10, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // punching bag + {0468, new(0468, 04081, 7, [06, 07, 01, 04, 11, 06, 12, 05], [06, 07, 01, 04, 10, 09, 12, 07], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // camping cot + {0469, new(0469, 04075, 1, [09, 01, 14, 14, 14, 14, 14, 14], [07, 07, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // gong + {0470, new(0470, 04052, 5, [12, 05, 04, 05, 06, 11, 14, 14], [09, 00, 07, 12, 04, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan bed + {0471, new(0471, 04113, 5, [11, 07, 01, 06, 04, 10, 14, 14], [05, 06, 04, 08, 05, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hose reel + {0472, new(0472, 03962, 7, [05, 06, 03, 02, 07, 13, 13, 08], [05, 06, 03, 02, 07, 12, 13, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // inflatable sofa + {0474, new(0474, 04094, 3, [09, 04, 12, 10, 14, 14, 14, 14], [06, 06, 06, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // floating-biotope planter + {0475, new(0475, 04073, 5, [08, 12, 05, 00, 07, 11, 14, 14], [08, 12, 05, 00, 01, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // classic pitcher + {0476, new(0476, 00870, 3, [12, 04, 10, 02, 14, 14, 14, 14], [13, 13, 10, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // book stands + {0477, new(0477, 04379, 6, [12, 08, 09, 01, 07, 02, 12, 14], [06, 07, 12, 00, 06, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // springy ride-on + {0478, new(0478, 03950, 2, [09, 08, 10, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique chair + {0479, new(0479, 03951, 2, [09, 08, 10, 14, 14, 14, 14, 14], [09, 08, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique console table + {0480, new(0480, 03952, 2, [09, 08, 10, 14, 14, 14, 14, 14], [09, 08, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique table + {0481, new(0481, 03953, 2, [09, 08, 10, 14, 14, 14, 14, 14], [07, 07, 07, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique phone + {0482, new(0482, 03954, 2, [09, 08, 10, 14, 14, 14, 14, 14], [07, 07, 07, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique clock + {0483, new(0483, 03955, 2, [09, 08, 10, 14, 14, 14, 14, 14], [05, 05, 05, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique vanity + {0484, new(0484, 03956, 2, [09, 08, 10, 14, 14, 14, 14, 14], [09, 08, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique bureau + {0485, new(0485, 03957, 2, [09, 08, 10, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique bed + {0486, new(0486, 03958, 2, [09, 08, 10, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique mini table + {0487, new(0487, 03959, 2, [09, 08, 10, 14, 14, 14, 14, 14], [09, 08, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique wardrobe + {0488, new(0488, 04111, 7, [05, 01, 07, 08, 10, 09, 11, 07], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // old-fashioned alarm clock + {0489, new(0489, 04029, 7, [10, 08, 06, 04, 01, 07, 00, 12], [10, 08, 06, 04, 01, 10, 10, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rotary phone + {0490, new(0490, 01606, 5, [08, 09, 12, 12, 01, 10, 14, 14], [08, 09, 12, 11, 10, 07, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // serving cart + {0491, new(0491, 04392, 1, [10, 12, 14, 14, 14, 14, 14, 14], [01, 04, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // magic kit + {0492, new(0492, 03960, 5, [04, 01, 06, 07, 08, 13, 14, 14], [12, 12, 12, 09, 06, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // handy water cooler + {0493, new(0493, 03949, 4, [01, 01, 01, 02, 12, 14, 14, 14], [06, 06, 06, 06, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // anthurium plant + {0494, new(0494, 01829, 4, [06, 06, 06, 06, 06, 14, 14, 14], [09, 05, 07, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cypress plant + {0497, new(0497, 04129, 5, [10, 09, 01, 07, 04, 12, 14, 14], [06, 06, 06, 06, 06, 06, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // monstera + {0498, new(0498, 04132, 4, [12, 09, 06, 04, 10, 14, 14, 14], [06, 06, 06, 06, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // yucca + {0499, new(0499, 04080, 6, [12, 10, 08, 02, 05, 06, 05, 14], [12, 10, 12, 12, 12, 12, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // long bathtub + {0500, new(0500, 04078, 3, [10, 12, 01, 13, 14, 14, 14, 14], [11, 11, 11, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // barbell + {0501, new(0501, 01838, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 07, 02, 04, 14, 14, 14, 14], false)}, // ironing set + {0502, new(0502, 04412, 2, [02, 12, 10, 14, 14, 14, 14, 14], [01, 04, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cotton-candy stall + {0503, new(0503, 04045, 5, [09, 00, 07, 12, 04, 10, 14, 14], [09, 00, 07, 12, 04, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan waste bin + {0504, new(0504, 04049, 5, [09, 00, 07, 12, 04, 10, 14, 14], [09, 00, 07, 12, 04, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan wardrobe + {0505, new(0505, 04046, 5, [09, 00, 07, 12, 04, 10, 14, 14], [09, 00, 07, 12, 04, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan end table + {0506, new(0506, 04047, 5, [12, 05, 04, 05, 06, 11, 14, 14], [09, 00, 07, 12, 04, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan stool + {0507, new(0507, 04053, 5, [12, 05, 04, 05, 06, 11, 14, 14], [09, 00, 07, 12, 04, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan armchair + {0508, new(0508, 04048, 5, [09, 00, 07, 12, 04, 10, 14, 14], [12, 12, 12, 11, 12, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan towel basket + {0509, new(0509, 04050, 5, [09, 00, 07, 12, 04, 10, 14, 14], [09, 09, 09, 12, 10, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan table lamp + {0510, new(0510, 04051, 5, [09, 00, 07, 12, 04, 10, 14, 14], [09, 00, 07, 12, 04, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan vanity + {0511, new(0511, 04054, 5, [09, 00, 07, 12, 04, 10, 14, 14], [09, 00, 07, 12, 04, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattan low table + {0512, new(0512, 04017, 3, [11, 07, 09, 10, 14, 14, 14, 14], [10, 07, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shower set + {0513, new(0513, 04104, 5, [10, 10, 10, 10, 10, 10, 14, 14], [10, 06, 08, 01, 07, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frying pan + {0515, new(0515, 04137, 6, [01, 04, 07, 06, 02, 08, 10, 14], [12, 12, 12, 12, 12, 12, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // diner chair + {0516, new(0516, 04138, 6, [11, 11, 11, 11, 11, 11, 11, 14], [01, 04, 07, 06, 02, 08, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 07, 05, 02, 12, 10, 14], false)}, // diner counter chair + {0517, new(0517, 04139, 6, [01, 04, 07, 06, 02, 08, 10, 14], [11, 11, 11, 11, 11, 11, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // diner counter table + {0518, new(0518, 04140, 5, [01, 06, 07, 12, 10, 09, 14, 14], [01, 06, 07, 12, 10, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 06, 07, 14, 14, 14, 14, 14], false)}, // retro gas pump + {0519, new(0519, 04141, 6, [01, 04, 07, 06, 02, 08, 10, 14], [12, 12, 12, 12, 12, 12, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // diner sofa + {0520, new(0520, 04142, 6, [11, 11, 11, 11, 11, 11, 11, 14], [01, 04, 07, 06, 02, 08, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 07, 05, 02, 12, 10, 14], false)}, // diner dining table + {0521, new(0521, 04143, 4, [04, 07, 01, 02, 01, 14, 14, 14], [01, 00, 06, 03, 04, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // diner neon sign + {0522, new(0522, 04144, 6, [01, 04, 07, 06, 02, 12, 03, 14], [01, 04, 07, 06, 02, 12, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [13, 04, 10, 14, 14, 14, 14, 14], false)}, // diner neon clock + {0523, new(0523, 04441, 6, [11, 11, 11, 11, 11, 11, 11, 14], [01, 04, 07, 06, 02, 08, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 07, 05, 02, 12, 10, 14], false)}, // diner mini table + {0524, new(0524, 03406, 4, [08, 12, 01, 04, 07, 14, 14, 14], [08, 12, 06, 10, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // beekeeper's hive + {0525, new(0525, 04023, 2, [09, 10, 11, 14, 14, 14, 14, 14], [11, 12, 04, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pants press + {0526, new(0526, 01161, 3, [00, 11, 12, 12, 14, 14, 14, 14], [11, 11, 11, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cream and sugar + {0528, new(0528, 04445, 3, [08, 11, 09, 10, 14, 14, 14, 14], [08, 11, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 10, 12, 09, 14, 14, 14, 14], false)}, // vintage TV tray + {0529, new(0529, 03619, 7, [07, 12, 09, 00, 01, 06, 00, 12], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // soup kettle + {0530, new(0530, 04546, 1, [06, 07, 14, 14, 14, 14, 14, 14], [08, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pear bed + {0531, new(0531, 04125, 3, [07, 00, 09, 12, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden bookshelf + {0532, new(0532, 01840, 1, [12, 10, 14, 14, 14, 14, 14, 14], [12, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // whirlpool bath + {0543, new(0543, 04572, 7, [07, 04, 01, 06, 06, 02, 03, 12], [11, 11, 11, 11, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shaded floor lamp + {0544, new(0544, 01744, 4, [11, 12, 10, 01, 04, 14, 14, 14], [12, 12, 12, 12, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall clock + {0545, new(0545, 04133, 5, [10, 12, 11, 05, 01, 07, 14, 14], [12, 12, 12, 12, 10, 01, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // double-sided wall clock + {0546, new(0546, 04035, 3, [09, 00, 08, 12, 14, 14, 14, 14], [09, 00, 08, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 13, 13, 09, 05, 14, 14, 14], true)}, // log garden lounge + {0547, new(0547, 04036, 3, [09, 00, 08, 12, 14, 14, 14, 14], [09, 00, 08, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 13, 13, 09, 05, 14, 14, 14], true)}, // log decorative shelves + {0548, new(0548, 04037, 3, [09, 00, 08, 12, 14, 14, 14, 14], [08, 08, 08, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // log wall-mounted clock + {0549, new(0549, 04038, 3, [09, 00, 08, 12, 14, 14, 14, 14], [08, 08, 08, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // log stool + {0550, new(0550, 04039, 3, [09, 00, 08, 12, 14, 14, 14, 14], [09, 00, 08, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 13, 13, 09, 05, 14, 14, 14], true)}, // log chair + {0551, new(0551, 04040, 3, [09, 00, 08, 12, 14, 14, 14, 14], [09, 00, 08, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 13, 13, 09, 05, 14, 14, 14], true)}, // log dining table + {0552, new(0552, 04041, 3, [09, 00, 08, 12, 14, 14, 14, 14], [09, 00, 08, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [13, 13, 09, 05, 14, 14, 14, 14], false)}, // log bed + {0553, new(0553, 04042, 3, [09, 00, 08, 12, 14, 14, 14, 14], [08, 08, 08, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // log bench + {0554, new(0554, 04043, 3, [09, 00, 08, 12, 14, 14, 14, 14], [09, 00, 08, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 13, 13, 09, 05, 14, 14, 14], true)}, // log round table + {0555, new(0555, 04044, 3, [09, 00, 08, 12, 14, 14, 14, 14], [09, 00, 08, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 13, 13, 09, 05, 14, 14, 14], true)}, // log extra-long sofa + {0556, new(0556, 04110, 3, [12, 12, 12, 12, 14, 14, 14, 14], [10, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // essay set + {0558, new(0558, 04019, 5, [11, 01, 02, 05, 07, 10, 14, 14], [10, 10, 10, 10, 10, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stand mixer + {0559, new(0559, 01125, 2, [09, 00, 11, 14, 14, 14, 14, 14], [12, 13, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // revolving spice rack + {0561, new(0561, 04109, 3, [11, 12, 10, 01, 14, 14, 14, 14], [11, 11, 11, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // double-door refrigerator + {0562, new(0562, 04114, 5, [01, 07, 05, 08, 00, 09, 14, 14], [12, 12, 12, 12, 12, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tissue box + {0563, new(0563, 04687, 5, [01, 06, 04, 00, 05, 02, 14, 14], [11, 08, 12, 10, 00, 02, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // toolbox + {0564, new(0564, 03970, 3, [01, 04, 09, 10, 14, 14, 14, 14], [01, 04, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial decorative shelves + {0565, new(0565, 03971, 3, [01, 04, 09, 10, 14, 14, 14, 14], [01, 04, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial partition + {0566, new(0566, 03972, 3, [01, 04, 09, 10, 14, 14, 14, 14], [07, 11, 07, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial chest + {0567, new(0567, 03973, 3, [01, 04, 09, 10, 14, 14, 14, 14], [01, 04, 07, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial bed + {0568, new(0568, 03974, 3, [01, 04, 09, 10, 14, 14, 14, 14], [01, 04, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial low table + {0569, new(0569, 04708, 4, [09, 12, 09, 01, 07, 14, 14, 14], [08, 12, 09, 08, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mush low stool + {0571, new(0571, 04719, 4, [13, 13, 12, 04, 13, 14, 14, 14], [09, 08, 10, 05, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // celebratory candles + {0572, new(0572, 00954, 6, [11, 01, 07, 04, 06, 12, 10, 14], [11, 12, 12, 10, 09, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // espresso maker + {0573, new(0573, 04722, 3, [09, 04, 01, 10, 14, 14, 14, 14], [09, 04, 01, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // monster statue + {0574, new(0574, 01509, 7, [01, 04, 07, 06, 02, 12, 10, 11], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // robot hero + {0575, new(0575, 01507, 3, [13, 13, 13, 10, 14, 14, 14, 14], [13, 07, 12, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plaza teacup ride + {0576, new(0576, 04102, 2, [08, 00, 09, 14, 14, 14, 14, 14], [08, 00, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 10, 04, 01, 07, 14, 14, 14], false)}, // poolside bed + {0577, new(0577, 03977, 5, [12, 09, 02, 07, 03, 12, 14, 14], [13, 09, 02, 07, 03, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shell arch + {0578, new(0578, 03978, 5, [12, 09, 02, 07, 03, 12, 14, 14], [08, 09, 02, 07, 03, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shell partition + {0579, new(0579, 03979, 5, [12, 09, 02, 07, 03, 12, 14, 14], [09, 00, 02, 07, 03, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shell stool + {0580, new(0580, 03980, 5, [12, 09, 02, 07, 03, 12, 14, 14], [12, 09, 02, 07, 03, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shell table + {0582, new(0582, 03982, 5, [12, 09, 02, 07, 03, 12, 14, 14], [12, 09, 02, 07, 03, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shell fountain + {0583, new(0583, 03983, 5, [12, 09, 02, 07, 03, 12, 14, 14], [12, 09, 02, 07, 03, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shell bed + {0584, new(0584, 03984, 5, [12, 09, 02, 07, 03, 12, 14, 14], [12, 09, 02, 07, 03, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shell lamp + {0585, new(0585, 04069, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 10, 01, 04, 06, 07, 02, 14], false)}, // table lamp + {0586, new(0586, 04754, 2, [10, 12, 01, 14, 14, 14, 14, 14], [11, 11, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // throwback gothic mirror + {0587, new(0587, 04759, 6, [01, 04, 07, 02, 06, 12, 10, 14], [10, 10, 10, 10, 10, 10, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // throwback race-car bed + {0588, new(0588, 04757, 5, [12, 01, 10, 08, 06, 11, 14, 14], [02, 02, 02, 02, 02, 02, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // throwback skull radio + {0589, new(0589, 04756, 6, [07, 01, 06, 04, 12, 11, 03, 14], [01, 04, 07, 06, 02, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // throwback wall clock + {0591, new(0591, 04758, 5, [00, 09, 01, 04, 06, 12, 14, 14], [00, 09, 12, 12, 01, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // throwback mitt chair + {0592, new(0592, 04762, 6, [07, 01, 04, 07, 05, 12, 10, 14], [06, 12, 12, 11, 07, 00, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // throwback container + {0593, new(0593, 04753, 5, [01, 04, 06, 02, 10, 07, 14, 14], [08, 08, 08, 08, 08, 08, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // throwback wrestling figure + {0594, new(0594, 04760, 7, [01, 04, 06, 10, 10, 12, 12, 12], [01, 04, 06, 00, 07, 04, 01, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // throwback hat table + {0595, new(0595, 04761, 5, [11, 07, 01, 06, 04, 10, 14, 14], [00, 05, 04, 01, 01, 01, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // throwback rocket + {0596, new(0596, 04077, 5, [13, 13, 05, 00, 06, 10, 14, 14], [13, 13, 12, 10, 01, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // party garland + {0598, new(0598, 05150, 5, [12, 09, 02, 07, 03, 12, 14, 14], [12, 09, 02, 07, 03, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shell speaker + {0599, new(0599, 02326, 3, [06, 10, 12, 09, 14, 14, 14, 14], [11, 08, 11, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // water pump + {0600, new(0600, 05165, 4, [07, 11, 09, 10, 12, 14, 14, 14], [12, 12, 12, 12, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall-mounted candle + {0601, new(0601, 04122, 3, [10, 11, 02, 08, 14, 14, 14, 14], [10, 11, 02, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], false)}, // cartoonist's set + {0602, new(0602, 03986, 7, [10, 12, 11, 01, 07, 04, 02, 05], [10, 12, 11, 01, 07, 04, 02, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall-mounted TV (20 in.) + {0603, new(0603, 04072, 1, [10, 01, 14, 14, 14, 14, 14, 14], [12, 05, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // toilet-cleaning set + {0604, new(0604, 02772, 2, [09, 12, 10, 14, 14, 14, 14, 14], [10, 10, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fancy violin + {0605, new(0605, 03430, 4, [13, 12, 01, 04, 05, 14, 14, 14], [13, 10, 07, 05, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // playground gym + {0606, new(0606, 05337, 3, [04, 02, 05, 07, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // three-tiered snowperson + {0607, new(0607, 05338, 7, [11, 10, 12, 00, 08, 09, 11, 07], [11, 10, 12, 00, 08, 09, 11, 07], [14, 14, 14, 14, 14, 14, 14, 14], [11, 12, 09, 09, 12, 08, 11, 07], false)}, // simple panel + {0608, new(0608, 01330, 2, [00, 07, 12, 14, 14, 14, 14, 14], [11, 07, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // basic teacher's desk + {0609, new(0609, 03471, 3, [11, 07, 12, 09, 14, 14, 14, 14], [10, 11, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // light switch + {0610, new(0610, 03400, 5, [12, 10, 11, 01, 04, 06, 14, 14], [12, 10, 11, 02, 05, 07, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dish-drying rack + {0611, new(0611, 04308, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [07, 07, 11, 08, 05, 14, 14, 14], [03, 06, 12, 09, 04, 14, 14, 14], false)}, // unfinished puzzle + {0612, new(0612, 04093, 2, [06, 07, 09, 14, 14, 14, 14, 14], [02, 00, 05, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo drum + {0613, new(0613, 04015, 3, [12, 02, 05, 11, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shower booth + {0616, new(0616, 04071, 1, [06, 10, 14, 14, 14, 14, 14, 14], [13, 13, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // electronics kit + {0617, new(0617, 03976, 1, [00, 01, 14, 14, 14, 14, 14, 14], [00, 01, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // orange wall-mounted clock + {0618, new(0618, 03975, 1, [00, 01, 14, 14, 14, 14, 14, 14], [06, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // orange end table + {0619, new(0619, 04011, 1, [01, 01, 14, 14, 14, 14, 14, 14], [06, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cherry speakers + {0620, new(0620, 04012, 1, [01, 01, 14, 14, 14, 14, 14, 14], [06, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cherry lamp + {0622, new(0622, 04127, 1, [02, 07, 14, 14, 14, 14, 14, 14], [09, 01, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // peach chair + {0623, new(0623, 04128, 1, [02, 07, 14, 14, 14, 14, 14, 14], [06, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // peach surprise box + {0624, new(0624, 04134, 1, [01, 06, 14, 14, 14, 14, 14, 14], [07, 07, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // apple chair + {0625, new(0625, 02596, 1, [01, 06, 14, 14, 14, 14, 14, 14], [07, 07, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // juicy-apple TV + {0626, new(0626, 04070, 3, [00, 04, 07, 09, 14, 14, 14, 14], [09, 09, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // street organ + {0627, new(0627, 04033, 2, [00, 09, 10, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // traditional tea set + {0628, new(0628, 05543, 4, [09, 08, 01, 05, 07, 14, 14, 14], [09, 08, 01, 05, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-block stool + {0629, new(0629, 03251, 4, [11, 12, 01, 04, 10, 14, 14, 14], [01, 08, 00, 05, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // gas range + {0630, new(0630, 04226, 2, [04, 06, 10, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // basketball hoop + {0641, new(0641, 00863, 2, [06, 01, 04, 14, 14, 14, 14, 14], [00, 07, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // billiard table + {0642, new(0642, 05636, 3, [08, 10, 09, 01, 14, 14, 14, 14], [10, 07, 12, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden-plank sign + {0643, new(0643, 05635, 5, [00, 01, 05, 10, 09, 06, 14, 14], [00, 12, 13, 06, 08, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tiny library + {0644, new(0644, 04124, 2, [00, 08, 09, 14, 14, 14, 14, 14], [01, 01, 07, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden fish + {0647, new(0647, 05931, 2, [11, 10, 09, 14, 14, 14, 14, 14], [11, 10, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // jail bars + {0648, new(0648, 05976, 2, [06, 07, 09, 14, 14, 14, 14, 14], [04, 03, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo sphere + {0650, new(0650, 05978, 2, [06, 07, 09, 14, 14, 14, 14, 14], [13, 13, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo lunch box + {0651, new(0651, 00677, 2, [06, 08, 09, 14, 14, 14, 14, 14], [11, 09, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // deer scare + {0652, new(0652, 06426, 7, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Cyrano's photo + {0653, new(0653, 02379, 7, [04, 00, 06, 01, 03, 02, 12, 10], [04, 00, 06, 01, 03, 02, 12, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // watering can + {0654, new(0654, 06826, 6, [07, 06, 05, 03, 02, 00, 12, 14], [07, 06, 05, 03, 02, 00, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // nova light + {0655, new(0655, 04118, 2, [11, 08, 00, 14, 14, 14, 14, 14], [10, 09, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // magnetic knife rack + {0656, new(0656, 06832, 1, [02, 02, 14, 14, 14, 14, 14, 14], [02, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cherry-blossom clock + {0657, new(0657, 06831, 1, [09, 08, 14, 14, 14, 14, 14, 14], [02, 02, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // blossom-viewing lantern + {0658, new(0658, 07048, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 04, 01, 06, 05, 01, 07, 14], [04, 04, 02, 06, 13, 01, 03, 14], false)}, // pile of zen cushions + {0659, new(0659, 07047, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 04, 01, 06, 05, 01, 07, 14], [04, 05, 02, 06, 13, 01, 03, 14], false)}, // zen cushion + {0661, new(0661, 07133, 7, [08, 12, 00, 09, 10, 06, 04, 02], [08, 12, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 00, 02, 04, 06, 14, 14, 14], true)}, // wooden mini table + {0662, new(0662, 07134, 7, [07, 08, 00, 09, 10, 06, 04, 02], [07, 08, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden low table + {0663, new(0663, 07137, 7, [07, 08, 00, 09, 10, 06, 04, 02], [07, 08, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden full-length mirror + {0664, new(0664, 07132, 7, [08, 12, 00, 09, 10, 06, 04, 02], [08, 12, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [00, 02, 05, 06, 14, 14, 14, 14], false)}, // wooden double bed + {0665, new(0665, 07140, 5, [13, 12, 13, 13, 13, 13, 14, 14], [12, 12, 12, 12, 12, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mom's tissue box + {0666, new(0666, 07138, 5, [13, 06, 13, 13, 05, 13, 14, 14], [01, 12, 07, 02, 05, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mom's tea cozy + {0667, new(0667, 07141, 5, [13, 13, 13, 13, 13, 08, 14, 14], [01, 00, 09, 02, 00, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mom's pen stand + {0668, new(0668, 07145, 5, [13, 13, 13, 13, 13, 13, 14, 14], [07, 00, 09, 02, 06, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mom's embroidery + {0669, new(0669, 07147, 5, [12, 11, 09, 02, 06, 04, 14, 14], [06, 07, 00, 07, 07, 13, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mom's plushie + {0670, new(0670, 07144, 5, [13, 13, 13, 13, 07, 13, 14, 14], [01, 04, 06, 02, 04, 04, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mom's cushion + {0671, new(0671, 07143, 5, [13, 12, 12, 12, 01, 05, 14, 14], [13, 13, 08, 13, 03, 06, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mom's candle set + {0672, new(0672, 07146, 5, [13, 01, 13, 12, 13, 09, 14, 14], [12, 12, 12, 02, 04, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mom's homemade cake + {0673, new(0673, 07139, 7, [13, 13, 12, 13, 13, 13, 13, 13], [09, 08, 10, 07, 07, 12, 07, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mom's art + {0674, new(0674, 07135, 7, [12, 00, 01, 02, 03, 04, 05, 06], [12, 00, 01, 02, 03, 04, 05, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // floor light + {0675, new(0675, 07136, 4, [12, 10, 01, 05, 02, 14, 14, 14], [06, 06, 06, 06, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cat grass + {0676, new(0676, 07148, 3, [01, 04, 07, 00, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // life ring + {0678, new(0678, 07154, 7, [08, 09, 09, 06, 02, 12, 10, 01], [08, 09, 09, 06, 02, 12, 10, 01], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 08, 12, 07, 02, 12, 13], true)}, // wooden box + {0680, new(0680, 07189, 7, [10, 10, 10, 10, 10, 10, 10, 10], [12, 07, 00, 01, 02, 03, 04, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // studio spotlight + {0681, new(0681, 07190, 7, [10, 10, 10, 10, 10, 10, 10, 10], [12, 07, 00, 01, 02, 03, 04, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // studio wall spotlight + {0682, new(0682, 01645, 6, [01, 08, 01, 09, 05, 12, 10, 14], [01, 08, 00, 00, 05, 08, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 10, 12, 03, 06, 05, 13, 02], true)}, // electric guitar + {0684, new(0684, 07229, 5, [06, 04, 09, 07, 01, 11, 14, 14], [09, 12, 08, 09, 09, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // handcart + {0685, new(0685, 07237, 2, [07, 01, 12, 14, 14, 14, 14, 14], [06, 06, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pansy table + {0686, new(0686, 07236, 2, [12, 02, 07, 14, 14, 14, 14, 14], [06, 12, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lily record player + {0687, new(0687, 07235, 2, [01, 03, 10, 14, 14, 14, 14, 14], [06, 06, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rose bed + {0688, new(0688, 07234, 2, [03, 04, 07, 14, 14, 14, 14, 14], [09, 09, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hyacinth lamp + {0689, new(0689, 07233, 2, [01, 02, 03, 14, 14, 14, 14, 14], [06, 06, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // windflower fan + {0690, new(0690, 07232, 2, [07, 01, 12, 14, 14, 14, 14, 14], [07, 01, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mum cushion + {0691, new(0691, 07231, 2, [01, 12, 07, 14, 14, 14, 14, 14], [06, 06, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tulip surprise box + {0692, new(0692, 07230, 2, [02, 01, 12, 14, 14, 14, 14, 14], [06, 06, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cosmos shower + {0694, new(0694, 07247, 4, [01, 06, 04, 10, 05, 14, 14, 14], [09, 09, 11, 12, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // silo + {0696, new(0696, 07253, 6, [07, 06, 05, 03, 02, 00, 12, 14], [07, 06, 05, 03, 02, 00, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // star clock + {0697, new(0697, 06080, 1, [09, 12, 14, 14, 14, 14, 14, 14], [13, 13, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tree's bounty big tree + {0698, new(0698, 06079, 1, [09, 12, 14, 14, 14, 14, 14, 14], [13, 13, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tree's bounty little tree + {0699, new(0699, 06081, 1, [09, 12, 14, 14, 14, 14, 14, 14], [13, 13, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tree's bounty arch + {0700, new(0700, 06075, 1, [09, 12, 14, 14, 14, 14, 14, 14], [00, 07, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tree's bounty mobile + {0701, new(0701, 06078, 1, [09, 08, 14, 14, 14, 14, 14, 14], [01, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tree's bounty lamp + {0702, new(0702, 07257, 2, [10, 01, 06, 14, 14, 14, 14, 14], [04, 02, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pedal board + {0703, new(0703, 07258, 6, [05, 05, 07, 06, 02, 08, 08, 14], [11, 11, 11, 05, 13, 09, 09, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // modeling clay + {0705, new(0705, 07260, 4, [07, 07, 07, 07, 07, 14, 14, 14], [01, 01, 01, 01, 01, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // floor sign + {0707, new(0707, 07264, 3, [01, 04, 06, 10, 14, 14, 14, 14], [07, 07, 07, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // champion's pennant + {0708, new(0708, 04309, 5, [00, 12, 10, 13, 04, 08, 14, 14], [00, 12, 10, 09, 05, 08, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // destinations signpost + {0709, new(0709, 00690, 5, [13, 13, 13, 13, 13, 13, 14, 14], [06, 01, 02, 05, 07, 08, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hula doll + {0710, new(0710, 01750, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [05, 10, 01, 10, 14, 14, 14, 14], false)}, // document stack + {0711, new(0711, 07284, 1, [01, 04, 14, 14, 14, 14, 14, 14], [11, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // nutcracker + {0713, new(0713, 07280, 4, [11, 09, 10, 13, 09, 14, 14, 14], [11, 09, 10, 13, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // gears + {0714, new(0714, 07281, 3, [00, 09, 01, 12, 14, 14, 14, 14], [01, 04, 04, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sleigh + {0715, new(0715, 07282, 4, [06, 09, 02, 05, 03, 14, 14, 14], [06, 09, 02, 05, 03, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 11, 00, 00, 08, 14, 14, 14], false)}, // hanging scroll + {0717, new(0717, 07317, 4, [11, 11, 10, 09, 06, 14, 14, 14], [11, 11, 10, 09, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // zen-style stone + {0719, new(0719, 00685, 2, [01, 04, 12, 14, 14, 14, 14, 14], [13, 13, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Dala horse + {0721, new(0721, 07391, 3, [09, 07, 10, 12, 14, 14, 14, 14], [06, 06, 06, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tatami bed + {0722, new(0722, 07392, 3, [01, 04, 07, 02, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // candy machine + {0724, new(0724, 01804, 7, [12, 08, 00, 10, 04, 06, 02, 11], [09, 10, 09, 12, 05, 10, 02, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // electric bass + {0725, new(0725, 06827, 6, [07, 06, 05, 03, 02, 00, 12, 14], [07, 06, 05, 03, 02, 00, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // starry garland + {0726, new(0726, 01111, 3, [11, 10, 09, 12, 14, 14, 14, 14], [11, 10, 09, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // outdoor bath + {0727, new(0727, 07393, 1, [11, 06, 14, 14, 14, 14, 14, 14], [11, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pond stone + {0728, new(0728, 07379, 1, [12, 12, 14, 14, 14, 14, 14, 14], [04, 01, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wind turbine + {0731, new(0731, 01816, 7, [12, 07, 00, 09, 10, 04, 02, 05], [12, 07, 00, 09, 10, 04, 02, 05], [14, 14, 14, 14, 14, 14, 14, 14], [12, 03, 10, 07, 02, 01, 06, 05], false)}, // changing room + {0733, new(0733, 01127, 2, [00, 09, 07, 14, 14, 14, 14, 14], [10, 06, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // old sewing machine + {0734, new(0734, 00683, 2, [05, 05, 05, 14, 14, 14, 14, 14], [12, 06, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bottled ship + {0735, new(0735, 07238, 5, [10, 11, 09, 12, 04, 09, 14, 14], [08, 08, 08, 08, 12, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // anchor statue + {0736, new(0736, 02333, 1, [04, 10, 14, 14, 14, 14, 14, 14], [04, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // solar panel + {0742, new(0742, 00950, 5, [10, 12, 07, 04, 01, 02, 14, 14], [10, 12, 07, 04, 01, 02, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 12, 12, 03, 06, 05, 01, 02], false)}, // effects rack + {0743, new(0743, 00987, 4, [09, 08, 09, 12, 10, 14, 14, 14], [08, 08, 00, 08, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // harp + {0744, new(0744, 07153, 2, [08, 07, 09, 14, 14, 14, 14, 14], [08, 07, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cypress bathtub + {0745, new(0745, 07531, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [05, 02, 07, 06, 11, 14, 14, 14], false)}, // ironing board + {0746, new(0746, 07535, 5, [10, 01, 04, 07, 06, 02, 14, 14], [10, 11, 11, 11, 11, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // kettlebell + {0747, new(0747, 01449, 2, [09, 12, 10, 14, 14, 14, 14, 14], [09, 12, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cello + {0748, new(0748, 07045, 5, [11, 07, 06, 04, 01, 10, 14, 14], [07, 06, 00, 00, 09, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // recycled-can thumb piano + {0750, new(0750, 07150, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 01, 04, 10, 07, 14, 14, 14], false)}, // blue corner + {0752, new(0752, 07599, 2, [06, 00, 12, 14, 14, 14, 14, 14], [13, 13, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // board game + {0755, new(0755, 07653, 2, [01, 04, 10, 14, 14, 14, 14, 14], [10, 12, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // speed bag + {0756, new(0756, 07654, 5, [01, 12, 07, 06, 04, 02, 14, 14], [10, 11, 10, 10, 10, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // electric kick scooter + {0757, new(0757, 06829, 6, [07, 06, 05, 03, 02, 00, 12, 14], [07, 07, 07, 07, 07, 07, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // crescent-moon chair + {0758, new(0758, 00335, 1, [02, 02, 14, 14, 14, 14, 14, 14], [02, 02, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mr. Flamingo + {0759, new(0759, 00336, 1, [02, 02, 14, 14, 14, 14, 14, 14], [02, 02, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Mrs. Flamingo + {0762, new(0762, 07681, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 05, 01, 04, 14, 14, 14, 14], false)}, // loom + {0763, new(0763, 07682, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 05, 13, 04, 14, 14, 14, 14], false)}, // kimono stand + {0766, new(0766, 07454, 3, [08, 09, 13, 06, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden toolbox + {0767, new(0767, 07453, 1, [11, 11, 14, 14, 14, 14, 14, 14], [07, 07, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // aluminum briefcase + {0768, new(0768, 01087, 4, [12, 01, 03, 10, 09, 14, 14, 14], [13, 13, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pinball machine + {0771, new(0771, 00290, 3, [10, 01, 04, 12, 14, 14, 14, 14], [11, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // treadmill + {0772, new(0772, 01177, 2, [00, 09, 04, 14, 14, 14, 14, 14], [06, 06, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // foosball table + {0773, new(0773, 07525, 3, [12, 06, 04, 10, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tool shelf + {0774, new(0774, 07796, 1, [01, 09, 14, 14, 14, 14, 14, 14], [13, 13, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial dining table + {0775, new(0775, 07797, 1, [01, 06, 14, 14, 14, 14, 14, 14], [10, 09, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial dining chair + {0776, new(0776, 07803, 6, [12, 07, 06, 05, 02, 09, 10, 14], [00, 09, 01, 10, 07, 11, 05, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // kitty litter box + {0777, new(0777, 07800, 3, [01, 04, 06, 02, 14, 14, 14, 14], [10, 10, 06, 02, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // protein shaker bottle + {0778, new(0778, 07801, 4, [04, 00, 01, 06, 02, 14, 14, 14], [11, 11, 11, 10, 02, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pet food bowl + {0779, new(0779, 07802, 2, [08, 09, 12, 14, 14, 14, 14, 14], [08, 09, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 06, 05, 01, 06, 14, 14, 14], false)}, // pet bed + {0780, new(0780, 07804, 2, [08, 11, 10, 14, 14, 14, 14, 14], [10, 10, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // knife block + {0782, new(0782, 07390, 3, [09, 01, 07, 06, 14, 14, 14, 14], [08, 08, 09, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // leaf stool + {0784, new(0784, 05397, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // + {0785, new(0785, 07845, 3, [10, 01, 07, 04, 14, 14, 14, 14], [11, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pull-up-bar stand + {0787, new(0787, 07865, 4, [01, 05, 03, 02, 06, 14, 14, 14], [10, 12, 10, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // elaborate kimono stand + {0789, new(0789, 07867, 7, [08, 08, 08, 08, 08, 08, 08, 08], [09, 09, 09, 09, 09, 09, 09, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // angled signpost + {0790, new(0790, 05973, 3, [09, 00, 08, 12, 14, 14, 14, 14], [08, 08, 08, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // log stakes + {0791, new(0791, 05972, 3, [09, 00, 08, 12, 14, 14, 14, 14], [08, 08, 08, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wild log bench + {0793, new(0793, 01232, 1, [12, 10, 14, 14, 14, 14, 14, 14], [04, 04, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // water cooler + {0794, new(0794, 01211, 5, [10, 04, 09, 06, 07, 12, 14, 14], [07, 11, 07, 11, 11, 05, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // typewriter + {0796, new(0796, 00704, 5, [01, 06, 01, 12, 12, 04, 14, 14], [05, 12, 06, 01, 09, 05, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tapestry + {0799, new(0799, 07529, 5, [04, 06, 01, 09, 10, 12, 14, 14], [11, 11, 11, 11, 11, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // folding chair + {0800, new(0800, 06818, 5, [13, 04, 01, 02, 07, 12, 14, 14], [09, 11, 12, 02, 09, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ornament mobile + {0801, new(0801, 08178, 7, [06, 00, 05, 01, 08, 02, 07, 10], [11, 11, 11, 11, 11, 11, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // outdoorsy net + {0803, new(0803, 00688, 2, [06, 00, 09, 14, 14, 14, 14, 14], [01, 09, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pagoda + {0804, new(0804, 08298, 6, [11, 10, 12, 01, 04, 07, 02, 14], [11, 10, 12, 01, 04, 07, 02, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 04, 02, 05, 07, 14, 14, 14], false)}, // bunk bed + {0805, new(0805, 02319, 3, [08, 11, 09, 10, 14, 14, 14, 14], [08, 11, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // drinking fountain + {0806, new(0806, 00546, 2, [10, 04, 02, 14, 14, 14, 14, 14], [11, 11, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stadiometer + {0807, new(0807, 01412, 1, [10, 12, 14, 14, 14, 14, 14, 14], [10, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // TV camera + {0808, new(0808, 07527, 6, [13, 01, 02, 07, 03, 04, 12, 14], [06, 06, 06, 06, 06, 06, 06, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // flower stand + {0809, new(0809, 07528, 7, [01, 00, 07, 06, 04, 02, 10, 11], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tool cart + {0810, new(0810, 01243, 2, [01, 01, 12, 14, 14, 14, 14, 14], [13, 12, 03, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // flashy-flower sign + {0811, new(0811, 07789, 3, [11, 08, 10, 12, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // drying rack + {0812, new(0812, 08096, 7, [10, 12, 01, 07, 06, 04, 11, 02], [10, 12, 01, 07, 06, 04, 11, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 00, 03, 13, 14, 14, 14, 14], true)}, // record box + {0813, new(0813, 07159, 1, [08, 12, 14, 14, 14, 14, 14, 14], [08, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cardboard sofa + {0814, new(0814, 07160, 1, [07, 07, 14, 14, 14, 14, 14, 14], [07, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cardboard table + {0815, new(0815, 07161, 1, [07, 07, 14, 14, 14, 14, 14, 14], [07, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cardboard bed + {0816, new(0816, 07163, 1, [08, 08, 14, 14, 14, 14, 14, 14], [08, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cardboard chair + {0817, new(0817, 07526, 5, [01, 04, 07, 05, 10, 12, 14, 14], [11, 10, 10, 10, 00, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // outdoor generator + {0818, new(0818, 00287, 3, [10, 01, 07, 12, 14, 14, 14, 14], [11, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // exercise bike + {0819, new(0819, 07788, 1, [09, 09, 14, 14, 14, 14, 14, 14], [00, 00, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // leaf campfire + {0821, new(0821, 08419, 3, [00, 09, 06, 12, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // garden wagon + {0822, new(0822, 08418, 4, [12, 07, 02, 06, 05, 14, 14, 14], [08, 09, 02, 06, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fragrance diffuser + {0823, new(0823, 08417, 5, [12, 09, 07, 01, 04, 10, 14, 14], [13, 13, 13, 13, 13, 13, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall-mounted tool board + {0824, new(0824, 07868, 5, [12, 01, 08, 10, 04, 09, 14, 14], [12, 10, 13, 05, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // surfboard + {0825, new(0825, 05784, 7, [01, 07, 06, 04, 03, 02, 12, 10], [08, 08, 08, 08, 08, 08, 08, 08], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // net + {0826, new(0826, 02377, 7, [04, 07, 06, 01, 03, 02, 12, 10], [08, 08, 08, 08, 08, 08, 08, 08], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fishing rod + {0827, new(0827, 02099, 7, [01, 07, 06, 04, 03, 02, 12, 10], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shovel + {0828, new(0828, 08177, 7, [07, 01, 00, 02, 06, 03, 12, 11], [00, 07, 04, 07, 04, 02, 04, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // colorful net + {0829, new(0829, 08176, 7, [07, 01, 04, 06, 02, 03, 05, 06], [07, 01, 04, 06, 02, 03, 05, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // star net + {0830, new(0830, 08415, 3, [07, 10, 04, 01, 14, 14, 14, 14], [01, 01, 01, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial dining lantern + {0831, new(0831, 08760, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // customizable phone case kit + {0832, new(0832, 08826, 7, [07, 08, 00, 09, 10, 06, 04, 02], [07, 08, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden table mirror + {0833, new(0833, 08473, 7, [06, 00, 05, 01, 08, 02, 07, 10], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // outdoorsy fishing rod + {0835, new(0835, 08472, 7, [07, 00, 05, 02, 06, 03, 12, 10], [00, 07, 07, 07, 04, 02, 04, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // colorful fishing rod + {0836, new(0836, 08471, 7, [06, 07, 00, 05, 04, 03, 02, 01], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fish fishing rod + {0837, new(0837, 08297, 2, [11, 10, 01, 14, 14, 14, 14, 14], [10, 11, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stovetop espresso maker + {0838, new(0838, 07795, 2, [11, 12, 06, 14, 14, 14, 14, 14], [11, 12, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stone lion-dog + {0840, new(0840, 05718, 7, [08, 09, 09, 08, 08, 10, 04, 01], [02, 02, 01, 07, 01, 12, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // timber doorplate + {0841, new(0841, 05310, 7, [10, 07, 06, 02, 03, 01, 11, 04], [06, 03, 01, 05, 06, 04, 03, 01], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spider doorplate + {0842, new(0842, 04751, 7, [09, 12, 10, 02, 01, 07, 04, 08], [08, 01, 08, 01, 08, 09, 12, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bone doorplate + {0843, new(0843, 05309, 7, [02, 11, 10, 04, 06, 00, 01, 03], [12, 05, 12, 05, 06, 00, 01, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // heart doorplate + {0844, new(0844, 05716, 7, [08, 05, 10, 00, 09, 12, 05, 02], [09, 00, 08, 08, 08, 00, 04, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // paw-print doorplate + {0845, new(0845, 04738, 1, [08, 12, 14, 14, 14, 14, 14, 14], [09, 01, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // skull doorplate + {0846, new(0846, 05717, 5, [11, 07, 11, 01, 11, 13, 14, 14], [10, 11, 04, 12, 06, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // crest doorplate + {0847, new(0847, 05719, 1, [11, 04, 14, 14, 14, 14, 14, 14], [08, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fossil doorplate + {0848, new(0848, 04764, 7, [05, 01, 00, 07, 06, 03, 10, 11], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fish doorplate + {0849, new(0849, 04752, 7, [10, 12, 04, 11, 08, 07, 00, 09], [10, 12, 04, 11, 08, 07, 00, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron doorplate + {0850, new(0850, 04377, 7, [05, 07, 11, 06, 01, 06, 02, 03], [04, 00, 12, 07, 07, 11, 03, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ornament wreath + {0851, new(0851, 03345, 4, [04, 12, 07, 06, 01, 14, 14, 14], [12, 12, 12, 11, 01, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lifeguard chair + {0852, new(0852, 09502, 5, [08, 10, 00, 04, 02, 06, 14, 14], [08, 10, 00, 04, 02, 06, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // clothes closet + {0853, new(0853, 09565, 4, [13, 13, 13, 13, 00, 14, 14, 14], [13, 13, 13, 13, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mobile + {0854, new(0854, 09568, 4, [12, 12, 12, 04, 00, 14, 14, 14], [04, 04, 04, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // construction sign + {0856, new(0856, 02822, 7, [01, 07, 06, 04, 03, 02, 12, 11], [08, 08, 08, 08, 08, 08, 08, 08], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // slingshot + {0857, new(0857, 08579, 7, [06, 00, 05, 01, 08, 02, 07, 10], [11, 11, 11, 11, 11, 11, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // outdoorsy slingshot + {0858, new(0858, 08580, 7, [07, 01, 04, 02, 06, 03, 12, 10], [00, 06, 07, 05, 04, 02, 01, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // colorful slingshot + {0859, new(0859, 09584, 3, [13, 04, 01, 06, 14, 14, 14, 14], [13, 12, 12, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // beach ball + {0860, new(0860, 08534, 7, [07, 01, 04, 02, 06, 03, 12, 10], [04, 06, 00, 05, 07, 06, 00, 07], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // colorful watering can + {0861, new(0861, 08536, 7, [06, 00, 05, 01, 08, 02, 07, 10], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // outdoorsy watering can + {0862, new(0862, 08577, 7, [07, 01, 04, 02, 06, 03, 12, 10], [04, 06, 00, 05, 07, 06, 00, 07], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // colorful shovel + {0863, new(0863, 08575, 7, [06, 00, 05, 01, 08, 02, 07, 10], [11, 11, 11, 11, 11, 11, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // outdoorsy shovel + {0864, new(0864, 02562, 4, [07, 11, 09, 10, 12, 14, 14, 14], [12, 12, 12, 12, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // candle + {0866, new(0866, 09642, 1, [10, 12, 14, 14, 14, 14, 14, 14], [10, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron closet + {0867, new(0867, 02559, 4, [09, 12, 10, 08, 12, 14, 14, 14], [08, 12, 10, 08, 04, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pot + {0868, new(0868, 09619, 1, [11, 11, 14, 14, 14, 14, 14, 14], [11, 11, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // utility pole + {0869, new(0869, 01504, 5, [07, 08, 09, 07, 03, 03, 14, 14], [08, 08, 09, 13, 12, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 04, 07, 14, 14, 14, 14], true)}, // giant teddy bear + {0870, new(0870, 08576, 7, [05, 12, 07, 02, 06, 04, 03, 10], [08, 08, 08, 08, 08, 08, 08, 08], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // printed-design shovel + {0871, new(0871, 09766, 7, [12, 01, 02, 07, 04, 09, 10, 11], [12, 01, 02, 07, 04, 09, 10, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mini fridge + {0872, new(0872, 09767, 6, [06, 07, 09, 10, 12, 01, 04, 14], [06, 07, 09, 10, 11, 10, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // garbage bin + {0873, new(0873, 07805, 1, [09, 07, 14, 14, 14, 14, 14, 14], [10, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // butter churn + {0874, new(0874, 08031, 3, [11, 09, 10, 12, 14, 14, 14, 14], [11, 09, 10, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fountain + {0875, new(0875, 02352, 2, [12, 12, 12, 14, 14, 14, 14, 14], [12, 01, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // parabolic antenna + {0876, new(0876, 07151, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 01, 04, 10, 07, 14, 14, 14], false)}, // red corner + {0877, new(0877, 07152, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 01, 04, 10, 07, 14, 14, 14], false)}, // neutral corner + {0878, new(0878, 08535, 7, [11, 06, 04, 02, 01, 07, 05, 10], [11, 06, 04, 02, 01, 07, 05, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // elephant watering can + {0879, new(0879, 00131, 1, [12, 10, 14, 14, 14, 14, 14, 14], [07, 07, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lucky cat + {0880, new(0880, 10244, 3, [06, 04, 09, 11, 14, 14, 14, 14], [08, 08, 08, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fragrance sticks + {0882, new(0882, 02561, 3, [08, 09, 12, 10, 14, 14, 14, 14], [08, 09, 12, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 11, 02, 05, 07, 06, 01, 04], false)}, // floor lamp + {0883, new(0883, 10742, 2, [06, 07, 09, 14, 14, 14, 14, 14], [06, 07, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo stool + {0884, new(0884, 10743, 2, [06, 07, 09, 14, 14, 14, 14, 14], [08, 08, 08, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bamboo speaker + {0885, new(0885, 07588, 4, [09, 12, 03, 01, 07, 14, 14, 14], [08, 12, 03, 12, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mushroom wand + {0886, new(0886, 00971, 3, [10, 12, 01, 11, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // snack machine + {0887, new(0887, 00676, 2, [11, 12, 11, 14, 14, 14, 14, 14], [11, 12, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tall lantern + {0889, new(0889, 11941, 1, [11, 11, 14, 14, 14, 14, 14, 14], [11, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stone arch + {0890, new(0890, 11943, 1, [10, 11, 14, 14, 14, 14, 14, 14], [10, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stone tablet + {0891, new(0891, 12140, 3, [04, 07, 00, 06, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // DAL model plane + {0895, new(0895, 12207, 2, [01, 11, 04, 14, 14, 14, 14, 14], [11, 11, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // arcade seat + {0896, new(0896, 07259, 3, [06, 07, 02, 04, 14, 14, 14, 14], [00, 06, 02, 04, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // palm-tree lamp + {0897, new(0897, 11942, 1, [13, 13, 14, 14, 14, 14, 14, 14], [01, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // street piano + {0899, new(0899, 00667, 1, [05, 12, 14, 14, 14, 14, 14, 14], [04, 05, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shaved-ice maker + {0901, new(0901, 12332, 2, [08, 00, 12, 14, 14, 14, 14, 14], [10, 06, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // natural square table + {0902, new(0902, 12313, 2, [02, 01, 05, 14, 14, 14, 14, 14], [12, 01, 05, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // public telephone + {0903, new(0903, 12312, 3, [08, 00, 09, 00, 14, 14, 14, 14], [08, 00, 09, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wood-plank table + {0904, new(0904, 12314, 2, [00, 09, 08, 14, 14, 14, 14, 14], [08, 08, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // zen lowboard + {0905, new(0905, 12311, 5, [01, 06, 05, 12, 10, 00, 14, 14], [10, 10, 10, 10, 09, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cruiser bike + {0906, new(0906, 01906, 3, [01, 10, 12, 08, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // snare drum + {0907, new(0907, 12308, 3, [06, 08, 04, 01, 14, 14, 14, 14], [11, 11, 11, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // reception chair + {0909, new(0909, 12348, 5, [06, 02, 05, 07, 00, 04, 14, 14], [06, 02, 05, 07, 10, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // froggy chair + {0910, new(0910, 12349, 2, [00, 08, 09, 14, 14, 14, 14, 14], [00, 08, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // project table + {0911, new(0911, 12350, 2, [08, 08, 09, 14, 14, 14, 14, 14], [08, 08, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // box-shaped seat + {0912, new(0912, 12344, 7, [00, 09, 01, 04, 06, 07, 04, 12], [01, 08, 09, 05, 08, 10, 04, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // baseball set + {0913, new(0913, 01141, 4, [04, 13, 00, 12, 02, 14, 14, 14], [08, 08, 08, 08, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ski rack + {0914, new(0914, 12356, 5, [08, 06, 09, 04, 10, 12, 14, 14], [08, 06, 09, 04, 10, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // round pillow + {0915, new(0915, 12358, 3, [12, 12, 01, 06, 14, 14, 14, 14], [04, 00, 12, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // retro ice-cream case + {0918, new(0918, 12365, 7, [12, 10, 09, 01, 07, 06, 00, 05], [12, 10, 09, 01, 07, 06, 00, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // garden chair + {0919, new(0919, 12366, 6, [04, 12, 07, 01, 06, 02, 10, 14], [11, 11, 11, 11, 06, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 12, 12, 12, 12, 12, 12], true)}, // plastic bench + {0920, new(0920, 12373, 5, [01, 06, 11, 13, 00, 10, 14, 14], [12, 07, 11, 12, 00, 01, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Pocket vintage camper + {0921, new(0921, 12372, 5, [07, 01, 06, 13, 11, 00, 14, 14], [01, 10, 06, 13, 13, 13, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Pocket modern camper + {0922, new(0922, 12402, 2, [12, 12, 06, 14, 14, 14, 14, 14], [05, 09, 07, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding arch + {0923, new(0923, 12401, 2, [12, 09, 07, 14, 14, 14, 14, 14], [02, 09, 07, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding bench + {0924, new(0924, 12410, 2, [02, 09, 07, 14, 14, 14, 14, 14], [02, 09, 07, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [02, 12, 14, 14, 14, 14, 14, 14], false)}, // wedding welcome board + {0925, new(0925, 12408, 2, [02, 08, 12, 14, 14, 14, 14, 14], [12, 07, 07, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding candle set + {0926, new(0926, 12403, 2, [02, 12, 09, 14, 14, 14, 14, 14], [12, 07, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding cake + {0927, new(0927, 12411, 2, [02, 12, 07, 14, 14, 14, 14, 14], [12, 07, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding flower stand + {0928, new(0928, 12405, 2, [12, 09, 07, 14, 14, 14, 14, 14], [02, 08, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding chair + {0929, new(0929, 12406, 2, [02, 12, 06, 14, 14, 14, 14, 14], [12, 08, 07, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding table + {0930, new(0930, 12409, 2, [12, 09, 07, 14, 14, 14, 14, 14], [11, 07, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding pipe organ + {0931, new(0931, 12407, 2, [02, 12, 07, 14, 14, 14, 14, 14], [06, 06, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding decoration + {0932, new(0932, 12404, 2, [02, 08, 06, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding head table + {0933, new(0933, 12516, 4, [08, 04, 07, 06, 09, 14, 14, 14], [11, 10, 02, 10, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sampler + {0934, new(0934, 12543, 1, [10, 10, 14, 14, 14, 14, 14, 14], [13, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Nintendo Switch + {0935, new(0935, 12599, 3, [11, 00, 10, 06, 14, 14, 14, 14], [11, 11, 10, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // office chair + {0940, new(0940, 12612, 6, [05, 01, 06, 07, 06, 02, 10, 14], [13, 13, 13, 13, 13, 13, 13, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // capsule-toy machine + {0941, new(0941, 12608, 4, [11, 06, 01, 12, 10, 14, 14, 14], [13, 13, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // flower display case + {0942, new(0942, 12610, 2, [08, 05, 01, 14, 14, 14, 14, 14], [13, 13, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen-drink machine + {0943, new(0943, 12614, 6, [07, 09, 12, 10, 05, 02, 00, 14], [01, 12, 05, 11, 04, 12, 06, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // peacock chair + {0944, new(0944, 12613, 5, [04, 06, 07, 01, 05, 02, 14, 14], [11, 07, 11, 07, 11, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fancy tea set + {0945, new(0945, 12606, 3, [01, 07, 06, 04, 14, 14, 14, 14], [10, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tractor + {0946, new(0946, 00967, 3, [09, 02, 12, 09, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // flower bed + {0947, new(0947, 12605, 3, [07, 04, 06, 01, 14, 14, 14, 14], [07, 04, 06, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [07, 04, 13, 14, 14, 14, 14, 14], false)}, // safety barrier + {0948, new(0948, 12637, 3, [06, 12, 10, 08, 14, 14, 14, 14], [11, 11, 10, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 10, 10, 14, 14, 14, 14, 14], false)}, // examination-room desk + {0949, new(0949, 00538, 4, [12, 05, 02, 06, 07, 14, 14, 14], [11, 11, 11, 11, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // exam table + {0950, new(0950, 12670, 3, [12, 08, 10, 11, 14, 14, 14, 14], [12, 12, 10, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // office cabinet + {0951, new(0951, 00534, 3, [12, 02, 12, 12, 14, 14, 14, 14], [12, 02, 06, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hospital bed + {0952, new(0952, 12653, 3, [05, 02, 08, 09, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // modern hospital bed + {0955, new(0955, 12673, 2, [11, 10, 12, 14, 14, 14, 14, 14], [13, 13, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tall file cabinet + {0956, new(0956, 12674, 2, [11, 10, 12, 14, 14, 14, 14, 14], [13, 13, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // short file cabinet + {0957, new(0957, 12675, 7, [12, 09, 08, 10, 09, 08, 11, 00], [06, 06, 06, 06, 06, 06, 06, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plant partition + {0958, new(0958, 12676, 4, [08, 09, 09, 12, 06, 14, 14, 14], [08, 09, 09, 12, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // large magazine rack + {0959, new(0959, 12677, 3, [12, 12, 11, 09, 14, 14, 14, 14], [12, 02, 11, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // medicine chest + {0960, new(0960, 12669, 2, [11, 12, 10, 14, 14, 14, 14, 14], [11, 12, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 01, 06, 07, 12, 10, 02, 14], false)}, // donut stool + {0961, new(0961, 12678, 7, [12, 08, 09, 09, 05, 02, 09, 07], [11, 12, 10, 09, 12, 12, 12, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // arched reception counter + {0962, new(0962, 12679, 7, [12, 10, 08, 09, 05, 02, 10, 08], [12, 10, 08, 09, 12, 12, 10, 08], [14, 14, 14, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], false)}, // reception counter + {0964, new(0964, 12699, 2, [11, 12, 10, 14, 14, 14, 14, 14], [11, 12, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 06, 01, 05, 07, 12, 00, 14], false)}, // standing electric sign + {0994, new(0994, 12712, 2, [11, 09, 12, 14, 14, 14, 14, 14], [13, 13, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // salad bar + {0995, new(0995, 12714, 1, [12, 10, 14, 14, 14, 14, 14, 14], [11, 11, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // modern cash register + {0996, new(0996, 12713, 4, [07, 11, 09, 10, 12, 14, 14, 14], [07, 11, 09, 10, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique cash register + {0997, new(0997, 12715, 2, [06, 04, 12, 14, 14, 14, 14, 14], [12, 11, 00, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [05, 08, 12, 14, 14, 14, 14, 14], false)}, // bulletin board + {0998, new(0998, 12700, 5, [11, 06, 11, 09, 12, 00, 14, 14], [11, 11, 11, 09, 12, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sturdy office desk + {0999, new(0999, 12702, 4, [01, 04, 10, 09, 06, 14, 14, 14], [13, 13, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // strapped books + {1000, new(1000, 12704, 5, [04, 10, 01, 06, 07, 09, 14, 14], [11, 11, 11, 11, 11, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // basic school chair + {1001, new(1001, 12705, 5, [11, 11, 11, 11, 11, 11, 14, 14], [11, 12, 00, 01, 12, 00, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stewpot + {1002, new(1002, 12706, 6, [10, 10, 10, 10, 10, 10, 10, 14], [10, 01, 07, 07, 09, 07, 01, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial pot + {1003, new(1003, 12707, 2, [13, 13, 13, 14, 14, 14, 14, 14], [11, 11, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cans + {1004, new(1004, 12708, 1, [12, 08, 14, 14, 14, 14, 14, 14], [11, 13, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cooking tools + {1006, new(1006, 12717, 2, [06, 06, 10, 14, 14, 14, 14, 14], [00, 09, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // left chalkboard section + {1007, new(1007, 12718, 2, [06, 06, 10, 14, 14, 14, 14, 14], [00, 09, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // right chalkboard section + {1009, new(1009, 12720, 1, [11, 07, 14, 14, 14, 14, 14, 14], [11, 07, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fancy water pitcher + {1010, new(1010, 12709, 2, [10, 07, 01, 14, 14, 14, 14, 14], [08, 08, 08, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // carp on a cutting board + {1011, new(1011, 12701, 4, [11, 11, 12, 08, 10, 14, 14, 14], [11, 11, 12, 13, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // school locker + {1012, new(1012, 12741, 1, [04, 04, 14, 14, 14, 14, 14, 14], [06, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // world map + {1015, new(1015, 12745, 7, [12, 11, 06, 02, 01, 07, 05, 12], [12, 11, 06, 02, 01, 07, 12, 06], [14, 14, 14, 14, 14, 14, 14, 14], [12, 05, 10, 00, 06, 01, 03, 09], false)}, // large covered round table + {1016, new(1016, 12744, 7, [12, 11, 06, 02, 01, 07, 05, 12], [12, 11, 06, 02, 01, 07, 12, 06], [14, 14, 14, 14, 14, 14, 14, 14], [12, 05, 10, 00, 06, 01, 03, 09], false)}, // small covered round table + {1017, new(1017, 12766, 4, [09, 08, 09, 12, 10, 14, 14, 14], [11, 11, 11, 10, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // small café table + {1018, new(1018, 12767, 4, [09, 08, 09, 12, 10, 14, 14, 14], [11, 11, 11, 10, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // large café table + {1019, new(1019, 12768, 7, [11, 02, 08, 09, 12, 08, 12, 10], [12, 12, 12, 09, 12, 08, 08, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // checkout counter + {1020, new(1020, 12769, 3, [12, 08, 02, 09, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dessert case + {1021, new(1021, 12772, 2, [05, 02, 12, 14, 14, 14, 14, 14], [13, 13, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ice-cream display + {1022, new(1022, 12773, 7, [00, 09, 12, 10, 01, 06, 04, 02], [12, 10, 11, 11, 11, 11, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // counter chair + {1023, new(1023, 12774, 3, [11, 12, 08, 09, 14, 14, 14, 14], [08, 09, 12, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // busing station + {1024, new(1024, 12775, 2, [13, 13, 13, 14, 14, 14, 14, 14], [12, 04, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // afternoon-tea set + {1025, new(1025, 12776, 7, [00, 08, 09, 09, 02, 01, 12, 10], [00, 12, 10, 09, 02, 10, 12, 07], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // counter table + {1026, new(1026, 12777, 3, [09, 08, 12, 02, 14, 14, 14, 14], [09, 08, 08, 02, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // covered counter + {1027, new(1027, 12778, 1, [12, 10, 14, 14, 14, 14, 14, 14], [12, 04, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // touchscreen cash register + {1028, new(1028, 12779, 7, [08, 00, 09, 12, 10, 02, 05, 11], [08, 00, 09, 12, 10, 02, 12, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wood partition + {1029, new(1029, 12780, 3, [09, 11, 07, 11, 14, 14, 14, 14], [13, 13, 13, 05, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall shelf with bottles + {1030, new(1030, 12782, 3, [08, 09, 10, 12, 14, 14, 14, 14], [09, 12, 09, 05, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 04, 06, 01, 09, 08, 02, 05], false)}, // bistro table + {1031, new(1031, 01820, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 05, 04, 02, 01, 08, 14, 14], [12, 02, 10, 13, 13, 08, 14, 14], false)}, // stack of clothes + {1032, new(1032, 12886, 4, [08, 08, 09, 12, 13, 14, 14, 14], [13, 06, 09, 02, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 08, 11, 07, 12, 14, 14, 14], false)}, // corner clothing rack + {1033, new(1033, 12891, 4, [09, 09, 10, 12, 07, 14, 14, 14], [09, 09, 10, 12, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // full-length mirror + {1034, new(1034, 12887, 3, [12, 08, 09, 02, 14, 14, 14, 14], [12, 12, 08, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glass showcase + {1035, new(1035, 12882, 2, [12, 09, 10, 14, 14, 14, 14, 14], [13, 13, 13, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 12, 01, 07, 04, 14, 14, 14], false)}, // small mannequin + {1036, new(1036, 12885, 2, [08, 09, 12, 14, 14, 14, 14, 14], [13, 11, 02, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hanging clothing rack + {1037, new(1037, 12893, 3, [09, 10, 13, 13, 14, 14, 14, 14], [12, 09, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stacked shoeboxes + {1038, new(1038, 12890, 3, [12, 10, 01, 08, 14, 14, 14, 14], [12, 10, 01, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 07, 04, 06, 14, 14, 14], true)}, // merchandise table + {1039, new(1039, 12879, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 10, 07, 01, 12, 06, 07, 02], false)}, // tabletop POP display + {1040, new(1040, 12880, 1, [11, 10, 14, 14, 14, 14, 14, 14], [11, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 01, 10, 12, 05, 08, 11, 01], false)}, // standing shop sign + {1041, new(1041, 12888, 3, [11, 10, 12, 07, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hanger rack + {1042, new(1042, 12883, 4, [08, 08, 09, 12, 13, 14, 14, 14], [13, 13, 13, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 04, 10, 12, 13, 14, 14, 14], false)}, // midsized clothing rack + {1043, new(1043, 12884, 4, [08, 08, 09, 12, 13, 14, 14, 14], [13, 13, 12, 13, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // small clothing rack + {1044, new(1044, 12892, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [08, 12, 04, 10, 01, 06, 07, 12], [08, 12, 04, 10, 01, 06, 12, 13], false)}, // sturdy paper bag + {1045, new(1045, 12889, 7, [12, 09, 10, 01, 07, 06, 04, 02], [12, 09, 09, 09, 09, 09, 09, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // boxy stool + {1046, new(1046, 12881, 2, [12, 09, 10, 14, 14, 14, 14, 14], [12, 09, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 01, 07, 10, 12, 14, 14, 14], false)}, // dress mannequin + {1047, new(1047, 01314, 5, [08, 11, 11, 12, 02, 05, 14, 14], [08, 11, 11, 09, 12, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // handwashing area + {1048, new(1048, 12976, 7, [01, 04, 06, 02, 10, 12, 07, 01], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mini dharma + {1051, new(1051, 12604, 3, [07, 06, 01, 11, 14, 14, 14, 14], [09, 09, 09, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // jackhammer + {1059, new(1059, 12996, 7, [08, 09, 12, 02, 07, 06, 05, 03], [08, 09, 12, 02, 07, 06, 05, 03], [14, 14, 14, 14, 14, 14, 14, 14], [09, 04, 12, 02, 07, 06, 05, 03], false)}, // simple chair + {1061, new(1061, 12994, 7, [08, 09, 12, 02, 07, 06, 05, 03], [08, 09, 12, 02, 07, 06, 05, 03], [14, 14, 14, 14, 14, 14, 14, 14], [09, 04, 12, 02, 07, 06, 05, 03], false)}, // simple bed + {1062, new(1062, 12993, 7, [08, 09, 12, 02, 07, 06, 05, 03], [11, 11, 11, 11, 11, 11, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // simple vanity + {1063, new(1063, 12998, 7, [08, 09, 12, 02, 07, 06, 05, 03], [08, 09, 12, 02, 07, 06, 05, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 04, 12, 02, 07, 06, 05, 03], true)}, // simple small dresser + {1064, new(1064, 12995, 7, [08, 09, 12, 02, 07, 06, 05, 03], [08, 09, 12, 02, 07, 06, 05, 03], [14, 14, 14, 14, 14, 14, 14, 14], [09, 04, 12, 02, 07, 06, 05, 03], false)}, // simple sofa + {1065, new(1065, 12991, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [09, 04, 12, 02, 07, 06, 05, 03], [09, 04, 12, 02, 07, 06, 05, 03], false)}, // simple stool + {1066, new(1066, 12997, 7, [08, 09, 12, 02, 07, 06, 05, 03], [08, 09, 12, 02, 07, 06, 05, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // simple wall shelf + {1067, new(1067, 12999, 7, [08, 09, 12, 02, 07, 06, 05, 03], [08, 09, 12, 02, 07, 06, 05, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 04, 12, 02, 07, 06, 05, 03], true)}, // simple table + {1068, new(1068, 13005, 4, [11, 10, 00, 04, 01, 14, 14, 14], [11, 10, 00, 04, 01, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 00, 06, 03, 12, 11, 10], false)}, // artsy chair + {1069, new(1069, 13004, 7, [01, 04, 00, 06, 12, 10, 09, 07], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // artsy table + {1070, new(1070, 13006, 2, [11, 10, 12, 14, 14, 14, 14, 14], [11, 10, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 12, 01, 00, 04, 06, 07, 09], false)}, // cool low table + {1071, new(1071, 13007, 2, [11, 10, 12, 14, 14, 14, 14, 14], [11, 10, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 12, 01, 00, 04, 06, 07, 09], false)}, // cool side table + {1072, new(1072, 13008, 2, [11, 10, 12, 14, 14, 14, 14, 14], [11, 10, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 12, 01, 00, 04, 06, 07, 09], false)}, // cool chair + {1073, new(1073, 13009, 2, [11, 10, 12, 14, 14, 14, 14, 14], [11, 10, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 12, 01, 00, 04, 06, 07, 09], false)}, // cool bed + {1074, new(1074, 13010, 2, [11, 10, 12, 14, 14, 14, 14, 14], [11, 10, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 12, 01, 00, 04, 06, 07, 09], false)}, // cool sofa + {1088, new(1088, 13073, 7, [08, 00, 09, 12, 01, 05, 11, 10], [08, 00, 09, 12, 01, 05, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [07, 06, 05, 00, 02, 13, 06, 13], false)}, // Nordic chair + {1090, new(1090, 13075, 7, [08, 00, 09, 12, 01, 05, 11, 10], [08, 00, 09, 12, 01, 05, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [07, 06, 05, 00, 02, 13, 06, 13], false)}, // Nordic sofa + {1091, new(1091, 13076, 7, [08, 00, 09, 12, 01, 05, 11, 10], [08, 00, 09, 12, 01, 05, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 07, 06, 05, 00, 02, 13, 06], true)}, // Nordic low table + {1092, new(1092, 13077, 7, [08, 00, 09, 12, 01, 05, 11, 10], [08, 00, 09, 12, 01, 05, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 07, 06, 05, 00, 02, 13, 06], true)}, // Nordic lowboard + {1093, new(1093, 13078, 7, [08, 00, 09, 12, 01, 05, 11, 10], [08, 00, 09, 12, 01, 05, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 07, 06, 05, 00, 02, 13, 06], true)}, // Nordic shelves + {1094, new(1094, 13079, 7, [08, 00, 09, 12, 01, 05, 11, 10], [08, 00, 09, 12, 01, 05, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 07, 06, 05, 00, 02, 13, 06], true)}, // Nordic table + {1095, new(1095, 13080, 6, [08, 09, 12, 05, 02, 06, 11, 14], [08, 09, 07, 00, 02, 06, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ranch wardrobe + {1096, new(1096, 13081, 6, [08, 09, 12, 05, 02, 06, 11, 14], [08, 09, 07, 00, 02, 06, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 06, 02, 07, 14, 14], true)}, // ranch tea table + {1097, new(1097, 13082, 6, [08, 09, 12, 05, 02, 06, 11, 14], [08, 09, 07, 00, 02, 06, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 06, 02, 07, 14, 14], true)}, // ranch lowboard + {1098, new(1098, 13083, 7, [01, 07, 05, 02, 12, 06, 03, 09], [01, 07, 13, 02, 04, 08, 03, 00], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Moroccan footrest + {1099, new(1099, 13084, 7, [09, 07, 09, 11, 04, 06, 03, 10], [09, 09, 09, 12, 12, 09, 09, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Moroccan tray table + {1100, new(1100, 13085, 7, [01, 07, 05, 02, 12, 06, 03, 09], [08, 08, 08, 12, 12, 09, 09, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Moroccan sofa + {1101, new(1101, 13108, 7, [12, 10, 08, 09, 06, 02, 05, 07], [12, 10, 08, 09, 06, 02, 05, 07], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 08, 03, 00, 12, 05, 13], false)}, // upright organizer + {1102, new(1102, 13109, 7, [12, 10, 00, 09, 06, 02, 05, 07], [12, 10, 00, 09, 06, 02, 05, 07], [14, 14, 14, 14, 14, 14, 14, 14], [01, 05, 08, 03, 00, 02, 05, 07], false)}, // horizontal organizer + {1103, new(1103, 13110, 7, [10, 11, 12, 09, 06, 02, 04, 00], [10, 11, 12, 09, 06, 02, 04, 00], [14, 14, 14, 14, 14, 14, 14, 14], [04, 10, 07, 09, 06, 13, 13, 13], false)}, // plastic clothing organizer + {1104, new(1104, 13111, 5, [08, 00, 09, 10, 01, 11, 14, 14], [10, 10, 10, 10, 10, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Japanese dresser + {1105, new(1105, 13112, 5, [08, 00, 09, 10, 01, 11, 14, 14], [08, 00, 09, 10, 01, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // zen low table + {1106, new(1106, 13113, 7, [08, 09, 09, 08, 08, 08, 10, 10], [12, 12, 13, 12, 12, 13, 13, 13], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shoji divider + {1107, new(1107, 13114, 5, [08, 09, 11, 06, 12, 10, 14, 14], [10, 08, 11, 06, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vintage stool + {1108, new(1108, 13115, 5, [08, 09, 11, 06, 12, 10, 14, 14], [10, 08, 11, 06, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vintage desk + {1109, new(1109, 13116, 5, [09, 11, 06, 00, 04, 10, 14, 14], [10, 08, 11, 06, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vintage sofa + {1110, new(1110, 13117, 5, [08, 09, 11, 06, 12, 10, 14, 14], [10, 08, 11, 06, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vintage low table + {1111, new(1111, 13118, 5, [08, 09, 11, 06, 12, 10, 14, 14], [10, 08, 11, 06, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vintage dresser + {1112, new(1112, 13119, 6, [06, 05, 01, 07, 02, 12, 10, 14], [06, 05, 01, 07, 02, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // enamel lamp + {1113, new(1113, 13120, 2, [10, 11, 07, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // round light fixture + {1114, new(1114, 13121, 6, [09, 08, 09, 11, 07, 05, 02, 14], [10, 10, 10, 10, 10, 10, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wood-shade lamp + {1115, new(1115, 13122, 2, [00, 09, 08, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // zen light + {1117, new(1117, 13138, 7, [07, 11, 09, 12, 10, 05, 02, 08], [07, 11, 09, 12, 10, 05, 02, 08], [14, 14, 14, 14, 14, 14, 14, 14], [06, 12, 00, 01, 10, 05, 02, 14], false)}, // elegant chair + {1118, new(1118, 13139, 7, [07, 11, 09, 12, 10, 05, 02, 08], [07, 11, 09, 12, 10, 05, 02, 08], [14, 14, 14, 14, 14, 14, 14, 14], [06, 12, 00, 01, 10, 05, 02, 14], false)}, // elegant bed + {1119, new(1119, 13140, 7, [07, 11, 09, 12, 10, 05, 02, 08], [07, 11, 09, 12, 10, 05, 02, 08], [14, 14, 14, 14, 14, 14, 14, 14], [14, 06, 12, 00, 01, 10, 05, 02], true)}, // elegant console table + {1120, new(1120, 13141, 7, [07, 11, 09, 12, 10, 05, 02, 08], [07, 11, 09, 12, 10, 05, 02, 08], [14, 14, 14, 14, 14, 14, 14, 14], [06, 12, 00, 01, 10, 05, 02, 14], false)}, // elegant sofa + {1121, new(1121, 13142, 7, [07, 11, 09, 12, 10, 05, 02, 08], [07, 11, 09, 12, 10, 05, 02, 08], [14, 14, 14, 14, 14, 14, 14, 14], [06, 12, 00, 01, 10, 05, 02, 14], false)}, // elegant lamp + {1122, new(1122, 13143, 7, [07, 11, 09, 12, 10, 05, 02, 08], [07, 11, 09, 12, 10, 05, 02, 08], [14, 14, 14, 14, 14, 14, 14, 14], [14, 06, 12, 00, 01, 10, 05, 02], true)}, // elegant dresser + {1123, new(1123, 13144, 6, [10, 12, 01, 07, 02, 05, 06, 14], [10, 12, 01, 07, 02, 05, 06, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // simple shaded lamp + {1124, new(1124, 13145, 7, [12, 01, 06, 11, 03, 12, 08, 12], [13, 07, 01, 12, 05, 02, 02, 13], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stained-glass light + {1125, new(1125, 13146, 4, [12, 05, 02, 07, 06, 14, 14, 14], [09, 09, 09, 09, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // milk-glass lamp + {1126, new(1126, 13147, 2, [12, 10, 11, 14, 14, 14, 14, 14], [12, 10, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fluorescent light + {1127, new(1127, 13148, 7, [10, 12, 11, 07, 01, 07, 04, 13], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ceiling spotlight + {1128, new(1128, 13149, 6, [06, 04, 00, 01, 02, 11, 12, 14], [06, 04, 00, 01, 02, 11, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Nordic pendant light + {1129, new(1129, 13150, 7, [11, 07, 09, 12, 04, 06, 03, 10], [11, 07, 09, 12, 04, 06, 03, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Moroccan lights + {1130, new(1130, 13151, 3, [07, 10, 01, 09, 14, 14, 14, 14], [07, 10, 01, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 05, 01, 12, 01, 04, 07, 06], false)}, // festival lantern + {1131, new(1131, 13152, 6, [12, 02, 07, 01, 06, 04, 12, 14], [10, 10, 10, 01, 06, 04, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // imperial lamp + {1132, new(1132, 13153, 3, [09, 10, 08, 12, 14, 14, 14, 14], [10, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden pendant light + {1133, new(1133, 13154, 7, [07, 11, 12, 01, 05, 06, 02, 03], [12, 12, 07, 01, 05, 07, 12, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // chandelier + {1134, new(1134, 13155, 2, [11, 07, 10, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spiral chandelier + {1135, new(1135, 13156, 7, [12, 10, 11, 07, 06, 01, 07, 00], [12, 10, 11, 07, 06, 01, 07, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ceiling fan + {1136, new(1136, 13157, 2, [10, 12, 11, 14, 14, 14, 14, 14], [10, 12, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 05, 12, 10, 13, 04, 06, 04], false)}, // dual hanging monitors + {1137, new(1137, 13158, 7, [08, 00, 09, 08, 09, 10, 05, 02], [10, 10, 10, 10, 12, 10, 10, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hanging shelves + {1139, new(1139, 13161, 7, [06, 01, 12, 07, 06, 10, 04, 09], [12, 12, 01, 01, 07, 12, 12, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 13, 13, 04, 00, 12, 02, 06], true)}, // wooden field sign + {1142, new(1142, 13164, 5, [11, 07, 03, 04, 06, 13, 14, 14], [10, 10, 10, 10, 10, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // disco ball + {1143, new(1143, 13185, 4, [08, 05, 04, 12, 10, 14, 14, 14], [08, 04, 12, 01, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // small vase + {1144, new(1144, 13186, 3, [06, 06, 12, 05, 14, 14, 14, 14], [06, 07, 04, 05, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // porcelain vase + {1145, new(1145, 13187, 3, [01, 06, 08, 04, 14, 14, 14, 14], [12, 07, 09, 05, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fine vase + {1146, new(1146, 13188, 3, [09, 12, 12, 07, 14, 14, 14, 14], [06, 04, 11, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ball catcher + {1147, new(1147, 13189, 5, [08, 00, 09, 10, 01, 08, 14, 14], [08, 00, 09, 10, 01, 08, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stair dresser + {1148, new(1148, 13190, 4, [10, 01, 04, 11, 07, 14, 14, 14], [03, 00, 01, 03, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sword + {1149, new(1149, 13191, 4, [10, 01, 04, 11, 07, 14, 14, 14], [03, 00, 01, 03, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bow + {1150, new(1150, 13192, 4, [10, 01, 04, 03, 11, 14, 14, 14], [01, 10, 10, 10, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // samurai suit + {1152, new(1152, 13220, 3, [07, 10, 01, 09, 14, 14, 14, 14], [07, 10, 01, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 05, 01, 12, 01, 04, 07, 06], false)}, // festival-lantern set + {1153, new(1153, 13222, 3, [00, 07, 06, 12, 14, 14, 14, 14], [03, 13, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky garland + {1154, new(1154, 13223, 3, [03, 05, 08, 11, 14, 14, 14, 14], [00, 07, 06, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky table setting + {1155, new(1155, 04083, 3, [09, 09, 09, 11, 14, 14, 14, 14], [00, 07, 06, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky arch + {1156, new(1156, 04084, 3, [00, 07, 06, 12, 14, 14, 14, 14], [09, 09, 09, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky scarecrow + {1157, new(1157, 04086, 3, [00, 07, 06, 12, 14, 14, 14, 14], [00, 07, 06, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky tower + {1168, new(1168, 12949, 3, [00, 07, 06, 12, 14, 14, 14, 14], [09, 09, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky standing lamp + {1190, new(1190, 04087, 3, [00, 07, 06, 12, 14, 14, 14, 14], [09, 09, 08, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky carriage + {1191, new(1191, 04088, 3, [00, 07, 06, 12, 14, 14, 14, 14], [00, 07, 06, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky lantern + {1192, new(1192, 04089, 3, [00, 07, 06, 12, 14, 14, 14, 14], [06, 06, 06, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky chair + {1193, new(1193, 04090, 3, [00, 07, 06, 12, 14, 14, 14, 14], [06, 06, 00, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky table + {1194, new(1194, 04092, 3, [00, 07, 06, 12, 14, 14, 14, 14], [08, 08, 08, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky lantern set + {1195, new(1195, 12951, 3, [00, 07, 06, 12, 14, 14, 14, 14], [03, 02, 09, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky candy set + {1196, new(1196, 13163, 3, [08, 09, 09, 12, 14, 14, 14, 14], [08, 09, 09, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 08, 13, 13, 14, 14, 14], true)}, // study carrel + {1197, new(1197, 13229, 4, [11, 12, 10, 01, 04, 14, 14, 14], [11, 12, 10, 01, 04, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // range hood + {1198, new(1198, 13243, 7, [08, 09, 12, 12, 10, 09, 11, 02], [08, 09, 00, 10, 10, 12, 12, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // puppy plushie + {1199, new(1199, 13201, 7, [12, 07, 01, 09, 05, 02, 06, 03], [12, 07, 01, 09, 05, 02, 06, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 06, 06, 05, 02, 00, 12, 14], true)}, // bath bucket + {1200, new(1200, 13251, 4, [11, 07, 06, 04, 01, 14, 14, 14], [12, 12, 12, 05, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dinosaur toy + {1201, new(1201, 13249, 7, [12, 02, 04, 05, 07, 04, 09, 01], [08, 05, 10, 12, 06, 07, 06, 07], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // kids' tent + {1204, new(1204, 13246, 3, [04, 01, 00, 02, 14, 14, 14, 14], [05, 02, 06, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pop-up book + {1205, new(1205, 13252, 6, [01, 01, 04, 00, 06, 02, 03, 14], [08, 02, 05, 07, 13, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dollhouse + {1207, new(1207, 13245, 4, [09, 12, 12, 02, 06, 14, 14, 14], [07, 09, 01, 05, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Yule log + {1208, new(1208, 13247, 7, [11, 04, 01, 00, 07, 06, 02, 10], [01, 00, 04, 06, 03, 03, 06, 07], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tin robot + {1209, new(1209, 13244, 6, [01, 13, 02, 05, 04, 00, 06, 14], [06, 13, 12, 06, 11, 09, 08, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // gift pile + {1210, new(1210, 13250, 3, [10, 10, 11, 11, 14, 14, 14, 14], [01, 06, 04, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mini circuit + {1211, new(1211, 13242, 6, [04, 01, 07, 06, 02, 05, 03, 14], [12, 10, 12, 12, 12, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // RC helicopter + {1212, new(1212, 13202, 7, [12, 07, 01, 09, 05, 02, 06, 03], [12, 07, 01, 09, 05, 02, 06, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bath stool + {1213, new(1213, 13203, 6, [05, 12, 02, 06, 11, 09, 11, 14], [04, 04, 04, 04, 04, 04, 06, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // square bathtub + {1214, new(1214, 13206, 2, [08, 09, 12, 14, 14, 14, 14, 14], [01, 08, 08, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shopping bag + {1215, new(1215, 13210, 7, [00, 06, 01, 04, 07, 02, 12, 10], [00, 06, 01, 04, 07, 02, 12, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stacked shopping baskets + {1216, new(1216, 00079, 7, [08, 09, 12, 02, 07, 06, 04, 11], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [12, 08, 02, 07, 06, 05, 10, 14], false)}, // baby bed + {1217, new(1217, 01222, 3, [11, 10, 01, 04, 14, 14, 14, 14], [11, 10, 01, 04, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [13, 10, 13, 13, 14, 14, 14, 14], false)}, // TV with VCR + {1218, new(1218, 13209, 7, [10, 12, 09, 01, 07, 06, 05, 02], [10, 12, 10, 10, 12, 10, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [04, 13, 12, 13, 13, 13, 13, 11], false)}, // tablet device + {1219, new(1219, 13211, 6, [12, 10, 01, 07, 06, 04, 11, 14], [07, 07, 07, 07, 07, 07, 07, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // caged cart + {1220, new(1220, 13207, 1, [10, 11, 14, 14, 14, 14, 14, 14], [11, 11, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [07, 01, 06, 01, 05, 04, 01, 07], false)}, // small LED display + {1221, new(1221, 13255, 4, [10, 09, 00, 12, 07, 14, 14, 14], [12, 09, 01, 12, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // elaborate display case + {1222, new(1222, 13214, 7, [11, 12, 09, 10, 01, 07, 06, 04], [11, 12, 09, 10, 01, 07, 06, 04], [14, 14, 14, 14, 14, 14, 14, 14], [14, 11, 11, 11, 11, 11, 11, 14], true)}, // steel trash can + {1223, new(1223, 13274, 6, [11, 10, 12, 01, 04, 09, 07, 14], [11, 10, 12, 01, 04, 09, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wristwatch + {1224, new(1224, 13271, 7, [11, 12, 10, 08, 01, 07, 04, 06], [11, 12, 10, 08, 01, 07, 04, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // upright speaker + {1225, new(1225, 13205, 4, [12, 10, 11, 08, 09, 14, 14, 14], [12, 10, 11, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], false)}, // store shelf + {1226, new(1226, 12361, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 12, 10, 14, 14, 14, 14, 14], false)}, // zen bench + {1227, new(1227, 13270, 2, [09, 00, 10, 14, 14, 14, 14, 14], [09, 00, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // antique radio + {1228, new(1228, 13266, 3, [09, 09, 08, 12, 14, 14, 14, 14], [09, 09, 08, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // owl clock + {1229, new(1229, 13288, 7, [08, 09, 12, 02, 07, 06, 04, 11], [08, 09, 12, 02, 07, 06, 04, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 08, 02, 07, 06, 05, 11, 14], true)}, // high chair + {1230, new(1230, 13294, 5, [12, 10, 04, 00, 07, 02, 14, 14], [12, 10, 04, 00, 07, 02, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 01, 07, 02, 05, 13, 13, 06], false)}, // beach chairs with parasol + {1231, new(1231, 13296, 7, [04, 01, 07, 06, 12, 11, 09, 10], [11, 11, 11, 11, 11, 11, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 01, 07, 06, 05, 11, 10], true)}, // vehicle cabin seat + {1232, new(1232, 13295, 7, [01, 07, 06, 04, 02, 00, 03, 09], [12, 12, 12, 12, 12, 12, 12, 08], [14, 14, 14, 14, 14, 14, 14, 14], [04, 04, 04, 04, 01, 01, 01, 01], false)}, // game-show stand + {1233, new(1233, 13299, 6, [06, 05, 09, 04, 06, 02, 12, 14], [06, 05, 09, 04, 06, 02, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 00, 12, 04, 10, 14, 14], true)}, // decorative bottles + {1234, new(1234, 13302, 6, [00, 01, 12, 10, 11, 11, 09, 14], [08, 10, 12, 10, 11, 10, 09, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // decorative pillar + {1235, new(1235, 13300, 2, [12, 10, 11, 14, 14, 14, 14, 14], [12, 10, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stylish wall spotlight + {1236, new(1236, 13307, 2, [12, 10, 11, 14, 14, 14, 14, 14], [12, 10, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stylish spotlight + {1237, new(1237, 13304, 5, [04, 06, 01, 06, 11, 10, 14, 14], [11, 11, 11, 11, 11, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // winnowing machine + {1238, new(1238, 13305, 5, [11, 12, 10, 07, 04, 06, 14, 14], [10, 10, 10, 10, 10, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // conveyor belt + {1240, new(1240, 13306, 5, [11, 12, 10, 07, 04, 06, 14, 14], [11, 11, 11, 11, 11, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // robot arm + {1241, new(1241, 13303, 7, [12, 12, 12, 12, 12, 12, 12, 12], [12, 07, 08, 09, 06, 08, 13, 13], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 08, 10, 14, 14, 14, 14], true)}, // glass jar + {1244, new(1244, 13313, 3, [10, 12, 09, 06, 14, 14, 14, 14], [10, 12, 09, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // curved streetlight + {1245, new(1245, 13312, 3, [10, 11, 12, 09, 14, 14, 14, 14], [10, 11, 12, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // round streetlight + {1249, new(1249, 04196, 4, [10, 12, 07, 06, 01, 14, 14, 14], [10, 12, 07, 06, 01, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 06, 06, 06, 06, 06, 06, 14], false)}, // crosswalk signal + {1252, new(1252, 13268, 4, [12, 08, 12, 12, 12, 14, 14, 14], [09, 09, 05, 01, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // covered wagon + {1253, new(1253, 13269, 6, [09, 08, 12, 05, 01, 06, 07, 14], [09, 08, 12, 05, 09, 10, 09, 14], [14, 14, 14, 14, 14, 14, 14, 14], [08, 08, 14, 14, 14, 14, 14, 14], false)}, // storefront + {1254, new(1254, 13273, 1, [06, 06, 14, 14, 14, 14, 14, 14], [08, 02, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cactus + {1255, new(1255, 13340, 7, [12, 10, 09, 01, 07, 06, 00, 05], [12, 10, 09, 01, 07, 06, 00, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // garden table + {1256, new(1256, 13335, 7, [08, 12, 01, 07, 05, 02, 09, 10], [08, 12, 01, 07, 05, 02, 09, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bird mobile + {1257, new(1257, 13336, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 05, 06, 12, 11, 00, 14, 14], [14, 05, 06, 12, 11, 00, 14, 14], true)}, // construction scaffolding + {1258, new(1258, 13345, 7, [07, 07, 00, 08, 08, 09, 00, 01], [07, 07, 00, 09, 08, 02, 00, 00], [14, 14, 14, 14, 14, 14, 14, 14], [06, 05, 09, 09, 04, 02, 07, 10], false)}, // snack + {1259, new(1259, 13338, 7, [08, 09, 09, 12, 11, 05, 02, 09], [11, 13, 11, 13, 13, 13, 13, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sloppy sink + {1260, new(1260, 13339, 7, [08, 11, 04, 07, 06, 05, 02, 09], [08, 11, 04, 07, 06, 05, 02, 09], [14, 14, 14, 14, 14, 14, 14, 14], [12, 05, 04, 01, 06, 07, 02, 08], false)}, // sloppy sofa + {1261, new(1261, 13337, 7, [08, 09, 09, 12, 11, 05, 02, 09], [12, 08, 09, 07, 06, 05, 02, 09], [14, 14, 14, 14, 14, 14, 14, 14], [13, 13, 13, 13, 13, 13, 13, 14], false)}, // sloppy table + {1262, new(1262, 13341, 7, [12, 11, 04, 08, 12, 05, 02, 11], [08, 09, 09, 12, 11, 05, 02, 09], [14, 14, 14, 14, 14, 14, 14, 14], [08, 11, 04, 07, 06, 05, 02, 09], false)}, // sloppy bed + {1263, new(1263, 13343, 5, [02, 05, 06, 07, 12, 10, 14, 14], [03, 04, 07, 00, 13, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dreamy wall rack + {1264, new(1264, 13344, 5, [02, 05, 06, 07, 12, 10, 14, 14], [03, 04, 07, 00, 13, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dreamy shelves + {1265, new(1265, 13342, 5, [02, 05, 06, 07, 12, 10, 14, 14], [03, 04, 07, 00, 13, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dreamy bed + {1266, new(1266, 13347, 5, [12, 04, 01, 07, 09, 11, 14, 14], [05, 00, 11, 11, 06, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 10, 10, 04, 14, 14, 14, 14], true)}, // yacht + {1267, new(1267, 13367, 7, [12, 08, 09, 11, 10, 12, 02, 05], [12, 08, 08, 12, 10, 12, 02, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bunny garden decoration + {1268, new(1268, 13368, 7, [07, 11, 09, 12, 10, 05, 02, 08], [07, 11, 09, 12, 10, 05, 02, 08], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // elegant mirror + {1269, new(1269, 13363, 5, [11, 12, 10, 07, 04, 06, 14, 14], [10, 10, 10, 10, 10, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 12, 13, 06, 01, 14, 14, 14], false)}, // inspection equipment + {1270, new(1270, 13362, 4, [11, 11, 11, 10, 09, 14, 14, 14], [01, 04, 07, 07, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 00, 14, 14, 14, 14, 14, 14], true)}, // double-edged sword + {1272, new(1272, 13366, 5, [01, 07, 04, 00, 12, 06, 14, 14], [11, 11, 11, 11, 11, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // chainsaw + {1273, new(1273, 13365, 7, [12, 07, 01, 04, 00, 06, 03, 11], [13, 13, 13, 06, 13, 13, 02, 13], [14, 14, 14, 14, 14, 14, 14, 14], [14, 10, 01, 04, 14, 14, 14, 14], true)}, // toothbrush-and-cup set + {1274, new(1274, 13360, 6, [12, 05, 08, 09, 06, 00, 03, 14], [12, 05, 08, 09, 06, 00, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [05, 08, 02, 04, 07, 00, 03, 14], false)}, // bottled beverage + {1275, new(1275, 13361, 5, [11, 11, 11, 11, 11, 11, 14, 14], [13, 13, 13, 13, 08, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // paint cans + {1276, new(1276, 13369, 7, [11, 09, 12, 06, 04, 01, 10, 11], [11, 09, 12, 06, 04, 01, 10, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 09, 11, 14, 14, 14, 14], true)}, // milk can + {1277, new(1277, 13370, 2, [00, 08, 06, 14, 14, 14, 14, 14], [00, 08, 06, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wheat field + {1278, new(1278, 13356, 3, [04, 06, 01, 10, 14, 14, 14, 14], [12, 11, 10, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [08, 04, 12, 07, 05, 10, 14, 14], false)}, // rolling cart + {1279, new(1279, 13455, 7, [00, 06, 01, 04, 07, 02, 12, 10], [00, 06, 01, 04, 07, 02, 12, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shopping basket + {1280, new(1280, 13454, 2, [11, 10, 12, 14, 14, 14, 14, 14], [11, 10, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [10, 12, 01, 00, 04, 06, 07, 09], false)}, // cool dining table + {1283, new(1283, 13464, 7, [01, 07, 06, 04, 02, 05, 12, 10], [08, 09, 12, 06, 07, 09, 09, 01], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // crane game + {1285, new(1285, 13469, 7, [10, 10, 10, 10, 10, 10, 10, 10], [12, 07, 00, 01, 02, 03, 04, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stage lights + {1286, new(1286, 13468, 7, [10, 10, 10, 10, 10, 10, 10, 10], [12, 07, 00, 01, 02, 03, 04, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hanging stage lights + {1287, new(1287, 13467, 4, [10, 10, 10, 10, 10, 14, 14, 14], [01, 07, 02, 03, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stage flame machine + {1288, new(1288, 13466, 4, [11, 07, 04, 02, 06, 14, 14, 14], [11, 07, 04, 02, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // silver confetti blower + {1290, new(1290, 13479, 5, [10, 11, 01, 07, 05, 09, 14, 14], [11, 10, 11, 10, 11, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // nearly busted radio + {1291, new(1291, 13474, 5, [01, 07, 06, 04, 03, 12, 14, 14], [10, 10, 10, 10, 10, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // siren + {1292, new(1292, 13450, 1, [00, 06, 14, 14, 14, 14, 14, 14], [09, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Turkey Day chair + {1293, new(1293, 13449, 1, [00, 06, 14, 14, 14, 14, 14, 14], [07, 07, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Turkey Day decorations + {1295, new(1295, 13447, 1, [12, 11, 14, 14, 14, 14, 14, 14], [12, 11, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Turkey Day garden stand + {1296, new(1296, 13448, 1, [12, 11, 14, 14, 14, 14, 14, 14], [00, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Turkey Day hearth + {1297, new(1297, 13453, 1, [09, 08, 14, 14, 14, 14, 14, 14], [12, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Turkey Day table + {1298, new(1298, 01206, 1, [07, 11, 14, 14, 14, 14, 14, 14], [07, 11, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // trumpet + {1299, new(1299, 02358, 5, [11, 11, 11, 11, 11, 11, 14, 14], [12, 01, 07, 06, 05, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stadium light + {1301, new(1301, 13472, 5, [08, 08, 08, 08, 09, 09, 14, 14], [12, 06, 00, 05, 10, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // windmill + {1302, new(1302, 13496, 4, [11, 08, 12, 10, 06, 14, 14, 14], [11, 08, 09, 09, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stonework kitchen + {1303, new(1303, 13522, 6, [07, 10, 09, 08, 01, 02, 10, 14], [07, 10, 09, 08, 01, 02, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 05, 10, 13, 01, 00, 04, 04], false)}, // dress-up doll + {1304, new(1304, 13511, 5, [11, 09, 10, 13, 08, 09, 14, 14], [11, 09, 10, 12, 08, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // gear apparatus + {1305, new(1305, 13509, 5, [11, 09, 10, 13, 08, 09, 14, 14], [11, 09, 10, 12, 08, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // gear tower + {1306, new(1306, 13520, 3, [11, 08, 10, 06, 14, 14, 14, 14], [11, 08, 10, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // forbidden altar + {1307, new(1307, 13510, 3, [10, 06, 00, 01, 14, 14, 14, 14], [11, 10, 12, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // crew member's seat + {1308, new(1308, 13519, 7, [10, 10, 10, 10, 10, 12, 02, 05], [01, 00, 06, 04, 11, 10, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // gaming chair + {1309, new(1309, 13521, 7, [10, 10, 10, 10, 10, 12, 02, 05], [01, 00, 06, 04, 11, 10, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [03, 04, 05, 08, 02, 07, 10, 11], false)}, // gaming desk + {1310, new(1310, 13508, 3, [11, 10, 12, 10, 14, 14, 14, 14], [04, 06, 00, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cold sleep pod + {1311, new(1311, 13513, 7, [05, 07, 06, 00, 11, 12, 01, 04], [11, 10, 08, 11, 01, 04, 09, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 04, 10, 02, 04, 14, 14], true)}, // fish container + {1312, new(1312, 13504, 3, [11, 10, 12, 10, 14, 14, 14, 14], [05, 06, 00, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // strategic meeting table + {1313, new(1313, 13518, 7, [11, 12, 10, 06, 04, 01, 07, 09], [10, 11, 11, 09, 09, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lab chair + {1314, new(1314, 13523, 7, [10, 07, 05, 02, 01, 03, 12, 10], [01, 06, 02, 07, 12, 00, 01, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 07, 05, 12, 13, 14, 14, 14], true)}, // skateboard + {1315, new(1315, 13516, 7, [11, 12, 10, 06, 04, 01, 07, 11], [10, 11, 11, 11, 09, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // amazing machine + {1316, new(1316, 13502, 3, [11, 10, 12, 10, 14, 14, 14, 14], [05, 06, 00, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spaceship control panel + {1317, new(1317, 13515, 7, [11, 12, 07, 06, 04, 01, 10, 09], [11, 12, 07, 06, 04, 01, 10, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 05, 13, 07, 01, 10, 10, 14], true)}, // tank + {1318, new(1318, 13524, 7, [11, 08, 09, 11, 07, 02, 05, 11], [10, 00, 10, 10, 06, 01, 04, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // medieval building side + {1319, new(1319, 13512, 5, [11, 07, 06, 04, 01, 09, 14, 14], [09, 09, 09, 10, 10, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [05, 07, 01, 14, 14, 14, 14, 14], false)}, // retro transportation stop + {1320, new(1320, 13505, 5, [09, 01, 04, 07, 06, 10, 14, 14], [11, 10, 10, 06, 11, 02, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mining car + {1321, new(1321, 13506, 3, [04, 06, 00, 01, 14, 14, 14, 14], [11, 10, 12, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // science pod + {1322, new(1322, 13514, 4, [12, 02, 10, 03, 08, 14, 14, 14], [09, 12, 11, 10, 01, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // powder-room booth + {1323, new(1323, 13507, 4, [06, 04, 12, 10, 00, 14, 14, 14], [09, 09, 08, 11, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // banker's lamp + {1324, new(1324, 13503, 4, [11, 09, 10, 12, 09, 14, 14, 14], [11, 09, 10, 12, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // meter and pipes + {1325, new(1325, 13272, 7, [06, 06, 06, 06, 06, 06, 06, 06], [00, 12, 07, 09, 05, 06, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // evergreen ash + {1326, new(1326, 13578, 5, [02, 02, 12, 10, 06, 12, 14, 14], [02, 02, 12, 10, 04, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // inflatable bird ring + {1327, new(1327, 13575, 6, [10, 11, 12, 09, 04, 01, 02, 14], [01, 07, 10, 11, 10, 10, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // SLR camera + {1328, new(1328, 13582, 7, [11, 08, 09, 11, 02, 04, 08, 09], [11, 08, 09, 10, 02, 12, 08, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 00, 06, 14, 14, 14], true)}, // castle tower + {1329, new(1329, 13581, 7, [11, 08, 09, 11, 02, 04, 08, 09], [11, 08, 09, 10, 02, 12, 08, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // castle gate + {1330, new(1330, 13580, 4, [08, 13, 02, 10, 09, 14, 14, 14], [09, 09, 07, 11, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // skateboard wall rack + {1331, new(1331, 13584, 3, [11, 07, 02, 10, 14, 14, 14, 14], [02, 01, 05, 03, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 01, 05, 10, 02, 05, 04, 14], false)}, // makeup pouch + {1332, new(1332, 13576, 6, [06, 06, 06, 06, 06, 06, 06, 14], [10, 12, 06, 09, 08, 11, 00, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // schefflera + {1333, new(1333, 13586, 3, [11, 12, 10, 09, 14, 14, 14, 14], [11, 11, 11, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 01, 06, 07, 03, 03, 09, 09], false)}, // transit seat + {1335, new(1335, 13587, 5, [08, 07, 02, 05, 12, 02, 14, 14], [07, 06, 12, 04, 06, 13, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dried-flower garland + {1336, new(1336, 13579, 1, [09, 09, 14, 14, 14, 14, 14, 14], [06, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // baobab + {1337, new(1337, 13589, 7, [10, 11, 12, 09, 01, 00, 06, 04], [10, 10, 12, 09, 01, 00, 06, 04], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 09, 10, 12, 14, 14], true)}, // professional headphones + {1338, new(1338, 13577, 5, [10, 06, 04, 12, 02, 11, 14, 14], [09, 09, 09, 07, 02, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // potted starter plants + {1339, new(1339, 13573, 7, [08, 12, 00, 09, 10, 06, 04, 02], [08, 12, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // medium wooden partition + {1340, new(1340, 13574, 7, [08, 12, 00, 09, 10, 06, 04, 02], [08, 12, 00, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // small wooden partition + {1341, new(1341, 13588, 7, [08, 12, 00, 09, 08, 06, 04, 02], [08, 12, 00, 09, 08, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tension-pole rack + {1342, new(1342, 13583, 2, [12, 08, 09, 14, 14, 14, 14, 14], [12, 08, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 01, 07, 06, 12, 11, 10, 14], false)}, // rescue mannequin + {1343, new(1343, 13590, 7, [11, 08, 09, 11, 02, 04, 08, 09], [11, 08, 09, 10, 02, 12, 08, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 00, 06, 14, 14, 14], true)}, // castle wall + {1344, new(1344, 13591, 6, [12, 12, 04, 12, 07, 11, 02, 14], [10, 08, 12, 09, 06, 10, 02, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fancy bathroom vanity + {1345, new(1345, 13606, 7, [05, 07, 06, 00, 11, 12, 01, 04], [11, 10, 08, 11, 01, 04, 09, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 04, 10, 02, 04, 14, 14], true)}, // stacked fish containers + {1350, new(1350, 13719, 5, [07, 03, 02, 10, 12, 04, 14, 14], [00, 00, 07, 07, 07, 07, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // toy duck + {1353, new(1353, 13662, 4, [12, 12, 08, 10, 11, 14, 14, 14], [06, 06, 08, 01, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ruined decorated pillar + {1355, new(1355, 13657, 3, [09, 10, 08, 11, 14, 14, 14, 14], [09, 10, 08, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [13, 10, 06, 11, 04, 08, 01, 01], false)}, // decorative plate + {1357, new(1357, 13626, 4, [12, 08, 01, 07, 05, 14, 14, 14], [07, 09, 09, 08, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ornithopter + {1358, new(1358, 13666, 1, [11, 07, 14, 14, 14, 14, 14, 14], [11, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pile of cash + {1360, new(1360, 13620, 3, [08, 08, 12, 12, 14, 14, 14, 14], [12, 12, 05, 05, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // office materials + {1361, new(1361, 13637, 3, [11, 10, 01, 04, 14, 14, 14, 14], [11, 10, 01, 04, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 07, 01, 04, 00, 10, 07, 02], false)}, // outdoor folding chair + {1362, new(1362, 13680, 3, [11, 10, 01, 04, 14, 14, 14, 14], [11, 10, 01, 04, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [11, 10, 08, 09, 14, 14, 14, 14], false)}, // outdoor folding table + {1363, new(1363, 13630, 2, [11, 07, 09, 14, 14, 14, 14, 14], [11, 07, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [08, 04, 01, 06, 02, 05, 10, 12], false)}, // curtain partition + {1365, new(1365, 13744, 7, [09, 11, 12, 10, 01, 04, 07, 06], [09, 11, 12, 10, 01, 04, 07, 06], [14, 14, 14, 14, 14, 14, 14, 14], [12, 08, 13, 13, 08, 05, 11, 13], false)}, // framed poster + {1368, new(1368, 13691, 5, [06, 01, 03, 05, 12, 04, 14, 14], [02, 06, 12, 02, 06, 01, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mounted mountain bike + {1370, new(1370, 13640, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [07, 01, 06, 01, 05, 04, 01, 07], false)}, // wall-mounted LED display + {1375, new(1375, 13614, 3, [08, 11, 02, 07, 14, 14, 14, 14], [06, 10, 05, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // key tray + {1377, new(1377, 13638, 3, [10, 11, 01, 06, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 07, 01, 04, 00, 09, 12, 02], false)}, // utility wagon + {1378, new(1378, 13656, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 07, 00, 01, 02, 03, 04, 06], false)}, // cube light + {1379, new(1379, 13633, 4, [07, 11, 12, 10, 01, 14, 14, 14], [07, 11, 12, 10, 01, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 06, 03, 12, 10, 07, 14], false)}, // throne + {1380, new(1380, 13717, 3, [10, 05, 09, 11, 14, 14, 14, 14], [10, 05, 09, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // metal pot + {1381, new(1381, 13621, 7, [12, 10, 04, 01, 07, 06, 02, 08], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 06, 05, 07, 02, 14, 14], true)}, // minicar + {1382, new(1382, 13622, 6, [10, 11, 12, 01, 04, 06, 07, 14], [11, 10, 10, 10, 10, 10, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // luxury car + {1385, new(1385, 13722, 7, [11, 08, 05, 02, 01, 04, 05, 09], [11, 09, 12, 12, 13, 13, 13, 00], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // recycled-paper bundle + {1386, new(1386, 13643, 7, [12, 10, 01, 07, 06, 04, 00, 11], [10, 12, 12, 10, 12, 12, 09, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // die + {1387, new(1387, 13747, 2, [10, 11, 12, 14, 14, 14, 14, 14], [10, 11, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 06, 01, 04, 07, 07, 01, 06], false)}, // backlit sign + {1388, new(1388, 13678, 3, [06, 06, 00, 05, 14, 14, 14, 14], [06, 06, 00, 05, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // triangular topiary + {1392, new(1392, 13655, 7, [08, 09, 12, 10, 07, 11, 02, 05], [08, 09, 12, 10, 07, 11, 02, 05], [14, 14, 14, 14, 14, 14, 14, 14], [01, 05, 06, 00, 05, 09, 13, 13], false)}, // framed photo + {1396, new(1396, 13639, 7, [11, 10, 12, 00, 08, 09, 11, 07], [11, 10, 12, 00, 08, 09, 11, 07], [14, 14, 14, 14, 14, 14, 14, 14], [11, 12, 09, 09, 12, 08, 11, 07], false)}, // short simple panel + {1397, new(1397, 13727, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 09, 01, 06, 09, 02, 07, 05], [12, 08, 12, 06, 00, 12, 06, 12], false)}, // dessert carrier + {1399, new(1399, 13615, 7, [08, 11, 10, 04, 01, 07, 06, 05], [09, 10, 09, 12, 09, 09, 09, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 12, 05, 06, 02, 00, 14, 14], true)}, // scooter + {1402, new(1402, 13645, 7, [09, 07, 10, 12, 05, 02, 06, 08], [13, 11, 04, 13, 13, 13, 13, 13], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // scrapbook + {1403, new(1403, 13709, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [11, 00, 10, 07, 05, 06, 14, 14], false)}, // spray can + {1404, new(1404, 13634, 6, [12, 12, 12, 12, 12, 04, 10, 14], [00, 08, 02, 01, 00, 12, 01, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 07, 14, 14, 14, 14], true)}, // fresh-food trays + {1407, new(1407, 13652, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [00, 08, 05, 14, 14, 14, 14, 14], [01, 09, 07, 14, 14, 14, 14, 14], false)}, // antique map + {1411, new(1411, 13696, 7, [08, 08, 07, 10, 08, 05, 09, 12], [08, 04, 00, 01, 06, 00, 06, 00], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pile of cardboard boxes + {1417, new(1417, 13642, 7, [13, 13, 01, 07, 06, 05, 03, 07], [12, 02, 02, 00, 06, 04, 10, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // paper-chain ceiling garland + {1421, new(1421, 13624, 2, [06, 12, 10, 14, 14, 14, 14, 14], [06, 12, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [07, 12, 10, 13, 14, 14, 14, 14], false)}, // scoreboard + {1422, new(1422, 13651, 3, [06, 12, 01, 11, 14, 14, 14, 14], [09, 08, 09, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 11, 08, 07, 08, 00, 14, 14], false)}, // tokonoma + {1423, new(1423, 13746, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 10, 06, 08, 07, 12, 08, 14], [12, 10, 06, 08, 06, 04, 08, 14], false)}, // stacked bags + {1426, new(1426, 13748, 2, [04, 01, 06, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cards + {1427, new(1427, 13712, 2, [04, 01, 06, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // card tower + {1428, new(1428, 13631, 3, [01, 11, 08, 06, 14, 14, 14, 14], [10, 11, 08, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 10, 10, 10, 10, 14, 14, 14], true)}, // torii + {1429, new(1429, 13701, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 10, 12, 04, 06, 07, 05, 03], [01, 10, 12, 04, 06, 07, 05, 02], false)}, // drapery + {1436, new(1436, 13649, 2, [06, 07, 00, 14, 14, 14, 14, 14], [12, 12, 08, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lily-pad table + {1437, new(1437, 13616, 3, [10, 11, 07, 00, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hanging lightbulb + {1438, new(1438, 13729, 7, [05, 09, 02, 00, 01, 03, 12, 00], [12, 12, 12, 12, 07, 03, 13, 07], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // carton beverage + {1439, new(1439, 13618, 7, [13, 13, 04, 11, 08, 05, 06, 01], [13, 13, 05, 12, 13, 07, 07, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // patchwork sofa chair + {1440, new(1440, 13625, 7, [13, 13, 04, 11, 08, 05, 06, 01], [13, 13, 05, 12, 13, 07, 07, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // patchwork chair + {1441, new(1441, 13627, 7, [13, 13, 04, 11, 08, 05, 06, 01], [13, 13, 05, 12, 13, 07, 07, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // patchwork low table + {1442, new(1442, 13629, 7, [13, 13, 04, 11, 08, 05, 06, 01], [13, 13, 05, 12, 13, 07, 07, 05], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // patchwork bed + {1448, new(1448, 13636, 4, [11, 12, 10, 09, 08, 14, 14, 14], [11, 12, 10, 09, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 10, 13, 13, 01, 10, 13, 13], false)}, // wide display stand + {1449, new(1449, 13647, 7, [06, 05, 00, 10, 12, 02, 11, 09], [06, 05, 00, 10, 12, 02, 11, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 07, 13, 04, 13, 08, 13, 14], true)}, // fence + {1452, new(1452, 13628, 6, [01, 12, 07, 04, 06, 10, 12, 14], [13, 13, 13, 13, 13, 04, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // model kit + {1453, new(1453, 13740, 6, [01, 01, 06, 10, 04, 08, 06, 14], [13, 13, 13, 13, 13, 13, 13, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // model kits + {1456, new(1456, 13681, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 07, 06, 04, 00, 12, 10, 12], [12, 10, 12, 12, 12, 05, 12, 04], false)}, // light-bulb sign + {1458, new(1458, 13632, 5, [12, 12, 12, 00, 00, 07, 14, 14], [04, 01, 07, 06, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 04, 06, 07, 13, 08, 13, 02], false)}, // popcorn snack set + {1460, new(1460, 13676, 3, [06, 06, 00, 05, 14, 14, 14, 14], [06, 06, 00, 05, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // round topiary + {1462, new(1462, 13690, 3, [12, 11, 10, 06, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // futuristic meal + {1465, new(1465, 13623, 4, [06, 00, 12, 08, 11, 14, 14, 14], [08, 08, 10, 08, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dormant volcano + {1467, new(1467, 13745, 6, [12, 09, 06, 04, 09, 02, 04, 14], [07, 06, 00, 06, 07, 00, 07, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // yunomi teacup + {1468, new(1468, 13692, 5, [02, 05, 06, 07, 12, 10, 14, 14], [03, 04, 06, 00, 01, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dreamy hanging decoration + {1469, new(1469, 13683, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [03, 04, 02, 06, 00, 09, 12, 10], [03, 04, 02, 06, 00, 09, 12, 10], false)}, // yoga mat + {1470, new(1470, 13730, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 11, 02, 05, 07, 06, 00, 04], false)}, // shaded pendant lamp + {1486, new(1486, 13751, 7, [08, 12, 00, 09, 08, 06, 04, 02], [08, 12, 00, 09, 08, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [06, 04, 06, 07, 08, 14, 14, 14], false)}, // open wooden shelves + {1487, new(1487, 13756, 6, [07, 01, 06, 04, 10, 12, 11, 14], [07, 01, 06, 04, 10, 12, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 04, 12, 00, 01, 02, 06, 01], true)}, // bottle crate + {1492, new(1492, 13764, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 07, 00, 01, 02, 03, 04, 06], false)}, // hanging cube light + {1494, new(1494, 13765, 3, [09, 01, 08, 12, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plain party-lights arch + {1495, new(1495, 13767, 4, [06, 01, 04, 03, 13, 14, 14, 14], [07, 00, 05, 02, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Festivale garland + {1496, new(1496, 13776, 4, [06, 01, 04, 03, 13, 14, 14, 14], [07, 00, 05, 02, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Festivale confetti machine + {1497, new(1497, 13775, 4, [06, 01, 04, 03, 13, 14, 14, 14], [07, 00, 12, 02, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Festivale stage + {1498, new(1498, 13774, 4, [06, 01, 04, 03, 13, 14, 14, 14], [09, 09, 12, 02, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Festivale drum + {1500, new(1500, 13770, 4, [06, 01, 04, 03, 13, 14, 14, 14], [07, 00, 05, 02, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Festivale parasol + {1501, new(1501, 13772, 4, [06, 01, 04, 03, 13, 14, 14, 14], [07, 00, 12, 02, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Festivale balloon lamp + {1504, new(1504, 13773, 4, [06, 01, 04, 03, 13, 14, 14, 14], [07, 00, 05, 02, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Festivale stall + {1505, new(1505, 13777, 4, [06, 01, 04, 03, 13, 14, 14, 14], [07, 00, 05, 02, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Festivale lamp + {1506, new(1506, 13778, 4, [06, 01, 04, 03, 13, 14, 14, 14], [08, 09, 12, 02, 12, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Festivale flag + {1508, new(1508, 13820, 1, [00, 06, 14, 14, 14, 14, 14, 14], [12, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Turkey Day table setting + {1509, new(1509, 13818, 1, [12, 06, 14, 14, 14, 14, 14, 14], [00, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Turkey Day casserole + {1510, new(1510, 13819, 1, [09, 07, 14, 14, 14, 14, 14, 14], [08, 06, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Turkey Day wheat decor + {1511, new(1511, 13829, 1, [06, 01, 14, 14, 14, 14, 14, 14], [08, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Shell + {1512, new(1512, 13517, 7, [11, 12, 10, 06, 04, 01, 07, 11], [01, 04, 01, 06, 04, 01, 07, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // unknown machine + {1513, new(1513, 13884, 6, [08, 09, 12, 05, 02, 06, 11, 14], [12, 08, 07, 00, 12, 12, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ranch cupboard + {1514, new(1514, 02606, 6, [08, 09, 12, 05, 02, 06, 11, 14], [12, 12, 12, 12, 12, 12, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 01, 04, 06, 02, 07, 14, 14], false)}, // ranch bed + {1515, new(1515, 00522, 1, [12, 06, 14, 14, 14, 14, 14, 14], [12, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // creepy skeleton + {1516, new(1516, 13488, 3, [09, 10, 12, 02, 14, 14, 14, 14], [01, 07, 04, 05, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // chocolate heart + {1519, new(1519, 13926, 6, [12, 10, 01, 04, 07, 06, 08, 14], [11, 12, 12, 12, 11, 12, 09, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 11, 11, 11, 01, 06, 04, 07], true)}, // hanging guide sign + {1520, new(1520, 13925, 2, [10, 12, 11, 14, 14, 14, 14, 14], [10, 12, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 12, 10, 11, 05, 06, 04, 04], false)}, // hanging monitor + {1521, new(1521, 13927, 3, [05, 11, 02, 07, 14, 14, 14, 14], [12, 12, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Nintendo Switch Lite + {1522, new(1522, 13831, 2, [01, 04, 06, 14, 14, 14, 14, 14], [08, 08, 08, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // large Mushroom Platform + {1523, new(1523, 13832, 2, [07, 02, 06, 14, 14, 14, 14, 14], [08, 08, 08, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // small Mushroom Platform + {1524, new(1524, 13930, 5, [13, 02, 04, 11, 01, 11, 14, 14], [13, 12, 05, 04, 12, 08, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // set of stockings + {1542, new(1542, 14017, 3, [09, 11, 10, 06, 14, 14, 14, 14], [06, 06, 09, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cave + {1543, new(1543, 14018, 4, [12, 12, 08, 10, 11, 14, 14, 14], [06, 06, 08, 01, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ruined arch + {1544, new(1544, 14019, 4, [06, 06, 06, 09, 11, 14, 14, 14], [09, 12, 09, 08, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vine hanging chair + {1546, new(1546, 14029, 5, [01, 02, 07, 03, 12, 10, 14, 14], [12, 12, 00, 12, 06, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // heart-shaped bouquet + {1547, new(1547, 14049, 7, [11, 11, 11, 11, 11, 11, 11, 11], [12, 10, 11, 01, 07, 00, 06, 04], [14, 14, 14, 14, 14, 14, 14, 14], [14, 10, 05, 09, 04, 08, 14, 14], true)}, // truck + {1548, new(1548, 14055, 5, [12, 08, 01, 06, 04, 10, 14, 14], [06, 12, 00, 08, 11, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // outdoor kitchen + {1549, new(1549, 14053, 7, [06, 06, 06, 06, 06, 06, 06, 06], [08, 12, 10, 11, 01, 07, 05, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall planter + {1550, new(1550, 14054, 6, [08, 09, 12, 05, 02, 06, 11, 14], [12, 12, 07, 00, 12, 12, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ranch kitchen + {1552, new(1552, 14051, 7, [07, 11, 09, 12, 10, 06, 02, 08], [07, 11, 09, 12, 10, 06, 02, 08], [14, 14, 14, 14, 14, 14, 14, 14], [13, 09, 08, 08, 13, 13, 13, 13], false)}, // fancy frame + {1553, new(1553, 14050, 6, [11, 11, 11, 11, 11, 11, 11, 14], [01, 06, 07, 13, 04, 12, 00, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // deep fryer + {1554, new(1554, 14106, 7, [12, 00, 06, 10, 11, 05, 02, 09], [12, 00, 06, 10, 04, 05, 02, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // gazebo + {1556, new(1556, 14108, 3, [08, 08, 09, 06, 14, 14, 14, 14], [09, 08, 09, 08, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // azumaya gazebo + {1567, new(1567, 14184, 6, [06, 04, 03, 02, 02, 07, 00, 14], [09, 09, 09, 09, 11, 12, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pergola + {1568, new(1568, 12611, 1, [11, 11, 14, 14, 14, 14, 14, 14], [11, 08, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plate armor + {1569, new(1569, 14192, 4, [06, 06, 06, 09, 11, 14, 14, 14], [06, 06, 04, 09, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // giant vine + {1570, new(1570, 14193, 4, [06, 06, 06, 09, 11, 14, 14, 14], [06, 06, 04, 08, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vine bench + {1574, new(1574, 14206, 4, [06, 06, 06, 09, 11, 14, 14, 14], [06, 06, 04, 08, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vine garland + {1575, new(1575, 14205, 4, [06, 06, 06, 09, 11, 14, 14, 14], [09, 12, 09, 08, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vine lamp + {1576, new(1576, 14207, 7, [06, 06, 05, 01, 07, 02, 12, 11], [06, 05, 04, 01, 07, 02, 11, 04], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glowing-moss stool + {1577, new(1577, 14210, 7, [06, 06, 05, 01, 07, 02, 12, 11], [06, 05, 05, 01, 07, 02, 11, 04], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // hanging glowing moss + {1578, new(1578, 14209, 7, [06, 06, 05, 01, 07, 02, 12, 11], [06, 05, 04, 01, 07, 02, 11, 04], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glowing-moss boulder + {1579, new(1579, 14211, 7, [06, 06, 05, 01, 07, 02, 12, 11], [06, 06, 05, 01, 07, 02, 12, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glowing-moss wreath + {1580, new(1580, 14208, 7, [06, 06, 05, 01, 07, 02, 12, 11], [11, 11, 11, 11, 11, 11, 11, 04], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glowing-moss balloon + {1581, new(1581, 14216, 4, [06, 05, 02, 07, 13, 14, 14, 14], [10, 10, 10, 10, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // suspicious cauldron + {1582, new(1582, 14212, 2, [06, 06, 03, 14, 14, 14, 14, 14], [05, 12, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glowing-moss pond + {1583, new(1583, 14213, 3, [11, 08, 10, 06, 14, 14, 14, 14], [11, 08, 10, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glowing-moss statue + {1584, new(1584, 14215, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [06, 06, 04, 01, 07, 02, 12, 05], [06, 06, 04, 01, 07, 02, 12, 05], false)}, // glow-in-the-dark stickers + {1585, new(1585, 14214, 3, [11, 10, 12, 09, 14, 14, 14, 14], [06, 06, 07, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glowing-moss-jar shelves + {1591, new(1591, 12343, 4, [11, 10, 01, 04, 07, 14, 14, 14], [06, 11, 10, 01, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stepladder + {1593, new(1593, 13902, 2, [08, 00, 09, 14, 14, 14, 14, 14], [08, 00, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tall wooden island counter + {1595, new(1595, 14313, 2, [08, 00, 09, 14, 14, 14, 14, 14], [08, 00, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // low wooden island counter + {1599, new(1599, 14308, 7, [12, 02, 05, 07, 01, 04, 11, 10], [12, 02, 05, 07, 01, 04, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // low simple island counter + {1602, new(1602, 14310, 7, [12, 02, 05, 07, 01, 04, 11, 10], [12, 02, 05, 07, 01, 04, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tall simple island counter + {1605, new(1605, 13897, 2, [01, 12, 11, 14, 14, 14, 14, 14], [09, 09, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tall brick island counter + {1607, new(1607, 13901, 2, [01, 12, 11, 14, 14, 14, 14, 14], [09, 09, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // low brick island counter + {1615, new(1615, 14340, 2, [01, 06, 07, 14, 14, 14, 14, 14], [11, 11, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // whoopee cushion + {1620, new(1620, 14346, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [01, 06, 10, 07, 02, 05, 08, 14], [01, 12, 12, 10, 02, 05, 08, 14], false)}, // hanging sign + {1622, new(1622, 14353, 5, [04, 05, 07, 00, 01, 03, 14, 14], [04, 05, 07, 00, 01, 03, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dreamy rabbit toy + {1623, new(1623, 14352, 5, [03, 04, 06, 07, 02, 10, 14, 14], [03, 04, 06, 07, 02, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dreamy bear toy + {1624, new(1624, 14354, 5, [02, 05, 12, 07, 00, 03, 14, 14], [05, 03, 05, 06, 01, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dreamy unicorn toy + {1629, new(1629, 14530, 3, [12, 00, 09, 11, 14, 14, 14, 14], [10, 12, 10, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // meeting-room table + {1630, new(1630, 14534, 5, [01, 05, 00, 06, 03, 01, 14, 14], [12, 07, 09, 07, 13, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // instant noodles + {1631, new(1631, 14520, 7, [05, 06, 07, 01, 02, 03, 04, 12], [05, 06, 07, 01, 02, 03, 04, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wall-mounted neon lamps + {1632, new(1632, 14523, 3, [10, 11, 04, 03, 14, 14, 14, 14], [11, 01, 01, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tangled cords + {1633, new(1633, 14528, 7, [04, 01, 07, 06, 10, 12, 11, 11], [04, 01, 07, 06, 10, 12, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // steel fence + {1634, new(1634, 14527, 6, [04, 10, 01, 07, 06, 12, 09, 14], [04, 10, 01, 07, 06, 12, 09, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 12, 12, 12, 10, 12, 12, 12], false)}, // clipboard + {1635, new(1635, 14531, 2, [00, 09, 12, 14, 14, 14, 14, 14], [11, 10, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // long folding table + {1636, new(1636, 14525, 6, [12, 09, 06, 04, 02, 03, 11, 14], [12, 09, 06, 04, 02, 10, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 08, 11, 02, 14, 14, 14, 14], true)}, // dispenser + {1637, new(1637, 14524, 5, [12, 05, 02, 03, 07, 08, 14, 14], [07, 11, 12, 10, 06, 09, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // floral sconce + {1639, new(1639, 14526, 2, [07, 00, 09, 14, 14, 14, 14, 14], [07, 00, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden locker + {1640, new(1640, 14476, 2, [12, 04, 09, 14, 14, 14, 14, 14], [02, 05, 01, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // nuptial bell + {1641, new(1641, 14477, 2, [12, 05, 01, 14, 14, 14, 14, 14], [02, 04, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // nuptial ring pillow + {1642, new(1642, 14475, 2, [02, 05, 01, 14, 14, 14, 14, 14], [12, 04, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 12, 12, 14, 14, 14, 14, 14], false)}, // nuptial doorplate + {1645, new(1645, 14550, 3, [09, 09, 09, 11, 14, 14, 14, 14], [00, 07, 06, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky tree + {1647, new(1647, 14551, 3, [00, 07, 06, 12, 14, 14, 14, 14], [00, 07, 06, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky trick lamp + {1648, new(1648, 14561, 6, [11, 11, 11, 11, 11, 11, 11, 14], [11, 01, 08, 13, 01, 08, 12, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // chafing dish + {1649, new(1649, 14592, 7, [08, 12, 01, 09, 10, 06, 04, 02], [08, 12, 01, 09, 10, 06, 04, 02], [14, 14, 14, 14, 14, 14, 14, 14], [14, 00, 04, 07, 12, 00, 07, 12], true)}, // wooden music box + {1651, new(1651, 14601, 2, [08, 00, 09, 14, 14, 14, 14, 14], [08, 00, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden pillar + {1652, new(1652, 14598, 7, [12, 02, 05, 07, 01, 04, 11, 10], [12, 02, 05, 07, 01, 04, 11, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // simple pillar + {1653, new(1653, 14596, 2, [01, 12, 11, 14, 14, 14, 14, 14], [09, 08, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // brick pillar + {1654, new(1654, 14549, 3, [09, 09, 12, 09, 14, 14, 14, 14], [11, 09, 12, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // decayed tree + {1655, new(1655, 14046, 4, [07, 05, 02, 12, 09, 14, 14, 14], [03, 07, 06, 07, 04, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // xylophoid + {1656, new(1656, 14047, 5, [05, 02, 06, 03, 09, 12, 14, 14], [12, 02, 12, 02, 08, 13, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // babbloid + {1657, new(1657, 14092, 4, [00, 09, 06, 02, 12, 14, 14, 14], [09, 01, 06, 03, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // scatteroid + {1658, new(1658, 14074, 3, [11, 09, 04, 10, 14, 14, 14, 14], [11, 09, 05, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // aluminoid + {1659, new(1659, 14597, 2, [11, 12, 10, 14, 14, 14, 14, 14], [11, 12, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // marble pillar + {1660, new(1660, 14332, 2, [11, 12, 10, 14, 14, 14, 14, 14], [11, 12, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tall marble island counter + {1662, new(1662, 14337, 2, [11, 12, 10, 14, 14, 14, 14, 14], [11, 12, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // low marble island counter + {1663, new(1663, 14604, 7, [06, 06, 05, 01, 07, 02, 12, 11], [11, 11, 11, 11, 11, 11, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // glowing-moss jar + {1664, new(1664, 14080, 3, [02, 08, 06, 11, 14, 14, 14, 14], [06, 00, 09, 06, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // thwopoid + {1665, new(1665, 14081, 6, [03, 07, 06, 02, 05, 12, 11, 14], [03, 07, 06, 02, 04, 00, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rumbloid + {1666, new(1666, 14082, 5, [00, 08, 06, 09, 05, 11, 14, 14], [07, 09, 06, 01, 12, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bendoid + {1667, new(1667, 14083, 5, [09, 07, 06, 04, 03, 10, 14, 14], [09, 09, 09, 05, 02, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // boomoid + {1670, new(1670, 14098, 5, [08, 06, 05, 03, 10, 09, 14, 14], [09, 06, 08, 02, 11, 08, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // boioingoid + {1671, new(1671, 14099, 4, [06, 07, 04, 12, 10, 14, 14, 14], [06, 07, 05, 05, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // stelloid + {1672, new(1672, 14100, 4, [03, 07, 02, 11, 05, 14, 14, 14], [03, 07, 02, 11, 13, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // jingloid + {1673, new(1673, 14101, 5, [01, 09, 12, 05, 06, 10, 14, 14], [00, 09, 02, 12, 06, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // rattloid + {1676, new(1676, 14086, 3, [05, 00, 07, 03, 14, 14, 14, 14], [04, 01, 06, 03, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bloopoid + {1677, new(1677, 14087, 3, [08, 06, 01, 04, 14, 14, 14, 14], [09, 06, 01, 04, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sproingoid + {1678, new(1678, 14088, 5, [07, 09, 05, 02, 06, 10, 14, 14], [00, 09, 04, 01, 06, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // crumploid + {1679, new(1679, 14089, 4, [08, 08, 07, 02, 12, 14, 14, 14], [13, 09, 04, 13, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // clatteroid + {1682, new(1682, 14075, 5, [08, 09, 06, 05, 12, 10, 14, 14], [08, 09, 04, 02, 02, 01, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wallopoid + {1683, new(1683, 14076, 4, [04, 06, 09, 03, 10, 14, 14, 14], [07, 00, 05, 02, 11, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // drummoid + {1684, new(1684, 14077, 6, [11, 09, 06, 02, 04, 12, 10, 14], [11, 08, 06, 02, 04, 08, 11, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dootoid + {1685, new(1685, 14078, 3, [05, 01, 07, 11, 14, 14, 14, 14], [11, 11, 11, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // whirroid + {1688, new(1688, 14093, 6, [06, 00, 09, 06, 04, 07, 11, 14], [07, 06, 09, 00, 05, 03, 09, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spikenoid + {1689, new(1689, 14094, 5, [08, 07, 02, 05, 12, 10, 14, 14], [08, 07, 02, 05, 12, 10, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // squeezoid + {1690, new(1690, 14095, 4, [00, 07, 06, 02, 03, 14, 14, 14], [03, 12, 06, 02, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // flutteroid + {1693, new(1693, 14056, 4, [07, 09, 06, 02, 05, 14, 14, 14], [00, 09, 06, 02, 04, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // arfoid + {1694, new(1694, 14057, 5, [05, 09, 07, 06, 02, 12, 14, 14], [05, 09, 07, 06, 02, 12, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // whistloid + {1695, new(1695, 14058, 3, [09, 07, 06, 05, 14, 14, 14, 14], [04, 06, 09, 03, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bwongoid + {1696, new(1696, 14059, 4, [09, 07, 06, 04, 10, 14, 14, 14], [01, 09, 09, 10, 07, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // twangoid + {1697, new(1697, 14060, 4, [06, 07, 02, 05, 11, 14, 14, 14], [02, 00, 02, 02, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // laseroid + {1698, new(1698, 14061, 4, [07, 12, 08, 02, 05, 14, 14, 14], [13, 13, 06, 07, 04, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // squeakoid + {1699, new(1699, 14062, 4, [08, 08, 07, 02, 11, 14, 14, 14], [01, 09, 04, 03, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tockoid + {1700, new(1700, 14063, 5, [01, 07, 06, 05, 03, 12, 14, 14], [04, 08, 12, 02, 07, 05, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ringoid + {1701, new(1701, 14064, 5, [08, 09, 07, 05, 02, 10, 14, 14], [03, 04, 09, 06, 01, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // oinkoid + {1702, new(1702, 14065, 4, [05, 07, 06, 03, 12, 14, 14, 14], [04, 09, 12, 03, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tremoloid + {1703, new(1703, 14066, 4, [09, 06, 02, 03, 12, 14, 14, 14], [09, 06, 02, 03, 05, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bubbloid + {1704, new(1704, 14067, 6, [06, 09, 07, 05, 02, 03, 12, 14], [07, 08, 03, 07, 07, 06, 08, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // petaloid + {1742, new(1742, 12693, 5, [06, 09, 12, 10, 04, 02, 14, 14], [06, 09, 12, 10, 04, 02, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [07, 01, 06, 05, 10, 14, 14, 14], false)}, // street lamp with banners + {1743, new(1743, 06830, 4, [12, 10, 02, 07, 03, 14, 14, 14], [12, 04, 02, 07, 03, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // shell music box + {1747, new(1747, 14619, 2, [09, 10, 12, 14, 14, 14, 14, 14], [09, 10, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 01, 04, 06, 07, 09, 03, 10], false)}, // vertical split curtains + {1748, new(1748, 14620, 2, [09, 10, 12, 14, 14, 14, 14, 14], [09, 10, 12, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 01, 04, 06, 07, 09, 03, 10], false)}, // horizontal split curtains + {1749, new(1749, 14621, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [12, 04, 12, 12, 12, 12, 00, 14], [05, 13, 13, 13, 05, 13, 13, 14], false)}, // unfolded reference sheet + {1750, new(1750, 14542, 3, [00, 07, 06, 12, 14, 14, 14, 14], [10, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // spooky treats basket + {1751, new(1751, 14575, 4, [11, 04, 07, 01, 06, 14, 14, 14], [11, 05, 11, 12, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ABD + {1752, new(1752, 14714, 2, [08, 12, 09, 14, 14, 14, 14, 14], [08, 12, 09, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 06, 02, 07, 14, 14, 14, 14], true)}, // donation box + {1754, new(1754, 14414, 5, [10, 10, 13, 07, 07, 07, 14, 14], [07, 07, 00, 00, 12, 06, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // handheld lantern + {1755, new(1755, 14639, 4, [04, 03, 06, 05, 09, 14, 14, 14], [12, 13, 13, 13, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pocketbook + {1756, new(1756, 14640, 3, [05, 04, 11, 00, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // pocket magazine + {1757, new(1757, 14735, 1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // + {1758, new(1758, 14539, 5, [10, 12, 01, 07, 07, 11, 14, 14], [11, 11, 11, 11, 07, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // dumbbell + {1759, new(1759, 05208, 7, [08, 12, 00, 10, 04, 01, 06, 03], [08, 12, 00, 10, 04, 01, 06, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // large lattice fence + {1760, new(1760, 14756, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen fence + {1761, new(1761, 14594, 4, [01, 06, 04, 02, 03, 14, 14, 14], [07, 09, 12, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // giant ornament + {1762, new(1762, 14591, 4, [01, 06, 04, 02, 03, 14, 14, 14], [07, 09, 12, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ornament table lamp + {1763, new(1763, 14728, 4, [01, 06, 04, 02, 03, 14, 14, 14], [07, 09, 12, 12, 10, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ornament tree + {1764, new(1764, 14593, 4, [07, 09, 12, 12, 10, 14, 14, 14], [01, 06, 04, 02, 03, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ornament garland + {1765, new(1765, 12600, 3, [07, 05, 01, 11, 14, 14, 14, 14], [10, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bulldozer + {1766, new(1766, 12603, 3, [07, 06, 01, 11, 14, 14, 14, 14], [10, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // steamroller + {1767, new(1767, 12601, 3, [07, 04, 01, 11, 14, 14, 14, 14], [10, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // cement mixer + {1768, new(1768, 12602, 3, [07, 05, 01, 11, 14, 14, 14, 14], [10, 10, 10, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // excavator + {1769, new(1769, 12345, 2, [08, 00, 09, 14, 14, 14, 14, 14], [11, 11, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // metal-and-wood table + {1770, new(1770, 12346, 2, [08, 00, 09, 14, 14, 14, 14, 14], [11, 11, 11, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // metal-and-wood chair + {1771, new(1771, 00537, 3, [11, 05, 02, 06, 14, 14, 14, 14], [05, 05, 02, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // IV drip + {1772, new(1772, 14538, 3, [01, 04, 06, 02, 14, 14, 14, 14], [08, 08, 09, 02, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // protein shake + {1774, new(1774, 14758, 7, [11, 07, 06, 04, 01, 12, 10, 09], [11, 07, 06, 04, 01, 12, 10, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // corrugated iron fence + {1775, new(1775, 14759, 7, [04, 01, 07, 06, 02, 01, 02, 00], [04, 01, 07, 06, 02, 07, 05, 06], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // park fence + {1776, new(1776, 14574, 4, [11, 01, 06, 04, 10, 14, 14, 14], [09, 08, 08, 12, 09, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // coffee beans + {1777, new(1777, 12305, 4, [12, 02, 01, 07, 03, 14, 14, 14], [06, 06, 06, 06, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // Casablanca lilies + {1778, new(1778, 12341, 3, [04, 06, 00, 08, 14, 14, 14, 14], [11, 11, 11, 11, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // gurney + {1779, new(1779, 14556, 3, [01, 01, 01, 01, 14, 14, 14, 14], [10, 13, 12, 09, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // osechi + {1781, new(1781, 14572, 7, [05, 04, 06, 01, 08, 10, 02, 12], [10, 10, 10, 10, 09, 10, 11, 00], [14, 14, 14, 14, 14, 14, 14, 14], [14, 01, 04, 07, 00, 13, 13, 12], true)}, // storage shed + {1782, new(1782, 14821, 7, [12, 07, 00, 01, 02, 03, 04, 06], [10, 10, 10, 10, 02, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ring light + {1783, new(1783, 13475, 4, [10, 12, 11, 07, 09, 14, 14, 14], [12, 12, 12, 12, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // candle chandelier + {1784, new(1784, 14826, 4, [11, 12, 10, 09, 08, 14, 14, 14], [11, 12, 10, 09, 08, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lighted display stand + {1785, new(1785, 14831, 7, [09, 12, 06, 05, 01, 09, 11, 10], [06, 09, 10, 09, 06, 10, 05, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden storage shed + {1786, new(1786, 13465, 1, [10, 12, 14, 14, 14, 14, 14, 14], [10, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // bubble machine + {1787, new(1787, 01235, 6, [12, 11, 08, 09, 05, 02, 10, 14], [11, 11, 08, 09, 05, 02, 10, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 13, 13, 13, 13, 14, 14, 14], true)}, // bathroom stall + {1788, new(1788, 12340, 4, [12, 12, 12, 12, 12, 14, 14, 14], [01, 06, 10, 04, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // volleyball net + {1789, new(1789, 03402, 7, [08, 12, 10, 06, 04, 02, 07, 03], [08, 12, 10, 06, 04, 02, 07, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vertical-board fence + {1795, new(1795, 04357, 7, [04, 01, 06, 07, 04, 00, 12, 10], [04, 01, 06, 07, 04, 00, 12, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron fence + {1796, new(1796, 05207, 7, [10, 04, 01, 00, 07, 08, 06, 03], [12, 12, 12, 12, 12, 12, 12, 12], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // zen fence + {1797, new(1797, 11711, 7, [08, 12, 00, 10, 06, 04, 02, 03], [08, 12, 00, 10, 06, 04, 02, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // simple wooden fence + {1798, new(1798, 11712, 7, [08, 12, 10, 04, 02, 05, 07, 03], [08, 12, 10, 04, 02, 05, 07, 03], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // lattice fence + {1799, new(1799, 12894, 7, [12, 02, 06, 01, 05, 07, 03, 10], [08, 12, 08, 08, 12, 08, 03, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wedding fence + {1800, new(1800, 13530, 5, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // wooden ladder set-up kit + {1801, new(1801, 13526, 2, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // vine ladder set-up kit + {1802, new(1802, 13534, 2, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // iron ladder set-up kit + {1803, new(1803, 14882, 4, [12, 12, 08, 10, 11, 14, 14, 14], [06, 06, 08, 01, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ruined seat + {1804, new(1804, 14887, 4, [12, 12, 08, 10, 11, 14, 14, 14], [06, 06, 08, 01, 06, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // ruined broken pillar + {1805, new(1805, 12689, 3, [12, 06, 12, 10, 14, 14, 14, 14], [04, 00, 02, 03, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plaza arch + {1806, new(1806, 12685, 3, [04, 07, 02, 03, 14, 14, 14, 14], [06, 06, 06, 10, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // inflatable plaza toy + {1807, new(1807, 12683, 3, [01, 06, 02, 10, 14, 14, 14, 14], [07, 00, 05, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plaza ferris wheel + {1808, new(1808, 12803, 3, [04, 06, 02, 10, 14, 14, 14, 14], [06, 00, 05, 03, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plaza train + {1809, new(1809, 12690, 3, [01, 06, 02, 10, 14, 14, 14, 14], [12, 07, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plaza game stand + {1810, new(1810, 12692, 3, [12, 06, 12, 10, 14, 14, 14, 14], [01, 09, 02, 01, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plaza clock + {1811, new(1811, 12691, 3, [04, 06, 05, 10, 14, 14, 14, 14], [13, 13, 13, 13, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plaza balloon wagon + {1812, new(1812, 12688, 3, [01, 06, 05, 10, 14, 14, 14, 14], [04, 09, 02, 07, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plaza bench + {1813, new(1813, 12684, 3, [04, 06, 02, 10, 14, 14, 14, 14], [12, 07, 12, 12, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // plaza merry-go-round + {1815, new(1815, 00963, 6, [01, 07, 06, 10, 04, 12, 09, 14], [01, 07, 06, 10, 04, 12, 09, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // fire hydrant + {1816, new(1816, 12781, 2, [10, 11, 08, 14, 14, 14, 14, 14], [10, 11, 08, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // sample case + {1817, new(1817, 03465, 1, [10, 12, 14, 14, 14, 14, 14, 14], [12, 10, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // projection screen + {1818, new(1818, 12703, 5, [05, 06, 10, 07, 01, 12, 14, 14], [12, 12, 12, 12, 12, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // mop + {1819, new(1819, 03063, 1, [09, 08, 14, 14, 14, 14, 14, 14], [12, 12, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // theremin + {1820, new(1820, 13478, 7, [11, 10, 12, 01, 04, 07, 02, 09], [10, 10, 10, 10, 10, 10, 10, 10], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // tabletop record player + {1821, new(1821, 00735, 2, [08, 09, 12, 14, 14, 14, 14, 14], [11, 10, 10, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // low folding table + {1822, new(1822, 00741, 5, [08, 09, 07, 06, 10, 11, 14, 14], [12, 10, 11, 06, 10, 11, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // safety railing + {1823, new(1823, 14799, 7, [01, 05, 07, 06, 03, 02, 12, 10], [11, 11, 11, 11, 11, 11, 11, 11], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // flower tabletop mirror + {1824, new(1824, 00743, 6, [05, 04, 02, 07, 00, 06, 03, 14], [05, 04, 02, 07, 00, 06, 03, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // frozen mini snowperson + {1825, new(1825, 00744, 7, [08, 09, 10, 12, 02, 05, 06, 04], [12, 11, 11, 12, 02, 12, 08, 09], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], false)}, // compact kitchen + {1826, new(1826, 01133, -1, [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [14, 14, 14, 14, 14, 14, 14, 14], [04, 01, 07, 06, 14, 14, 14, 14], false)}, // shopping cart + }; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/Remake/ItemRemakeUtil.cs b/NHSE.Core/Structures/Item/Remake/ItemRemakeUtil.cs index 3553079..bf9f3f2 100644 --- a/NHSE.Core/Structures/Item/Remake/ItemRemakeUtil.cs +++ b/NHSE.Core/Structures/Item/Remake/ItemRemakeUtil.cs @@ -1,1755 +1,1754 @@ using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Fetches the customization definition index for a given item (metadata). +/// +public static class ItemRemakeUtil { - /// - /// Fetches the customization definition index for a given item (metadata). - /// - public static class ItemRemakeUtil + public static short GetRemakeIndex(ushort id) => List.GetValueOrDefault(id, (short)-1); + + public static Dictionary GetInvertedDictionary() { - public static short GetRemakeIndex(ushort id) => List.TryGetValue(id, out var value) ? value : (short)-1; - - public static Dictionary GetInvertedDictionary() + var dict = new Dictionary(); + foreach (var kvp in List) { - var dict = new Dictionary(); - foreach (var kvp in List) - { - if (!dict.ContainsKey(kvp.Value)) - dict.Add(kvp.Value, kvp.Key); - } - return dict; + if (!dict.ContainsKey(kvp.Value)) + dict.Add(kvp.Value, kvp.Key); } - - private static readonly IReadOnlyDictionary List = new Dictionary - { - {00079, 1216}, // baby bed - {00080, 0102}, // clackercart - {00083, 0129}, // rocking horse - {00085, 0197}, // train set - {00086, 0086}, // elephant slide - {00088, 0119}, // ringtoss - {00131, 0879}, // lucky cat - {00144, 0156}, // manhole cover - {00146, 0172}, // cone - {00287, 0818}, // exercise bike - {00290, 0771}, // treadmill - {00330, 0171}, // barbecue - {00331, 0399}, // birdbath - {00333, 0232}, // birdhouse - {00335, 0758}, // Mr. Flamingo - {00336, 0759}, // Mrs. Flamingo - {00338, 0258}, // lawn mower - {00370, 0652}, // Cyrus's photo - {00371, 0652}, // Reese's photo - {00372, 0652}, // Chip's photo - {00373, 0652}, // Phineas's photo - {00374, 0652}, // Joan's photo - {00375, 0652}, // Katrina's photo - {00376, 0652}, // Nat's photo - {00377, 0652}, // Saharah's photo - {00378, 0652}, // K.K.'s photo - {00379, 0652}, // Redd's photo - {00380, 0652}, // Gracie's photo - {00381, 0652}, // Label's photo - {00382, 0652}, // Mabel's photo - {00383, 0310}, // acoustic guitar - {00384, 0652}, // Sable's photo - {00385, 0652}, // Grams's photo - {00386, 0652}, // Leilani's photo - {00387, 0652}, // Kapp'n's photo - {00388, 0652}, // Leila's photo - {00389, 0652}, // Porter's photo - {00390, 0652}, // Don's photo - {00391, 0652}, // Resetti's photo - {00392, 0652}, // Lyle's photo - {00393, 0652}, // Blathers's photo - {00394, 0652}, // Celeste's photo - {00395, 0652}, // Pavé's photo - {00396, 0652}, // Pelly's photo - {00397, 0652}, // Phyllis's photo - {00398, 0652}, // Copper's photo - {00399, 0652}, // Pete's photo - {00400, 0652}, // Booker's photo - {00401, 0652}, // Harriet's photo - {00402, 0652}, // Gulliver's photo - {00403, 0652}, // Pascal's photo - {00404, 0652}, // Kicks's photo - {00405, 0652}, // Tortimer's photo - {00406, 0652}, // Franklin's photo - {00407, 0652}, // Shrunk's photo - {00408, 0652}, // Leif's photo - {00409, 0652}, // Blanca's photo - {00410, 0652}, // Luna's photo - {00411, 0652}, // Katie's photo - {00412, 0652}, // Zipper's photo - {00413, 0652}, // Digby's photo - {00414, 0652}, // Wendell's photo - {00415, 0652}, // Wisp's photo - {00416, 0652}, // Lottie's photo - {00417, 0652}, // Jack's photo - {00418, 0652}, // Harvey's photo - {00419, 0652}, // C.J.'s photo - {00420, 0652}, // Daisy Mae's photo - {00421, 0652}, // Orville's photo - {00422, 0652}, // Flick's photo - {00423, 0652}, // DJ KK's photo - {00424, 0652}, // Wilbur's photo - {00425, 0652}, // Wardell's photo - {00426, 0652}, // Niko's photo - {00522, 1515}, // creepy skeleton - {00530, 0178}, // grass standee - {00531, 0176}, // hedge standee - {00532, 0179}, // mountain standee - {00533, 0177}, // tree standee - {00534, 0951}, // hospital bed - {00537, 1771}, // IV drip - {00538, 0949}, // exam table - {00546, 0806}, // stadiometer - {00547, 0225}, // washbasin - {00664, 0182}, // beach chair - {00667, 0899}, // shaved-ice maker - {00669, 0456}, // ukulele - {00676, 0887}, // tall lantern - {00677, 0651}, // deer scare - {00682, 0373}, // boomerang - {00683, 0734}, // bottled ship - {00685, 0719}, // Dala horse - {00688, 0803}, // pagoda - {00690, 0709}, // hula doll - {00704, 0796}, // tapestry - {00710, 0216}, // bamboo bench - {00716, 0360}, // screen - {00725, 0312}, // paper lantern - {00735, 1821}, // low folding table - {00739, 0224}, // tea table - {00741, 1822}, // safety railing - {00742, 0221}, // fireplace - {00743, 1824}, // frozen mini snowperson - {00744, 1825}, // compact kitchen - {00787, 0127}, // tape deck - {00796, 0374}, // retro stereo - {00805, 0383}, // mush lamp - {00808, 0340}, // mush table - {00832, 0354}, // modern office chair - {00833, 0085}, // upright locker - {00839, 0281}, // safe - {00840, 0355}, // office desk - {00849, 0402}, // amp - {00863, 0641}, // billiard table - {00865, 0190}, // birdcage - {00870, 0476}, // book stands - {00889, 0463}, // camp stove - {00891, 0368}, // holiday candle - {00896, 0279}, // cat tower - {00907, 0228}, // vacuum cleaner - {00908, 0229}, // upright vacuum - {00915, 0396}, // cuckoo clock - {00918, 0242}, // coffee cup - {00922, 0262}, // stacked bottle crates - {00928, 0317}, // pot rack - {00929, 0316}, // air conditioner - {00941, 0410}, // DJ's turntable - {00950, 0742}, // effects rack - {00954, 0572}, // espresso maker - {00955, 0359}, // exit sign - {00957, 0277}, // ventilation fan - {00963, 1815}, // fire hydrant - {00967, 0946}, // flower bed - {00971, 0886}, // snack machine - {00987, 0743}, // harp - {00997, 0267}, // incense burner - {00998, 0309}, // kitchen island - {01019, 0280}, // first-aid kit - {01029, 0183}, // low screen - {01032, 0152}, // magazine rack - {01042, 0166}, // metronome - {01043, 0199}, // microwave - {01050, 0157}, // mixer - {01051, 0159}, // water bird - {01058, 0140}, // music stand - {01072, 0170}, // rope partition - {01081, 0328}, // upright piano - {01082, 0184}, // picnic basket - {01087, 0768}, // pinball machine - {01092, 0148}, // popcorn machine - {01103, 0117}, // rocking chair - {01108, 0120}, // retro TV - {01111, 0726}, // outdoor bath - {01112, 0125}, // colorful wheel - {01117, 0231}, // sand castle - {01125, 0559}, // revolving spice rack - {01127, 0733}, // old sewing machine - {01128, 0158}, // sewing machine - {01133, 1826}, // shopping cart - {01141, 0913}, // ski rack - {01143, 0236}, // smoker - {01157, 0407}, // brick oven - {01161, 0526}, // cream and sugar - {01170, 0142}, // swinging bench - {01171, 0408}, // synthesizer - {01177, 0772}, // foosball table - {01185, 0200}, // phone box - {01189, 0370}, // tire stack - {01199, 0255}, // tricycle - {01206, 1298}, // trumpet - {01211, 0794}, // typewriter - {01221, 0409}, // video camera - {01222, 1217}, // TV with VCR - {01227, 0194}, // deluxe washer - {01229, 0227}, // bathroom sink - {01232, 0793}, // water cooler - {01234, 0273}, // portable toilet - {01235, 1787}, // bathroom stall - {01241, 0253}, // DIY workbench - {01243, 0810}, // flashy-flower sign - {01263, 0325}, // pear wardrobe - {01288, 0072}, // fan palm - {01308, 0274}, // school chair - {01314, 1047}, // handwashing area - {01319, 0240}, // microscope - {01328, 0275}, // school desk - {01330, 0608}, // basic teacher's desk - {01348, 0174}, // hamster cage - {01411, 0223}, // globe - {01412, 0807}, // TV camera - {01432, 0124}, // lantern - {01434, 0263}, // sleeping bag - {01449, 0747}, // cello - {01493, 0315}, // stroller - {01495, 0268}, // dolly - {01499, 0285}, // Papa bear - {01500, 0287}, // Mama bear - {01501, 0286}, // Baby bear - {01504, 0869}, // giant teddy bear - {01507, 0575}, // plaza teacup ride - {01509, 0574}, // robot hero - {01557, 0084}, // wooden-block bed - {01558, 0105}, // wooden-block bookshelf - {01559, 0106}, // wooden-block bench - {01561, 0107}, // wooden-block chest - {01565, 0108}, // wooden-block table - {01567, 0090}, // oil barrel - {01573, 0219}, // dharma - {01598, 0175}, // exercise ball - {01606, 0490}, // serving cart - {01608, 0081}, // vertical banner - {01620, 0180}, // hammock - {01621, 0185}, // lawn chair - {01624, 0189}, // garden gnome - {01625, 0305}, // iron garden bench - {01626, 0303}, // iron garden chair - {01627, 0304}, // iron garden table - {01628, 0269}, // garden lantern - {01631, 0314}, // garden faucet - {01632, 0250}, // golf bag - {01644, 0096}, // rock guitar - {01645, 0682}, // electric guitar - {01652, 0381}, // matryoshka - {01708, 0218}, // cassette player - {01712, 0144}, // poster stand - {01716, 0198}, // display stand - {01744, 0544}, // wall clock - {01745, 0247}, // copy machine - {01750, 0710}, // document stack - {01753, 0311}, // aroma pot - {01757, 0193}, // claw-foot tub - {01759, 0357}, // stack of books - {01778, 0130}, // clothesline pole - {01779, 0342}, // table with cloth - {01783, 0249}, // corkboard - {01792, 0284}, // cushion - {01797, 0202}, // decoy duck - {01799, 0313}, // doghouse - {01802, 0259}, // drink machine - {01803, 0089}, // drum set - {01804, 0724}, // electric bass - {01816, 0731}, // changing room - {01820, 1031}, // stack of clothes - {01823, 0248}, // trash bags - {01829, 0494}, // cypress plant - {01836, 0272}, // humidifier - {01838, 0501}, // ironing set - {01840, 0532}, // whirlpool bath - {01845, 0239}, // simple kettle - {01849, 0246}, // kotatsu - {01850, 0083}, // laptop - {01851, 0087}, // rocket lamp - {01852, 0145}, // box sofa - {01853, 0146}, // box corner sofa - {01861, 0353}, // stacked magazines - {01866, 0167}, // menu chalkboard - {01868, 0266}, // desk mirror - {01870, 0153}, // mug - {01875, 0103}, // grand piano - {01877, 0137}, // piggy bank - {01881, 0149}, // plastic canister - {01888, 0098}, // rice cooker - {01889, 0132}, // ring - {01892, 0230}, // hourglass - {01899, 0257}, // autograph cards - {01906, 0906}, // snare drum - {01913, 0135}, // wooden chair - {01929, 0099}, // toilet - {02010, 0143}, // ball - {02012, 0244}, // chalkboard - {02013, 0406}, // lecture-hall bench - {02014, 0404}, // lecture-hall desk - {02020, 0358}, // director's chair - {02099, 0827}, // shovel - {02319, 0805}, // drinking fountain - {02326, 0599}, // water pump - {02329, 0206}, // tire toy - {02333, 0736}, // solar panel - {02335, 0201}, // lighthouse - {02352, 0875}, // parabolic antenna - {02358, 1299}, // stadium light - {02377, 0826}, // fishing rod - {02379, 0653}, // watering can - {02553, 0196}, // iron frame - {02554, 0138}, // double sofa - {02558, 0109}, // wooden-block chair - {02559, 0867}, // pot - {02560, 0095}, // wooden chest - {02561, 0882}, // floor lamp - {02562, 0864}, // candle - {02575, 0278}, // ranch chair - {02586, 0431}, // natural garden chair - {02587, 0075}, // hospital screen - {02596, 0625}, // juicy-apple TV - {02605, 0076}, // wooden simple bed - {02606, 1514}, // ranch bed - {02614, 0151}, // mountain bike - {02713, 0121}, // refrigerator - {02731, 0078}, // digital alarm clock - {02736, 0123}, // retro fan - {02740, 0115}, // automatic washer - {02770, 0222}, // chessboard - {02771, 0155}, // round space heater - {02772, 0604}, // fancy violin - {02776, 0220}, // tankless toilet - {02822, 0856}, // slingshot - {03063, 1819}, // theremin - {03064, 0282}, // cooler box - {03078, 0097}, // tourist telescope - {03122, 0161}, // mini DIY workbench - {03191, 0298}, // ironwood table - {03193, 0296}, // ironwood chair - {03194, 0301}, // ironwood low table - {03195, 0302}, // ironwood cart - {03196, 0297}, // ironwood dresser - {03200, 0299}, // ironwood bed - {03205, 0111}, // wooden-block stereo - {03206, 0112}, // wooden-block toy - {03208, 0113}, // wooden-block wall clock - {03229, 0131}, // clothesline - {03230, 0139}, // futon - {03251, 0629}, // gas range - {03252, 0101}, // LCD TV (50 in.) - {03270, 0293}, // ironwood kitchenette - {03271, 0292}, // ironwood cupboard - {03275, 0294}, // ironwood clock - {03282, 0147}, // pop-up toaster - {03305, 0154}, // baby chair - {03307, 0205}, // digital scale - {03333, 0100}, // LCD TV (20 in.) - {03340, 0256}, // deer decoration - {03345, 0851}, // lifeguard chair - {03346, 0173}, // public bench - {03348, 0186}, // plastic pool - {03396, 0441}, // natural garden table - {03400, 0610}, // dish-drying rack - {03402, 1789}, // vertical-board fence - {03406, 0524}, // beekeeper's hive - {03407, 0192}, // katana - {03416, 0204}, // soft-serve lamp - {03428, 0104}, // wall-mounted TV (50 in.) - {03430, 0605}, // playground gym - {03431, 0403}, // wall fan - {03436, 0168}, // wooden wardrobe - {03438, 0169}, // wooden end table - {03439, 0128}, // wooden table - {03442, 0252}, // sturdy sewing box - {03443, 0203}, // sewing project - {03444, 0234}, // wheelchair - {03445, 0271}, // standard umbrella stand - {03446, 0126}, // western-style stone - {03449, 0134}, // wooden stool - {03465, 1817}, // projection screen - {03467, 0226}, // tea set - {03468, 0181}, // beach towel - {03471, 0609}, // light switch - {03490, 0114}, // wooden waste bin - {03497, 0347}, // frozen table - {03498, 0346}, // frozen partition - {03499, 0343}, // frozen arch - {03500, 0345}, // frozen pillar - {03501, 0352}, // frozen sculpture - {03502, 0344}, // frozen bed - {03503, 0351}, // frozen chair - {03504, 0348}, // frozen tree - {03505, 0350}, // frozen counter - {03509, 0300}, // garden bench - {03551, 0211}, // bamboo shelf - {03553, 0213}, // bamboo partition - {03554, 0209}, // bamboo candleholder - {03556, 0210}, // bamboo stopblock - {03557, 0215}, // bamboo floor lamp - {03558, 0208}, // bamboo wall decoration - {03559, 0291}, // iron wall lamp - {03560, 0308}, // iron worktable - {03561, 0307}, // iron hanger stand - {03562, 0290}, // iron wall rack - {03563, 0306}, // iron shelf - {03581, 0188}, // fish-drying rack - {03582, 0150}, // book - {03583, 0207}, // fishing-boat flag - {03584, 0270}, // study poster - {03586, 0254}, // magazine - {03587, 0362}, // fishing-rod stand - {03588, 0160}, // signpost - {03590, 0195}, // desktop computer - {03591, 0363}, // birthday candles - {03592, 0364}, // birthday cake - {03593, 0365}, // birthday table - {03594, 0366}, // birthday sign - {03595, 0241}, // park clock - {03596, 0367}, // pool - {03616, 0318}, // system kitchen - {03617, 0324}, // stall - {03618, 0321}, // cutting board - {03619, 0529}, // soup kettle - {03621, 0323}, // loft bed with desk - {03622, 0322}, // floor seat - {03623, 0320}, // toy box - {03624, 0398}, // cute bed - {03658, 0326}, // bamboo basket - {03672, 0327}, // cardboard box - {03675, 0329}, // hay bed - {03681, 0397}, // piano bench - {03683, 0400}, // plain sink - {03692, 0356}, // plain wooden shop sign - {03697, 0334}, // portable radio - {03699, 0335}, // fish print - {03701, 0337}, // study desk - {03702, 0336}, // study chair - {03773, 0375}, // terrarium - {03775, 0376}, // hanging terrarium - {03776, 0377}, // brick well - {03783, 0380}, // den desk - {03784, 0379}, // den chair - {03785, 0378}, // potted ivy - {03805, 0389}, // mush parasol - {03806, 0387}, // mush partition - {03808, 0385}, // mush log - {03816, 0391}, // streetlamp - {03818, 0392}, // pennant - {03819, 0393}, // oil-barrel bathtub - {03820, 0394}, // fan - {03821, 0395}, // air circulator - {03822, 0405}, // pro tape recorder - {03943, 0432}, // ironwood DIY workbench - {03946, 0433}, // outdoor table - {03947, 0434}, // outdoor bench - {03948, 0446}, // accessories stand - {03949, 0493}, // anthurium plant - {03950, 0478}, // antique chair - {03951, 0479}, // antique console table - {03952, 0480}, // antique table - {03953, 0481}, // antique phone - {03954, 0482}, // antique clock - {03955, 0483}, // antique vanity - {03956, 0484}, // antique bureau - {03957, 0485}, // antique bed - {03958, 0486}, // antique mini table - {03959, 0487}, // antique wardrobe - {03960, 0492}, // handy water cooler - {03961, 0455}, // fortune-telling set - {03962, 0472}, // inflatable sofa - {03965, 0444}, // painting set - {03966, 0452}, // big festive tree - {03967, 0461}, // broom and dustpan - {03970, 0564}, // imperial decorative shelves - {03971, 0565}, // imperial partition - {03972, 0566}, // imperial chest - {03973, 0567}, // imperial bed - {03974, 0568}, // imperial low table - {03975, 0618}, // orange end table - {03976, 0617}, // orange wall-mounted clock - {03977, 0577}, // shell arch - {03978, 0578}, // shell partition - {03979, 0579}, // shell stool - {03980, 0580}, // shell table - {03982, 0582}, // shell fountain - {03983, 0583}, // shell bed - {03984, 0584}, // shell lamp - {03986, 0602}, // wall-mounted TV (20 in.) - {03987, 0435}, // wall-mounted phone - {03991, 0451}, // festive tree - {03992, 0460}, // key holder - {03993, 0454}, // analog kitchen scale - {03995, 0422}, // cute DIY table - {03996, 0423}, // cute wall-mounted clock - {03997, 0424}, // cute wardrobe - {03998, 0425}, // cute sofa - {03999, 0426}, // cute chair - {04000, 0427}, // cute tea table - {04001, 0428}, // cute vanity - {04002, 0429}, // cute floor lamp - {04003, 0430}, // cute music player - {04006, 0457}, // climbing wall - {04009, 0436}, // cordless phone - {04011, 0619}, // cherry speakers - {04012, 0620}, // cherry lamp - {04013, 0467}, // punching bag - {04014, 0465}, // folding floor lamp - {04015, 0613}, // shower booth - {04017, 0512}, // shower set - {04019, 0558}, // stand mixer - {04023, 0525}, // pants press - {04025, 0448}, // unglazed dish set - {04027, 0440}, // floral swag - {04029, 0489}, // rotary phone - {04030, 0445}, // bathroom towel rack - {04033, 0627}, // traditional tea set - {04034, 0442}, // scattered papers - {04035, 0546}, // log garden lounge - {04036, 0547}, // log decorative shelves - {04037, 0548}, // log wall-mounted clock - {04038, 0549}, // log stool - {04039, 0550}, // log chair - {04040, 0551}, // log dining table - {04041, 0552}, // log bed - {04042, 0553}, // log bench - {04043, 0554}, // log round table - {04044, 0555}, // log extra-long sofa - {04045, 0503}, // rattan waste bin - {04046, 0505}, // rattan end table - {04047, 0506}, // rattan stool - {04048, 0508}, // rattan towel basket - {04049, 0504}, // rattan wardrobe - {04050, 0509}, // rattan table lamp - {04051, 0510}, // rattan vanity - {04052, 0470}, // rattan bed - {04053, 0507}, // rattan armchair - {04054, 0511}, // rattan low table - {04066, 0415}, // illuminated tree - {04067, 0453}, // tabletop festive tree - {04068, 0420}, // table setting - {04069, 0585}, // table lamp - {04070, 0626}, // street organ - {04071, 0616}, // electronics kit - {04072, 0603}, // toilet-cleaning set - {04073, 0475}, // classic pitcher - {04074, 0416}, // illuminated reindeer - {04075, 0469}, // gong - {04076, 0462}, // nail-art set - {04077, 0596}, // party garland - {04078, 0500}, // barbell - {04080, 0499}, // long bathtub - {04081, 0468}, // camping cot - {04083, 1155}, // spooky arch - {04084, 1156}, // spooky scarecrow - {04086, 1157}, // spooky tower - {04087, 1190}, // spooky carriage - {04088, 1191}, // spooky lantern - {04089, 1192}, // spooky chair - {04090, 1193}, // spooky table - {04092, 1194}, // spooky lantern set - {04093, 0612}, // bamboo drum - {04094, 0474}, // floating-biotope planter - {04099, 0419}, // formal paper - {04101, 0437}, // fax machine - {04102, 0576}, // poolside bed - {04104, 0513}, // frying pan - {04108, 0417}, // illuminated present - {04109, 0561}, // double-door refrigerator - {04110, 0556}, // essay set - {04111, 0488}, // old-fashioned alarm clock - {04113, 0471}, // hose reel - {04114, 0562}, // tissue box - {04116, 0414}, // whiteboard - {04118, 0655}, // magnetic knife rack - {04119, 0458}, // macrame tapestry - {04122, 0601}, // cartoonist's set - {04124, 0644}, // wooden fish - {04125, 0531}, // wooden bookshelf - {04127, 0622}, // peach chair - {04128, 0623}, // peach surprise box - {04129, 0497}, // monstera - {04131, 0418}, // illuminated snowflakes - {04132, 0498}, // yucca - {04133, 0545}, // double-sided wall clock - {04134, 0624}, // apple chair - {04135, 0443}, // freezer - {04137, 0515}, // diner chair - {04138, 0516}, // diner counter chair - {04139, 0517}, // diner counter table - {04140, 0518}, // retro gas pump - {04141, 0519}, // diner sofa - {04142, 0520}, // diner dining table - {04143, 0521}, // diner neon sign - {04144, 0522}, // diner neon clock - {04196, 1249}, // crosswalk signal - {04226, 0630}, // basketball hoop - {04230, 0421}, // glass holder with candle - {04279, 0438}, // frozen-treat set - {04308, 0611}, // unfinished puzzle - {04309, 0708}, // destinations signpost - {04338, 0466}, // portable record player - {04357, 1795}, // iron fence - {04377, 0850}, // ornament wreath - {04379, 0477}, // springy ride-on - {04392, 0491}, // magic kit - {04412, 0502}, // cotton-candy stall - {04441, 0523}, // diner mini table - {04445, 0528}, // vintage TV tray - {04546, 0530}, // pear bed - {04572, 0543}, // shaded floor lamp - {04687, 0563}, // toolbox - {04708, 0569}, // mush low stool - {04719, 0571}, // celebratory candles - {04722, 0573}, // monster statue - {04738, 0845}, // skull doorplate - {04751, 0842}, // bone doorplate - {04752, 0849}, // iron doorplate - {04753, 0593}, // throwback wrestling figure - {04754, 0586}, // throwback gothic mirror - {04756, 0589}, // throwback wall clock - {04757, 0588}, // throwback skull radio - {04758, 0591}, // throwback mitt chair - {04759, 0587}, // throwback race-car bed - {04760, 0594}, // throwback hat table - {04761, 0595}, // throwback rocket - {04762, 0592}, // throwback container - {04764, 0848}, // fish doorplate - {05150, 0598}, // shell speaker - {05165, 0600}, // wall-mounted candle - {05207, 1796}, // zen fence - {05208, 1759}, // large lattice fence - {05309, 0843}, // heart doorplate - {05310, 0841}, // spider doorplate - {05337, 0606}, // three-tiered snowperson - {05338, 0607}, // simple panel - {05397, 0784}, // - {05543, 0628}, // wooden-block stool - {05635, 0643}, // tiny library - {05636, 0642}, // wooden-plank sign - {05716, 0844}, // paw-print doorplate - {05717, 0846}, // crest doorplate - {05718, 0840}, // timber doorplate - {05719, 0847}, // fossil doorplate - {05784, 0825}, // net - {05931, 0647}, // jail bars - {05972, 0791}, // wild log bench - {05973, 0790}, // log stakes - {05976, 0648}, // bamboo sphere - {05978, 0650}, // bamboo lunch box - {06075, 0700}, // tree's bounty mobile - {06078, 0701}, // tree's bounty lamp - {06079, 0698}, // tree's bounty little tree - {06080, 0697}, // tree's bounty big tree - {06081, 0699}, // tree's bounty arch - {06426, 0652}, // Cyrano's photo - {06427, 0652}, // Curt's photo - {06428, 0652}, // Zell's photo - {06429, 0652}, // Bruce's photo - {06430, 0652}, // Deirdre's photo - {06431, 0652}, // Lopez's photo - {06432, 0652}, // Fuchsia's photo - {06433, 0652}, // Beau's photo - {06434, 0652}, // Diana's photo - {06435, 0652}, // Erik's photo - {06436, 0652}, // Goldie's photo - {06437, 0652}, // Butch's photo - {06438, 0652}, // Chow's photo - {06439, 0652}, // Lucky's photo - {06440, 0652}, // Biskit's photo - {06441, 0652}, // Bones's photo - {06442, 0652}, // Portia's photo - {06443, 0652}, // Walker's photo - {06444, 0652}, // Daisy's photo - {06445, 0652}, // Cookie's photo - {06446, 0652}, // Maddie's photo - {06447, 0652}, // Bea's photo - {06448, 0652}, // Mac's photo - {06449, 0652}, // Nate's photo - {06450, 0652}, // Marcel's photo - {06451, 0652}, // Benjamin's photo - {06452, 0652}, // Cherry's photo - {06453, 0652}, // Shep's photo - {06454, 0652}, // Bill's photo - {06455, 0652}, // Joey's photo - {06456, 0652}, // Pate's photo - {06457, 0652}, // Maelle's photo - {06458, 0652}, // Deena's photo - {06459, 0652}, // Pompom's photo - {06460, 0652}, // Groucho's photo - {06461, 0652}, // Mallary's photo - {06462, 0652}, // Freckles's photo - {06463, 0652}, // Derwin's photo - {06464, 0652}, // Drake's photo - {06465, 0652}, // Scoot's photo - {06466, 0652}, // Weber's photo - {06467, 0652}, // Miranda's photo - {06468, 0652}, // Ketchup's photo - {06469, 0652}, // Gloria's photo - {06470, 0652}, // Molly's photo - {06471, 0652}, // Tutu's photo - {06472, 0652}, // Quillson's photo - {06473, 0652}, // Opal's photo - {06474, 0652}, // Dizzy's photo - {06475, 0652}, // Big Top's photo - {06476, 0652}, // Eloise's photo - {06477, 0652}, // Margie's photo - {06478, 0652}, // Paolo's photo - {06479, 0652}, // Axel's photo - {06480, 0652}, // Ellie's photo - {06481, 0652}, // Tucker's photo - {06482, 0652}, // Ursala's photo - {06483, 0652}, // Tia's photo - {06484, 0652}, // Lily's photo - {06485, 0652}, // Ribbot's photo - {06486, 0652}, // Frobert's photo - {06487, 0652}, // Camofrog's photo - {06488, 0652}, // Drift's photo - {06489, 0652}, // Wart Jr.'s photo - {06490, 0652}, // Puddles's photo - {06491, 0652}, // Jeremiah's photo - {06492, 0652}, // Tad's photo - {06493, 0652}, // Grizzly's photo - {06494, 0652}, // Cousteau's photo - {06495, 0652}, // Huck's photo - {06496, 0652}, // Prince's photo - {06497, 0652}, // Jambette's photo - {06498, 0652}, // Raddle's photo - {06499, 0652}, // Gigi's photo - {06500, 0652}, // Croque's photo - {06501, 0652}, // Diva's photo - {06502, 0652}, // Henry's photo - {06503, 0652}, // Chevre's photo - {06504, 0652}, // Paula's photo - {06505, 0652}, // Nan's photo - {06506, 0652}, // Billy's photo - {06507, 0652}, // Gruff's photo - {06508, 0652}, // Velma's photo - {06509, 0652}, // Kidd's photo - {06510, 0652}, // Pashmina's photo - {06511, 0652}, // Cesar's photo - {06512, 0652}, // Peewee's photo - {06513, 0652}, // Boone's photo - {06514, 0652}, // Louie's photo - {06515, 0652}, // Ike's photo - {06516, 0652}, // Boyd's photo - {06517, 0652}, // Violet's photo - {06518, 0652}, // Al's photo - {06519, 0652}, // Rocket's photo - {06520, 0652}, // Hans's photo - {06521, 0652}, // Hamlet's photo - {06522, 0652}, // Apple's photo - {06523, 0652}, // Graham's photo - {06524, 0652}, // Rodney's photo - {06525, 0652}, // Soleil's photo - {06526, 0652}, // Charlise's photo - {06527, 0652}, // Clay's photo - {06528, 0652}, // Flurry's photo - {06529, 0652}, // Hamphrey's photo - {06530, 0652}, // Rocco's photo - {06531, 0652}, // Bubbles's photo - {06532, 0652}, // Bertha's photo - {06533, 0652}, // Biff's photo - {06534, 0652}, // Bitty's photo - {06535, 0652}, // Harry's photo - {06536, 0652}, // Hippeux's photo - {06537, 0652}, // Antonio's photo - {06538, 0652}, // Beardo's photo - {06539, 0652}, // Buck's photo - {06540, 0652}, // Victoria's photo - {06541, 0652}, // Savannah's photo - {06542, 0652}, // Elmer's photo - {06543, 0652}, // Roscoe's photo - {06544, 0652}, // Winnie's photo - {06545, 0652}, // Ed's photo - {06546, 0652}, // Cleo's photo - {06547, 0652}, // Peaches's photo - {06548, 0652}, // Annalise's photo - {06549, 0652}, // Klaus's photo - {06550, 0652}, // Clyde's photo - {06551, 0652}, // Colton's photo - {06552, 0652}, // Papi's photo - {06553, 0652}, // Julian's photo - {06554, 0652}, // Yuka's photo - {06555, 0652}, // Alice's photo - {06556, 0652}, // Melba's photo - {06557, 0652}, // Sydney's photo - {06558, 0652}, // Gonzo's photo - {06559, 0652}, // Ozzie's photo - {06560, 0652}, // Jay's photo - {06561, 0652}, // Canberra's photo - {06562, 0652}, // Lyman's photo - {06563, 0652}, // Eugene's photo - {06564, 0652}, // Kitt's photo - {06565, 0652}, // Mathilda's photo - {06566, 0652}, // Carrie's photo - {06567, 0652}, // Astrid's photo - {06568, 0652}, // Sylvia's photo - {06569, 0652}, // Walt's photo - {06570, 0652}, // Rooney's photo - {06571, 0652}, // Robin's photo - {06572, 0652}, // Marcie's photo - {06573, 0652}, // Bud's photo - {06574, 0652}, // Elvis's photo - {06575, 0652}, // Rex's photo - {06576, 0652}, // Leopold's photo - {06577, 0652}, // Mott's photo - {06578, 0652}, // Rory's photo - {06579, 0652}, // Lionel's photo - {06580, 0652}, // Nana's photo - {06581, 0652}, // Simon's photo - {06582, 0652}, // Anchovy's photo - {06583, 0652}, // Tammi's photo - {06584, 0652}, // Monty's photo - {06585, 0652}, // Elise's photo - {06586, 0652}, // Flip's photo - {06587, 0652}, // Shari's photo - {06588, 0652}, // Deli's photo - {06589, 0652}, // Dora's photo - {06590, 0652}, // Limberg's photo - {06591, 0652}, // Bella's photo - {06592, 0652}, // Bree's photo - {06593, 0652}, // Twiggy's photo - {06594, 0652}, // Samson's photo - {06595, 0652}, // Rod's photo - {06596, 0652}, // Candi's photo - {06597, 0652}, // Rizzo's photo - {06598, 0652}, // Anicotti's photo - {06599, 0652}, // Broccolo's photo - {06600, 0652}, // Moose's photo - {06601, 0652}, // Bettina's photo - {06602, 0652}, // Greta's photo - {06603, 0652}, // Penelope's photo - {06604, 0652}, // Jitters's photo - {06605, 0652}, // Chadder's photo - {06606, 0652}, // Octavian's photo - {06607, 0652}, // Marina's photo - {06608, 0652}, // Zucker's photo - {06609, 0652}, // Queenie's photo - {06610, 0652}, // Gladys's photo - {06611, 0652}, // Sandy's photo - {06612, 0652}, // Sprocket's photo - {06613, 0652}, // Julia's photo - {06614, 0652}, // Cranston's photo - {06615, 0652}, // Piper's photo - {06616, 0652}, // Phil's photo - {06617, 0652}, // Blanche's photo - {06618, 0652}, // Flora's photo - {06619, 0652}, // Phoebe's photo - {06620, 0652}, // Apollo's photo - {06621, 0652}, // Amelia's photo - {06622, 0652}, // Pierce's photo - {06623, 0652}, // Buzz's photo - {06624, 0652}, // Avery's photo - {06625, 0652}, // Frank's photo - {06626, 0652}, // Admiral's photo - {06627, 0652}, // Sterling's photo - {06628, 0652}, // Keaton's photo - {06629, 0652}, // Celia's photo - {06630, 0652}, // Aurora's photo - {06631, 0652}, // Roald's photo - {06632, 0652}, // Cube's photo - {06633, 0652}, // Hopper's photo - {06634, 0652}, // Friga's photo - {06635, 0652}, // Gwen's photo - {06636, 0652}, // Puck's photo - {06637, 0652}, // Midge's photo - {06638, 0652}, // Wade's photo - {06639, 0652}, // Boomer's photo - {06640, 0652}, // Iggly's photo - {06641, 0652}, // Tex's photo - {06642, 0652}, // Flo's photo - {06643, 0652}, // Sprinkle's photo - {06644, 0652}, // Curly's photo - {06645, 0652}, // Truffles's photo - {06646, 0652}, // Rasher's photo - {06647, 0652}, // Hugh's photo - {06648, 0652}, // Pango's photo - {06649, 0652}, // Jacob's photo - {06650, 0652}, // Lucy's photo - {06651, 0652}, // Spork's photo - {06652, 0652}, // Cobb's photo - {06653, 0652}, // Boris's photo - {06654, 0652}, // Maggie's photo - {06655, 0652}, // Peggy's photo - {06656, 0652}, // Gala's photo - {06657, 0652}, // Chops's photo - {06658, 0652}, // Kevin's photo - {06659, 0652}, // Pancetti's photo - {06660, 0652}, // Lucha's photo - {06661, 0652}, // Agnes's photo - {06662, 0652}, // Bunnie's photo - {06663, 0652}, // Dotty's photo - {06664, 0652}, // Coco's photo - {06665, 0652}, // Snake's photo - {06666, 0652}, // Gaston's photo - {06667, 0652}, // Gabi's photo - {06668, 0652}, // Pippy's photo - {06669, 0652}, // Tiffany's photo - {06670, 0652}, // Genji's photo - {06671, 0652}, // Jacques's photo - {06672, 0652}, // Ruby's photo - {06673, 0652}, // Doc's photo - {06674, 0652}, // Claude's photo - {06675, 0652}, // Francine's photo - {06676, 0652}, // Chrissy's photo - {06677, 0652}, // Hopkins's photo - {06678, 0652}, // O'Hare's photo - {06679, 0652}, // Carmen's photo - {06680, 0652}, // Bonbon's photo - {06681, 0652}, // Cole's photo - {06682, 0652}, // Peck's photo - {06683, 0652}, // Mira's photo - {06684, 0652}, // Tank's photo - {06685, 0652}, // Rhonda's photo - {06686, 0652}, // Spike's photo - {06687, 0652}, // Hornsby's photo - {06688, 0652}, // Merengue's photo - {06689, 0652}, // Renée's photo - {06690, 0652}, // Vesta's photo - {06691, 0652}, // Baabara's photo - {06692, 0652}, // Eunice's photo - {06693, 0652}, // Sparro's photo - {06694, 0652}, // Stella's photo - {06695, 0652}, // Cashmere's photo - {06696, 0652}, // Willow's photo - {06697, 0652}, // Curlos's photo - {06698, 0652}, // Wendy's photo - {06699, 0652}, // Timbra's photo - {06700, 0652}, // Frita's photo - {06701, 0652}, // Muffy's photo - {06702, 0652}, // Pietro's photo - {06703, 0652}, // Peanut's photo - {06704, 0652}, // Angus's photo - {06705, 0652}, // Blaire's photo - {06706, 0652}, // Filbert's photo - {06707, 0652}, // Pecan's photo - {06708, 0652}, // Nibbles's photo - {06709, 0652}, // Agent S's photo - {06710, 0652}, // Caroline's photo - {06711, 0652}, // Sally's photo - {06712, 0652}, // Static's photo - {06713, 0652}, // Mint's photo - {06714, 0652}, // Ricky's photo - {06715, 0652}, // Rodeo's photo - {06716, 0652}, // Cally's photo - {06717, 0652}, // Tasha's photo - {06718, 0652}, // Sylvana's photo - {06719, 0652}, // Poppy's photo - {06720, 0652}, // Sheldon's photo - {06721, 0652}, // Marshal's photo - {06722, 0652}, // Hazel's photo - {06723, 0652}, // Rolf's photo - {06724, 0652}, // Rowan's photo - {06725, 0652}, // Tybalt's photo - {06726, 0652}, // Stu's photo - {06727, 0652}, // Bangle's photo - {06728, 0652}, // Leonardo's photo - {06729, 0652}, // Claudia's photo - {06730, 0652}, // Bianca's photo - {06731, 0652}, // Chief's photo - {06732, 0652}, // Lobo's photo - {06733, 0652}, // Wolfgang's photo - {06734, 0652}, // Whitney's photo - {06735, 0652}, // Dobie's photo - {06736, 0652}, // Freya's photo - {06737, 0652}, // T-Bone's photo - {06738, 0652}, // Fang's photo - {06739, 0652}, // Vivian's photo - {06740, 0652}, // Skye's photo - {06741, 0652}, // Kyle's photo - {06742, 0652}, // Coach's photo - {06743, 0652}, // Anabelle's photo - {06744, 0652}, // Vic's photo - {06745, 0652}, // Bob's photo - {06746, 0652}, // Mitzi's photo - {06747, 0652}, // Rosie's photo - {06748, 0652}, // Olivia's photo - {06749, 0652}, // Kiki's photo - {06750, 0652}, // Tangy's photo - {06751, 0652}, // Punchy's photo - {06752, 0652}, // Purrl's photo - {06753, 0652}, // Moe's photo - {06754, 0652}, // Snooty's photo - {06755, 0652}, // Kabuki's photo - {06756, 0652}, // Kid Cat's photo - {06757, 0652}, // Monique's photo - {06758, 0652}, // Tabby's photo - {06759, 0652}, // Stinky's photo - {06760, 0652}, // Kitty's photo - {06761, 0652}, // Tom's photo - {06762, 0652}, // Merry's photo - {06763, 0652}, // Felicity's photo - {06764, 0652}, // Lolly's photo - {06765, 0652}, // Annalisa's photo - {06766, 0652}, // Ankha's photo - {06767, 0652}, // Rudy's photo - {06768, 0652}, // Katt's photo - {06769, 0652}, // Bluebear's photo - {06770, 0652}, // Maple's photo - {06771, 0652}, // Poncho's photo - {06772, 0652}, // Pudge's photo - {06773, 0652}, // Kody's photo - {06774, 0652}, // Stitches's photo - {06775, 0652}, // Vladimir's photo - {06776, 0652}, // Olaf's photo - {06777, 0652}, // Murphy's photo - {06778, 0652}, // Olive's photo - {06779, 0652}, // Cheri's photo - {06780, 0652}, // June's photo - {06781, 0652}, // Pekoe's photo - {06782, 0652}, // Chester's photo - {06783, 0652}, // Barold's photo - {06784, 0652}, // Tammy's photo - {06785, 0652}, // Goose's photo - {06786, 0652}, // Benedict's photo - {06787, 0652}, // Teddy's photo - {06788, 0652}, // Egbert's photo - {06789, 0652}, // Ava's photo - {06790, 0652}, // Becky's photo - {06791, 0652}, // Plucky's photo - {06792, 0652}, // Knox's photo - {06793, 0652}, // Broffina's photo - {06794, 0652}, // Ken's photo - {06795, 0652}, // Patty's photo - {06796, 0652}, // Tipper's photo - {06797, 0652}, // Norma's photo - {06798, 0652}, // Pinky's photo - {06799, 0652}, // Naomi's photo - {06800, 0652}, // Alfonso's photo - {06801, 0652}, // Alli's photo - {06802, 0652}, // Boots's photo - {06803, 0652}, // Del's photo - {06804, 0652}, // Sly's photo - {06805, 0652}, // Gayle's photo - {06806, 0652}, // Drago's photo - {06807, 0652}, // Fauna's photo - {06808, 0652}, // Bam's photo - {06818, 0800}, // ornament mobile - {06826, 0654}, // nova light - {06827, 0725}, // starry garland - {06829, 0757}, // crescent-moon chair - {06830, 1743}, // shell music box - {06831, 0657}, // blossom-viewing lantern - {06832, 0656}, // cherry-blossom clock - {06992, 0652}, // Reneigh's photo - {06993, 0652}, // Judy's photo - {06994, 0652}, // Audie's photo - {06995, 0652}, // Megan's photo - {06996, 0652}, // Raymond's photo - {06997, 0652}, // Cyd's photo - {07045, 0748}, // recycled-can thumb piano - {07047, 0659}, // zen cushion - {07048, 0658}, // pile of zen cushions - {07132, 0664}, // wooden double bed - {07133, 0661}, // wooden mini table - {07134, 0662}, // wooden low table - {07135, 0674}, // floor light - {07136, 0675}, // cat grass - {07137, 0663}, // wooden full-length mirror - {07138, 0666}, // Mom's tea cozy - {07139, 0673}, // Mom's art - {07140, 0665}, // Mom's tissue box - {07141, 0667}, // Mom's pen stand - {07143, 0671}, // Mom's candle set - {07144, 0670}, // Mom's cushion - {07145, 0668}, // Mom's embroidery - {07146, 0672}, // Mom's homemade cake - {07147, 0669}, // Mom's plushie - {07148, 0676}, // life ring - {07150, 0750}, // blue corner - {07151, 0876}, // red corner - {07152, 0877}, // neutral corner - {07153, 0744}, // cypress bathtub - {07154, 0678}, // wooden box - {07159, 0813}, // cardboard sofa - {07160, 0814}, // cardboard table - {07161, 0815}, // cardboard bed - {07163, 0816}, // cardboard chair - {07189, 0680}, // studio spotlight - {07190, 0681}, // studio wall spotlight - {07212, 0652}, // Sherb's photo - {07213, 0652}, // Dom's photo - {07229, 0684}, // handcart - {07230, 0692}, // cosmos shower - {07231, 0691}, // tulip surprise box - {07232, 0690}, // mum cushion - {07233, 0689}, // windflower fan - {07234, 0688}, // hyacinth lamp - {07235, 0687}, // rose bed - {07236, 0686}, // lily record player - {07237, 0685}, // pansy table - {07238, 0735}, // anchor statue - {07247, 0694}, // silo - {07253, 0696}, // star clock - {07257, 0702}, // pedal board - {07258, 0703}, // modeling clay - {07259, 0896}, // palm-tree lamp - {07260, 0705}, // floor sign - {07264, 0707}, // champion's pennant - {07280, 0713}, // gears - {07281, 0714}, // sleigh - {07282, 0715}, // hanging scroll - {07284, 0711}, // nutcracker - {07317, 0717}, // zen-style stone - {07379, 0728}, // wind turbine - {07390, 0782}, // leaf stool - {07391, 0721}, // tatami bed - {07392, 0722}, // candy machine - {07393, 0727}, // pond stone - {07453, 0767}, // aluminum briefcase - {07454, 0766}, // wooden toolbox - {07525, 0773}, // tool shelf - {07526, 0817}, // outdoor generator - {07527, 0808}, // flower stand - {07528, 0809}, // tool cart - {07529, 0799}, // folding chair - {07531, 0745}, // ironing board - {07535, 0746}, // kettlebell - {07588, 0885}, // mushroom wand - {07599, 0752}, // board game - {07653, 0755}, // speed bag - {07654, 0756}, // electric kick scooter - {07681, 0762}, // loom - {07682, 0763}, // kimono stand - {07788, 0819}, // leaf campfire - {07789, 0811}, // drying rack - {07795, 0838}, // stone lion-dog - {07796, 0774}, // imperial dining table - {07797, 0775}, // imperial dining chair - {07800, 0777}, // protein shaker bottle - {07801, 0778}, // pet food bowl - {07802, 0779}, // pet bed - {07803, 0776}, // kitty litter box - {07804, 0780}, // knife block - {07805, 0873}, // butter churn - {07845, 0785}, // pull-up-bar stand - {07865, 0787}, // elaborate kimono stand - {07867, 0789}, // angled signpost - {07868, 0824}, // surfboard - {08031, 0874}, // fountain - {08096, 0812}, // record box - {08176, 0829}, // star net - {08177, 0828}, // colorful net - {08178, 0801}, // outdoorsy net - {08297, 0837}, // stovetop espresso maker - {08298, 0804}, // bunk bed - {08415, 0830}, // imperial dining lantern - {08417, 0823}, // wall-mounted tool board - {08418, 0822}, // fragrance diffuser - {08419, 0821}, // garden wagon - {08471, 0836}, // fish fishing rod - {08472, 0835}, // colorful fishing rod - {08473, 0833}, // outdoorsy fishing rod - {08534, 0860}, // colorful watering can - {08535, 0878}, // elephant watering can - {08536, 0861}, // outdoorsy watering can - {08575, 0863}, // outdoorsy shovel - {08576, 0870}, // printed-design shovel - {08577, 0862}, // colorful shovel - {08579, 0857}, // outdoorsy slingshot - {08580, 0858}, // colorful slingshot - {08760, 0831}, // customizable phone case kit - {08826, 0832}, // wooden table mirror - {09502, 0852}, // clothes closet - {09565, 0853}, // mobile - {09568, 0854}, // construction sign - {09584, 0859}, // beach ball - {09619, 0868}, // utility pole - {09642, 0866}, // iron closet - {09766, 0871}, // mini fridge - {09767, 0872}, // garbage bin - {10244, 0880}, // fragrance sticks - {10742, 0883}, // bamboo stool - {10743, 0884}, // bamboo speaker - {11115, 0652}, // Rilla's photo - {11116, 0652}, // Marty's photo - {11117, 0652}, // Étoile's photo - {11118, 0652}, // Chai's photo - {11119, 0652}, // Chelsea's photo - {11120, 0652}, // Toby's photo - {11711, 1797}, // simple wooden fence - {11712, 1798}, // lattice fence - {11941, 0889}, // stone arch - {11942, 0897}, // street piano - {11943, 0890}, // stone tablet - {12140, 0891}, // DAL model plane - {12207, 0895}, // arcade seat - {12305, 1777}, // Casablanca lilies - {12308, 0907}, // reception chair - {12311, 0905}, // cruiser bike - {12312, 0903}, // wood-plank table - {12313, 0902}, // public telephone - {12314, 0904}, // zen lowboard - {12332, 0901}, // natural square table - {12340, 1788}, // volleyball net - {12341, 1778}, // gurney - {12343, 1591}, // stepladder - {12344, 0912}, // baseball set - {12345, 1769}, // metal-and-wood table - {12346, 1770}, // metal-and-wood chair - {12348, 0909}, // froggy chair - {12349, 0910}, // project table - {12350, 0911}, // box-shaped seat - {12356, 0914}, // round pillow - {12358, 0915}, // retro ice-cream case - {12361, 1226}, // zen bench - {12365, 0918}, // garden chair - {12366, 0919}, // plastic bench - {12372, 0921}, // Pocket modern camper - {12373, 0920}, // Pocket vintage camper - {12401, 0923}, // wedding bench - {12402, 0922}, // wedding arch - {12403, 0926}, // wedding cake - {12404, 0932}, // wedding head table - {12405, 0928}, // wedding chair - {12406, 0929}, // wedding table - {12407, 0931}, // wedding decoration - {12408, 0925}, // wedding candle set - {12409, 0930}, // wedding pipe organ - {12410, 0924}, // wedding welcome board - {12411, 0927}, // wedding flower stand - {12516, 0933}, // sampler - {12543, 0934}, // Nintendo Switch - {12582, 0652}, // Zoe's photo - {12583, 0652}, // Rio's photo - {12584, 0652}, // Azalea's photo - {12585, 0652}, // Faith's photo - {12586, 0652}, // Chabwick's photo - {12587, 0652}, // Ace's photo - {12588, 0652}, // Frett's photo - {12589, 0652}, // Roswell's photo - {12590, 0652}, // Ione's photo - {12591, 0652}, // Shino's photo - {12592, 0652}, // Petri's photo - {12593, 0652}, // Quinn's photo - {12594, 0652}, // Sasha's photo - {12595, 0652}, // Cephalobot's photo - {12596, 0652}, // Marlo's photo - {12597, 0652}, // Tiansheng's photo - {12599, 0935}, // office chair - {12600, 1765}, // bulldozer - {12601, 1767}, // cement mixer - {12602, 1768}, // excavator - {12603, 1766}, // steamroller - {12604, 1051}, // jackhammer - {12605, 0947}, // safety barrier - {12606, 0945}, // tractor - {12608, 0941}, // flower display case - {12610, 0942}, // frozen-drink machine - {12611, 1568}, // plate armor - {12612, 0940}, // capsule-toy machine - {12613, 0944}, // fancy tea set - {12614, 0943}, // peacock chair - {12637, 0948}, // examination-room desk - {12653, 0952}, // modern hospital bed - {12669, 0960}, // donut stool - {12670, 0950}, // office cabinet - {12673, 0955}, // tall file cabinet - {12674, 0956}, // short file cabinet - {12675, 0957}, // plant partition - {12676, 0958}, // large magazine rack - {12677, 0959}, // medicine chest - {12678, 0961}, // arched reception counter - {12679, 0962}, // reception counter - {12683, 1807}, // plaza ferris wheel - {12684, 1813}, // plaza merry-go-round - {12685, 1806}, // inflatable plaza toy - {12688, 1812}, // plaza bench - {12689, 1805}, // plaza arch - {12690, 1809}, // plaza game stand - {12691, 1811}, // plaza balloon wagon - {12692, 1810}, // plaza clock - {12693, 1742}, // street lamp with banners - {12699, 0964}, // standing electric sign - {12700, 0998}, // sturdy office desk - {12701, 1011}, // school locker - {12702, 0999}, // strapped books - {12703, 1818}, // mop - {12704, 1000}, // basic school chair - {12705, 1001}, // stewpot - {12706, 1002}, // imperial pot - {12707, 1003}, // cans - {12708, 1004}, // cooking tools - {12709, 1010}, // carp on a cutting board - {12712, 0994}, // salad bar - {12713, 0996}, // antique cash register - {12714, 0995}, // modern cash register - {12715, 0997}, // bulletin board - {12717, 1006}, // left chalkboard section - {12718, 1007}, // right chalkboard section - {12720, 1009}, // fancy water pitcher - {12741, 1012}, // world map - {12744, 1016}, // small covered round table - {12745, 1015}, // large covered round table - {12766, 1017}, // small café table - {12767, 1018}, // large café table - {12768, 1019}, // checkout counter - {12769, 1020}, // dessert case - {12772, 1021}, // ice-cream display - {12773, 1022}, // counter chair - {12774, 1023}, // busing station - {12775, 1024}, // afternoon-tea set - {12776, 1025}, // counter table - {12777, 1026}, // covered counter - {12778, 1027}, // touchscreen cash register - {12779, 1028}, // wood partition - {12780, 1029}, // wall shelf with bottles - {12781, 1816}, // sample case - {12782, 1030}, // bistro table - {12803, 1808}, // plaza train - {12879, 1039}, // tabletop POP display - {12880, 1040}, // standing shop sign - {12881, 1046}, // dress mannequin - {12882, 1035}, // small mannequin - {12883, 1042}, // midsized clothing rack - {12884, 1043}, // small clothing rack - {12885, 1036}, // hanging clothing rack - {12886, 1032}, // corner clothing rack - {12887, 1034}, // glass showcase - {12888, 1041}, // hanger rack - {12889, 1045}, // boxy stool - {12890, 1038}, // merchandise table - {12891, 1033}, // full-length mirror - {12892, 1044}, // sturdy paper bag - {12893, 1037}, // stacked shoeboxes - {12894, 1799}, // wedding fence - {12949, 1168}, // spooky standing lamp - {12951, 1195}, // spooky candy set - {12976, 1048}, // mini dharma - {12991, 1065}, // simple stool - {12993, 1062}, // simple vanity - {12994, 1061}, // simple bed - {12995, 1064}, // simple sofa - {12996, 1059}, // simple chair - {12997, 1066}, // simple wall shelf - {12998, 1063}, // simple small dresser - {12999, 1067}, // simple table - {13004, 1069}, // artsy table - {13005, 1068}, // artsy chair - {13006, 1070}, // cool low table - {13007, 1071}, // cool side table - {13008, 1072}, // cool chair - {13009, 1073}, // cool bed - {13010, 1074}, // cool sofa - {13073, 1088}, // Nordic chair - {13075, 1090}, // Nordic sofa - {13076, 1091}, // Nordic low table - {13077, 1092}, // Nordic lowboard - {13078, 1093}, // Nordic shelves - {13079, 1094}, // Nordic table - {13080, 1095}, // ranch wardrobe - {13081, 1096}, // ranch tea table - {13082, 1097}, // ranch lowboard - {13083, 1098}, // Moroccan footrest - {13084, 1099}, // Moroccan tray table - {13085, 1100}, // Moroccan sofa - {13108, 1101}, // upright organizer - {13109, 1102}, // horizontal organizer - {13110, 1103}, // plastic clothing organizer - {13111, 1104}, // Japanese dresser - {13112, 1105}, // zen low table - {13113, 1106}, // shoji divider - {13114, 1107}, // vintage stool - {13115, 1108}, // vintage desk - {13116, 1109}, // vintage sofa - {13117, 1110}, // vintage low table - {13118, 1111}, // vintage dresser - {13119, 1112}, // enamel lamp - {13120, 1113}, // round light fixture - {13121, 1114}, // wood-shade lamp - {13122, 1115}, // zen light - {13138, 1117}, // elegant chair - {13139, 1118}, // elegant bed - {13140, 1119}, // elegant console table - {13141, 1120}, // elegant sofa - {13142, 1121}, // elegant lamp - {13143, 1122}, // elegant dresser - {13144, 1123}, // simple shaded lamp - {13145, 1124}, // stained-glass light - {13146, 1125}, // milk-glass lamp - {13147, 1126}, // fluorescent light - {13148, 1127}, // ceiling spotlight - {13149, 1128}, // Nordic pendant light - {13150, 1129}, // Moroccan lights - {13151, 1130}, // festival lantern - {13152, 1131}, // imperial lamp - {13153, 1132}, // wooden pendant light - {13154, 1133}, // chandelier - {13155, 1134}, // spiral chandelier - {13156, 1135}, // ceiling fan - {13157, 1136}, // dual hanging monitors - {13158, 1137}, // hanging shelves - {13161, 1139}, // wooden field sign - {13163, 1196}, // study carrel - {13164, 1142}, // disco ball - {13185, 1143}, // small vase - {13186, 1144}, // porcelain vase - {13187, 1145}, // fine vase - {13188, 1146}, // ball catcher - {13189, 1147}, // stair dresser - {13190, 1148}, // sword - {13191, 1149}, // bow - {13192, 1150}, // samurai suit - {13201, 1199}, // bath bucket - {13202, 1212}, // bath stool - {13203, 1213}, // square bathtub - {13205, 1225}, // store shelf - {13206, 1214}, // shopping bag - {13207, 1220}, // small LED display - {13209, 1218}, // tablet device - {13210, 1215}, // stacked shopping baskets - {13211, 1219}, // caged cart - {13214, 1222}, // steel trash can - {13220, 1152}, // festival-lantern set - {13222, 1153}, // spooky garland - {13223, 1154}, // spooky table setting - {13229, 1197}, // range hood - {13242, 1211}, // RC helicopter - {13243, 1198}, // puppy plushie - {13244, 1209}, // gift pile - {13245, 1207}, // Yule log - {13246, 1204}, // pop-up book - {13247, 1208}, // tin robot - {13249, 1201}, // kids' tent - {13250, 1210}, // mini circuit - {13251, 1200}, // dinosaur toy - {13252, 1205}, // dollhouse - {13255, 1221}, // elaborate display case - {13266, 1228}, // owl clock - {13268, 1252}, // covered wagon - {13269, 1253}, // storefront - {13270, 1227}, // antique radio - {13271, 1224}, // upright speaker - {13272, 1325}, // evergreen ash - {13273, 1254}, // cactus - {13274, 1223}, // wristwatch - {13288, 1229}, // high chair - {13294, 1230}, // beach chairs with parasol - {13295, 1232}, // game-show stand - {13296, 1231}, // vehicle cabin seat - {13299, 1233}, // decorative bottles - {13300, 1235}, // stylish wall spotlight - {13302, 1234}, // decorative pillar - {13303, 1241}, // glass jar - {13304, 1237}, // winnowing machine - {13305, 1238}, // conveyor belt - {13306, 1240}, // robot arm - {13307, 1236}, // stylish spotlight - {13312, 1245}, // round streetlight - {13313, 1244}, // curved streetlight - {13335, 1256}, // bird mobile - {13336, 1257}, // construction scaffolding - {13337, 1261}, // sloppy table - {13338, 1259}, // sloppy sink - {13339, 1260}, // sloppy sofa - {13340, 1255}, // garden table - {13341, 1262}, // sloppy bed - {13342, 1265}, // dreamy bed - {13343, 1263}, // dreamy wall rack - {13344, 1264}, // dreamy shelves - {13345, 1258}, // snack - {13347, 1266}, // yacht - {13352, 1157}, // - {13356, 1278}, // rolling cart - {13360, 1274}, // bottled beverage - {13361, 1275}, // paint cans - {13362, 1270}, // double-edged sword - {13363, 1269}, // inspection equipment - {13365, 1273}, // toothbrush-and-cup set - {13366, 1272}, // chainsaw - {13367, 1267}, // bunny garden decoration - {13368, 1268}, // elegant mirror - {13369, 1276}, // milk can - {13370, 1277}, // wheat field - {13447, 1295}, // Turkey Day garden stand - {13448, 1296}, // Turkey Day hearth - {13449, 1293}, // Turkey Day decorations - {13450, 1292}, // Turkey Day chair - {13453, 1297}, // Turkey Day table - {13454, 1280}, // cool dining table - {13455, 1279}, // shopping basket - {13464, 1283}, // crane game - {13465, 1786}, // bubble machine - {13466, 1288}, // silver confetti blower - {13467, 1287}, // stage flame machine - {13468, 1286}, // hanging stage lights - {13469, 1285}, // stage lights - {13472, 1301}, // windmill - {13474, 1291}, // siren - {13475, 1783}, // candle chandelier - {13478, 1820}, // tabletop record player - {13479, 1290}, // nearly busted radio - {13488, 1516}, // chocolate heart - {13496, 1302}, // stonework kitchen - {13502, 1316}, // spaceship control panel - {13503, 1324}, // meter and pipes - {13504, 1312}, // strategic meeting table - {13505, 1320}, // mining car - {13506, 1321}, // science pod - {13507, 1323}, // banker's lamp - {13508, 1310}, // cold sleep pod - {13509, 1305}, // gear tower - {13510, 1307}, // crew member's seat - {13511, 1304}, // gear apparatus - {13512, 1319}, // retro transportation stop - {13513, 1311}, // fish container - {13514, 1322}, // powder-room booth - {13515, 1317}, // tank - {13516, 1315}, // amazing machine - {13517, 1512}, // unknown machine - {13518, 1313}, // lab chair - {13519, 1308}, // gaming chair - {13520, 1306}, // forbidden altar - {13521, 1309}, // gaming desk - {13522, 1303}, // dress-up doll - {13523, 1314}, // skateboard - {13524, 1318}, // medieval building side - {13526, 1801}, // vine ladder set-up kit - {13530, 1800}, // wooden ladder set-up kit - {13534, 1802}, // iron ladder set-up kit - {13573, 1339}, // medium wooden partition - {13574, 1340}, // small wooden partition - {13575, 1327}, // SLR camera - {13576, 1332}, // schefflera - {13577, 1338}, // potted starter plants - {13578, 1326}, // inflatable bird ring - {13579, 1336}, // baobab - {13580, 1330}, // skateboard wall rack - {13581, 1329}, // castle gate - {13582, 1328}, // castle tower - {13583, 1342}, // rescue mannequin - {13584, 1331}, // makeup pouch - {13586, 1333}, // transit seat - {13587, 1335}, // dried-flower garland - {13588, 1341}, // tension-pole rack - {13589, 1337}, // professional headphones - {13590, 1343}, // castle wall - {13591, 1344}, // fancy bathroom vanity - {13606, 1345}, // stacked fish containers - {13614, 1375}, // key tray - {13615, 1399}, // scooter - {13616, 1437}, // hanging lightbulb - {13618, 1439}, // patchwork sofa chair - {13620, 1360}, // office materials - {13621, 1381}, // minicar - {13622, 1382}, // luxury car - {13623, 1465}, // dormant volcano - {13624, 1421}, // scoreboard - {13625, 1440}, // patchwork chair - {13626, 1357}, // ornithopter - {13627, 1441}, // patchwork low table - {13628, 1452}, // model kit - {13629, 1442}, // patchwork bed - {13630, 1363}, // curtain partition - {13631, 1428}, // torii - {13632, 1458}, // popcorn snack set - {13633, 1379}, // throne - {13634, 1404}, // fresh-food trays - {13636, 1448}, // wide display stand - {13637, 1361}, // outdoor folding chair - {13638, 1377}, // utility wagon - {13639, 1396}, // short simple panel - {13640, 1370}, // wall-mounted LED display - {13642, 1417}, // paper-chain ceiling garland - {13643, 1386}, // die - {13645, 1402}, // scrapbook - {13647, 1449}, // fence - {13649, 1436}, // lily-pad table - {13651, 1422}, // tokonoma - {13652, 1407}, // antique map - {13655, 1392}, // framed photo - {13656, 1378}, // cube light - {13657, 1355}, // decorative plate - {13662, 1353}, // ruined decorated pillar - {13666, 1358}, // pile of cash - {13676, 1460}, // round topiary - {13678, 1388}, // triangular topiary - {13680, 1362}, // outdoor folding table - {13681, 1456}, // light-bulb sign - {13683, 1469}, // yoga mat - {13690, 1462}, // futuristic meal - {13691, 1368}, // mounted mountain bike - {13692, 1468}, // dreamy hanging decoration - {13696, 1411}, // pile of cardboard boxes - {13701, 1429}, // drapery - {13709, 1403}, // spray can - {13712, 1427}, // card tower - {13717, 1380}, // metal pot - {13719, 1350}, // toy duck - {13722, 1385}, // recycled-paper bundle - {13727, 1397}, // dessert carrier - {13729, 1438}, // carton beverage - {13730, 1470}, // shaded pendant lamp - {13740, 1453}, // model kits - {13744, 1365}, // framed poster - {13745, 1467}, // yunomi teacup - {13746, 1423}, // stacked bags - {13747, 1387}, // backlit sign - {13748, 1426}, // cards - {13751, 1486}, // open wooden shelves - {13756, 1487}, // bottle crate - {13764, 1492}, // hanging cube light - {13765, 1494}, // plain party-lights arch - {13767, 1495}, // Festivale garland - {13770, 1500}, // Festivale parasol - {13772, 1501}, // Festivale balloon lamp - {13773, 1504}, // Festivale stall - {13774, 1498}, // Festivale drum - {13775, 1497}, // Festivale stage - {13776, 1496}, // Festivale confetti machine - {13777, 1505}, // Festivale lamp - {13778, 1506}, // Festivale flag - {13818, 1509}, // Turkey Day casserole - {13819, 1510}, // Turkey Day wheat decor - {13820, 1508}, // Turkey Day table setting - {13829, 1511}, // Shell - {13831, 1522}, // large Mushroom Platform - {13832, 1523}, // small Mushroom Platform - {13862, 0652}, // Jingle's photo - {13884, 1513}, // ranch cupboard - {13897, 1605}, // tall brick island counter - {13901, 1607}, // low brick island counter - {13902, 1593}, // tall wooden island counter - {13925, 1520}, // hanging monitor - {13926, 1519}, // hanging guide sign - {13927, 1521}, // Nintendo Switch Lite - {13930, 1524}, // set of stockings - {14017, 1542}, // cave - {14018, 1543}, // ruined arch - {14019, 1544}, // vine hanging chair - {14029, 1546}, // heart-shaped bouquet - {14046, 1655}, // xylophoid - {14047, 1656}, // babbloid - {14049, 1547}, // truck - {14050, 1553}, // deep fryer - {14051, 1552}, // fancy frame - {14053, 1549}, // wall planter - {14054, 1550}, // ranch kitchen - {14055, 1548}, // outdoor kitchen - {14056, 1693}, // arfoid - {14057, 1694}, // whistloid - {14058, 1695}, // bwongoid - {14059, 1696}, // twangoid - {14060, 1697}, // laseroid - {14061, 1698}, // squeakoid - {14062, 1699}, // tockoid - {14063, 1700}, // ringoid - {14064, 1701}, // oinkoid - {14065, 1702}, // tremoloid - {14066, 1703}, // bubbloid - {14067, 1704}, // petaloid - {14074, 1658}, // aluminoid - {14075, 1682}, // wallopoid - {14076, 1683}, // drummoid - {14077, 1684}, // dootoid - {14078, 1685}, // whirroid - {14080, 1664}, // thwopoid - {14081, 1665}, // rumbloid - {14082, 1666}, // bendoid - {14083, 1667}, // boomoid - {14086, 1676}, // bloopoid - {14087, 1677}, // sproingoid - {14088, 1678}, // crumploid - {14089, 1679}, // clatteroid - {14092, 1657}, // scatteroid - {14093, 1688}, // spikenoid - {14094, 1689}, // squeezoid - {14095, 1690}, // flutteroid - {14098, 1670}, // boioingoid - {14099, 1671}, // stelloid - {14100, 1672}, // jingloid - {14101, 1673}, // rattloid - {14106, 1554}, // gazebo - {14108, 1556}, // azumaya gazebo - {14184, 1567}, // pergola - {14192, 1569}, // giant vine - {14193, 1570}, // vine bench - {14205, 1575}, // vine lamp - {14206, 1574}, // vine garland - {14207, 1576}, // glowing-moss stool - {14208, 1580}, // glowing-moss balloon - {14209, 1578}, // glowing-moss boulder - {14210, 1577}, // hanging glowing moss - {14211, 1579}, // glowing-moss wreath - {14212, 1582}, // glowing-moss pond - {14213, 1583}, // glowing-moss statue - {14214, 1585}, // glowing-moss-jar shelves - {14215, 1584}, // glow-in-the-dark stickers - {14216, 1581}, // suspicious cauldron - {14254, 0652}, // Tom Nook's photo - {14255, 0652}, // Timmy and Tommy's photo - {14256, 0652}, // Isabelle's photo - {14308, 1599}, // low simple island counter - {14310, 1602}, // tall simple island counter - {14313, 1595}, // low wooden island counter - {14332, 1660}, // tall marble island counter - {14337, 1662}, // low marble island counter - {14340, 1615}, // whoopee cushion - {14346, 1620}, // hanging sign - {14352, 1623}, // dreamy bear toy - {14353, 1622}, // dreamy rabbit toy - {14354, 1624}, // dreamy unicorn toy - {14414, 1754}, // handheld lantern - {14472, 0652}, // Rover's photo - {14475, 1642}, // nuptial doorplate - {14476, 1640}, // nuptial bell - {14477, 1641}, // nuptial ring pillow - {14520, 1631}, // wall-mounted neon lamps - {14523, 1632}, // tangled cords - {14524, 1637}, // floral sconce - {14525, 1636}, // dispenser - {14526, 1639}, // wooden locker - {14527, 1634}, // clipboard - {14528, 1633}, // steel fence - {14530, 1629}, // meeting-room table - {14531, 1635}, // long folding table - {14534, 1630}, // instant noodles - {14538, 1772}, // protein shake - {14539, 1758}, // dumbbell - {14542, 1750}, // spooky treats basket - {14549, 1654}, // decayed tree - {14550, 1645}, // spooky tree - {14551, 1647}, // spooky trick lamp - {14556, 1779}, // osechi - {14561, 1648}, // chafing dish - {14572, 1781}, // storage shed - {14574, 1776}, // coffee beans - {14575, 1751}, // ABD - {14591, 1762}, // ornament table lamp - {14592, 1649}, // wooden music box - {14593, 1764}, // ornament garland - {14594, 1761}, // giant ornament - {14596, 1653}, // brick pillar - {14597, 1659}, // marble pillar - {14598, 1652}, // simple pillar - {14601, 1651}, // wooden pillar - {14604, 1663}, // glowing-moss jar - {14611, 0652}, // Brewster's photo - {14619, 1747}, // vertical split curtains - {14620, 1748}, // horizontal split curtains - {14621, 1749}, // unfolded reference sheet - {14639, 1755}, // pocketbook - {14640, 1756}, // pocket magazine - {14714, 1752}, // donation box - {14728, 1763}, // ornament tree - {14735, 1757}, // - {14756, 1760}, // frozen fence - {14758, 1774}, // corrugated iron fence - {14759, 1775}, // park fence - {14799, 1823}, // flower tabletop mirror - {14821, 1782}, // ring light - {14826, 1784}, // lighted display stand - {14831, 1785}, // wooden storage shed - {14882, 1803}, // ruined seat - {14887, 1804}, // ruined broken pillar - }; + return dict; } -} + + private static readonly IReadOnlyDictionary List = new Dictionary + { + {00079, 1216}, // baby bed + {00080, 0102}, // clackercart + {00083, 0129}, // rocking horse + {00085, 0197}, // train set + {00086, 0086}, // elephant slide + {00088, 0119}, // ringtoss + {00131, 0879}, // lucky cat + {00144, 0156}, // manhole cover + {00146, 0172}, // cone + {00287, 0818}, // exercise bike + {00290, 0771}, // treadmill + {00330, 0171}, // barbecue + {00331, 0399}, // birdbath + {00333, 0232}, // birdhouse + {00335, 0758}, // Mr. Flamingo + {00336, 0759}, // Mrs. Flamingo + {00338, 0258}, // lawn mower + {00370, 0652}, // Cyrus's photo + {00371, 0652}, // Reese's photo + {00372, 0652}, // Chip's photo + {00373, 0652}, // Phineas's photo + {00374, 0652}, // Joan's photo + {00375, 0652}, // Katrina's photo + {00376, 0652}, // Nat's photo + {00377, 0652}, // Saharah's photo + {00378, 0652}, // K.K.'s photo + {00379, 0652}, // Redd's photo + {00380, 0652}, // Gracie's photo + {00381, 0652}, // Label's photo + {00382, 0652}, // Mabel's photo + {00383, 0310}, // acoustic guitar + {00384, 0652}, // Sable's photo + {00385, 0652}, // Grams's photo + {00386, 0652}, // Leilani's photo + {00387, 0652}, // Kapp'n's photo + {00388, 0652}, // Leila's photo + {00389, 0652}, // Porter's photo + {00390, 0652}, // Don's photo + {00391, 0652}, // Resetti's photo + {00392, 0652}, // Lyle's photo + {00393, 0652}, // Blathers's photo + {00394, 0652}, // Celeste's photo + {00395, 0652}, // Pavé's photo + {00396, 0652}, // Pelly's photo + {00397, 0652}, // Phyllis's photo + {00398, 0652}, // Copper's photo + {00399, 0652}, // Pete's photo + {00400, 0652}, // Booker's photo + {00401, 0652}, // Harriet's photo + {00402, 0652}, // Gulliver's photo + {00403, 0652}, // Pascal's photo + {00404, 0652}, // Kicks's photo + {00405, 0652}, // Tortimer's photo + {00406, 0652}, // Franklin's photo + {00407, 0652}, // Shrunk's photo + {00408, 0652}, // Leif's photo + {00409, 0652}, // Blanca's photo + {00410, 0652}, // Luna's photo + {00411, 0652}, // Katie's photo + {00412, 0652}, // Zipper's photo + {00413, 0652}, // Digby's photo + {00414, 0652}, // Wendell's photo + {00415, 0652}, // Wisp's photo + {00416, 0652}, // Lottie's photo + {00417, 0652}, // Jack's photo + {00418, 0652}, // Harvey's photo + {00419, 0652}, // C.J.'s photo + {00420, 0652}, // Daisy Mae's photo + {00421, 0652}, // Orville's photo + {00422, 0652}, // Flick's photo + {00423, 0652}, // DJ KK's photo + {00424, 0652}, // Wilbur's photo + {00425, 0652}, // Wardell's photo + {00426, 0652}, // Niko's photo + {00522, 1515}, // creepy skeleton + {00530, 0178}, // grass standee + {00531, 0176}, // hedge standee + {00532, 0179}, // mountain standee + {00533, 0177}, // tree standee + {00534, 0951}, // hospital bed + {00537, 1771}, // IV drip + {00538, 0949}, // exam table + {00546, 0806}, // stadiometer + {00547, 0225}, // washbasin + {00664, 0182}, // beach chair + {00667, 0899}, // shaved-ice maker + {00669, 0456}, // ukulele + {00676, 0887}, // tall lantern + {00677, 0651}, // deer scare + {00682, 0373}, // boomerang + {00683, 0734}, // bottled ship + {00685, 0719}, // Dala horse + {00688, 0803}, // pagoda + {00690, 0709}, // hula doll + {00704, 0796}, // tapestry + {00710, 0216}, // bamboo bench + {00716, 0360}, // screen + {00725, 0312}, // paper lantern + {00735, 1821}, // low folding table + {00739, 0224}, // tea table + {00741, 1822}, // safety railing + {00742, 0221}, // fireplace + {00743, 1824}, // frozen mini snowperson + {00744, 1825}, // compact kitchen + {00787, 0127}, // tape deck + {00796, 0374}, // retro stereo + {00805, 0383}, // mush lamp + {00808, 0340}, // mush table + {00832, 0354}, // modern office chair + {00833, 0085}, // upright locker + {00839, 0281}, // safe + {00840, 0355}, // office desk + {00849, 0402}, // amp + {00863, 0641}, // billiard table + {00865, 0190}, // birdcage + {00870, 0476}, // book stands + {00889, 0463}, // camp stove + {00891, 0368}, // holiday candle + {00896, 0279}, // cat tower + {00907, 0228}, // vacuum cleaner + {00908, 0229}, // upright vacuum + {00915, 0396}, // cuckoo clock + {00918, 0242}, // coffee cup + {00922, 0262}, // stacked bottle crates + {00928, 0317}, // pot rack + {00929, 0316}, // air conditioner + {00941, 0410}, // DJ's turntable + {00950, 0742}, // effects rack + {00954, 0572}, // espresso maker + {00955, 0359}, // exit sign + {00957, 0277}, // ventilation fan + {00963, 1815}, // fire hydrant + {00967, 0946}, // flower bed + {00971, 0886}, // snack machine + {00987, 0743}, // harp + {00997, 0267}, // incense burner + {00998, 0309}, // kitchen island + {01019, 0280}, // first-aid kit + {01029, 0183}, // low screen + {01032, 0152}, // magazine rack + {01042, 0166}, // metronome + {01043, 0199}, // microwave + {01050, 0157}, // mixer + {01051, 0159}, // water bird + {01058, 0140}, // music stand + {01072, 0170}, // rope partition + {01081, 0328}, // upright piano + {01082, 0184}, // picnic basket + {01087, 0768}, // pinball machine + {01092, 0148}, // popcorn machine + {01103, 0117}, // rocking chair + {01108, 0120}, // retro TV + {01111, 0726}, // outdoor bath + {01112, 0125}, // colorful wheel + {01117, 0231}, // sand castle + {01125, 0559}, // revolving spice rack + {01127, 0733}, // old sewing machine + {01128, 0158}, // sewing machine + {01133, 1826}, // shopping cart + {01141, 0913}, // ski rack + {01143, 0236}, // smoker + {01157, 0407}, // brick oven + {01161, 0526}, // cream and sugar + {01170, 0142}, // swinging bench + {01171, 0408}, // synthesizer + {01177, 0772}, // foosball table + {01185, 0200}, // phone box + {01189, 0370}, // tire stack + {01199, 0255}, // tricycle + {01206, 1298}, // trumpet + {01211, 0794}, // typewriter + {01221, 0409}, // video camera + {01222, 1217}, // TV with VCR + {01227, 0194}, // deluxe washer + {01229, 0227}, // bathroom sink + {01232, 0793}, // water cooler + {01234, 0273}, // portable toilet + {01235, 1787}, // bathroom stall + {01241, 0253}, // DIY workbench + {01243, 0810}, // flashy-flower sign + {01263, 0325}, // pear wardrobe + {01288, 0072}, // fan palm + {01308, 0274}, // school chair + {01314, 1047}, // handwashing area + {01319, 0240}, // microscope + {01328, 0275}, // school desk + {01330, 0608}, // basic teacher's desk + {01348, 0174}, // hamster cage + {01411, 0223}, // globe + {01412, 0807}, // TV camera + {01432, 0124}, // lantern + {01434, 0263}, // sleeping bag + {01449, 0747}, // cello + {01493, 0315}, // stroller + {01495, 0268}, // dolly + {01499, 0285}, // Papa bear + {01500, 0287}, // Mama bear + {01501, 0286}, // Baby bear + {01504, 0869}, // giant teddy bear + {01507, 0575}, // plaza teacup ride + {01509, 0574}, // robot hero + {01557, 0084}, // wooden-block bed + {01558, 0105}, // wooden-block bookshelf + {01559, 0106}, // wooden-block bench + {01561, 0107}, // wooden-block chest + {01565, 0108}, // wooden-block table + {01567, 0090}, // oil barrel + {01573, 0219}, // dharma + {01598, 0175}, // exercise ball + {01606, 0490}, // serving cart + {01608, 0081}, // vertical banner + {01620, 0180}, // hammock + {01621, 0185}, // lawn chair + {01624, 0189}, // garden gnome + {01625, 0305}, // iron garden bench + {01626, 0303}, // iron garden chair + {01627, 0304}, // iron garden table + {01628, 0269}, // garden lantern + {01631, 0314}, // garden faucet + {01632, 0250}, // golf bag + {01644, 0096}, // rock guitar + {01645, 0682}, // electric guitar + {01652, 0381}, // matryoshka + {01708, 0218}, // cassette player + {01712, 0144}, // poster stand + {01716, 0198}, // display stand + {01744, 0544}, // wall clock + {01745, 0247}, // copy machine + {01750, 0710}, // document stack + {01753, 0311}, // aroma pot + {01757, 0193}, // claw-foot tub + {01759, 0357}, // stack of books + {01778, 0130}, // clothesline pole + {01779, 0342}, // table with cloth + {01783, 0249}, // corkboard + {01792, 0284}, // cushion + {01797, 0202}, // decoy duck + {01799, 0313}, // doghouse + {01802, 0259}, // drink machine + {01803, 0089}, // drum set + {01804, 0724}, // electric bass + {01816, 0731}, // changing room + {01820, 1031}, // stack of clothes + {01823, 0248}, // trash bags + {01829, 0494}, // cypress plant + {01836, 0272}, // humidifier + {01838, 0501}, // ironing set + {01840, 0532}, // whirlpool bath + {01845, 0239}, // simple kettle + {01849, 0246}, // kotatsu + {01850, 0083}, // laptop + {01851, 0087}, // rocket lamp + {01852, 0145}, // box sofa + {01853, 0146}, // box corner sofa + {01861, 0353}, // stacked magazines + {01866, 0167}, // menu chalkboard + {01868, 0266}, // desk mirror + {01870, 0153}, // mug + {01875, 0103}, // grand piano + {01877, 0137}, // piggy bank + {01881, 0149}, // plastic canister + {01888, 0098}, // rice cooker + {01889, 0132}, // ring + {01892, 0230}, // hourglass + {01899, 0257}, // autograph cards + {01906, 0906}, // snare drum + {01913, 0135}, // wooden chair + {01929, 0099}, // toilet + {02010, 0143}, // ball + {02012, 0244}, // chalkboard + {02013, 0406}, // lecture-hall bench + {02014, 0404}, // lecture-hall desk + {02020, 0358}, // director's chair + {02099, 0827}, // shovel + {02319, 0805}, // drinking fountain + {02326, 0599}, // water pump + {02329, 0206}, // tire toy + {02333, 0736}, // solar panel + {02335, 0201}, // lighthouse + {02352, 0875}, // parabolic antenna + {02358, 1299}, // stadium light + {02377, 0826}, // fishing rod + {02379, 0653}, // watering can + {02553, 0196}, // iron frame + {02554, 0138}, // double sofa + {02558, 0109}, // wooden-block chair + {02559, 0867}, // pot + {02560, 0095}, // wooden chest + {02561, 0882}, // floor lamp + {02562, 0864}, // candle + {02575, 0278}, // ranch chair + {02586, 0431}, // natural garden chair + {02587, 0075}, // hospital screen + {02596, 0625}, // juicy-apple TV + {02605, 0076}, // wooden simple bed + {02606, 1514}, // ranch bed + {02614, 0151}, // mountain bike + {02713, 0121}, // refrigerator + {02731, 0078}, // digital alarm clock + {02736, 0123}, // retro fan + {02740, 0115}, // automatic washer + {02770, 0222}, // chessboard + {02771, 0155}, // round space heater + {02772, 0604}, // fancy violin + {02776, 0220}, // tankless toilet + {02822, 0856}, // slingshot + {03063, 1819}, // theremin + {03064, 0282}, // cooler box + {03078, 0097}, // tourist telescope + {03122, 0161}, // mini DIY workbench + {03191, 0298}, // ironwood table + {03193, 0296}, // ironwood chair + {03194, 0301}, // ironwood low table + {03195, 0302}, // ironwood cart + {03196, 0297}, // ironwood dresser + {03200, 0299}, // ironwood bed + {03205, 0111}, // wooden-block stereo + {03206, 0112}, // wooden-block toy + {03208, 0113}, // wooden-block wall clock + {03229, 0131}, // clothesline + {03230, 0139}, // futon + {03251, 0629}, // gas range + {03252, 0101}, // LCD TV (50 in.) + {03270, 0293}, // ironwood kitchenette + {03271, 0292}, // ironwood cupboard + {03275, 0294}, // ironwood clock + {03282, 0147}, // pop-up toaster + {03305, 0154}, // baby chair + {03307, 0205}, // digital scale + {03333, 0100}, // LCD TV (20 in.) + {03340, 0256}, // deer decoration + {03345, 0851}, // lifeguard chair + {03346, 0173}, // public bench + {03348, 0186}, // plastic pool + {03396, 0441}, // natural garden table + {03400, 0610}, // dish-drying rack + {03402, 1789}, // vertical-board fence + {03406, 0524}, // beekeeper's hive + {03407, 0192}, // katana + {03416, 0204}, // soft-serve lamp + {03428, 0104}, // wall-mounted TV (50 in.) + {03430, 0605}, // playground gym + {03431, 0403}, // wall fan + {03436, 0168}, // wooden wardrobe + {03438, 0169}, // wooden end table + {03439, 0128}, // wooden table + {03442, 0252}, // sturdy sewing box + {03443, 0203}, // sewing project + {03444, 0234}, // wheelchair + {03445, 0271}, // standard umbrella stand + {03446, 0126}, // western-style stone + {03449, 0134}, // wooden stool + {03465, 1817}, // projection screen + {03467, 0226}, // tea set + {03468, 0181}, // beach towel + {03471, 0609}, // light switch + {03490, 0114}, // wooden waste bin + {03497, 0347}, // frozen table + {03498, 0346}, // frozen partition + {03499, 0343}, // frozen arch + {03500, 0345}, // frozen pillar + {03501, 0352}, // frozen sculpture + {03502, 0344}, // frozen bed + {03503, 0351}, // frozen chair + {03504, 0348}, // frozen tree + {03505, 0350}, // frozen counter + {03509, 0300}, // garden bench + {03551, 0211}, // bamboo shelf + {03553, 0213}, // bamboo partition + {03554, 0209}, // bamboo candleholder + {03556, 0210}, // bamboo stopblock + {03557, 0215}, // bamboo floor lamp + {03558, 0208}, // bamboo wall decoration + {03559, 0291}, // iron wall lamp + {03560, 0308}, // iron worktable + {03561, 0307}, // iron hanger stand + {03562, 0290}, // iron wall rack + {03563, 0306}, // iron shelf + {03581, 0188}, // fish-drying rack + {03582, 0150}, // book + {03583, 0207}, // fishing-boat flag + {03584, 0270}, // study poster + {03586, 0254}, // magazine + {03587, 0362}, // fishing-rod stand + {03588, 0160}, // signpost + {03590, 0195}, // desktop computer + {03591, 0363}, // birthday candles + {03592, 0364}, // birthday cake + {03593, 0365}, // birthday table + {03594, 0366}, // birthday sign + {03595, 0241}, // park clock + {03596, 0367}, // pool + {03616, 0318}, // system kitchen + {03617, 0324}, // stall + {03618, 0321}, // cutting board + {03619, 0529}, // soup kettle + {03621, 0323}, // loft bed with desk + {03622, 0322}, // floor seat + {03623, 0320}, // toy box + {03624, 0398}, // cute bed + {03658, 0326}, // bamboo basket + {03672, 0327}, // cardboard box + {03675, 0329}, // hay bed + {03681, 0397}, // piano bench + {03683, 0400}, // plain sink + {03692, 0356}, // plain wooden shop sign + {03697, 0334}, // portable radio + {03699, 0335}, // fish print + {03701, 0337}, // study desk + {03702, 0336}, // study chair + {03773, 0375}, // terrarium + {03775, 0376}, // hanging terrarium + {03776, 0377}, // brick well + {03783, 0380}, // den desk + {03784, 0379}, // den chair + {03785, 0378}, // potted ivy + {03805, 0389}, // mush parasol + {03806, 0387}, // mush partition + {03808, 0385}, // mush log + {03816, 0391}, // streetlamp + {03818, 0392}, // pennant + {03819, 0393}, // oil-barrel bathtub + {03820, 0394}, // fan + {03821, 0395}, // air circulator + {03822, 0405}, // pro tape recorder + {03943, 0432}, // ironwood DIY workbench + {03946, 0433}, // outdoor table + {03947, 0434}, // outdoor bench + {03948, 0446}, // accessories stand + {03949, 0493}, // anthurium plant + {03950, 0478}, // antique chair + {03951, 0479}, // antique console table + {03952, 0480}, // antique table + {03953, 0481}, // antique phone + {03954, 0482}, // antique clock + {03955, 0483}, // antique vanity + {03956, 0484}, // antique bureau + {03957, 0485}, // antique bed + {03958, 0486}, // antique mini table + {03959, 0487}, // antique wardrobe + {03960, 0492}, // handy water cooler + {03961, 0455}, // fortune-telling set + {03962, 0472}, // inflatable sofa + {03965, 0444}, // painting set + {03966, 0452}, // big festive tree + {03967, 0461}, // broom and dustpan + {03970, 0564}, // imperial decorative shelves + {03971, 0565}, // imperial partition + {03972, 0566}, // imperial chest + {03973, 0567}, // imperial bed + {03974, 0568}, // imperial low table + {03975, 0618}, // orange end table + {03976, 0617}, // orange wall-mounted clock + {03977, 0577}, // shell arch + {03978, 0578}, // shell partition + {03979, 0579}, // shell stool + {03980, 0580}, // shell table + {03982, 0582}, // shell fountain + {03983, 0583}, // shell bed + {03984, 0584}, // shell lamp + {03986, 0602}, // wall-mounted TV (20 in.) + {03987, 0435}, // wall-mounted phone + {03991, 0451}, // festive tree + {03992, 0460}, // key holder + {03993, 0454}, // analog kitchen scale + {03995, 0422}, // cute DIY table + {03996, 0423}, // cute wall-mounted clock + {03997, 0424}, // cute wardrobe + {03998, 0425}, // cute sofa + {03999, 0426}, // cute chair + {04000, 0427}, // cute tea table + {04001, 0428}, // cute vanity + {04002, 0429}, // cute floor lamp + {04003, 0430}, // cute music player + {04006, 0457}, // climbing wall + {04009, 0436}, // cordless phone + {04011, 0619}, // cherry speakers + {04012, 0620}, // cherry lamp + {04013, 0467}, // punching bag + {04014, 0465}, // folding floor lamp + {04015, 0613}, // shower booth + {04017, 0512}, // shower set + {04019, 0558}, // stand mixer + {04023, 0525}, // pants press + {04025, 0448}, // unglazed dish set + {04027, 0440}, // floral swag + {04029, 0489}, // rotary phone + {04030, 0445}, // bathroom towel rack + {04033, 0627}, // traditional tea set + {04034, 0442}, // scattered papers + {04035, 0546}, // log garden lounge + {04036, 0547}, // log decorative shelves + {04037, 0548}, // log wall-mounted clock + {04038, 0549}, // log stool + {04039, 0550}, // log chair + {04040, 0551}, // log dining table + {04041, 0552}, // log bed + {04042, 0553}, // log bench + {04043, 0554}, // log round table + {04044, 0555}, // log extra-long sofa + {04045, 0503}, // rattan waste bin + {04046, 0505}, // rattan end table + {04047, 0506}, // rattan stool + {04048, 0508}, // rattan towel basket + {04049, 0504}, // rattan wardrobe + {04050, 0509}, // rattan table lamp + {04051, 0510}, // rattan vanity + {04052, 0470}, // rattan bed + {04053, 0507}, // rattan armchair + {04054, 0511}, // rattan low table + {04066, 0415}, // illuminated tree + {04067, 0453}, // tabletop festive tree + {04068, 0420}, // table setting + {04069, 0585}, // table lamp + {04070, 0626}, // street organ + {04071, 0616}, // electronics kit + {04072, 0603}, // toilet-cleaning set + {04073, 0475}, // classic pitcher + {04074, 0416}, // illuminated reindeer + {04075, 0469}, // gong + {04076, 0462}, // nail-art set + {04077, 0596}, // party garland + {04078, 0500}, // barbell + {04080, 0499}, // long bathtub + {04081, 0468}, // camping cot + {04083, 1155}, // spooky arch + {04084, 1156}, // spooky scarecrow + {04086, 1157}, // spooky tower + {04087, 1190}, // spooky carriage + {04088, 1191}, // spooky lantern + {04089, 1192}, // spooky chair + {04090, 1193}, // spooky table + {04092, 1194}, // spooky lantern set + {04093, 0612}, // bamboo drum + {04094, 0474}, // floating-biotope planter + {04099, 0419}, // formal paper + {04101, 0437}, // fax machine + {04102, 0576}, // poolside bed + {04104, 0513}, // frying pan + {04108, 0417}, // illuminated present + {04109, 0561}, // double-door refrigerator + {04110, 0556}, // essay set + {04111, 0488}, // old-fashioned alarm clock + {04113, 0471}, // hose reel + {04114, 0562}, // tissue box + {04116, 0414}, // whiteboard + {04118, 0655}, // magnetic knife rack + {04119, 0458}, // macrame tapestry + {04122, 0601}, // cartoonist's set + {04124, 0644}, // wooden fish + {04125, 0531}, // wooden bookshelf + {04127, 0622}, // peach chair + {04128, 0623}, // peach surprise box + {04129, 0497}, // monstera + {04131, 0418}, // illuminated snowflakes + {04132, 0498}, // yucca + {04133, 0545}, // double-sided wall clock + {04134, 0624}, // apple chair + {04135, 0443}, // freezer + {04137, 0515}, // diner chair + {04138, 0516}, // diner counter chair + {04139, 0517}, // diner counter table + {04140, 0518}, // retro gas pump + {04141, 0519}, // diner sofa + {04142, 0520}, // diner dining table + {04143, 0521}, // diner neon sign + {04144, 0522}, // diner neon clock + {04196, 1249}, // crosswalk signal + {04226, 0630}, // basketball hoop + {04230, 0421}, // glass holder with candle + {04279, 0438}, // frozen-treat set + {04308, 0611}, // unfinished puzzle + {04309, 0708}, // destinations signpost + {04338, 0466}, // portable record player + {04357, 1795}, // iron fence + {04377, 0850}, // ornament wreath + {04379, 0477}, // springy ride-on + {04392, 0491}, // magic kit + {04412, 0502}, // cotton-candy stall + {04441, 0523}, // diner mini table + {04445, 0528}, // vintage TV tray + {04546, 0530}, // pear bed + {04572, 0543}, // shaded floor lamp + {04687, 0563}, // toolbox + {04708, 0569}, // mush low stool + {04719, 0571}, // celebratory candles + {04722, 0573}, // monster statue + {04738, 0845}, // skull doorplate + {04751, 0842}, // bone doorplate + {04752, 0849}, // iron doorplate + {04753, 0593}, // throwback wrestling figure + {04754, 0586}, // throwback gothic mirror + {04756, 0589}, // throwback wall clock + {04757, 0588}, // throwback skull radio + {04758, 0591}, // throwback mitt chair + {04759, 0587}, // throwback race-car bed + {04760, 0594}, // throwback hat table + {04761, 0595}, // throwback rocket + {04762, 0592}, // throwback container + {04764, 0848}, // fish doorplate + {05150, 0598}, // shell speaker + {05165, 0600}, // wall-mounted candle + {05207, 1796}, // zen fence + {05208, 1759}, // large lattice fence + {05309, 0843}, // heart doorplate + {05310, 0841}, // spider doorplate + {05337, 0606}, // three-tiered snowperson + {05338, 0607}, // simple panel + {05397, 0784}, // + {05543, 0628}, // wooden-block stool + {05635, 0643}, // tiny library + {05636, 0642}, // wooden-plank sign + {05716, 0844}, // paw-print doorplate + {05717, 0846}, // crest doorplate + {05718, 0840}, // timber doorplate + {05719, 0847}, // fossil doorplate + {05784, 0825}, // net + {05931, 0647}, // jail bars + {05972, 0791}, // wild log bench + {05973, 0790}, // log stakes + {05976, 0648}, // bamboo sphere + {05978, 0650}, // bamboo lunch box + {06075, 0700}, // tree's bounty mobile + {06078, 0701}, // tree's bounty lamp + {06079, 0698}, // tree's bounty little tree + {06080, 0697}, // tree's bounty big tree + {06081, 0699}, // tree's bounty arch + {06426, 0652}, // Cyrano's photo + {06427, 0652}, // Curt's photo + {06428, 0652}, // Zell's photo + {06429, 0652}, // Bruce's photo + {06430, 0652}, // Deirdre's photo + {06431, 0652}, // Lopez's photo + {06432, 0652}, // Fuchsia's photo + {06433, 0652}, // Beau's photo + {06434, 0652}, // Diana's photo + {06435, 0652}, // Erik's photo + {06436, 0652}, // Goldie's photo + {06437, 0652}, // Butch's photo + {06438, 0652}, // Chow's photo + {06439, 0652}, // Lucky's photo + {06440, 0652}, // Biskit's photo + {06441, 0652}, // Bones's photo + {06442, 0652}, // Portia's photo + {06443, 0652}, // Walker's photo + {06444, 0652}, // Daisy's photo + {06445, 0652}, // Cookie's photo + {06446, 0652}, // Maddie's photo + {06447, 0652}, // Bea's photo + {06448, 0652}, // Mac's photo + {06449, 0652}, // Nate's photo + {06450, 0652}, // Marcel's photo + {06451, 0652}, // Benjamin's photo + {06452, 0652}, // Cherry's photo + {06453, 0652}, // Shep's photo + {06454, 0652}, // Bill's photo + {06455, 0652}, // Joey's photo + {06456, 0652}, // Pate's photo + {06457, 0652}, // Maelle's photo + {06458, 0652}, // Deena's photo + {06459, 0652}, // Pompom's photo + {06460, 0652}, // Groucho's photo + {06461, 0652}, // Mallary's photo + {06462, 0652}, // Freckles's photo + {06463, 0652}, // Derwin's photo + {06464, 0652}, // Drake's photo + {06465, 0652}, // Scoot's photo + {06466, 0652}, // Weber's photo + {06467, 0652}, // Miranda's photo + {06468, 0652}, // Ketchup's photo + {06469, 0652}, // Gloria's photo + {06470, 0652}, // Molly's photo + {06471, 0652}, // Tutu's photo + {06472, 0652}, // Quillson's photo + {06473, 0652}, // Opal's photo + {06474, 0652}, // Dizzy's photo + {06475, 0652}, // Big Top's photo + {06476, 0652}, // Eloise's photo + {06477, 0652}, // Margie's photo + {06478, 0652}, // Paolo's photo + {06479, 0652}, // Axel's photo + {06480, 0652}, // Ellie's photo + {06481, 0652}, // Tucker's photo + {06482, 0652}, // Ursala's photo + {06483, 0652}, // Tia's photo + {06484, 0652}, // Lily's photo + {06485, 0652}, // Ribbot's photo + {06486, 0652}, // Frobert's photo + {06487, 0652}, // Camofrog's photo + {06488, 0652}, // Drift's photo + {06489, 0652}, // Wart Jr.'s photo + {06490, 0652}, // Puddles's photo + {06491, 0652}, // Jeremiah's photo + {06492, 0652}, // Tad's photo + {06493, 0652}, // Grizzly's photo + {06494, 0652}, // Cousteau's photo + {06495, 0652}, // Huck's photo + {06496, 0652}, // Prince's photo + {06497, 0652}, // Jambette's photo + {06498, 0652}, // Raddle's photo + {06499, 0652}, // Gigi's photo + {06500, 0652}, // Croque's photo + {06501, 0652}, // Diva's photo + {06502, 0652}, // Henry's photo + {06503, 0652}, // Chevre's photo + {06504, 0652}, // Paula's photo + {06505, 0652}, // Nan's photo + {06506, 0652}, // Billy's photo + {06507, 0652}, // Gruff's photo + {06508, 0652}, // Velma's photo + {06509, 0652}, // Kidd's photo + {06510, 0652}, // Pashmina's photo + {06511, 0652}, // Cesar's photo + {06512, 0652}, // Peewee's photo + {06513, 0652}, // Boone's photo + {06514, 0652}, // Louie's photo + {06515, 0652}, // Ike's photo + {06516, 0652}, // Boyd's photo + {06517, 0652}, // Violet's photo + {06518, 0652}, // Al's photo + {06519, 0652}, // Rocket's photo + {06520, 0652}, // Hans's photo + {06521, 0652}, // Hamlet's photo + {06522, 0652}, // Apple's photo + {06523, 0652}, // Graham's photo + {06524, 0652}, // Rodney's photo + {06525, 0652}, // Soleil's photo + {06526, 0652}, // Charlise's photo + {06527, 0652}, // Clay's photo + {06528, 0652}, // Flurry's photo + {06529, 0652}, // Hamphrey's photo + {06530, 0652}, // Rocco's photo + {06531, 0652}, // Bubbles's photo + {06532, 0652}, // Bertha's photo + {06533, 0652}, // Biff's photo + {06534, 0652}, // Bitty's photo + {06535, 0652}, // Harry's photo + {06536, 0652}, // Hippeux's photo + {06537, 0652}, // Antonio's photo + {06538, 0652}, // Beardo's photo + {06539, 0652}, // Buck's photo + {06540, 0652}, // Victoria's photo + {06541, 0652}, // Savannah's photo + {06542, 0652}, // Elmer's photo + {06543, 0652}, // Roscoe's photo + {06544, 0652}, // Winnie's photo + {06545, 0652}, // Ed's photo + {06546, 0652}, // Cleo's photo + {06547, 0652}, // Peaches's photo + {06548, 0652}, // Annalise's photo + {06549, 0652}, // Klaus's photo + {06550, 0652}, // Clyde's photo + {06551, 0652}, // Colton's photo + {06552, 0652}, // Papi's photo + {06553, 0652}, // Julian's photo + {06554, 0652}, // Yuka's photo + {06555, 0652}, // Alice's photo + {06556, 0652}, // Melba's photo + {06557, 0652}, // Sydney's photo + {06558, 0652}, // Gonzo's photo + {06559, 0652}, // Ozzie's photo + {06560, 0652}, // Jay's photo + {06561, 0652}, // Canberra's photo + {06562, 0652}, // Lyman's photo + {06563, 0652}, // Eugene's photo + {06564, 0652}, // Kitt's photo + {06565, 0652}, // Mathilda's photo + {06566, 0652}, // Carrie's photo + {06567, 0652}, // Astrid's photo + {06568, 0652}, // Sylvia's photo + {06569, 0652}, // Walt's photo + {06570, 0652}, // Rooney's photo + {06571, 0652}, // Robin's photo + {06572, 0652}, // Marcie's photo + {06573, 0652}, // Bud's photo + {06574, 0652}, // Elvis's photo + {06575, 0652}, // Rex's photo + {06576, 0652}, // Leopold's photo + {06577, 0652}, // Mott's photo + {06578, 0652}, // Rory's photo + {06579, 0652}, // Lionel's photo + {06580, 0652}, // Nana's photo + {06581, 0652}, // Simon's photo + {06582, 0652}, // Anchovy's photo + {06583, 0652}, // Tammi's photo + {06584, 0652}, // Monty's photo + {06585, 0652}, // Elise's photo + {06586, 0652}, // Flip's photo + {06587, 0652}, // Shari's photo + {06588, 0652}, // Deli's photo + {06589, 0652}, // Dora's photo + {06590, 0652}, // Limberg's photo + {06591, 0652}, // Bella's photo + {06592, 0652}, // Bree's photo + {06593, 0652}, // Twiggy's photo + {06594, 0652}, // Samson's photo + {06595, 0652}, // Rod's photo + {06596, 0652}, // Candi's photo + {06597, 0652}, // Rizzo's photo + {06598, 0652}, // Anicotti's photo + {06599, 0652}, // Broccolo's photo + {06600, 0652}, // Moose's photo + {06601, 0652}, // Bettina's photo + {06602, 0652}, // Greta's photo + {06603, 0652}, // Penelope's photo + {06604, 0652}, // Jitters's photo + {06605, 0652}, // Chadder's photo + {06606, 0652}, // Octavian's photo + {06607, 0652}, // Marina's photo + {06608, 0652}, // Zucker's photo + {06609, 0652}, // Queenie's photo + {06610, 0652}, // Gladys's photo + {06611, 0652}, // Sandy's photo + {06612, 0652}, // Sprocket's photo + {06613, 0652}, // Julia's photo + {06614, 0652}, // Cranston's photo + {06615, 0652}, // Piper's photo + {06616, 0652}, // Phil's photo + {06617, 0652}, // Blanche's photo + {06618, 0652}, // Flora's photo + {06619, 0652}, // Phoebe's photo + {06620, 0652}, // Apollo's photo + {06621, 0652}, // Amelia's photo + {06622, 0652}, // Pierce's photo + {06623, 0652}, // Buzz's photo + {06624, 0652}, // Avery's photo + {06625, 0652}, // Frank's photo + {06626, 0652}, // Admiral's photo + {06627, 0652}, // Sterling's photo + {06628, 0652}, // Keaton's photo + {06629, 0652}, // Celia's photo + {06630, 0652}, // Aurora's photo + {06631, 0652}, // Roald's photo + {06632, 0652}, // Cube's photo + {06633, 0652}, // Hopper's photo + {06634, 0652}, // Friga's photo + {06635, 0652}, // Gwen's photo + {06636, 0652}, // Puck's photo + {06637, 0652}, // Midge's photo + {06638, 0652}, // Wade's photo + {06639, 0652}, // Boomer's photo + {06640, 0652}, // Iggly's photo + {06641, 0652}, // Tex's photo + {06642, 0652}, // Flo's photo + {06643, 0652}, // Sprinkle's photo + {06644, 0652}, // Curly's photo + {06645, 0652}, // Truffles's photo + {06646, 0652}, // Rasher's photo + {06647, 0652}, // Hugh's photo + {06648, 0652}, // Pango's photo + {06649, 0652}, // Jacob's photo + {06650, 0652}, // Lucy's photo + {06651, 0652}, // Spork's photo + {06652, 0652}, // Cobb's photo + {06653, 0652}, // Boris's photo + {06654, 0652}, // Maggie's photo + {06655, 0652}, // Peggy's photo + {06656, 0652}, // Gala's photo + {06657, 0652}, // Chops's photo + {06658, 0652}, // Kevin's photo + {06659, 0652}, // Pancetti's photo + {06660, 0652}, // Lucha's photo + {06661, 0652}, // Agnes's photo + {06662, 0652}, // Bunnie's photo + {06663, 0652}, // Dotty's photo + {06664, 0652}, // Coco's photo + {06665, 0652}, // Snake's photo + {06666, 0652}, // Gaston's photo + {06667, 0652}, // Gabi's photo + {06668, 0652}, // Pippy's photo + {06669, 0652}, // Tiffany's photo + {06670, 0652}, // Genji's photo + {06671, 0652}, // Jacques's photo + {06672, 0652}, // Ruby's photo + {06673, 0652}, // Doc's photo + {06674, 0652}, // Claude's photo + {06675, 0652}, // Francine's photo + {06676, 0652}, // Chrissy's photo + {06677, 0652}, // Hopkins's photo + {06678, 0652}, // O'Hare's photo + {06679, 0652}, // Carmen's photo + {06680, 0652}, // Bonbon's photo + {06681, 0652}, // Cole's photo + {06682, 0652}, // Peck's photo + {06683, 0652}, // Mira's photo + {06684, 0652}, // Tank's photo + {06685, 0652}, // Rhonda's photo + {06686, 0652}, // Spike's photo + {06687, 0652}, // Hornsby's photo + {06688, 0652}, // Merengue's photo + {06689, 0652}, // Renée's photo + {06690, 0652}, // Vesta's photo + {06691, 0652}, // Baabara's photo + {06692, 0652}, // Eunice's photo + {06693, 0652}, // Sparro's photo + {06694, 0652}, // Stella's photo + {06695, 0652}, // Cashmere's photo + {06696, 0652}, // Willow's photo + {06697, 0652}, // Curlos's photo + {06698, 0652}, // Wendy's photo + {06699, 0652}, // Timbra's photo + {06700, 0652}, // Frita's photo + {06701, 0652}, // Muffy's photo + {06702, 0652}, // Pietro's photo + {06703, 0652}, // Peanut's photo + {06704, 0652}, // Angus's photo + {06705, 0652}, // Blaire's photo + {06706, 0652}, // Filbert's photo + {06707, 0652}, // Pecan's photo + {06708, 0652}, // Nibbles's photo + {06709, 0652}, // Agent S's photo + {06710, 0652}, // Caroline's photo + {06711, 0652}, // Sally's photo + {06712, 0652}, // Static's photo + {06713, 0652}, // Mint's photo + {06714, 0652}, // Ricky's photo + {06715, 0652}, // Rodeo's photo + {06716, 0652}, // Cally's photo + {06717, 0652}, // Tasha's photo + {06718, 0652}, // Sylvana's photo + {06719, 0652}, // Poppy's photo + {06720, 0652}, // Sheldon's photo + {06721, 0652}, // Marshal's photo + {06722, 0652}, // Hazel's photo + {06723, 0652}, // Rolf's photo + {06724, 0652}, // Rowan's photo + {06725, 0652}, // Tybalt's photo + {06726, 0652}, // Stu's photo + {06727, 0652}, // Bangle's photo + {06728, 0652}, // Leonardo's photo + {06729, 0652}, // Claudia's photo + {06730, 0652}, // Bianca's photo + {06731, 0652}, // Chief's photo + {06732, 0652}, // Lobo's photo + {06733, 0652}, // Wolfgang's photo + {06734, 0652}, // Whitney's photo + {06735, 0652}, // Dobie's photo + {06736, 0652}, // Freya's photo + {06737, 0652}, // T-Bone's photo + {06738, 0652}, // Fang's photo + {06739, 0652}, // Vivian's photo + {06740, 0652}, // Skye's photo + {06741, 0652}, // Kyle's photo + {06742, 0652}, // Coach's photo + {06743, 0652}, // Anabelle's photo + {06744, 0652}, // Vic's photo + {06745, 0652}, // Bob's photo + {06746, 0652}, // Mitzi's photo + {06747, 0652}, // Rosie's photo + {06748, 0652}, // Olivia's photo + {06749, 0652}, // Kiki's photo + {06750, 0652}, // Tangy's photo + {06751, 0652}, // Punchy's photo + {06752, 0652}, // Purrl's photo + {06753, 0652}, // Moe's photo + {06754, 0652}, // Snooty's photo + {06755, 0652}, // Kabuki's photo + {06756, 0652}, // Kid Cat's photo + {06757, 0652}, // Monique's photo + {06758, 0652}, // Tabby's photo + {06759, 0652}, // Stinky's photo + {06760, 0652}, // Kitty's photo + {06761, 0652}, // Tom's photo + {06762, 0652}, // Merry's photo + {06763, 0652}, // Felicity's photo + {06764, 0652}, // Lolly's photo + {06765, 0652}, // Annalisa's photo + {06766, 0652}, // Ankha's photo + {06767, 0652}, // Rudy's photo + {06768, 0652}, // Katt's photo + {06769, 0652}, // Bluebear's photo + {06770, 0652}, // Maple's photo + {06771, 0652}, // Poncho's photo + {06772, 0652}, // Pudge's photo + {06773, 0652}, // Kody's photo + {06774, 0652}, // Stitches's photo + {06775, 0652}, // Vladimir's photo + {06776, 0652}, // Olaf's photo + {06777, 0652}, // Murphy's photo + {06778, 0652}, // Olive's photo + {06779, 0652}, // Cheri's photo + {06780, 0652}, // June's photo + {06781, 0652}, // Pekoe's photo + {06782, 0652}, // Chester's photo + {06783, 0652}, // Barold's photo + {06784, 0652}, // Tammy's photo + {06785, 0652}, // Goose's photo + {06786, 0652}, // Benedict's photo + {06787, 0652}, // Teddy's photo + {06788, 0652}, // Egbert's photo + {06789, 0652}, // Ava's photo + {06790, 0652}, // Becky's photo + {06791, 0652}, // Plucky's photo + {06792, 0652}, // Knox's photo + {06793, 0652}, // Broffina's photo + {06794, 0652}, // Ken's photo + {06795, 0652}, // Patty's photo + {06796, 0652}, // Tipper's photo + {06797, 0652}, // Norma's photo + {06798, 0652}, // Pinky's photo + {06799, 0652}, // Naomi's photo + {06800, 0652}, // Alfonso's photo + {06801, 0652}, // Alli's photo + {06802, 0652}, // Boots's photo + {06803, 0652}, // Del's photo + {06804, 0652}, // Sly's photo + {06805, 0652}, // Gayle's photo + {06806, 0652}, // Drago's photo + {06807, 0652}, // Fauna's photo + {06808, 0652}, // Bam's photo + {06818, 0800}, // ornament mobile + {06826, 0654}, // nova light + {06827, 0725}, // starry garland + {06829, 0757}, // crescent-moon chair + {06830, 1743}, // shell music box + {06831, 0657}, // blossom-viewing lantern + {06832, 0656}, // cherry-blossom clock + {06992, 0652}, // Reneigh's photo + {06993, 0652}, // Judy's photo + {06994, 0652}, // Audie's photo + {06995, 0652}, // Megan's photo + {06996, 0652}, // Raymond's photo + {06997, 0652}, // Cyd's photo + {07045, 0748}, // recycled-can thumb piano + {07047, 0659}, // zen cushion + {07048, 0658}, // pile of zen cushions + {07132, 0664}, // wooden double bed + {07133, 0661}, // wooden mini table + {07134, 0662}, // wooden low table + {07135, 0674}, // floor light + {07136, 0675}, // cat grass + {07137, 0663}, // wooden full-length mirror + {07138, 0666}, // Mom's tea cozy + {07139, 0673}, // Mom's art + {07140, 0665}, // Mom's tissue box + {07141, 0667}, // Mom's pen stand + {07143, 0671}, // Mom's candle set + {07144, 0670}, // Mom's cushion + {07145, 0668}, // Mom's embroidery + {07146, 0672}, // Mom's homemade cake + {07147, 0669}, // Mom's plushie + {07148, 0676}, // life ring + {07150, 0750}, // blue corner + {07151, 0876}, // red corner + {07152, 0877}, // neutral corner + {07153, 0744}, // cypress bathtub + {07154, 0678}, // wooden box + {07159, 0813}, // cardboard sofa + {07160, 0814}, // cardboard table + {07161, 0815}, // cardboard bed + {07163, 0816}, // cardboard chair + {07189, 0680}, // studio spotlight + {07190, 0681}, // studio wall spotlight + {07212, 0652}, // Sherb's photo + {07213, 0652}, // Dom's photo + {07229, 0684}, // handcart + {07230, 0692}, // cosmos shower + {07231, 0691}, // tulip surprise box + {07232, 0690}, // mum cushion + {07233, 0689}, // windflower fan + {07234, 0688}, // hyacinth lamp + {07235, 0687}, // rose bed + {07236, 0686}, // lily record player + {07237, 0685}, // pansy table + {07238, 0735}, // anchor statue + {07247, 0694}, // silo + {07253, 0696}, // star clock + {07257, 0702}, // pedal board + {07258, 0703}, // modeling clay + {07259, 0896}, // palm-tree lamp + {07260, 0705}, // floor sign + {07264, 0707}, // champion's pennant + {07280, 0713}, // gears + {07281, 0714}, // sleigh + {07282, 0715}, // hanging scroll + {07284, 0711}, // nutcracker + {07317, 0717}, // zen-style stone + {07379, 0728}, // wind turbine + {07390, 0782}, // leaf stool + {07391, 0721}, // tatami bed + {07392, 0722}, // candy machine + {07393, 0727}, // pond stone + {07453, 0767}, // aluminum briefcase + {07454, 0766}, // wooden toolbox + {07525, 0773}, // tool shelf + {07526, 0817}, // outdoor generator + {07527, 0808}, // flower stand + {07528, 0809}, // tool cart + {07529, 0799}, // folding chair + {07531, 0745}, // ironing board + {07535, 0746}, // kettlebell + {07588, 0885}, // mushroom wand + {07599, 0752}, // board game + {07653, 0755}, // speed bag + {07654, 0756}, // electric kick scooter + {07681, 0762}, // loom + {07682, 0763}, // kimono stand + {07788, 0819}, // leaf campfire + {07789, 0811}, // drying rack + {07795, 0838}, // stone lion-dog + {07796, 0774}, // imperial dining table + {07797, 0775}, // imperial dining chair + {07800, 0777}, // protein shaker bottle + {07801, 0778}, // pet food bowl + {07802, 0779}, // pet bed + {07803, 0776}, // kitty litter box + {07804, 0780}, // knife block + {07805, 0873}, // butter churn + {07845, 0785}, // pull-up-bar stand + {07865, 0787}, // elaborate kimono stand + {07867, 0789}, // angled signpost + {07868, 0824}, // surfboard + {08031, 0874}, // fountain + {08096, 0812}, // record box + {08176, 0829}, // star net + {08177, 0828}, // colorful net + {08178, 0801}, // outdoorsy net + {08297, 0837}, // stovetop espresso maker + {08298, 0804}, // bunk bed + {08415, 0830}, // imperial dining lantern + {08417, 0823}, // wall-mounted tool board + {08418, 0822}, // fragrance diffuser + {08419, 0821}, // garden wagon + {08471, 0836}, // fish fishing rod + {08472, 0835}, // colorful fishing rod + {08473, 0833}, // outdoorsy fishing rod + {08534, 0860}, // colorful watering can + {08535, 0878}, // elephant watering can + {08536, 0861}, // outdoorsy watering can + {08575, 0863}, // outdoorsy shovel + {08576, 0870}, // printed-design shovel + {08577, 0862}, // colorful shovel + {08579, 0857}, // outdoorsy slingshot + {08580, 0858}, // colorful slingshot + {08760, 0831}, // customizable phone case kit + {08826, 0832}, // wooden table mirror + {09502, 0852}, // clothes closet + {09565, 0853}, // mobile + {09568, 0854}, // construction sign + {09584, 0859}, // beach ball + {09619, 0868}, // utility pole + {09642, 0866}, // iron closet + {09766, 0871}, // mini fridge + {09767, 0872}, // garbage bin + {10244, 0880}, // fragrance sticks + {10742, 0883}, // bamboo stool + {10743, 0884}, // bamboo speaker + {11115, 0652}, // Rilla's photo + {11116, 0652}, // Marty's photo + {11117, 0652}, // Étoile's photo + {11118, 0652}, // Chai's photo + {11119, 0652}, // Chelsea's photo + {11120, 0652}, // Toby's photo + {11711, 1797}, // simple wooden fence + {11712, 1798}, // lattice fence + {11941, 0889}, // stone arch + {11942, 0897}, // street piano + {11943, 0890}, // stone tablet + {12140, 0891}, // DAL model plane + {12207, 0895}, // arcade seat + {12305, 1777}, // Casablanca lilies + {12308, 0907}, // reception chair + {12311, 0905}, // cruiser bike + {12312, 0903}, // wood-plank table + {12313, 0902}, // public telephone + {12314, 0904}, // zen lowboard + {12332, 0901}, // natural square table + {12340, 1788}, // volleyball net + {12341, 1778}, // gurney + {12343, 1591}, // stepladder + {12344, 0912}, // baseball set + {12345, 1769}, // metal-and-wood table + {12346, 1770}, // metal-and-wood chair + {12348, 0909}, // froggy chair + {12349, 0910}, // project table + {12350, 0911}, // box-shaped seat + {12356, 0914}, // round pillow + {12358, 0915}, // retro ice-cream case + {12361, 1226}, // zen bench + {12365, 0918}, // garden chair + {12366, 0919}, // plastic bench + {12372, 0921}, // Pocket modern camper + {12373, 0920}, // Pocket vintage camper + {12401, 0923}, // wedding bench + {12402, 0922}, // wedding arch + {12403, 0926}, // wedding cake + {12404, 0932}, // wedding head table + {12405, 0928}, // wedding chair + {12406, 0929}, // wedding table + {12407, 0931}, // wedding decoration + {12408, 0925}, // wedding candle set + {12409, 0930}, // wedding pipe organ + {12410, 0924}, // wedding welcome board + {12411, 0927}, // wedding flower stand + {12516, 0933}, // sampler + {12543, 0934}, // Nintendo Switch + {12582, 0652}, // Zoe's photo + {12583, 0652}, // Rio's photo + {12584, 0652}, // Azalea's photo + {12585, 0652}, // Faith's photo + {12586, 0652}, // Chabwick's photo + {12587, 0652}, // Ace's photo + {12588, 0652}, // Frett's photo + {12589, 0652}, // Roswell's photo + {12590, 0652}, // Ione's photo + {12591, 0652}, // Shino's photo + {12592, 0652}, // Petri's photo + {12593, 0652}, // Quinn's photo + {12594, 0652}, // Sasha's photo + {12595, 0652}, // Cephalobot's photo + {12596, 0652}, // Marlo's photo + {12597, 0652}, // Tiansheng's photo + {12599, 0935}, // office chair + {12600, 1765}, // bulldozer + {12601, 1767}, // cement mixer + {12602, 1768}, // excavator + {12603, 1766}, // steamroller + {12604, 1051}, // jackhammer + {12605, 0947}, // safety barrier + {12606, 0945}, // tractor + {12608, 0941}, // flower display case + {12610, 0942}, // frozen-drink machine + {12611, 1568}, // plate armor + {12612, 0940}, // capsule-toy machine + {12613, 0944}, // fancy tea set + {12614, 0943}, // peacock chair + {12637, 0948}, // examination-room desk + {12653, 0952}, // modern hospital bed + {12669, 0960}, // donut stool + {12670, 0950}, // office cabinet + {12673, 0955}, // tall file cabinet + {12674, 0956}, // short file cabinet + {12675, 0957}, // plant partition + {12676, 0958}, // large magazine rack + {12677, 0959}, // medicine chest + {12678, 0961}, // arched reception counter + {12679, 0962}, // reception counter + {12683, 1807}, // plaza ferris wheel + {12684, 1813}, // plaza merry-go-round + {12685, 1806}, // inflatable plaza toy + {12688, 1812}, // plaza bench + {12689, 1805}, // plaza arch + {12690, 1809}, // plaza game stand + {12691, 1811}, // plaza balloon wagon + {12692, 1810}, // plaza clock + {12693, 1742}, // street lamp with banners + {12699, 0964}, // standing electric sign + {12700, 0998}, // sturdy office desk + {12701, 1011}, // school locker + {12702, 0999}, // strapped books + {12703, 1818}, // mop + {12704, 1000}, // basic school chair + {12705, 1001}, // stewpot + {12706, 1002}, // imperial pot + {12707, 1003}, // cans + {12708, 1004}, // cooking tools + {12709, 1010}, // carp on a cutting board + {12712, 0994}, // salad bar + {12713, 0996}, // antique cash register + {12714, 0995}, // modern cash register + {12715, 0997}, // bulletin board + {12717, 1006}, // left chalkboard section + {12718, 1007}, // right chalkboard section + {12720, 1009}, // fancy water pitcher + {12741, 1012}, // world map + {12744, 1016}, // small covered round table + {12745, 1015}, // large covered round table + {12766, 1017}, // small café table + {12767, 1018}, // large café table + {12768, 1019}, // checkout counter + {12769, 1020}, // dessert case + {12772, 1021}, // ice-cream display + {12773, 1022}, // counter chair + {12774, 1023}, // busing station + {12775, 1024}, // afternoon-tea set + {12776, 1025}, // counter table + {12777, 1026}, // covered counter + {12778, 1027}, // touchscreen cash register + {12779, 1028}, // wood partition + {12780, 1029}, // wall shelf with bottles + {12781, 1816}, // sample case + {12782, 1030}, // bistro table + {12803, 1808}, // plaza train + {12879, 1039}, // tabletop POP display + {12880, 1040}, // standing shop sign + {12881, 1046}, // dress mannequin + {12882, 1035}, // small mannequin + {12883, 1042}, // midsized clothing rack + {12884, 1043}, // small clothing rack + {12885, 1036}, // hanging clothing rack + {12886, 1032}, // corner clothing rack + {12887, 1034}, // glass showcase + {12888, 1041}, // hanger rack + {12889, 1045}, // boxy stool + {12890, 1038}, // merchandise table + {12891, 1033}, // full-length mirror + {12892, 1044}, // sturdy paper bag + {12893, 1037}, // stacked shoeboxes + {12894, 1799}, // wedding fence + {12949, 1168}, // spooky standing lamp + {12951, 1195}, // spooky candy set + {12976, 1048}, // mini dharma + {12991, 1065}, // simple stool + {12993, 1062}, // simple vanity + {12994, 1061}, // simple bed + {12995, 1064}, // simple sofa + {12996, 1059}, // simple chair + {12997, 1066}, // simple wall shelf + {12998, 1063}, // simple small dresser + {12999, 1067}, // simple table + {13004, 1069}, // artsy table + {13005, 1068}, // artsy chair + {13006, 1070}, // cool low table + {13007, 1071}, // cool side table + {13008, 1072}, // cool chair + {13009, 1073}, // cool bed + {13010, 1074}, // cool sofa + {13073, 1088}, // Nordic chair + {13075, 1090}, // Nordic sofa + {13076, 1091}, // Nordic low table + {13077, 1092}, // Nordic lowboard + {13078, 1093}, // Nordic shelves + {13079, 1094}, // Nordic table + {13080, 1095}, // ranch wardrobe + {13081, 1096}, // ranch tea table + {13082, 1097}, // ranch lowboard + {13083, 1098}, // Moroccan footrest + {13084, 1099}, // Moroccan tray table + {13085, 1100}, // Moroccan sofa + {13108, 1101}, // upright organizer + {13109, 1102}, // horizontal organizer + {13110, 1103}, // plastic clothing organizer + {13111, 1104}, // Japanese dresser + {13112, 1105}, // zen low table + {13113, 1106}, // shoji divider + {13114, 1107}, // vintage stool + {13115, 1108}, // vintage desk + {13116, 1109}, // vintage sofa + {13117, 1110}, // vintage low table + {13118, 1111}, // vintage dresser + {13119, 1112}, // enamel lamp + {13120, 1113}, // round light fixture + {13121, 1114}, // wood-shade lamp + {13122, 1115}, // zen light + {13138, 1117}, // elegant chair + {13139, 1118}, // elegant bed + {13140, 1119}, // elegant console table + {13141, 1120}, // elegant sofa + {13142, 1121}, // elegant lamp + {13143, 1122}, // elegant dresser + {13144, 1123}, // simple shaded lamp + {13145, 1124}, // stained-glass light + {13146, 1125}, // milk-glass lamp + {13147, 1126}, // fluorescent light + {13148, 1127}, // ceiling spotlight + {13149, 1128}, // Nordic pendant light + {13150, 1129}, // Moroccan lights + {13151, 1130}, // festival lantern + {13152, 1131}, // imperial lamp + {13153, 1132}, // wooden pendant light + {13154, 1133}, // chandelier + {13155, 1134}, // spiral chandelier + {13156, 1135}, // ceiling fan + {13157, 1136}, // dual hanging monitors + {13158, 1137}, // hanging shelves + {13161, 1139}, // wooden field sign + {13163, 1196}, // study carrel + {13164, 1142}, // disco ball + {13185, 1143}, // small vase + {13186, 1144}, // porcelain vase + {13187, 1145}, // fine vase + {13188, 1146}, // ball catcher + {13189, 1147}, // stair dresser + {13190, 1148}, // sword + {13191, 1149}, // bow + {13192, 1150}, // samurai suit + {13201, 1199}, // bath bucket + {13202, 1212}, // bath stool + {13203, 1213}, // square bathtub + {13205, 1225}, // store shelf + {13206, 1214}, // shopping bag + {13207, 1220}, // small LED display + {13209, 1218}, // tablet device + {13210, 1215}, // stacked shopping baskets + {13211, 1219}, // caged cart + {13214, 1222}, // steel trash can + {13220, 1152}, // festival-lantern set + {13222, 1153}, // spooky garland + {13223, 1154}, // spooky table setting + {13229, 1197}, // range hood + {13242, 1211}, // RC helicopter + {13243, 1198}, // puppy plushie + {13244, 1209}, // gift pile + {13245, 1207}, // Yule log + {13246, 1204}, // pop-up book + {13247, 1208}, // tin robot + {13249, 1201}, // kids' tent + {13250, 1210}, // mini circuit + {13251, 1200}, // dinosaur toy + {13252, 1205}, // dollhouse + {13255, 1221}, // elaborate display case + {13266, 1228}, // owl clock + {13268, 1252}, // covered wagon + {13269, 1253}, // storefront + {13270, 1227}, // antique radio + {13271, 1224}, // upright speaker + {13272, 1325}, // evergreen ash + {13273, 1254}, // cactus + {13274, 1223}, // wristwatch + {13288, 1229}, // high chair + {13294, 1230}, // beach chairs with parasol + {13295, 1232}, // game-show stand + {13296, 1231}, // vehicle cabin seat + {13299, 1233}, // decorative bottles + {13300, 1235}, // stylish wall spotlight + {13302, 1234}, // decorative pillar + {13303, 1241}, // glass jar + {13304, 1237}, // winnowing machine + {13305, 1238}, // conveyor belt + {13306, 1240}, // robot arm + {13307, 1236}, // stylish spotlight + {13312, 1245}, // round streetlight + {13313, 1244}, // curved streetlight + {13335, 1256}, // bird mobile + {13336, 1257}, // construction scaffolding + {13337, 1261}, // sloppy table + {13338, 1259}, // sloppy sink + {13339, 1260}, // sloppy sofa + {13340, 1255}, // garden table + {13341, 1262}, // sloppy bed + {13342, 1265}, // dreamy bed + {13343, 1263}, // dreamy wall rack + {13344, 1264}, // dreamy shelves + {13345, 1258}, // snack + {13347, 1266}, // yacht + {13352, 1157}, // + {13356, 1278}, // rolling cart + {13360, 1274}, // bottled beverage + {13361, 1275}, // paint cans + {13362, 1270}, // double-edged sword + {13363, 1269}, // inspection equipment + {13365, 1273}, // toothbrush-and-cup set + {13366, 1272}, // chainsaw + {13367, 1267}, // bunny garden decoration + {13368, 1268}, // elegant mirror + {13369, 1276}, // milk can + {13370, 1277}, // wheat field + {13447, 1295}, // Turkey Day garden stand + {13448, 1296}, // Turkey Day hearth + {13449, 1293}, // Turkey Day decorations + {13450, 1292}, // Turkey Day chair + {13453, 1297}, // Turkey Day table + {13454, 1280}, // cool dining table + {13455, 1279}, // shopping basket + {13464, 1283}, // crane game + {13465, 1786}, // bubble machine + {13466, 1288}, // silver confetti blower + {13467, 1287}, // stage flame machine + {13468, 1286}, // hanging stage lights + {13469, 1285}, // stage lights + {13472, 1301}, // windmill + {13474, 1291}, // siren + {13475, 1783}, // candle chandelier + {13478, 1820}, // tabletop record player + {13479, 1290}, // nearly busted radio + {13488, 1516}, // chocolate heart + {13496, 1302}, // stonework kitchen + {13502, 1316}, // spaceship control panel + {13503, 1324}, // meter and pipes + {13504, 1312}, // strategic meeting table + {13505, 1320}, // mining car + {13506, 1321}, // science pod + {13507, 1323}, // banker's lamp + {13508, 1310}, // cold sleep pod + {13509, 1305}, // gear tower + {13510, 1307}, // crew member's seat + {13511, 1304}, // gear apparatus + {13512, 1319}, // retro transportation stop + {13513, 1311}, // fish container + {13514, 1322}, // powder-room booth + {13515, 1317}, // tank + {13516, 1315}, // amazing machine + {13517, 1512}, // unknown machine + {13518, 1313}, // lab chair + {13519, 1308}, // gaming chair + {13520, 1306}, // forbidden altar + {13521, 1309}, // gaming desk + {13522, 1303}, // dress-up doll + {13523, 1314}, // skateboard + {13524, 1318}, // medieval building side + {13526, 1801}, // vine ladder set-up kit + {13530, 1800}, // wooden ladder set-up kit + {13534, 1802}, // iron ladder set-up kit + {13573, 1339}, // medium wooden partition + {13574, 1340}, // small wooden partition + {13575, 1327}, // SLR camera + {13576, 1332}, // schefflera + {13577, 1338}, // potted starter plants + {13578, 1326}, // inflatable bird ring + {13579, 1336}, // baobab + {13580, 1330}, // skateboard wall rack + {13581, 1329}, // castle gate + {13582, 1328}, // castle tower + {13583, 1342}, // rescue mannequin + {13584, 1331}, // makeup pouch + {13586, 1333}, // transit seat + {13587, 1335}, // dried-flower garland + {13588, 1341}, // tension-pole rack + {13589, 1337}, // professional headphones + {13590, 1343}, // castle wall + {13591, 1344}, // fancy bathroom vanity + {13606, 1345}, // stacked fish containers + {13614, 1375}, // key tray + {13615, 1399}, // scooter + {13616, 1437}, // hanging lightbulb + {13618, 1439}, // patchwork sofa chair + {13620, 1360}, // office materials + {13621, 1381}, // minicar + {13622, 1382}, // luxury car + {13623, 1465}, // dormant volcano + {13624, 1421}, // scoreboard + {13625, 1440}, // patchwork chair + {13626, 1357}, // ornithopter + {13627, 1441}, // patchwork low table + {13628, 1452}, // model kit + {13629, 1442}, // patchwork bed + {13630, 1363}, // curtain partition + {13631, 1428}, // torii + {13632, 1458}, // popcorn snack set + {13633, 1379}, // throne + {13634, 1404}, // fresh-food trays + {13636, 1448}, // wide display stand + {13637, 1361}, // outdoor folding chair + {13638, 1377}, // utility wagon + {13639, 1396}, // short simple panel + {13640, 1370}, // wall-mounted LED display + {13642, 1417}, // paper-chain ceiling garland + {13643, 1386}, // die + {13645, 1402}, // scrapbook + {13647, 1449}, // fence + {13649, 1436}, // lily-pad table + {13651, 1422}, // tokonoma + {13652, 1407}, // antique map + {13655, 1392}, // framed photo + {13656, 1378}, // cube light + {13657, 1355}, // decorative plate + {13662, 1353}, // ruined decorated pillar + {13666, 1358}, // pile of cash + {13676, 1460}, // round topiary + {13678, 1388}, // triangular topiary + {13680, 1362}, // outdoor folding table + {13681, 1456}, // light-bulb sign + {13683, 1469}, // yoga mat + {13690, 1462}, // futuristic meal + {13691, 1368}, // mounted mountain bike + {13692, 1468}, // dreamy hanging decoration + {13696, 1411}, // pile of cardboard boxes + {13701, 1429}, // drapery + {13709, 1403}, // spray can + {13712, 1427}, // card tower + {13717, 1380}, // metal pot + {13719, 1350}, // toy duck + {13722, 1385}, // recycled-paper bundle + {13727, 1397}, // dessert carrier + {13729, 1438}, // carton beverage + {13730, 1470}, // shaded pendant lamp + {13740, 1453}, // model kits + {13744, 1365}, // framed poster + {13745, 1467}, // yunomi teacup + {13746, 1423}, // stacked bags + {13747, 1387}, // backlit sign + {13748, 1426}, // cards + {13751, 1486}, // open wooden shelves + {13756, 1487}, // bottle crate + {13764, 1492}, // hanging cube light + {13765, 1494}, // plain party-lights arch + {13767, 1495}, // Festivale garland + {13770, 1500}, // Festivale parasol + {13772, 1501}, // Festivale balloon lamp + {13773, 1504}, // Festivale stall + {13774, 1498}, // Festivale drum + {13775, 1497}, // Festivale stage + {13776, 1496}, // Festivale confetti machine + {13777, 1505}, // Festivale lamp + {13778, 1506}, // Festivale flag + {13818, 1509}, // Turkey Day casserole + {13819, 1510}, // Turkey Day wheat decor + {13820, 1508}, // Turkey Day table setting + {13829, 1511}, // Shell + {13831, 1522}, // large Mushroom Platform + {13832, 1523}, // small Mushroom Platform + {13862, 0652}, // Jingle's photo + {13884, 1513}, // ranch cupboard + {13897, 1605}, // tall brick island counter + {13901, 1607}, // low brick island counter + {13902, 1593}, // tall wooden island counter + {13925, 1520}, // hanging monitor + {13926, 1519}, // hanging guide sign + {13927, 1521}, // Nintendo Switch Lite + {13930, 1524}, // set of stockings + {14017, 1542}, // cave + {14018, 1543}, // ruined arch + {14019, 1544}, // vine hanging chair + {14029, 1546}, // heart-shaped bouquet + {14046, 1655}, // xylophoid + {14047, 1656}, // babbloid + {14049, 1547}, // truck + {14050, 1553}, // deep fryer + {14051, 1552}, // fancy frame + {14053, 1549}, // wall planter + {14054, 1550}, // ranch kitchen + {14055, 1548}, // outdoor kitchen + {14056, 1693}, // arfoid + {14057, 1694}, // whistloid + {14058, 1695}, // bwongoid + {14059, 1696}, // twangoid + {14060, 1697}, // laseroid + {14061, 1698}, // squeakoid + {14062, 1699}, // tockoid + {14063, 1700}, // ringoid + {14064, 1701}, // oinkoid + {14065, 1702}, // tremoloid + {14066, 1703}, // bubbloid + {14067, 1704}, // petaloid + {14074, 1658}, // aluminoid + {14075, 1682}, // wallopoid + {14076, 1683}, // drummoid + {14077, 1684}, // dootoid + {14078, 1685}, // whirroid + {14080, 1664}, // thwopoid + {14081, 1665}, // rumbloid + {14082, 1666}, // bendoid + {14083, 1667}, // boomoid + {14086, 1676}, // bloopoid + {14087, 1677}, // sproingoid + {14088, 1678}, // crumploid + {14089, 1679}, // clatteroid + {14092, 1657}, // scatteroid + {14093, 1688}, // spikenoid + {14094, 1689}, // squeezoid + {14095, 1690}, // flutteroid + {14098, 1670}, // boioingoid + {14099, 1671}, // stelloid + {14100, 1672}, // jingloid + {14101, 1673}, // rattloid + {14106, 1554}, // gazebo + {14108, 1556}, // azumaya gazebo + {14184, 1567}, // pergola + {14192, 1569}, // giant vine + {14193, 1570}, // vine bench + {14205, 1575}, // vine lamp + {14206, 1574}, // vine garland + {14207, 1576}, // glowing-moss stool + {14208, 1580}, // glowing-moss balloon + {14209, 1578}, // glowing-moss boulder + {14210, 1577}, // hanging glowing moss + {14211, 1579}, // glowing-moss wreath + {14212, 1582}, // glowing-moss pond + {14213, 1583}, // glowing-moss statue + {14214, 1585}, // glowing-moss-jar shelves + {14215, 1584}, // glow-in-the-dark stickers + {14216, 1581}, // suspicious cauldron + {14254, 0652}, // Tom Nook's photo + {14255, 0652}, // Timmy and Tommy's photo + {14256, 0652}, // Isabelle's photo + {14308, 1599}, // low simple island counter + {14310, 1602}, // tall simple island counter + {14313, 1595}, // low wooden island counter + {14332, 1660}, // tall marble island counter + {14337, 1662}, // low marble island counter + {14340, 1615}, // whoopee cushion + {14346, 1620}, // hanging sign + {14352, 1623}, // dreamy bear toy + {14353, 1622}, // dreamy rabbit toy + {14354, 1624}, // dreamy unicorn toy + {14414, 1754}, // handheld lantern + {14472, 0652}, // Rover's photo + {14475, 1642}, // nuptial doorplate + {14476, 1640}, // nuptial bell + {14477, 1641}, // nuptial ring pillow + {14520, 1631}, // wall-mounted neon lamps + {14523, 1632}, // tangled cords + {14524, 1637}, // floral sconce + {14525, 1636}, // dispenser + {14526, 1639}, // wooden locker + {14527, 1634}, // clipboard + {14528, 1633}, // steel fence + {14530, 1629}, // meeting-room table + {14531, 1635}, // long folding table + {14534, 1630}, // instant noodles + {14538, 1772}, // protein shake + {14539, 1758}, // dumbbell + {14542, 1750}, // spooky treats basket + {14549, 1654}, // decayed tree + {14550, 1645}, // spooky tree + {14551, 1647}, // spooky trick lamp + {14556, 1779}, // osechi + {14561, 1648}, // chafing dish + {14572, 1781}, // storage shed + {14574, 1776}, // coffee beans + {14575, 1751}, // ABD + {14591, 1762}, // ornament table lamp + {14592, 1649}, // wooden music box + {14593, 1764}, // ornament garland + {14594, 1761}, // giant ornament + {14596, 1653}, // brick pillar + {14597, 1659}, // marble pillar + {14598, 1652}, // simple pillar + {14601, 1651}, // wooden pillar + {14604, 1663}, // glowing-moss jar + {14611, 0652}, // Brewster's photo + {14619, 1747}, // vertical split curtains + {14620, 1748}, // horizontal split curtains + {14621, 1749}, // unfolded reference sheet + {14639, 1755}, // pocketbook + {14640, 1756}, // pocket magazine + {14714, 1752}, // donation box + {14728, 1763}, // ornament tree + {14735, 1757}, // + {14756, 1760}, // frozen fence + {14758, 1774}, // corrugated iron fence + {14759, 1775}, // park fence + {14799, 1823}, // flower tabletop mirror + {14821, 1782}, // ring light + {14826, 1784}, // lighted display stand + {14831, 1785}, // wooden storage shed + {14882, 1803}, // ruined seat + {14887, 1804}, // ruined broken pillar + }; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Item/VillagerItem.cs b/NHSE.Core/Structures/Item/VillagerItem.cs index 98d5e7b..589ad74 100644 --- a/NHSE.Core/Structures/Item/VillagerItem.cs +++ b/NHSE.Core/Structures/Item/VillagerItem.cs @@ -1,43 +1,43 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential)] +public sealed class VillagerItem : Item, ICopyableItem { - [StructLayout(LayoutKind.Sequential)] - public sealed class VillagerItem : Item, ICopyableItem + public new const int SIZE = 0x2C; + public new static readonly VillagerItem NO_ITEM = new() { ItemId = NONE }; + + public uint U08; + public uint U0C; + public uint U10; + public uint U14; + public uint U18; + public uint U1C; + public uint U20; + public uint U24; + public uint U28; + + public new static VillagerItem[] GetArray(ReadOnlySpan data) => data.GetArray(SIZE); + public static byte[] SetArray(IReadOnlyList data) => data.SetArray(SIZE); + + public void CopyFrom(VillagerItem item) { - public new const int SIZE = 0x2C; - public new static readonly VillagerItem NO_ITEM = new() { ItemId = NONE }; - - public uint U08; - public uint U0C; - public uint U10; - public uint U14; - public uint U18; - public uint U1C; - public uint U20; - public uint U24; - public uint U28; - - public new static VillagerItem[] GetArray(byte[] data) => data.GetArray(SIZE); - public static byte[] SetArray(IReadOnlyList data) => data.SetArray(SIZE); - - public void CopyFrom(VillagerItem item) - { - CopyFrom((Item) item); - U08 = item.U08; - U0C = item.U0C; - U10 = item.U10; - U14 = item.U14; - U18 = item.U18; - U1C = item.U1C; - U20 = item.U20; - U24 = item.U24; - U28 = item.U28; - } - - public new void Delete() => CopyFrom(NO_ITEM); - - public override int Size => SIZE; + CopyFrom((Item) item); + U08 = item.U08; + U0C = item.U0C; + U10 = item.U10; + U14 = item.U14; + U18 = item.U18; + U1C = item.U1C; + U20 = item.U20; + U24 = item.U24; + U28 = item.U28; } -} + + public new void Delete() => CopyFrom(NO_ITEM); + + public override int Size => SIZE; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Layers/FieldItemLayer.cs b/NHSE.Core/Structures/Map/Layers/FieldItemLayer.cs index a9fbe25..1f6856f 100644 --- a/NHSE.Core/Structures/Map/Layers/FieldItemLayer.cs +++ b/NHSE.Core/Structures/Map/Layers/FieldItemLayer.cs @@ -1,123 +1,122 @@ using System; using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public class FieldItemLayer : ItemLayer { - public class FieldItemLayer : ItemLayer + public const int TilesPerAcreDim = 32; + public const int FieldItemWidth = TilesPerAcreDim * AcreWidth; + public const int FieldItemHeight = TilesPerAcreDim * AcreHeight; + + public FieldItemLayer(Item[] tiles) : base(tiles, FieldItemWidth, FieldItemHeight, TilesPerAcreDim, TilesPerAcreDim) { - public const int TilesPerAcreDim = 32; - public const int FieldItemWidth = TilesPerAcreDim * AcreWidth; - public const int FieldItemHeight = TilesPerAcreDim * AcreHeight; + } - public FieldItemLayer(Item[] tiles) : base(tiles, FieldItemWidth, FieldItemHeight, TilesPerAcreDim, TilesPerAcreDim) + public Item GetTile(int acreX, int acreY, int gridX, int gridY) => this[GetTileIndex(acreX, acreY, gridX, gridY)]; + public Item GetAcreTile(int acreIndex, int tileIndex) => this[GetAcreTileIndex(acreIndex, tileIndex)]; + + public byte[] DumpAcre(int acre) + { + int count = GridTileCount; + var result = new byte[Item.SIZE * count]; + for (int i = 0; i < count; i++) { + var tile = GetAcreTile(acre, i); + var bytes = tile.ToBytesClass(); + bytes.CopyTo(result, i * Item.SIZE); } + return result; + } - public Item GetTile(int acreX, int acreY, int gridX, int gridY) => this[GetTileIndex(acreX, acreY, gridX, gridY)]; - public Item GetAcreTile(int acreIndex, int tileIndex) => this[GetAcreTileIndex(acreIndex, tileIndex)]; - - public byte[] DumpAcre(int acre) + public void ImportAcre(int acre, ReadOnlySpan data) + { + int count = GridTileCount; + var tiles = Item.GetArray(data); + for (int i = 0; i < count; i++) { - int count = GridTileCount; - var result = new byte[Item.SIZE * count]; - for (int i = 0; i < count; i++) - { - var tile = GetAcreTile(acre, i); - var bytes = tile.ToBytesClass(); - bytes.CopyTo(result, i * Item.SIZE); - } - return result; - } - - public void ImportAcre(int acre, byte[] data) - { - int count = GridTileCount; - var tiles = Item.GetArray(data); - for (int i = 0; i < count; i++) - { - var tile = GetAcreTile(acre, i); - tile.CopyFrom(tiles[i]); - } - } - - public int ClearFieldPlanted(Func criteria) => ClearFieldPlanted(0, 0, MaxWidth, MaxHeight, criteria); - public int RemoveAll(Func criteria) => RemoveAll(0, 0, MaxWidth, MaxHeight, criteria); - public int RemoveAll(HashSet items) => RemoveAll(0, 0, MaxWidth, MaxHeight, z => items.Contains(z.DisplayItemId)); - public int RemoveAll(ushort item) => RemoveAll(0, 0, MaxWidth, MaxHeight, z => z.DisplayItemId == item); - - public int ClearFieldPlanted(int xmin, int ymin, int width, int height, Func criteria) - { - int count = 0; - var fi = FieldItemList.Items; - - for (int x = xmin; x < xmin + width; x++) - { - for (int y = ymin; y < ymin + height; y++) - { - var t = GetTile(x, y); - var disp = t.DisplayItemId; - if (!fi.TryGetValue(disp, out var val)) - continue; - - if (!criteria(val.Kind)) - continue; - t.Delete(); - count++; - } - } - return count; - } - - public int ModifyAll(int xmin, int ymin, int width, int height, Func criteria, Action action) - { - int count = 0; - for (int x = xmin; x < xmin + width; x++) - { - for (int y = ymin; y < ymin + height; y++) - { - var t = GetTile(x, y); - if (!criteria(t)) - continue; - action(t); - count++; - } - } - return count; - } - - public int RemoveAllHoles(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z == FieldItemKind.UnitIconHole); - public int RemoveAllWeeds(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsWeed()); - public int RemoveAllTrees(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsTree()); - public int RemoveAllPlants(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsPlant()); - public int RemoveAllFences(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsFence()); - public int RemoveAllFlowers(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsFlower()); - public int RemoveAllBushes(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsBush()); - public int RemoveAllObjects(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, _ => true); - - public int RemoveAll(int xmin, int ymin, int width, int height) => RemoveAll(xmin, ymin, width, height, _ => true); - public int RemoveAllShells(int xmin, int ymin, int width, int height) => RemoveAll(xmin, ymin, width, height, z => GameLists.Shells.Contains(z.DisplayItemId)); - public int RemoveAllBranches(int xmin, int ymin, int width, int height) => RemoveAll(xmin, ymin, width, height, z => z.DisplayItemId == 2500); - public int RemoveAllPlacedItems(int xmin, int ymin, int width, int height) => RemoveAll(xmin, ymin, width, height, z => !z.IsNone && !FieldItemList.Items.ContainsKey(z.DisplayItemId)); - public int RemoveAllLike(int xmin, int ymin, int width, int height, Item item) => RemoveAll(xmin, ymin, width, height, z => !z.IsNone && item.DisplayItemId == z.DisplayItemId); - - public int WaterAllFlowers(int xmin, int ymin, int width, int height, bool all) - { - var fi = FieldItemList.Items; - - bool IsFlowerWaterable(Item item) - { - if (item.IsNone) - return false; - if (!item.IsRoot) - return false; - if (!fi.TryGetValue(item.ItemId, out var def)) - return false; - if (!def.Kind.IsFlower()) - return false; - return true; - } - - return ModifyAll(xmin, ymin, width, height, IsFlowerWaterable, z => z.Water(all)); + var tile = GetAcreTile(acre, i); + tile.CopyFrom(tiles[i]); } } -} + + public int ClearFieldPlanted(Func criteria) => ClearFieldPlanted(0, 0, MaxWidth, MaxHeight, criteria); + public int RemoveAll(Func criteria) => RemoveAll(0, 0, MaxWidth, MaxHeight, criteria); + public int RemoveAll(HashSet items) => RemoveAll(0, 0, MaxWidth, MaxHeight, z => items.Contains(z.DisplayItemId)); + public int RemoveAll(ushort item) => RemoveAll(0, 0, MaxWidth, MaxHeight, z => z.DisplayItemId == item); + + public int ClearFieldPlanted(int xmin, int ymin, int width, int height, Func criteria) + { + int count = 0; + var fi = FieldItemList.Items; + + for (int x = xmin; x < xmin + width; x++) + { + for (int y = ymin; y < ymin + height; y++) + { + var t = GetTile(x, y); + var disp = t.DisplayItemId; + if (!fi.TryGetValue(disp, out var val)) + continue; + + if (!criteria(val.Kind)) + continue; + t.Delete(); + count++; + } + } + return count; + } + + public int ModifyAll(int xmin, int ymin, int width, int height, Func criteria, Action action) + { + int count = 0; + for (int x = xmin; x < xmin + width; x++) + { + for (int y = ymin; y < ymin + height; y++) + { + var t = GetTile(x, y); + if (!criteria(t)) + continue; + action(t); + count++; + } + } + return count; + } + + public int RemoveAllHoles(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z == FieldItemKind.UnitIconHole); + public int RemoveAllWeeds(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsWeed); + public int RemoveAllTrees(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsTree); + public int RemoveAllPlants(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsPlant); + public int RemoveAllFences(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsFence); + public int RemoveAllFlowers(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsFlower); + public int RemoveAllBushes(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, z => z.IsBush); + public int RemoveAllObjects(int xmin, int ymin, int width, int height) => ClearFieldPlanted(xmin, ymin, width, height, _ => true); + + public int RemoveAll(int xmin, int ymin, int width, int height) => RemoveAll(xmin, ymin, width, height, _ => true); + public int RemoveAllShells(int xmin, int ymin, int width, int height) => RemoveAll(xmin, ymin, width, height, z => GameLists.Shells.Contains(z.DisplayItemId)); + public int RemoveAllBranches(int xmin, int ymin, int width, int height) => RemoveAll(xmin, ymin, width, height, z => z.DisplayItemId == 2500); + public int RemoveAllPlacedItems(int xmin, int ymin, int width, int height) => RemoveAll(xmin, ymin, width, height, z => !z.IsNone && !FieldItemList.Items.ContainsKey(z.DisplayItemId)); + public int RemoveAllLike(int xmin, int ymin, int width, int height, Item item) => RemoveAll(xmin, ymin, width, height, z => !z.IsNone && item.DisplayItemId == z.DisplayItemId); + + public int WaterAllFlowers(int xmin, int ymin, int width, int height, bool all) + { + var fi = FieldItemList.Items; + + bool IsFlowerWaterable(Item item) + { + if (item.IsNone) + return false; + if (!item.IsRoot) + return false; + if (!fi.TryGetValue(item.ItemId, out var def)) + return false; + if (!def.Kind.IsFlower) + return false; + return true; + } + + return ModifyAll(xmin, ymin, width, height, IsFlowerWaterable, z => z.Water(all)); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Layers/ItemLayer.cs b/NHSE.Core/Structures/Map/Layers/ItemLayer.cs index e3310f4..bf79d85 100644 --- a/NHSE.Core/Structures/Map/Layers/ItemLayer.cs +++ b/NHSE.Core/Structures/Map/Layers/ItemLayer.cs @@ -1,216 +1,207 @@ using System; using System.Diagnostics; -namespace NHSE.Core +namespace NHSE.Core; + +public abstract class ItemLayer : MapGrid { - public abstract class ItemLayer : MapGrid + public readonly Item[] Tiles; + + protected ItemLayer(Item[] tiles, int w, int h) : this(tiles, w, h, w, h) { - public readonly Item[] Tiles; + } - protected ItemLayer(Item[] tiles, int w, int h) : this(tiles, w, h, w, h) + protected ItemLayer(Item[] tiles, int w, int h, int gw, int gh) : base(gw, gh, w, h) + { + Tiles = tiles; + Debug.Assert(MaxWidth * MaxHeight == tiles.Length); + } + + public Item GetTile(in int x, in int y) => this[GetTileIndex(x, y)]; + + public Item this[int index] + { + get => Tiles[index]; + set => Tiles[index] = value; + } + + public byte[] DumpAll() + { + var result = new byte[Tiles.Length * Item.SIZE]; + for (int i = 0; i < Tiles.Length; i++) + Tiles[i].ToBytesClass().CopyTo(result, i * Item.SIZE); + return result; + } + + public void ImportAll(ReadOnlySpan data) + { + var tiles = Item.GetArray(data); + for (int i = 0; i < tiles.Length; i++) + Tiles[i].CopyFrom(tiles[i]); + } + + public int RemoveAll(in int xmin, in int ymin, in int width, in int height, Func criteria) + { + int count = 0; + for (int x = xmin; x < xmin + width; x++) { - } - - protected ItemLayer(Item[] tiles, int w, int h, int gw, int gh) : base(gw, gh, w, h) - { - Tiles = tiles; - Debug.Assert(MaxWidth * MaxHeight == tiles.Length); - } - - public Item GetTile(in int x, in int y) => this[GetTileIndex(x, y)]; - - public Item this[int index] - { - get => Tiles[index]; - set => Tiles[index] = value; - } - - public byte[] DumpAll() - { - var result = new byte[Tiles.Length * Item.SIZE]; - for (int i = 0; i < Tiles.Length; i++) - Tiles[i].ToBytesClass().CopyTo(result, i * Item.SIZE); - return result; - } - - public void ImportAll(byte[] data) - { - var tiles = Item.GetArray(data); - for (int i = 0; i < tiles.Length; i++) - Tiles[i].CopyFrom(tiles[i]); - } - - public int RemoveAll(in int xmin, in int ymin, in int width, in int height, Func criteria) - { - int count = 0; - for (int x = xmin; x < xmin + width; x++) + for (int y = ymin; y < ymin + height; y++) { - for (int y = ymin; y < ymin + height; y++) - { - var t = GetTile(x, y); - if (!criteria(t)) - continue; - t.Delete(); - count++; - } - } - - return count; - } - - public void DeleteExtensionTiles(Item tile, int x, int y) - { - GetTileWidthHeight(tile, x, y, out var w, out var h); - - for (int ix = 0; ix < w; ix++) - { - for (int iy = 0; iy < h; iy++) - { - if (iy == 0 && ix == 0) - continue; - var t = GetTile(x + ix, y + iy); - t.Delete(); - } + var t = GetTile(x, y); + if (!criteria(t)) + continue; + t.Delete(); + count++; } } - public void SetExtensionTiles(Item tile, in int x, in int y) + return count; + } + + public void DeleteExtensionTiles(Item tile, int x, int y) + { + GetTileWidthHeight(tile, x, y, out var w, out var h); + + for (int ix = 0; ix < w; ix++) { - GetTileWidthHeight(tile, x, y, out var w, out var h); - - for (byte ix = 0; ix < w; ix++) + for (int iy = 0; iy < h; iy++) { - for (byte iy = 0; iy < h; iy++) - { - if (iy == 0 && ix == 0) - continue; - var t = GetTile(x + ix, y + iy); - t.SetAsExtension(tile, ix, iy); - } + if (iy == 0 && ix == 0) + continue; + var t = GetTile(x + ix, y + iy); + t.Delete(); } } - - private void GetTileWidthHeight(Item tile, int x, int y, out int w, out int h) - { - var type = ItemInfo.GetItemSize(tile); - w = type.GetWidth(); - h = type.GetHeight(); - - // Rotation - if ((tile.Rotation & 1) == 1) - { - var tmp = w; - w = h; - h = tmp; - } - - // Clamp to grid bounds - if (x + w - 1 >= MaxWidth) - w = MaxWidth - x; - if (y + h - 1 >= MaxHeight) - h = MaxHeight - y; - } - - /// - /// Checks if writing the at the specified and coordinates will overlap with any existing tiles. - /// - /// True if any tile will be overwritten, false if nothing is there. - public PlacedItemPermission IsOccupied(Item tile, in int x, in int y) - { - var type = ItemInfo.GetItemSize(tile); - var w = type.GetWidth(); - var h = type.GetHeight(); - - if ((tile.Rotation & 1) == 1) - { - var tmp = w; - w = h; - h = tmp; - } - - if (x + w - 1 >= MaxWidth) - return PlacedItemPermission.OutOfBounds; - if (y + h - 1 >= MaxHeight) - return PlacedItemPermission.OutOfBounds; - - for (byte ix = 0; ix < w; ix++) - { - for (byte iy = 0; iy < h; iy++) - { - var t = GetTile(x + ix, y + iy); - if (!t.IsNone) - return PlacedItemPermission.Collision; - } - } - - return PlacedItemPermission.NoCollision; - } - - public int ReplaceAll(Item oldItem, Item newItem, in int xmin, in int ymin, in int width, in int height) - { - var sizeOld = ItemInfo.GetItemSize(oldItem); - var sizeNew = ItemInfo.GetItemSize(newItem); - - if (sizeOld != sizeNew) - return -1; - - int count = 0; - for (int x = xmin; x < xmin + width; x++) - { - for (int y = ymin; y < ymin + height; y++) - { - var t = GetTile(x, y); - if (!t.IsRoot) - continue; - - if (!t.Equals(oldItem)) - continue; - - DeleteExtensionTiles(t, x, y); - t.CopyFrom(newItem); - SetExtensionTiles(t, x, y); - count++; - } - } - - return count; - } - - public int ClearDanglingExtensions(in int xmin, in int ymin, in int width, in int height) - { - int count = 0; - for (int x = xmin; x < xmin + width; x++) - { - for (int y = ymin; y < ymin + height; y++) - { - var t = GetTile(x, y); - if (IsValidExtension(t, x, y)) - continue; - t.Delete(); - count++; - } - } - return count; - } - - private bool IsValidExtension(Item t, int x, int y) - { - if (!t.IsExtension) - return true; - var parentX = x - t.ExtensionX; - var parentY = y - t.ExtensionY; - - try - { - var parent = GetTile(parentX, parentY); - if (parent.ItemId == t.ExtensionItemId) - return true; - } - catch - { - // corrupt? - } - return false; - } } -} + + public void SetExtensionTiles(Item tile, in int x, in int y) + { + GetTileWidthHeight(tile, x, y, out var w, out var h); + + for (byte ix = 0; ix < w; ix++) + { + for (byte iy = 0; iy < h; iy++) + { + if (iy == 0 && ix == 0) + continue; + var t = GetTile(x + ix, y + iy); + t.SetAsExtension(tile, ix, iy); + } + } + } + + private void GetTileWidthHeight(Item tile, int x, int y, out int w, out int h) + { + var type = ItemInfo.GetItemSize(tile); + w = type.Width; + h = type.Height; + + // Rotation + if ((tile.Rotation & 1) == 1) + (w, h) = (h, w); + + // Clamp to grid bounds + if (x + w - 1 >= MaxWidth) + w = MaxWidth - x; + if (y + h - 1 >= MaxHeight) + h = MaxHeight - y; + } + + /// + /// Checks if writing the at the specified and coordinates will overlap with any existing tiles. + /// + /// True if any tile will be overwritten, false if nothing is there. + public PlacedItemPermission IsOccupied(Item tile, in int x, in int y) + { + var type = ItemInfo.GetItemSize(tile); + var w = type.Width; + var h = type.Height; + + if ((tile.Rotation & 1) == 1) + (w, h) = (h, w); + + if (x + w - 1 >= MaxWidth) + return PlacedItemPermission.OutOfBounds; + if (y + h - 1 >= MaxHeight) + return PlacedItemPermission.OutOfBounds; + + for (byte ix = 0; ix < w; ix++) + { + for (byte iy = 0; iy < h; iy++) + { + var t = GetTile(x + ix, y + iy); + if (!t.IsNone) + return PlacedItemPermission.Collision; + } + } + + return PlacedItemPermission.NoCollision; + } + + public int ReplaceAll(Item oldItem, Item newItem, in int xmin, in int ymin, in int width, in int height) + { + var sizeOld = ItemInfo.GetItemSize(oldItem); + var sizeNew = ItemInfo.GetItemSize(newItem); + + if (sizeOld != sizeNew) + return -1; + + int count = 0; + for (int x = xmin; x < xmin + width; x++) + { + for (int y = ymin; y < ymin + height; y++) + { + var t = GetTile(x, y); + if (!t.IsRoot) + continue; + + if (!t.Equals(oldItem)) + continue; + + DeleteExtensionTiles(t, x, y); + t.CopyFrom(newItem); + SetExtensionTiles(t, x, y); + count++; + } + } + + return count; + } + + public int ClearDanglingExtensions(in int xmin, in int ymin, in int width, in int height) + { + int count = 0; + for (int x = xmin; x < xmin + width; x++) + { + for (int y = ymin; y < ymin + height; y++) + { + var t = GetTile(x, y); + if (IsValidExtension(t, x, y)) + continue; + t.Delete(); + count++; + } + } + return count; + } + + private bool IsValidExtension(Item t, int x, int y) + { + if (!t.IsExtension) + return true; + var parentX = x - t.ExtensionX; + var parentY = y - t.ExtensionY; + + try + { + var parent = GetTile(parentX, parentY); + if (parent.ItemId == t.ExtensionItemId) + return true; + } + catch + { + // corrupt? + } + return false; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Layers/RoomItemLayer.cs b/NHSE.Core/Structures/Map/Layers/RoomItemLayer.cs index ac1a647..5d4c973 100644 --- a/NHSE.Core/Structures/Map/Layers/RoomItemLayer.cs +++ b/NHSE.Core/Structures/Map/Layers/RoomItemLayer.cs @@ -1,33 +1,33 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public class RoomItemLayer : ItemLayer { - public class RoomItemLayer : ItemLayer + public const int SIZE = Width * Height * Item.SIZE; + private const int Width = 20; + private const int Height = 20; + + public RoomItemLayer(ReadOnlySpan data) : this(Item.GetArray(data)) { } + public RoomItemLayer(Item[] tiles) : base(tiles, Width, Height) { } + + public static RoomItemLayer[] GetArray(ReadOnlySpan data) { - public const int SIZE = Width * Height * Item.SIZE; - private const int Width = 20; - private const int Height = 20; - - public RoomItemLayer(byte[] data) : this(Item.GetArray(data)) { } - public RoomItemLayer(Item[] tiles) : base(tiles, Width, Height) { } - - public static RoomItemLayer[] GetArray(byte[] data) + var result = new RoomItemLayer[data.Length / SIZE]; + for (int i = 0; i < result.Length; i++) { - var result = new RoomItemLayer[data.Length / SIZE]; - for (int i = 0; i < result.Length; i++) - { - var slice = data.Slice(i * SIZE, SIZE); - result[i] = new RoomItemLayer(slice); - } - return result; - } - - public static byte[] SetArray(IReadOnlyList data) - { - var result = new byte[data.Count * SIZE]; - for (int i = 0; i < data.Count; i++) - data[i].DumpAll().CopyTo(result, i * SIZE); - return result; + var slice = data.Slice(i * SIZE, SIZE); + result[i] = new RoomItemLayer(slice); } + return result; } -} + + public static byte[] SetArray(IReadOnlyList data) + { + var result = new byte[data.Count * SIZE]; + for (int i = 0; i < data.Count; i++) + data[i].DumpAll().CopyTo(result, i * SIZE); + return result; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Layers/TerrainLayer.cs b/NHSE.Core/Structures/Map/Layers/TerrainLayer.cs index c426245..d8127d9 100644 --- a/NHSE.Core/Structures/Map/Layers/TerrainLayer.cs +++ b/NHSE.Core/Structures/Map/Layers/TerrainLayer.cs @@ -1,166 +1,166 @@ using System; using System.Diagnostics; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Grid of +/// +public class TerrainLayer : MapGrid { - /// - /// Grid of - /// - public class TerrainLayer : MapGrid + public TerrainTile[] Tiles { get; init; } + public byte[] BaseAcres { get; init; } + + public TerrainLayer(TerrainTile[] tiles, byte[] acres) : base(16, 16, AcreWidth * 16, AcreHeight * 16) { - public TerrainTile[] Tiles { get; init; } - public byte[] BaseAcres { get; init; } + BaseAcres = acres; + Tiles = tiles; + Debug.Assert(MaxTileCount == tiles.Length); + } - public TerrainLayer(TerrainTile[] tiles, byte[] acres) : base(16, 16, AcreWidth * 16, AcreHeight * 16) + public TerrainTile GetTile(int x, int y) => this[GetTileIndex(x, y)]; + public TerrainTile GetTile(int acreX, int acreY, int gridX, int gridY) => this[GetTileIndex(acreX, acreY, gridX, gridY)]; + public TerrainTile GetAcreTile(int acreIndex, int tileIndex) => this[GetAcreTileIndex(acreIndex, tileIndex)]; + + public TerrainTile this[int index] + { + get => Tiles[index]; + set => Tiles[index] = value; + } + + public byte[] DumpAll() + { + var result = new byte[Tiles.Length * TerrainTile.SIZE]; + for (int i = 0; i < Tiles.Length; i++) + Tiles[i].ToBytesClass().CopyTo(result, i * TerrainTile.SIZE); + return result; + } + + public byte[] DumpAcre(int acre) + { + int count = GridTileCount; + var result = new byte[TerrainTile.SIZE * count]; + for (int i = 0; i < count; i++) { - BaseAcres = acres; - Tiles = tiles; - Debug.Assert(MaxTileCount == tiles.Length); + var tile = GetAcreTile(acre, i); + var bytes = tile.ToBytesClass(); + bytes.CopyTo(result, i * TerrainTile.SIZE); } - public TerrainTile GetTile(int x, int y) => this[GetTileIndex(x, y)]; - public TerrainTile GetTile(int acreX, int acreY, int gridX, int gridY) => this[GetTileIndex(acreX, acreY, gridX, gridY)]; - public TerrainTile GetAcreTile(int acreIndex, int tileIndex) => this[GetAcreTileIndex(acreIndex, tileIndex)]; + return result; + } - public TerrainTile this[int index] + public void ImportAll(ReadOnlySpan data) + { + var tiles = TerrainTile.GetArray(data); + for (int i = 0; i < tiles.Length; i++) + Tiles[i].CopyFrom(tiles[i]); + } + + public void ImportAcre(int acre, ReadOnlySpan data) + { + int count = GridTileCount; + var tiles = TerrainTile.GetArray(data); + for (int i = 0; i < count; i++) { - get => Tiles[index]; - set => Tiles[index] = value; - } - - public byte[] DumpAll() - { - var result = new byte[Tiles.Length * TerrainTile.SIZE]; - for (int i = 0; i < Tiles.Length; i++) - Tiles[i].ToBytesClass().CopyTo(result, i * TerrainTile.SIZE); - return result; - } - - public byte[] DumpAcre(int acre) - { - int count = GridTileCount; - var result = new byte[TerrainTile.SIZE * count]; - for (int i = 0; i < count; i++) - { - var tile = GetAcreTile(acre, i); - var bytes = tile.ToBytesClass(); - bytes.CopyTo(result, i * TerrainTile.SIZE); - } - - return result; - } - - public void ImportAll(byte[] data) - { - var tiles = TerrainTile.GetArray(data); - for (int i = 0; i < tiles.Length; i++) - Tiles[i].CopyFrom(tiles[i]); - } - - public void ImportAcre(int acre, byte[] data) - { - int count = GridTileCount; - var tiles = TerrainTile.GetArray(data); - for (int i = 0; i < count; i++) - { - var tile = GetAcreTile(acre, i); - tile.CopyFrom(tiles[i]); - } - } - - public void SetAll(TerrainTile tile, in bool interiorOnly) - { - if (interiorOnly) - { - // skip outermost ring of tiles - int xmin = GridWidth; - int ymin = GridHeight; - int xmax = MaxWidth - GridWidth; - int ymax = MaxHeight - GridHeight; - for (int x = xmin; x < xmax; x++) - { - for (int y = ymin; y < ymax; y++) - GetTile(x, y).CopyFrom(tile); - } - } - else - { - foreach (var t in Tiles) - t.CopyFrom(tile); - } - } - - public void SetAllRoad(TerrainTile tile, in bool interiorOnly) - { - if (interiorOnly) - { - // skip outermost ring of tiles - int xmin = GridWidth; - int ymin = GridHeight; - int xmax = MaxWidth - GridWidth; - int ymax = MaxHeight - GridHeight; - for (int x = xmin; x < xmax; x++) - { - for (int y = ymin; y < ymax; y++) - GetTile(x, y).CopyRoadFrom(tile); - } - } - else - { - foreach (var t in Tiles) - t.CopyRoadFrom(tile); - } - } - - public void GetBuildingCoordinate(ushort bx, ushort by, int scale, out int x, out int y) - { - // Although there is terrain in the Top Row and Left Column, no buildings can be placed there. - // Adjust the building coordinates down-right by an acre. - int buildingShift = GridWidth; - x = (int)(((bx / 2f) - buildingShift) * scale); - y = (int)(((by / 2f) - buildingShift) * scale); - } - - public void GetBuildingRelativeCoordinates(int topX, int topY, int acreScale, ushort bx, ushort by, out int relX, out int relY) - { - GetBuildingCoordinate(bx, by, acreScale, out var x, out var y); - relX = x - (topX * acreScale); - relY = y - (topY * acreScale); - } - - public bool IsWithinGrid(int acreScale, int relX, int relY) - { - if ((uint)relX >= GridWidth * acreScale) - return false; - - if ((uint)relY >= GridHeight * acreScale) - return false; - - return true; - } - - public int GetTileColor(int x, in int y, int relativeX, int relativeY) - { - var acre = GetTileAcre(x, y); - if (acre != 0) - { - var c = AcreTileColor.GetAcreTileColor(acre, x % 16, y % 16); - if (c != -0x1000000) // transparent - return c; - } - - var tile = GetTile(x, y); - return TerrainTileColor.GetTileColor(tile, relativeX, relativeY).ToArgb(); - } - - private ushort GetTileAcre(int x, int y) - { - var acreX = 1 + (x / 16); - var acreY = 1 + (y / 16); - - var acreIndex = ((AcreWidth + 2) * acreY) + acreX; - var ofs = acreIndex * 2; - return BitConverter.ToUInt16(BaseAcres, ofs); + var tile = GetAcreTile(acre, i); + tile.CopyFrom(tiles[i]); } } -} + + public void SetAll(TerrainTile tile, in bool interiorOnly) + { + if (interiorOnly) + { + // skip outermost ring of tiles + int xmin = GridWidth; + int ymin = GridHeight; + int xmax = MaxWidth - GridWidth; + int ymax = MaxHeight - GridHeight; + for (int x = xmin; x < xmax; x++) + { + for (int y = ymin; y < ymax; y++) + GetTile(x, y).CopyFrom(tile); + } + } + else + { + foreach (var t in Tiles) + t.CopyFrom(tile); + } + } + + public void SetAllRoad(TerrainTile tile, in bool interiorOnly) + { + if (interiorOnly) + { + // skip outermost ring of tiles + int xmin = GridWidth; + int ymin = GridHeight; + int xmax = MaxWidth - GridWidth; + int ymax = MaxHeight - GridHeight; + for (int x = xmin; x < xmax; x++) + { + for (int y = ymin; y < ymax; y++) + GetTile(x, y).CopyRoadFrom(tile); + } + } + else + { + foreach (var t in Tiles) + t.CopyRoadFrom(tile); + } + } + + public void GetBuildingCoordinate(ushort bx, ushort by, int scale, out int x, out int y) + { + // Although there is terrain in the Top Row and Left Column, no buildings can be placed there. + // Adjust the building coordinates down-right by an acre. + int buildingShift = GridWidth; + x = (int)(((bx / 2f) - buildingShift) * scale); + y = (int)(((by / 2f) - buildingShift) * scale); + } + + public void GetBuildingRelativeCoordinates(int topX, int topY, int acreScale, ushort bx, ushort by, out int relX, out int relY) + { + GetBuildingCoordinate(bx, by, acreScale, out var x, out var y); + relX = x - (topX * acreScale); + relY = y - (topY * acreScale); + } + + public bool IsWithinGrid(int acreScale, int relX, int relY) + { + if ((uint)relX >= GridWidth * acreScale) + return false; + + if ((uint)relY >= GridHeight * acreScale) + return false; + + return true; + } + + public int GetTileColor(int x, in int y, int relativeX, int relativeY) + { + var acre = GetTileAcre(x, y); + if (acre != 0) + { + var c = AcreTileColor.GetAcreTileColor(acre, x % 16, y % 16); + if (c != -0x1000000) // transparent + return c; + } + + var tile = GetTile(x, y); + return TerrainTileColor.GetTileColor(tile, relativeX, relativeY).ToArgb(); + } + + private ushort GetTileAcre(int x, int y) + { + var acreX = 1 + (x / 16); + var acreY = 1 + (y / 16); + + var acreIndex = ((AcreWidth + 2) * acreY) + acreX; + var ofs = acreIndex * 2; + return ReadUInt16LittleEndian(BaseAcres.AsSpan(ofs)); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Managers/FieldItemManager.cs b/NHSE.Core/Structures/Map/Managers/FieldItemManager.cs index bc334a5..7deea64 100644 --- a/NHSE.Core/Structures/Map/Managers/FieldItemManager.cs +++ b/NHSE.Core/Structures/Map/Managers/FieldItemManager.cs @@ -1,100 +1,99 @@ using System.Collections.Generic; using System.Diagnostics; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Manages the data for the player's outside overworld. +/// +public class FieldItemManager { /// - /// Manages the data for the player's outside overworld. + /// Base layer of items /// - public class FieldItemManager + public readonly FieldItemLayer Layer1; + + /// + /// Layer of items that are supported by + /// + public readonly FieldItemLayer Layer2; + + /// + /// Reference to the save file that will be updated when is called. + /// + public readonly MainSave SAV; + + public FieldItemManager(MainSave sav) { - /// - /// Base layer of items - /// - public readonly FieldItemLayer Layer1; - - /// - /// Layer of items that are supported by - /// - public readonly FieldItemLayer Layer2; - - /// - /// Reference to the save file that will be updated when is called. - /// - public readonly MainSave SAV; - - public FieldItemManager(MainSave sav) - { - Layer1 = new FieldItemLayer(sav.GetFieldItemLayer1()); - Layer2 = new FieldItemLayer(sav.GetFieldItemLayer2()); - SAV = sav; - } - - /// - /// Stores all values for the back to the . - /// - public void Save() - { - SAV.SetFieldItemLayer1(Layer1.Tiles); - SAV.SetFieldItemLayer2(Layer2.Tiles); - - SetTileActiveFlags(Layer1, SAV.FieldItemFlag1); - SetTileActiveFlags(Layer2, SAV.FieldItemFlag2); - } - - /// - /// Lists out all coordinates of tiles present in that don't have anything underneath in to support them. - /// - /// - public List GetUnsupportedTiles() - { - var result = new List(); - for (int x = 0; x < FieldItemLayer.FieldItemWidth; x++) - { - for (int y = 0; y < FieldItemLayer.FieldItemHeight; y++) - { - var tile = Layer2.GetTile(x, y); - if (tile.IsNone) - continue; - - var support = Layer1.GetTile(x, y); - if (!support.IsNone) - continue; // dunno how to check if the tile can actually have an item put on top of it... - - result.Add($"{x:000},{y:000}"); - } - } - return result; - } - - private void SetTileActiveFlags(ItemLayer tiles, int ofs) - { - // this doesn't set anything; just diagnostic - - // Although the Tiles are arranged y-column (y-x) based, the 'isActive' flags are arranged x-row (x-y) based. - // We can turn the isActive flag off if the item is not a root or the item cannot be animated. - for (int x = 0; x < FieldItemLayer.FieldItemWidth; x++) - { - for (int y = 0; y < FieldItemLayer.FieldItemHeight; y++) - { - var tile = tiles.GetTile(x, y); - var isActive = GetIsActive(ofs, x, y); - if (!isActive) - continue; - - bool empty = tile.IsNone; - if (empty) - Debug.WriteLine($"Flag at ({x},{y}) is not a root object."); - } - } - } - - public bool GetIsActive(bool baseLayer, int x, int y) => GetIsActive(baseLayer ? SAV.FieldItemFlag1 : SAV.FieldItemFlag2, x, y); - public void SetIsActive(bool baseLayer, int x, int y, bool value) => SetIsActive(baseLayer ? SAV.FieldItemFlag1 : SAV.FieldItemFlag2, x, y, value); - - private bool GetIsActive(int ofs, int x, int y) => FlagUtil.GetFlag(SAV.Data, ofs, (y * FieldItemLayer.FieldItemWidth) + x); - private void SetIsActive(int ofs, int x, int y, bool value) => FlagUtil.SetFlag(SAV.Data, ofs, (y * FieldItemLayer.FieldItemWidth) + x, value); - - public bool IsOccupied(int x, int y) => !Layer1.GetTile(x, y).IsNone || !Layer2.GetTile(x, y).IsNone; + Layer1 = new FieldItemLayer(sav.GetFieldItemLayer1()); + Layer2 = new FieldItemLayer(sav.GetFieldItemLayer2()); + SAV = sav; } -} + + /// + /// Stores all values for the back to the . + /// + public void Save() + { + SAV.SetFieldItemLayer1(Layer1.Tiles); + SAV.SetFieldItemLayer2(Layer2.Tiles); + + SetTileActiveFlags(Layer1, SAV.FieldItemFlag1); + SetTileActiveFlags(Layer2, SAV.FieldItemFlag2); + } + + /// + /// Lists out all coordinates of tiles present in that don't have anything underneath in to support them. + /// + /// + public List GetUnsupportedTiles() + { + var result = new List(); + for (int x = 0; x < FieldItemLayer.FieldItemWidth; x++) + { + for (int y = 0; y < FieldItemLayer.FieldItemHeight; y++) + { + var tile = Layer2.GetTile(x, y); + if (tile.IsNone) + continue; + + var support = Layer1.GetTile(x, y); + if (!support.IsNone) + continue; // dunno how to check if the tile can actually have an item put on top of it... + + result.Add($"{x:000},{y:000}"); + } + } + return result; + } + + private void SetTileActiveFlags(ItemLayer tiles, int ofs) + { + // this doesn't set anything; just diagnostic + + // Although the Tiles are arranged y-column (y-x) based, the 'isActive' flags are arranged x-row (x-y) based. + // We can turn the isActive flag off if the item is not a root or the item cannot be animated. + for (int x = 0; x < FieldItemLayer.FieldItemWidth; x++) + { + for (int y = 0; y < FieldItemLayer.FieldItemHeight; y++) + { + var tile = tiles.GetTile(x, y); + var isActive = GetIsActive(ofs, x, y); + if (!isActive) + continue; + + bool empty = tile.IsNone; + if (empty) + Debug.WriteLine($"Flag at ({x},{y}) is not a root object."); + } + } + } + + public bool GetIsActive(bool baseLayer, int x, int y) => GetIsActive(baseLayer ? SAV.FieldItemFlag1 : SAV.FieldItemFlag2, x, y); + public void SetIsActive(bool baseLayer, int x, int y, bool value) => SetIsActive(baseLayer ? SAV.FieldItemFlag1 : SAV.FieldItemFlag2, x, y, value); + + private bool GetIsActive(int ofs, int x, int y) => FlagUtil.GetFlag(SAV.Data, ofs, (y * FieldItemLayer.FieldItemWidth) + x); + private void SetIsActive(int ofs, int x, int y, bool value) => FlagUtil.SetFlag(SAV.Data, ofs, (y * FieldItemLayer.FieldItemWidth) + x, value); + + public bool IsOccupied(int x, int y) => !Layer1.GetTile(x, y).IsNone || !Layer2.GetTile(x, y).IsNone; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Managers/RoomItemManager.cs b/NHSE.Core/Structures/Map/Managers/RoomItemManager.cs index c18c1d9..c964d5d 100644 --- a/NHSE.Core/Structures/Map/Managers/RoomItemManager.cs +++ b/NHSE.Core/Structures/Map/Managers/RoomItemManager.cs @@ -2,55 +2,54 @@ using System.Collections.Generic; using System.Diagnostics; -namespace NHSE.Core +namespace NHSE.Core; + +public class RoomItemManager { - public class RoomItemManager + public readonly RoomItemLayer[] Layers; + + public readonly IPlayerRoom Room; + private const int LayerCount = 8; + + public RoomItemManager(IPlayerRoom room) { - public readonly RoomItemLayer[] Layers; - - public readonly IPlayerRoom Room; - private const int LayerCount = 8; - - public RoomItemManager(IPlayerRoom room) - { - Layers = room.GetItemLayers(); - Room = room; - Debug.Assert(Layers.Length == LayerCount); - } - - public void Save() => Room.SetItemLayers(Layers); - - public bool IsOccupied(int layer, int x, int y) - { - if ((uint)layer >= LayerCount) - throw new ArgumentOutOfRangeException(nameof(layer)); - - var l = Layers[layer]; - var tile = l.GetTile(x, y); - return !tile.IsNone || (layer == (int)RoomLayerSurface.FloorSupported && IsOccupied((int)RoomLayerSurface.Floor, x, y)); - } - - public List GetUnsupportedTiles() - { - var lBase = Layers[(int)RoomLayerSurface.Floor]; - var lSupport = Layers[(int)RoomLayerSurface.FloorSupported]; - var result = new List(); - for (int x = 0; x < lBase.MaxWidth; x++) - { - for (int y = 0; y < lBase.MaxHeight; y++) - { - var tile = lSupport.GetTile(x, y); - if (tile.IsNone) - continue; - - var support = lBase.GetTile(x, y); - if (!support.IsNone) - continue; // dunno how to check if the tile can actually have an item put on top of it... - - result.Add($"{x:000},{y:000}"); - } - } - return result; - } + Layers = room.GetItemLayers(); + Room = room; + Debug.Assert(Layers.Length == LayerCount); } -} + + public void Save() => Room.SetItemLayers(Layers); + + public bool IsOccupied(int layer, int x, int y) + { + if ((uint)layer >= LayerCount) + throw new ArgumentOutOfRangeException(nameof(layer)); + + var l = Layers[layer]; + var tile = l.GetTile(x, y); + return !tile.IsNone || (layer == (int)RoomLayerSurface.FloorSupported && IsOccupied((int)RoomLayerSurface.Floor, x, y)); + } + + public List GetUnsupportedTiles() + { + var lBase = Layers[(int)RoomLayerSurface.Floor]; + var lSupport = Layers[(int)RoomLayerSurface.FloorSupported]; + var result = new List(); + for (int x = 0; x < lBase.MaxWidth; x++) + { + for (int y = 0; y < lBase.MaxHeight; y++) + { + var tile = lSupport.GetTile(x, y); + if (tile.IsNone) + continue; + + var support = lBase.GetTile(x, y); + if (!support.IsNone) + continue; // dunno how to check if the tile can actually have an item put on top of it... + + result.Add($"{x:000},{y:000}"); + } + } + return result; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Managers/RoomLayerSurface.cs b/NHSE.Core/Structures/Map/Managers/RoomLayerSurface.cs index 7457169..d4686eb 100644 --- a/NHSE.Core/Structures/Map/Managers/RoomLayerSurface.cs +++ b/NHSE.Core/Structures/Map/Managers/RoomLayerSurface.cs @@ -1,14 +1,13 @@ -namespace NHSE.Core +namespace NHSE.Core; + +public enum RoomLayerSurface { - public enum RoomLayerSurface - { - Floor = 0, - FloorSupported = 1, - WallNorth = 2, - WallWest = 3, - WallSouth = 4, - WallEast = 5, - Rugs = 6, - Ceiling = 7, - } -} + Floor = 0, + FloorSupported = 1, + WallNorth = 2, + WallWest = 3, + WallSouth = 4, + WallEast = 5, + Rugs = 6, + Ceiling = 7, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/MapGrid.cs b/NHSE.Core/Structures/Map/MapGrid.cs index f9e33f0..cfd3516 100644 --- a/NHSE.Core/Structures/Map/MapGrid.cs +++ b/NHSE.Core/Structures/Map/MapGrid.cs @@ -1,42 +1,41 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Basic logic implementation for interacting with the manipulatable map grid. +/// +public abstract class MapGrid : TileGrid { - /// - /// Basic logic implementation for interacting with the manipulatable map grid. - /// - public abstract class MapGrid : TileGrid + public static readonly AcreCoordinate[] Acres = AcreCoordinate.GetGrid(AcreWidth, AcreHeight); + + public const int AcreWidth = 7; + public const int AcreHeight = 6; + public const int AcreCount = AcreWidth * AcreHeight; + + public const int MapTileCount16x16 = 16 * 16 * AcreCount; + public const int MapTileCount32x32 = 32 * 32 * AcreCount; + + protected MapGrid(int gw, int gh, int mw, int mh) : base(gw, gh, mw, mh) { } + + protected int GetTileIndex(int acreX, int acreY, int gridX, int gridY) { - public static readonly AcreCoordinate[] Acres = AcreCoordinate.GetGrid(AcreWidth, AcreHeight); - - public const int AcreWidth = 7; - public const int AcreHeight = 6; - public const int AcreCount = AcreWidth * AcreHeight; - - public const int MapTileCount16x16 = 16 * 16 * AcreCount; - public const int MapTileCount32x32 = 32 * 32 * AcreCount; - - protected MapGrid(int gw, int gh, int mw, int mh) : base(gw, gh, mw, mh) { } - - protected int GetTileIndex(int acreX, int acreY, int gridX, int gridY) - { - var x = (acreX * GridWidth) + gridX; - var y = (acreY * GridHeight) + gridY; - return GetTileIndex(x, y); - } - - protected int GetAcreTileIndex(int acreIndex, int tileIndex) - { - var acre = Acres[acreIndex]; - var x = (tileIndex % GridWidth); - var y = (tileIndex / GridHeight); - return GetTileIndex(acre.X, acre.Y, x, y); - } - - public int GetAcre(int x, int y) => (x / GridWidth) + ((y / GridHeight) * AcreWidth); - - public void GetViewAnchorCoordinates(int acre, out int x, out int y) - { - x = (acre % AcreWidth) * GridWidth; - y = (acre / AcreWidth) * GridHeight; - } + var x = (acreX * GridWidth) + gridX; + var y = (acreY * GridHeight) + gridY; + return GetTileIndex(x, y); } -} + + protected int GetAcreTileIndex(int acreIndex, int tileIndex) + { + var acre = Acres[acreIndex]; + var x = (tileIndex % GridWidth); + var y = (tileIndex / GridHeight); + return GetTileIndex(acre.X, acre.Y, x, y); + } + + public int GetAcre(int x, int y) => (x / GridWidth) + ((y / GridHeight) * AcreWidth); + + public void GetViewAnchorCoordinates(int acre, out int x, out int y) + { + x = (acre % AcreWidth) * GridWidth; + y = (acre / AcreWidth) * GridHeight; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/OutsideAcre.cs b/NHSE.Core/Structures/Map/OutsideAcre.cs index 6190d69..8958b6e 100644 --- a/NHSE.Core/Structures/Map/OutsideAcre.cs +++ b/NHSE.Core/Structures/Map/OutsideAcre.cs @@ -1,261 +1,260 @@ using System.Collections.Generic; using System.Drawing; -namespace NHSE.Core +namespace NHSE.Core; + +public enum OutsideAcre : ushort { - public enum OutsideAcre : ushort - { - Flat = 00, + Flat = 00, - FldOutNShip00 = 16, + FldOutNShip00 = 16, - FldOutW00 = 20, - FldOutW01 = 21, - FldOutW02 = 22, - FldOutW03 = 23, + FldOutW00 = 20, + FldOutW01 = 21, + FldOutW02 = 22, + FldOutW03 = 23, - FldOutWRiver00 = 27, + FldOutWRiver00 = 27, - FldOutE00 = 29, - FldOutE01 = 30, - FldOutE02 = 31, - FldOutE03 = 32, + FldOutE00 = 29, + FldOutE01 = 30, + FldOutE02 = 31, + FldOutE03 = 32, - FldOutSW00 = 38, - FldOutS00 = 39, - FldOutSRiver00 = 40, - FldOutSAirPortLeft00 = 41, - FldOutSE00 = 42, - FldOutSeaN00 = 43, - FldOutSeaNW00 = 44, - FldOutSeaNE00 = 45, - FldOutSeaW00 = 46, + FldOutSW00 = 38, + FldOutS00 = 39, + FldOutSRiver00 = 40, + FldOutSAirPortLeft00 = 41, + FldOutSE00 = 42, + FldOutSeaN00 = 43, + FldOutSeaNW00 = 44, + FldOutSeaNE00 = 45, + FldOutSeaW00 = 46, - FldOutSeaE00 = 48, + FldOutSeaE00 = 48, - FldOutSeaSW00 = 50, - FldOutSeaS00 = 51, - FldOutSeaSE00 = 52, + FldOutSeaSW00 = 50, + FldOutSeaS00 = 51, + FldOutSeaSE00 = 52, - FldOutE04 = 62, + FldOutE04 = 62, - FldOutERiver00 = 91, - FldOutSW01 = 92, - FldOutSAirPortRight00 = 93, + FldOutERiver00 = 91, + FldOutSW01 = 92, + FldOutSAirPortRight00 = 93, - FldOutS01 = 97, - FldOutSE01 = 98, - FldOutSE03 = 99, - FldOutSE02 = 100, - FldOutSW03 = 101, - FldOutSW02 = 102, - FldOutS03 = 103, - FldOutS02 = 104, - FldOutS04 = 105, - FldOutNEStone00 = 106, - FldOutNStone03 = 107, - FldOutNStone02 = 108, - FldOutNStone01 = 109, - FldOutNStoneR00 = 110, - FldOutNStoneL00 = 111, - FldOutNStone00 = 112, - FldOutNStone04 = 113, + FldOutS01 = 97, + FldOutSE01 = 98, + FldOutSE03 = 99, + FldOutSE02 = 100, + FldOutSW03 = 101, + FldOutSW02 = 102, + FldOutS03 = 103, + FldOutS02 = 104, + FldOutS04 = 105, + FldOutNEStone00 = 106, + FldOutNStone03 = 107, + FldOutNStone02 = 108, + FldOutNStone01 = 109, + FldOutNStoneR00 = 110, + FldOutNStoneL00 = 111, + FldOutNStone00 = 112, + FldOutNStone04 = 113, - FldOutEIslandDown01 = 115, - FldOutEIslandDown00 = 116, - FldOutEIslandUp00 = 117, - FldOutEIslandUp01 = 118, - FldOutWStone01 = 119, - FldOutWStone00 = 120, - FldOutEStone00 = 121, - FldOutEStone01 = 122, - FldOutNEStone01 = 123, - FldOutNWStone01 = 124, - FldOutNWStone00 = 125, - FldOutWCliff00 = 126, - FldOutW04 = 127, - FldOutNShip02 = 128, - FldOutNShip01 = 129, + FldOutEIslandDown01 = 115, + FldOutEIslandDown00 = 116, + FldOutEIslandUp00 = 117, + FldOutEIslandUp01 = 118, + FldOutWStone01 = 119, + FldOutWStone00 = 120, + FldOutEStone00 = 121, + FldOutEStone01 = 122, + FldOutNEStone01 = 123, + FldOutNWStone01 = 124, + FldOutNWStone00 = 125, + FldOutWCliff00 = 126, + FldOutW04 = 127, + FldOutNShip02 = 128, + FldOutNShip01 = 129, - FldOutWCliff01 = 131, - FldOutSRiver01 = 132, - FldOutWRiver01 = 133, - FldOutERiver01 = 134, - FldOutSWBridge01 = 135, - FldOutSWBridge00 = 136, - FldOutSEBridge01 = 137, - FldOutSEBridge00 = 138, - FldOutECliff01 = 139, - FldOutECliff00 = 140, - FldOutWIslandDown00 = 141, - FldOutWIslandDown01 = 142, - FldOutWIslandUp00 = 143, - FldOutWIslandUp01 = 144, - FldOutEStone02 = 145, - FldOutWStone02 = 146, - FldOutSeaN02 = 147, - FldOutSeaN01 = 148, + FldOutWCliff01 = 131, + FldOutSRiver01 = 132, + FldOutWRiver01 = 133, + FldOutERiver01 = 134, + FldOutSWBridge01 = 135, + FldOutSWBridge00 = 136, + FldOutSEBridge01 = 137, + FldOutSEBridge00 = 138, + FldOutECliff01 = 139, + FldOutECliff00 = 140, + FldOutWIslandDown00 = 141, + FldOutWIslandDown01 = 142, + FldOutWIslandUp00 = 143, + FldOutWIslandUp01 = 144, + FldOutEStone02 = 145, + FldOutWStone02 = 146, + FldOutSeaN02 = 147, + FldOutSeaN01 = 148, - FldOutSeaW02 = 151, - FldOutSeaW01 = 152, + FldOutSeaW02 = 151, + FldOutSeaW01 = 152, - FldOutSeaS02 = 155, - FldOutSeaS01 = 156, - FldOutSeaSW02 = 157, - FldOutSeaSW01 = 158, - FldOutSeaNW02 = 159, - FldOutSeaNW01 = 160, - FldOutSeaN05 = 161, - FldOutSeaN04 = 162, - FldOutSeaN03 = 163, - FldOutSeaN08 = 164, - FldOutSeaN07 = 165, - FldOutSeaN06 = 166, + FldOutSeaS02 = 155, + FldOutSeaS01 = 156, + FldOutSeaSW02 = 157, + FldOutSeaSW01 = 158, + FldOutSeaNW02 = 159, + FldOutSeaNW01 = 160, + FldOutSeaN05 = 161, + FldOutSeaN04 = 162, + FldOutSeaN03 = 163, + FldOutSeaN08 = 164, + FldOutSeaN07 = 165, + FldOutSeaN06 = 166, - FldOutSeaNW03 = 172, - FldOutSeaW08 = 173, - FldOutSeaW07 = 174, - FldOutSeaW06 = 175, - FldOutSeaW04 = 176, - FldOutSeaW05 = 177, - FldOutSeaW03 = 178, + FldOutSeaNW03 = 172, + FldOutSeaW08 = 173, + FldOutSeaW07 = 174, + FldOutSeaW06 = 175, + FldOutSeaW04 = 176, + FldOutSeaW05 = 177, + FldOutSeaW03 = 178, - FldOutSeaSW03 = 184, + FldOutSeaSW03 = 184, - FldOutSeaS05 = 191, - FldOutSeaS04 = 192, - FldOutSeaS03 = 193, - FldOutSeaS08 = 194, - FldOutSeaS07 = 195, - FldOutSeaS06 = 196, - FldOutSeaSE02 = 197, - FldOutSeaSE01 = 198, + FldOutSeaS05 = 191, + FldOutSeaS04 = 192, + FldOutSeaS03 = 193, + FldOutSeaS08 = 194, + FldOutSeaS07 = 195, + FldOutSeaS06 = 196, + FldOutSeaSE02 = 197, + FldOutSeaSE01 = 198, - FldOutSeaSE03 = 200, + FldOutSeaSE03 = 200, - FldOutSeaE05 = 205, - FldOutSeaE04 = 206, - FldOutSeaE03 = 207, - FldOutSeaE01 = 208, - FldOutSeaE02 = 209, - FldOutSeaE08 = 210, - FldOutSeaE06 = 211, - FldOutSeaE07 = 212, + FldOutSeaE05 = 205, + FldOutSeaE04 = 206, + FldOutSeaE03 = 207, + FldOutSeaE01 = 208, + FldOutSeaE02 = 209, + FldOutSeaE08 = 210, + FldOutSeaE06 = 211, + FldOutSeaE07 = 212, - FldOutSeaNE03 = 216, - FldOutSeaNE01 = 219, - FldOutSeaNE02 = 220, + FldOutSeaNE03 = 216, + FldOutSeaNE01 = 219, + FldOutSeaNE02 = 220, - FldOutSBridge00 = 222, - FldOutWIslandDown02 = 223, - FldOutWIslandUp02 = 224, - FldOutEIslandDown02 = 225, - FldOutEIslandUp02 = 226, - FldOutECliff02 = 227, - FldOutWCliff02 = 228, - FldOutNEStone02 = 229, - FldOutNWStone02 = 230, - FldOutEStone03 = 231, - FldOutWStone03 = 232, - FldOutSRiver02 = 233, + FldOutSBridge00 = 222, + FldOutWIslandDown02 = 223, + FldOutWIslandUp02 = 224, + FldOutEIslandDown02 = 225, + FldOutEIslandUp02 = 226, + FldOutECliff02 = 227, + FldOutWCliff02 = 228, + FldOutNEStone02 = 229, + FldOutNWStone02 = 230, + FldOutEStone03 = 231, + FldOutWStone03 = 232, + FldOutSRiver02 = 233, - FldOutPhotoSBridge00 = 240, - FldOutPhotoSE00 = 241, - FldOutPhotoSW00 = 242, - FldOutSBridge02 = 243, - FldOutSBridge01 = 244, + FldOutPhotoSBridge00 = 240, + FldOutPhotoSE00 = 241, + FldOutPhotoSW00 = 242, + FldOutSBridge02 = 243, + FldOutSBridge01 = 244, - // New! - FldOutWherearenNW00 = 257, - FldOutWherearenW00 = 258, - FldOutWherearenSW00 = 259, - FldOutWherearenS01 = 260, - FldOutWherearenSE00 = 261, - FldOutWherearenN00 = 262, - FldOutWherearenN01 = 263, - FldOutWherearenNE00 = 264, - FldOutWherearenE00 = 266, - FldOutWherearenS02 = 267, - FldOutSESeaOnly00 = 269, - FldOutESeaOnly00 = 270, - FldOutNESeaOnly00 = 271, - FldOutNWSeaOnly00 = 272, - FldOutSWSeaOnly00 = 273, - FldOutSSeaOnly00 = 274, - FldOutNSeaOnly00 = 275, - FldOutWSeaOnly00 = 276, - FldOutCenterIsland01 = 277, - FldOutCenterIsland02 = 278, - FldOutSGarden00 = 280, - FldOutNGarden00 = 281, - FldOutCenterSand00 = 282, - FldOutNGardenL00 = 283, - FldOutNGardenR00 = 284, - FldOutSGardenL00 = 285, - FldOutSGardenR00 = 286, - FldOutCenterIsland03 = 288, - FldOutMidSea00 = 289, - FldOutCenterIsland04 = 290, - FldOutCenterIsland05 = 291, - FldOutCenterIslandL00 = 292, - FldOutCenterIslandR00 = 293, - FldOutCenterIslandLBack00 = 294, - FldOutCenterIslandRBack00 = 295, - FldOutSBridgeSP02 = 296, - FldOutSBridgeSP01 = 297, - FldOutSBridgeSP00 = 298, - FldOutWHarborN00 = 299, - FldOutWHarborS00 = 300, - FldOutSeaGardenS00 = 301, - FldOutCenterIslandL01 = 302, - FldOutCenterIslandR01 = 303, - FldOutCenterLock00 = 304, - FldOutAroundLock00 = 305, - FldOutCenterIce00 = 306, - FldOutAroundIce00 = 307, - FldOutCenterIsland06 = 308, - FldOutNGardenL01 = 309, - FldOutNGardenR01 = 310, - FldOutWHarborS01 = 311, - FldOutSSeaOnly01 = 312, - FldOutCenterIsland07 = 313, - FldOutSSeaOnly02 = 314, - FldOutEGarden00 = 315, - FldOutNGardenLFront00 = 316, - FldOutNGardenRFront00 = 317, - } - - public static class CollisionUtil - { - public static readonly Dictionary Dict = new() - { - {00, Color.FromArgb( 70, 120, 64)}, // Grass - {01, Color.FromArgb(128, 215, 195)}, // River - {03, Color.FromArgb(192, 192, 192)}, // Stone - {04, Color.FromArgb(240, 230, 170)}, // Sand - {05, Color.FromArgb(128, 215, 195)}, // Sea - {06, Color.FromArgb(255, 128, 128)}, // Wood - {07, Color.FromArgb(0 , 0, 0)}, // Null - {08, Color.FromArgb(32 , 32, 32)}, // Building - {09, Color.FromArgb(255, 0, 0)}, // ?? - {10, Color.FromArgb(48 , 48, 48)}, // Door - {12, Color.FromArgb(128, 215, 195)}, // Water at mouths of river - {15, Color.FromArgb(128, 215, 195)}, // Strip of water between river mouth and river - {22, Color.FromArgb(190, 98, 98)}, // Wood (thin) - {28, Color.FromArgb(255, 0, 0)}, // ?? this one isn't even in ColGroundAttributeParam... - {29, Color.FromArgb(232, 222, 162)}, // Edge of beach, next to sea - {41, Color.FromArgb(118, 122, 132)}, // Rocks at top of map - {42, Color.FromArgb(128, 133, 147)}, // Taller regions, rocks at top of map - {43, Color.Cyan}, // Tide pool - {44, Color.FromArgb( 62, 112, 56)}, // Edge connecting grass and beach - {45, Color.FromArgb(118, 122, 132)}, // Some kind of rock - {46, Color.FromArgb(120, 207, 187)}, // Edge of sea, next to beach - {47, Color.FromArgb(128, 128, 0)}, // Sandstone - {49, Color.FromArgb(190, 98, 98)}, // Pier - {51, Color.FromArgb(32 , 152, 32)}, // "Grass-growing building"?? - {70, Color.FromArgb(109, 113, 124)}, // Kapp'n's island rock - {149, Color.FromArgb(179, 207, 252)}, // Ice (traversable) - {150, Color.FromArgb(61 , 119, 212)}, // Ice (tall, with collision) - }; - } + // New! + FldOutWherearenNW00 = 257, + FldOutWherearenW00 = 258, + FldOutWherearenSW00 = 259, + FldOutWherearenS01 = 260, + FldOutWherearenSE00 = 261, + FldOutWherearenN00 = 262, + FldOutWherearenN01 = 263, + FldOutWherearenNE00 = 264, + FldOutWherearenE00 = 266, + FldOutWherearenS02 = 267, + FldOutSESeaOnly00 = 269, + FldOutESeaOnly00 = 270, + FldOutNESeaOnly00 = 271, + FldOutNWSeaOnly00 = 272, + FldOutSWSeaOnly00 = 273, + FldOutSSeaOnly00 = 274, + FldOutNSeaOnly00 = 275, + FldOutWSeaOnly00 = 276, + FldOutCenterIsland01 = 277, + FldOutCenterIsland02 = 278, + FldOutSGarden00 = 280, + FldOutNGarden00 = 281, + FldOutCenterSand00 = 282, + FldOutNGardenL00 = 283, + FldOutNGardenR00 = 284, + FldOutSGardenL00 = 285, + FldOutSGardenR00 = 286, + FldOutCenterIsland03 = 288, + FldOutMidSea00 = 289, + FldOutCenterIsland04 = 290, + FldOutCenterIsland05 = 291, + FldOutCenterIslandL00 = 292, + FldOutCenterIslandR00 = 293, + FldOutCenterIslandLBack00 = 294, + FldOutCenterIslandRBack00 = 295, + FldOutSBridgeSP02 = 296, + FldOutSBridgeSP01 = 297, + FldOutSBridgeSP00 = 298, + FldOutWHarborN00 = 299, + FldOutWHarborS00 = 300, + FldOutSeaGardenS00 = 301, + FldOutCenterIslandL01 = 302, + FldOutCenterIslandR01 = 303, + FldOutCenterLock00 = 304, + FldOutAroundLock00 = 305, + FldOutCenterIce00 = 306, + FldOutAroundIce00 = 307, + FldOutCenterIsland06 = 308, + FldOutNGardenL01 = 309, + FldOutNGardenR01 = 310, + FldOutWHarborS01 = 311, + FldOutSSeaOnly01 = 312, + FldOutCenterIsland07 = 313, + FldOutSSeaOnly02 = 314, + FldOutEGarden00 = 315, + FldOutNGardenLFront00 = 316, + FldOutNGardenRFront00 = 317, } + +public static class CollisionUtil +{ + public static readonly Dictionary Dict = new() + { + {00, Color.FromArgb( 70, 120, 64)}, // Grass + {01, Color.FromArgb(128, 215, 195)}, // River + {03, Color.FromArgb(192, 192, 192)}, // Stone + {04, Color.FromArgb(240, 230, 170)}, // Sand + {05, Color.FromArgb(128, 215, 195)}, // Sea + {06, Color.FromArgb(255, 128, 128)}, // Wood + {07, Color.FromArgb(0 , 0, 0)}, // Null + {08, Color.FromArgb(32 , 32, 32)}, // Building + {09, Color.FromArgb(255, 0, 0)}, // ?? + {10, Color.FromArgb(48 , 48, 48)}, // Door + {12, Color.FromArgb(128, 215, 195)}, // Water at mouths of river + {15, Color.FromArgb(128, 215, 195)}, // Strip of water between river mouth and river + {22, Color.FromArgb(190, 98, 98)}, // Wood (thin) + {28, Color.FromArgb(255, 0, 0)}, // ?? this one isn't even in ColGroundAttributeParam... + {29, Color.FromArgb(232, 222, 162)}, // Edge of beach, next to sea + {41, Color.FromArgb(118, 122, 132)}, // Rocks at top of map + {42, Color.FromArgb(128, 133, 147)}, // Taller regions, rocks at top of map + {43, Color.Cyan}, // Tide pool + {44, Color.FromArgb( 62, 112, 56)}, // Edge connecting grass and beach + {45, Color.FromArgb(118, 122, 132)}, // Some kind of rock + {46, Color.FromArgb(120, 207, 187)}, // Edge of sea, next to beach + {47, Color.FromArgb(128, 128, 0)}, // Sandstone + {49, Color.FromArgb(190, 98, 98)}, // Pier + {51, Color.FromArgb(32 , 152, 32)}, // "Grass-growing building"?? + {70, Color.FromArgb(109, 113, 124)}, // Kapp'n's island rock + {149, Color.FromArgb(179, 207, 252)}, // Ice (traversable) + {150, Color.FromArgb(61 , 119, 212)}, // Ice (tall, with collision) + }; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Terrain/AcreCoordinate.cs b/NHSE.Core/Structures/Map/Terrain/AcreCoordinate.cs index 72de250..9e19ba5 100644 --- a/NHSE.Core/Structures/Map/Terrain/AcreCoordinate.cs +++ b/NHSE.Core/Structures/Map/Terrain/AcreCoordinate.cs @@ -1,48 +1,47 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Navigation metadata for acre coordinates. +/// +public class AcreCoordinate { - /// - /// Navigation metadata for acre coordinates. - /// - public class AcreCoordinate + public readonly string Name; + public readonly int X, Y; + + public AcreCoordinate(int x, int y) : this((char)('0' + x), (char)('A' + y), x, y) { } + + public AcreCoordinate(char xName, char yName, int x, int y) { - public readonly string Name; - public readonly int X, Y; - - public AcreCoordinate(int x, int y) : this((char)('0' + x), (char)('A' + y), x, y) { } - - public AcreCoordinate(char xName, char yName, int x, int y) - { - Name = $"{yName}{xName}"; - X = x; - Y = y; - } - - public static AcreCoordinate[] GetGrid(int width, int height) - { - var result = new AcreCoordinate[width * height]; - int i = 0; - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - result[i++] = new AcreCoordinate(x, y); - } - return result; - } - - public static AcreCoordinate[] GetGridWithExterior(int width, int height) - { - var result = new AcreCoordinate[width * height]; - int i = 0; - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - var xn = (x == 0) ? '<' : x == width - 1 ? '>' : (char)('0' + x - 1); - var yn = (y == 0) ? '^' : y == height - 1 ? 'V' : (char)('A' + y - 1); - result[i++] = new AcreCoordinate(xn, yn, x, y); - } - } - return result; - } + Name = $"{yName}{xName}"; + X = x; + Y = y; } -} + + public static AcreCoordinate[] GetGrid(int width, int height) + { + var result = new AcreCoordinate[width * height]; + int i = 0; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + result[i++] = new AcreCoordinate(x, y); + } + return result; + } + + public static AcreCoordinate[] GetGridWithExterior(int width, int height) + { + var result = new AcreCoordinate[width * height]; + int i = 0; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + var xn = (x == 0) ? '<' : x == width - 1 ? '>' : (char)('0' + x - 1); + var yn = (y == 0) ? '^' : y == height - 1 ? 'V' : (char)('A' + y - 1); + result[i++] = new AcreCoordinate(xn, yn, x, y); + } + } + return result; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Terrain/PlacedItemPermission.cs b/NHSE.Core/Structures/Map/Terrain/PlacedItemPermission.cs index 01b2f02..c5547b2 100644 --- a/NHSE.Core/Structures/Map/Terrain/PlacedItemPermission.cs +++ b/NHSE.Core/Structures/Map/Terrain/PlacedItemPermission.cs @@ -1,23 +1,22 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Flagging various issues when trying to place an item. +/// +public enum PlacedItemPermission { /// - /// Flagging various issues when trying to place an item. + /// Item does not have any of its tiles overlapping with any other items. /// - public enum PlacedItemPermission - { - /// - /// Item does not have any of its tiles overlapping with any other items. - /// - NoCollision, + NoCollision, - /// - /// Item tiles are overlapping with another item. - /// - Collision, + /// + /// Item tiles are overlapping with another item. + /// + Collision, - /// - /// Item tiles would overflow out-of-bounds. - /// - OutOfBounds, - } -} + /// + /// Item tiles would overflow out-of-bounds. + /// + OutOfBounds, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Terrain/TerrainTile.cs b/NHSE.Core/Structures/Map/Terrain/TerrainTile.cs index 0d509ba..545f292 100644 --- a/NHSE.Core/Structures/Map/Terrain/TerrainTile.cs +++ b/NHSE.Core/Structures/Map/Terrain/TerrainTile.cs @@ -1,98 +1,98 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Represents a Terraform-able terrain tile. +/// +[StructLayout(LayoutKind.Sequential)] +public class TerrainTile { - /// - /// Represents a Terraform-able terrain tile. - /// - [StructLayout(LayoutKind.Sequential)] - public class TerrainTile + // tile[2] (u16 model, u16 variation, u16 angle) + // u16 elevation + public const int SIZE = 0xE; + private const string Terrain = nameof(Terrain); + private const string Road = nameof(Road); + private const string Details = nameof(Details); + + // Tile + [Category(Terrain), Description("Terrain model to be loaded for this tile.")] + public TerrainUnitModel UnitModel { get; set; } + + [Category(Terrain), Description("Variant of the terrain model.")] + public ushort Variation { get; set; } + + [Category(Terrain), Description("Angle of the terrain model.")] + public ushort LandMakingAngle { get; set; } + + // Road + [Category(Road), Description("Road model to be loaded on top of the Terrain model.")] + public TerrainUnitModel UnitModelRoad { get; set; } + + [Category(Road), Description("Variant of the road model.")] + public ushort VariationRoad { get; set; } + + [Category(Road), Description("Angle of the road model.")] + public ushort LandMakingAngleRoad { get; set; } + + // Elevation + [Category(Details), Description("How high the terrain tile is elevated.")] + public ushort Elevation { get; set; } + + public static TerrainTile[] GetArray(ReadOnlySpan data) => data.GetArray(SIZE); + public static byte[] SetArray(IReadOnlyList data) => data.SetArray(SIZE); + + public void Clear() { - // tile[2] (u16 model, u16 variation, u16 angle) - // u16 elevation - public const int SIZE = 0xE; - private const string Terrain = nameof(Terrain); - private const string Road = nameof(Road); - private const string Details = nameof(Details); - - // Tile - [Category(Terrain), Description("Terrain model to be loaded for this tile.")] - public TerrainUnitModel UnitModel { get; set; } - - [Category(Terrain), Description("Variant of the terrain model.")] - public ushort Variation { get; set; } - - [Category(Terrain), Description("Angle of the terrain model.")] - public ushort LandMakingAngle { get; set; } - - // Road - [Category(Road), Description("Road model to be loaded on top of the Terrain model.")] - public TerrainUnitModel UnitModelRoad { get; set; } - - [Category(Road), Description("Variant of the road model.")] - public ushort VariationRoad { get; set; } - - [Category(Road), Description("Angle of the road model.")] - public ushort LandMakingAngleRoad { get; set; } - - // Elevation - [Category(Details), Description("How high the terrain tile is elevated.")] - public ushort Elevation { get; set; } - - public static TerrainTile[] GetArray(byte[] data) => data.GetArray(SIZE); - public static byte[] SetArray(IReadOnlyList data) => data.SetArray(SIZE); - - public void Clear() - { - UnitModel = UnitModelRoad = 0; - Variation = LandMakingAngle = VariationRoad = LandMakingAngleRoad = Elevation = 0; - } - - public void CopyFrom(TerrainTile source) - { - UnitModel = source.UnitModel; - Variation = source.Variation; - LandMakingAngle = source.LandMakingAngle; - UnitModelRoad = source.UnitModelRoad; - VariationRoad = source.VariationRoad; - LandMakingAngleRoad = source.LandMakingAngleRoad; - Elevation = source.Elevation; - } - - public void CopyGroundFrom(TerrainTile tile) - { - UnitModel = tile.UnitModel; - Variation = tile.Variation; - LandMakingAngle = tile.LandMakingAngle; - } - - public void CopyRoadFrom(TerrainTile tile) - { - UnitModelRoad = tile.UnitModelRoad; - VariationRoad = tile.VariationRoad; - LandMakingAngleRoad = tile.LandMakingAngleRoad; - } - - public bool Rotate() => UnitModelRoad != 0 ? RotateRoad() : RotateTerrain(); - - private bool RotateTerrain() - { - if (UnitModel == TerrainUnitModel.Base) - return false; - var rot = LandMakingAngle; - rot = (ushort)((rot + 1) & 3); - LandMakingAngle = rot; - return true; - } - - private bool RotateRoad() - { - var rot = LandMakingAngleRoad; - rot = (ushort) ((rot + 1) & 3); - LandMakingAngleRoad = rot; - return true; - } + UnitModel = UnitModelRoad = 0; + Variation = LandMakingAngle = VariationRoad = LandMakingAngleRoad = Elevation = 0; } -} + + public void CopyFrom(TerrainTile source) + { + UnitModel = source.UnitModel; + Variation = source.Variation; + LandMakingAngle = source.LandMakingAngle; + UnitModelRoad = source.UnitModelRoad; + VariationRoad = source.VariationRoad; + LandMakingAngleRoad = source.LandMakingAngleRoad; + Elevation = source.Elevation; + } + + public void CopyGroundFrom(TerrainTile tile) + { + UnitModel = tile.UnitModel; + Variation = tile.Variation; + LandMakingAngle = tile.LandMakingAngle; + } + + public void CopyRoadFrom(TerrainTile tile) + { + UnitModelRoad = tile.UnitModelRoad; + VariationRoad = tile.VariationRoad; + LandMakingAngleRoad = tile.LandMakingAngleRoad; + } + + public bool Rotate() => UnitModelRoad != 0 ? RotateRoad() : RotateTerrain(); + + private bool RotateTerrain() + { + if (UnitModel == TerrainUnitModel.Base) + return false; + var rot = LandMakingAngle; + rot = (ushort)((rot + 1) & 3); + LandMakingAngle = rot; + return true; + } + + private bool RotateRoad() + { + var rot = LandMakingAngleRoad; + rot = (ushort) ((rot + 1) & 3); + LandMakingAngleRoad = rot; + return true; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/Terrain/TerrainUnitModel.cs b/NHSE.Core/Structures/Map/Terrain/TerrainUnitModel.cs index a980ec3..2cb040b 100644 --- a/NHSE.Core/Structures/Map/Terrain/TerrainUnitModel.cs +++ b/NHSE.Core/Structures/Map/Terrain/TerrainUnitModel.cs @@ -1,282 +1,283 @@ using static NHSE.Core.TerrainUnitModel; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Model to be used when the renders / references collision data. +/// +public enum TerrainUnitModel : ushort { - /// - /// Model to be used when the renders / references collision data. - /// - public enum TerrainUnitModel : ushort - { - Base = 0x00, - River0A = 0x01, - River1A = 0x04, - River2A = 0x07, - River2B = 0x08, - River2C = 0x09, - River3A = 0x0A, - River3B = 0x0B, - River3C = 0x0C, - River4A = 0x0D, - River4B = 0x0E, - River4C = 0x0F, - River5A = 0x10, - River5B = 0x11, - River6A = 0x12, - River6B = 0x13, - River7A = 0x14, - River8A = 0x15, - Cliff0A = 0x16, - Cliff0A_2 = 0x17, - Cliff0A_3 = 0x18, - Cliff1A = 0x19, - Cliff1A_2 = 0x1A, - Cliff1A_3 = 0x1B, - Cliff2A = 0x1C, - Cliff2C = 0x1D, - Cliff3A = 0x1E, - Cliff3B = 0x1F, - Cliff3C = 0x20, - Cliff4A = 0x21, - Cliff4B = 0x22, - Cliff4C = 0x23, - Cliff5A = 0x24, - Cliff5B = 0x25, - Cliff6A = 0x26, - Cliff6B = 0x27, - Cliff7A = 0x28, - Cliff8 = 0x29, - Fall101 = 0x3A, - Fall100 = 0x3B, - Fall300 = 0x3C, - Fall301 = 0x3D, - Fall302 = 0x3E, - Fall200 = 0x3F, - Fall201 = 0x40, - Fall202 = 0x41, - Fall400 = 0x42, - Fall401 = 0x43, - Fall402 = 0x44, - Fall403 = 0x45, - Fall404 = 0x46, - RoadSoil0A = 0x47, - RoadSoil1A = 0x48, - RoadSoil0B = 0x49, - RoadSoil1B = 0x4B, - RoadSoil1C = 0x4C, - RoadSoil2A = 0x4D, - RoadSoil2B = 0x4E, - RoadSoil2C = 0x4F, - RoadSoil3A = 0x50, - RoadSoil3B = 0x51, - RoadSoil3C = 0x52, - RoadSoil4A = 0x53, - RoadSoil4B = 0x54, - RoadSoil4C = 0x55, - RoadSoil5A = 0x56, - RoadSoil5B = 0x57, - RoadSoil6A = 0x58, - RoadSoil6B = 0x59, - RoadSoil7A = 0x5A, - RoadSoil8A = 0x5B, - RoadStone0A = 0x5C, - RoadStone0B = 0x5D, - RoadStone1A = 0x5F, - RoadStone1B = 0x60, - RoadStone1C = 0x61, - RoadStone2A = 0x62, - RoadStone2B = 0x63, - RoadStone2C = 0x64, - RoadStone3A = 0x65, - RoadStone3B = 0x66, - RoadStone3C = 0x67, - RoadStone4A = 0x68, - RoadStone4B = 0x69, - RoadStone4C = 0x6A, - RoadStone5A = 0x6B, - RoadStone5B = 0x6C, - RoadStone6A = 0x6D, - RoadStone6B = 0x6E, - RoadStone7A = 0x6F, - RoadStone8A = 0x70, - Fall103 = 0x71, - Fall102 = 0x72, - Fall303 = 0x73, - Fall304 = 0x74, - Fall305 = 0x75, - Fall306 = 0x76, - Fall307 = 0x77, - Fall308 = 0x78, - Fall203 = 0x79, - Fall204 = 0x7A, - Fall205 = 0x7B, - Fall206 = 0x7C, - Fall207 = 0x7D, - Fall208 = 0x7E, - Fall405 = 0x7F, - Fall406 = 0x80, - Fall407 = 0x81, - Fall408 = 0x82, - Fall410 = 0x83, - Fall409 = 0x84, - Fall411 = 0x85, - Fall412 = 0x86, - Fall414 = 0x87, - Fall413 = 0x88, - Fall415 = 0x89, - Fall416 = 0x8A, - Fall418 = 0x8B, - Fall417 = 0x8C, - Fall419 = 0x8D, - Fall420 = 0x8E, - Fall422 = 0x8F, - Fall421 = 0x90, - Fall423 = 0x91, - Fall424 = 0x92, - Cliff2B = 0x93, - RoadBrick0A = 0x94, - RoadBrick0B = 0x95, - RoadBrick1A = 0x97, - RoadBrick1B = 0x98, - RoadBrick1C = 0x99, - RoadBrick2A = 0x9A, - RoadBrick2B = 0x9B, - RoadBrick2C = 0x9C, - RoadBrick3A = 0x9D, - RoadBrick3B = 0x9E, - RoadBrick3C = 0x9F, - RoadBrick4A = 0xA0, - RoadBrick4B = 0xA1, - RoadBrick4C = 0xA2, - RoadBrick5A = 0xA3, - RoadBrick5B = 0xA4, - RoadBrick6A = 0xA5, - RoadBrick6B = 0xA6, - RoadBrick7A = 0xA7, - RoadBrick8A = 0xA8, - RoadDarkSoil0A = 0xA9, - RoadDarkSoil0B = 0xAA, - RoadDarkSoil1A = 0xAC, - RoadDarkSoil1B = 0xAD, - RoadDarkSoil1C = 0xAE, - RoadDarkSoil2A = 0xAF, - RoadDarkSoil2B = 0xB0, - RoadDarkSoil2C = 0xB1, - RoadDarkSoil3A = 0xB2, - RoadDarkSoil3B = 0xB3, - RoadDarkSoil3C = 0xB4, - RoadDarkSoil4A = 0xB5, - RoadDarkSoil4B = 0xB6, - RoadDarkSoil4C = 0xB7, - RoadDarkSoil5A = 0xB8, - RoadDarkSoil5B = 0xB9, - RoadDarkSoil6A = 0xBA, - RoadDarkSoil6B = 0xBB, - RoadDarkSoil7A = 0xBC, - RoadDarkSoil8A = 0xBD, - RoadFanPattern0A = 0xBE, - RoadFanPattern0B = 0xBF, - RoadFanPattern1A = 0xC1, - RoadFanPattern1B = 0xC2, - RoadFanPattern1C = 0xC3, - RoadFanPattern2A = 0xC4, - RoadFanPattern2B = 0xC5, - RoadFanPattern2C = 0xC6, - RoadFanPattern3A = 0xC7, - RoadFanPattern3B = 0xC8, - RoadFanPattern3C = 0xC9, - RoadFanPattern4A = 0xCA, - RoadFanPattern4B = 0xCB, - RoadFanPattern4C = 0xCC, - RoadFanPattern5A = 0xCD, - RoadFanPattern5B = 0xCE, - RoadFanPattern6A = 0xCF, - RoadFanPattern6B = 0xD0, - RoadFanPattern7A = 0xD1, - RoadFanPattern8A = 0xD2, - RoadSand0A = 0xD3, - RoadSand0B = 0xD4, - RoadSand1A = 0xD6, - RoadSand1B = 0xD7, - RoadSand1C = 0xD8, - RoadSand2A = 0xD9, - RoadSand2B = 0xDA, - RoadSand2C = 0xDB, - RoadSand3A = 0xDC, - RoadSand3B = 0xDD, - RoadSand3C = 0xDE, - RoadSand4A = 0xDF, - RoadSand4B = 0xE0, - RoadSand4C = 0xE1, - RoadSand5A = 0xE2, - RoadSand5B = 0xE3, - RoadSand6A = 0xE4, - RoadSand6B = 0xE5, - RoadSand7A = 0xE6, - RoadSand8A = 0xE7, - RoadTile0A = 0xE8, - RoadTile0B = 0xE9, - RoadTile1A = 0xEB, - RoadTile1B = 0xEC, - RoadTile1C = 0xED, - RoadTile2A = 0xEE, - RoadTile2B = 0xEF, - RoadTile2C = 0xF0, - RoadTile3A = 0xF1, - RoadTile3B = 0xF2, - RoadTile3C = 0xF3, - RoadTile4A = 0xF4, - RoadTile4B = 0xF5, - RoadTile4C = 0xF6, - RoadTile5A = 0xF7, - RoadTile5B = 0xF8, - RoadTile6A = 0xF9, - RoadTile6B = 0xFA, - RoadTile7A = 0xFB, - RoadTile8A = 0xFC, - RoadWood0A = 0xFD, - RoadWood0B = 0xFE, - RoadWood1A = 0x100, - RoadWood1B = 0x101, - RoadWood1C = 0x102, - RoadWood2A = 0x103, - RoadWood2B = 0x104, - RoadWood2C = 0x105, - RoadWood3A = 0x106, - RoadWood3B = 0x107, - RoadWood3C = 0x108, - RoadWood4A = 0x109, - RoadWood4B = 0x10A, - RoadWood4C = 0x10B, - RoadWood5A = 0x10C, - RoadWood5B = 0x10D, - RoadWood6A = 0x10E, - RoadWood6B = 0x10F, - RoadWood7A = 0x110, - RoadWood8A = 0x111, - } - - public enum LandAngles - { - Default = 0, - Rotate90ClockAnverse = 1, - Rotate180ClockAnverse = 2, - Rotate270ClockAnverse = 3, - } - - public static class TerrainUnitModelExtensions - { - public static bool IsRoad(this TerrainUnitModel t) => t >= RoadBrick0A || (RoadSoil0A <= t && t <= RoadStone8A); - public static bool IsRoadWood(this TerrainUnitModel t) => RoadWood0A <= t && t <= RoadWood8A; - public static bool IsRoadTile(this TerrainUnitModel t) => RoadTile0A <= t && t <= RoadTile8A; - public static bool IsRoadSand(this TerrainUnitModel t) => RoadSand0A <= t && t <= RoadSand8A; - public static bool IsRoadPattern(this TerrainUnitModel t) => RoadFanPattern0A <= t && t <= RoadFanPattern8A; - public static bool IsRoadDarkSoil(this TerrainUnitModel t) => RoadDarkSoil0A <= t && t <= RoadDarkSoil8A; - public static bool IsRoadBrick(this TerrainUnitModel t) => RoadBrick0A <= t && t <= RoadBrick8A; - public static bool IsRoadStone(this TerrainUnitModel t) => RoadStone0A <= t && t <= RoadStone8A; - public static bool IsRoadSoil(this TerrainUnitModel t) => RoadSoil0A <= t && t <= RoadSoil8A; - - public static bool IsFall(this TerrainUnitModel t) => (Fall101 <= t && t <= Fall404) || (Fall103 <= t && t <= Fall424); - public static bool IsCliff(this TerrainUnitModel t) => (Cliff0A <= t && t <= Cliff8) || (t == Cliff2B); - public static bool IsRiver(this TerrainUnitModel t) => River0A <= t && t <= River8A; - } + Base = 0x00, + River0A = 0x01, + River1A = 0x04, + River2A = 0x07, + River2B = 0x08, + River2C = 0x09, + River3A = 0x0A, + River3B = 0x0B, + River3C = 0x0C, + River4A = 0x0D, + River4B = 0x0E, + River4C = 0x0F, + River5A = 0x10, + River5B = 0x11, + River6A = 0x12, + River6B = 0x13, + River7A = 0x14, + River8A = 0x15, + Cliff0A = 0x16, + Cliff0A_2 = 0x17, + Cliff0A_3 = 0x18, + Cliff1A = 0x19, + Cliff1A_2 = 0x1A, + Cliff1A_3 = 0x1B, + Cliff2A = 0x1C, + Cliff2C = 0x1D, + Cliff3A = 0x1E, + Cliff3B = 0x1F, + Cliff3C = 0x20, + Cliff4A = 0x21, + Cliff4B = 0x22, + Cliff4C = 0x23, + Cliff5A = 0x24, + Cliff5B = 0x25, + Cliff6A = 0x26, + Cliff6B = 0x27, + Cliff7A = 0x28, + Cliff8 = 0x29, + Fall101 = 0x3A, + Fall100 = 0x3B, + Fall300 = 0x3C, + Fall301 = 0x3D, + Fall302 = 0x3E, + Fall200 = 0x3F, + Fall201 = 0x40, + Fall202 = 0x41, + Fall400 = 0x42, + Fall401 = 0x43, + Fall402 = 0x44, + Fall403 = 0x45, + Fall404 = 0x46, + RoadSoil0A = 0x47, + RoadSoil1A = 0x48, + RoadSoil0B = 0x49, + RoadSoil1B = 0x4B, + RoadSoil1C = 0x4C, + RoadSoil2A = 0x4D, + RoadSoil2B = 0x4E, + RoadSoil2C = 0x4F, + RoadSoil3A = 0x50, + RoadSoil3B = 0x51, + RoadSoil3C = 0x52, + RoadSoil4A = 0x53, + RoadSoil4B = 0x54, + RoadSoil4C = 0x55, + RoadSoil5A = 0x56, + RoadSoil5B = 0x57, + RoadSoil6A = 0x58, + RoadSoil6B = 0x59, + RoadSoil7A = 0x5A, + RoadSoil8A = 0x5B, + RoadStone0A = 0x5C, + RoadStone0B = 0x5D, + RoadStone1A = 0x5F, + RoadStone1B = 0x60, + RoadStone1C = 0x61, + RoadStone2A = 0x62, + RoadStone2B = 0x63, + RoadStone2C = 0x64, + RoadStone3A = 0x65, + RoadStone3B = 0x66, + RoadStone3C = 0x67, + RoadStone4A = 0x68, + RoadStone4B = 0x69, + RoadStone4C = 0x6A, + RoadStone5A = 0x6B, + RoadStone5B = 0x6C, + RoadStone6A = 0x6D, + RoadStone6B = 0x6E, + RoadStone7A = 0x6F, + RoadStone8A = 0x70, + Fall103 = 0x71, + Fall102 = 0x72, + Fall303 = 0x73, + Fall304 = 0x74, + Fall305 = 0x75, + Fall306 = 0x76, + Fall307 = 0x77, + Fall308 = 0x78, + Fall203 = 0x79, + Fall204 = 0x7A, + Fall205 = 0x7B, + Fall206 = 0x7C, + Fall207 = 0x7D, + Fall208 = 0x7E, + Fall405 = 0x7F, + Fall406 = 0x80, + Fall407 = 0x81, + Fall408 = 0x82, + Fall410 = 0x83, + Fall409 = 0x84, + Fall411 = 0x85, + Fall412 = 0x86, + Fall414 = 0x87, + Fall413 = 0x88, + Fall415 = 0x89, + Fall416 = 0x8A, + Fall418 = 0x8B, + Fall417 = 0x8C, + Fall419 = 0x8D, + Fall420 = 0x8E, + Fall422 = 0x8F, + Fall421 = 0x90, + Fall423 = 0x91, + Fall424 = 0x92, + Cliff2B = 0x93, + RoadBrick0A = 0x94, + RoadBrick0B = 0x95, + RoadBrick1A = 0x97, + RoadBrick1B = 0x98, + RoadBrick1C = 0x99, + RoadBrick2A = 0x9A, + RoadBrick2B = 0x9B, + RoadBrick2C = 0x9C, + RoadBrick3A = 0x9D, + RoadBrick3B = 0x9E, + RoadBrick3C = 0x9F, + RoadBrick4A = 0xA0, + RoadBrick4B = 0xA1, + RoadBrick4C = 0xA2, + RoadBrick5A = 0xA3, + RoadBrick5B = 0xA4, + RoadBrick6A = 0xA5, + RoadBrick6B = 0xA6, + RoadBrick7A = 0xA7, + RoadBrick8A = 0xA8, + RoadDarkSoil0A = 0xA9, + RoadDarkSoil0B = 0xAA, + RoadDarkSoil1A = 0xAC, + RoadDarkSoil1B = 0xAD, + RoadDarkSoil1C = 0xAE, + RoadDarkSoil2A = 0xAF, + RoadDarkSoil2B = 0xB0, + RoadDarkSoil2C = 0xB1, + RoadDarkSoil3A = 0xB2, + RoadDarkSoil3B = 0xB3, + RoadDarkSoil3C = 0xB4, + RoadDarkSoil4A = 0xB5, + RoadDarkSoil4B = 0xB6, + RoadDarkSoil4C = 0xB7, + RoadDarkSoil5A = 0xB8, + RoadDarkSoil5B = 0xB9, + RoadDarkSoil6A = 0xBA, + RoadDarkSoil6B = 0xBB, + RoadDarkSoil7A = 0xBC, + RoadDarkSoil8A = 0xBD, + RoadFanPattern0A = 0xBE, + RoadFanPattern0B = 0xBF, + RoadFanPattern1A = 0xC1, + RoadFanPattern1B = 0xC2, + RoadFanPattern1C = 0xC3, + RoadFanPattern2A = 0xC4, + RoadFanPattern2B = 0xC5, + RoadFanPattern2C = 0xC6, + RoadFanPattern3A = 0xC7, + RoadFanPattern3B = 0xC8, + RoadFanPattern3C = 0xC9, + RoadFanPattern4A = 0xCA, + RoadFanPattern4B = 0xCB, + RoadFanPattern4C = 0xCC, + RoadFanPattern5A = 0xCD, + RoadFanPattern5B = 0xCE, + RoadFanPattern6A = 0xCF, + RoadFanPattern6B = 0xD0, + RoadFanPattern7A = 0xD1, + RoadFanPattern8A = 0xD2, + RoadSand0A = 0xD3, + RoadSand0B = 0xD4, + RoadSand1A = 0xD6, + RoadSand1B = 0xD7, + RoadSand1C = 0xD8, + RoadSand2A = 0xD9, + RoadSand2B = 0xDA, + RoadSand2C = 0xDB, + RoadSand3A = 0xDC, + RoadSand3B = 0xDD, + RoadSand3C = 0xDE, + RoadSand4A = 0xDF, + RoadSand4B = 0xE0, + RoadSand4C = 0xE1, + RoadSand5A = 0xE2, + RoadSand5B = 0xE3, + RoadSand6A = 0xE4, + RoadSand6B = 0xE5, + RoadSand7A = 0xE6, + RoadSand8A = 0xE7, + RoadTile0A = 0xE8, + RoadTile0B = 0xE9, + RoadTile1A = 0xEB, + RoadTile1B = 0xEC, + RoadTile1C = 0xED, + RoadTile2A = 0xEE, + RoadTile2B = 0xEF, + RoadTile2C = 0xF0, + RoadTile3A = 0xF1, + RoadTile3B = 0xF2, + RoadTile3C = 0xF3, + RoadTile4A = 0xF4, + RoadTile4B = 0xF5, + RoadTile4C = 0xF6, + RoadTile5A = 0xF7, + RoadTile5B = 0xF8, + RoadTile6A = 0xF9, + RoadTile6B = 0xFA, + RoadTile7A = 0xFB, + RoadTile8A = 0xFC, + RoadWood0A = 0xFD, + RoadWood0B = 0xFE, + RoadWood1A = 0x100, + RoadWood1B = 0x101, + RoadWood1C = 0x102, + RoadWood2A = 0x103, + RoadWood2B = 0x104, + RoadWood2C = 0x105, + RoadWood3A = 0x106, + RoadWood3B = 0x107, + RoadWood3C = 0x108, + RoadWood4A = 0x109, + RoadWood4B = 0x10A, + RoadWood4C = 0x10B, + RoadWood5A = 0x10C, + RoadWood5B = 0x10D, + RoadWood6A = 0x10E, + RoadWood6B = 0x10F, + RoadWood7A = 0x110, + RoadWood8A = 0x111, } + +public enum LandAngles +{ + Default = 0, + Rotate90ClockAnverse = 1, + Rotate180ClockAnverse = 2, + Rotate270ClockAnverse = 3, +} + +public static class TerrainUnitModelExtensions +{ + extension(TerrainUnitModel t) + { + public bool IsRoad => t is >= RoadBrick0A or (>= RoadSoil0A and <= RoadStone8A); + public bool IsRoadWood => t is (>= RoadWood0A and <= RoadWood8A); + public bool IsRoadTile => t is (>= RoadTile0A and <= RoadTile8A); + public bool IsRoadSand => t is (>= RoadSand0A and <= RoadSand8A); + public bool IsRoadPattern => t is (>= RoadFanPattern0A and <= RoadFanPattern8A); + public bool IsRoadDarkSoil => t is (>= RoadDarkSoil0A and <= RoadDarkSoil8A); + public bool IsRoadBrick => t is (>= RoadBrick0A and <= RoadBrick8A); + public bool IsRoadStone => t is (>= RoadStone0A and <= RoadStone8A); + public bool IsRoadSoil => t is (>= RoadSoil0A and <= RoadSoil8A); + public bool IsFall => t is (>= Fall101 and <= Fall404) or (>= Fall103 and <= Fall424); + public bool IsCliff => t is (>= Cliff0A and <= Cliff8) or Cliff2B; + public bool IsRiver => t is (>= River0A and <= River8A); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Map/TileGrid.cs b/NHSE.Core/Structures/Map/TileGrid.cs index 90e3235..4a176e4 100644 --- a/NHSE.Core/Structures/Map/TileGrid.cs +++ b/NHSE.Core/Structures/Map/TileGrid.cs @@ -1,77 +1,76 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Basic logic implementation for interacting with the manipulatable tile grid. +/// +/// +/// Certain use this as a viewport on a subsection of the entire tile-set. +/// +public abstract class TileGrid { - /// - /// Basic logic implementation for interacting with the manipulatable tile grid. - /// - /// - /// Certain use this as a viewport on a subsection of the entire tile-set. - /// - public abstract class TileGrid + /// Amount of viewable tiles wide + public readonly int GridWidth; + + /// Amount of viewable tiles high + public readonly int GridHeight; + + /// Max amount of tiles wide the entire grid is + public readonly int MaxWidth; + + /// Max amount of tiles high the entire grid is + public readonly int MaxHeight; + + protected TileGrid(in int gw, in int gh, in int mw, in int mh) { - /// Amount of viewable tiles wide - public readonly int GridWidth; - - /// Amount of viewable tiles high - public readonly int GridHeight; - - /// Max amount of tiles wide the entire grid is - public readonly int MaxWidth; - - /// Max amount of tiles high the entire grid is - public readonly int MaxHeight; - - protected TileGrid(in int gw, in int gh, in int mw, in int mh) - { - GridWidth = gw; - GridHeight = gh; - MaxWidth = mw; - MaxHeight = mh; - } - - /// - /// Amount of tiles present in the grid. - /// - public int GridTileCount => GridWidth * GridHeight; - - /// - /// Amount of ALL tiles present in the entire grid (including the grid). - /// - public int MaxTileCount => MaxWidth * MaxHeight; - - protected int GetTileIndex(in int x, in int y) => (MaxHeight * x) + y; - - public void ClampCoordinatesInsideGrid(ref int x, ref int y) => ClampCoordinatesTo(ref x, ref y, MaxWidth - 1, MaxHeight - 1); - - public void ClampCoordinatesTopLeft(ref int x, ref int y) - { - int maxX = MaxWidth - GridWidth; - int maxY = MaxHeight - GridHeight; - ClampCoordinatesTo(ref x, ref y, maxX, maxY); - } - - private static void ClampCoordinatesTo(ref int x, ref int y, int maxX, int maxY) - { - x = Math.Max(0, Math.Min(x, maxX)); - y = Math.Max(0, Math.Min(y, maxY)); - } - - public void GetViewAnchorCoordinates(ref int x, ref int y, in bool centerReticle) - { - // If we aren't snapping the reticle to the nearest acre - // we want to put the middle of the reticle rectangle where the cursor is. - // Adjust the view coordinate - if (!centerReticle) - { - // Reticle size is GridWidth, center = /2 - x -= GridWidth / 2; - y -= GridWidth / 2; - } - - // Clamp to viewport dimensions, and center to nearest acre if desired. - // Clamp to boundaries so that we always have 16x16 to view. - ClampCoordinatesTopLeft(ref x, ref y); - } + GridWidth = gw; + GridHeight = gh; + MaxWidth = mw; + MaxHeight = mh; } -} + + /// + /// Amount of tiles present in the grid. + /// + public int GridTileCount => GridWidth * GridHeight; + + /// + /// Amount of ALL tiles present in the entire grid (including the grid). + /// + public int MaxTileCount => MaxWidth * MaxHeight; + + protected int GetTileIndex(in int x, in int y) => (MaxHeight * x) + y; + + public void ClampCoordinatesInsideGrid(ref int x, ref int y) => ClampCoordinatesTo(ref x, ref y, MaxWidth - 1, MaxHeight - 1); + + public void ClampCoordinatesTopLeft(ref int x, ref int y) + { + int maxX = MaxWidth - GridWidth; + int maxY = MaxHeight - GridHeight; + ClampCoordinatesTo(ref x, ref y, maxX, maxY); + } + + private static void ClampCoordinatesTo(ref int x, ref int y, int maxX, int maxY) + { + x = Math.Max(0, Math.Min(x, maxX)); + y = Math.Max(0, Math.Min(y, maxY)); + } + + public void GetViewAnchorCoordinates(ref int x, ref int y, in bool centerReticle) + { + // If we aren't snapping the reticle to the nearest acre + // we want to put the middle of the reticle rectangle where the cursor is. + // Adjust the view coordinate + if (!centerReticle) + { + // Reticle size is GridWidth, center = /2 + x -= GridWidth / 2; + y -= GridWidth / 2; + } + + // Clamp to viewport dimensions, and center to nearest acre if desired. + // Clamp to boundaries so that we always have 16x16 to view. + ClampCoordinatesTopLeft(ref x, ref y); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/AchievementList.cs b/NHSE.Core/Structures/Misc/AchievementList.cs index 60d00dc..f37e3f2 100644 --- a/NHSE.Core/Structures/Misc/AchievementList.cs +++ b/NHSE.Core/Structures/Misc/AchievementList.cs @@ -1,120 +1,119 @@ using System; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Custom structure to wrap logic for editing all milestone data. +/// +[StructLayout(LayoutKind.Sequential, Pack = 4)] +public struct AchievementList { - /// - /// Custom structure to wrap logic for editing all milestone data. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct AchievementList + /* + u32 CountAchievement[512]; + bool ReadAchievement[512][6]; + GSaveDate DateAchievement[512][6]; + _44c6787c NewAchievement[512]; + */ + + public const int MaxCount = 512; + public const int SIZE = MaxCount * (4 + (6 * 1) + (6 * 4) + 1); + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] + public uint[] Counts { get; set; } + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] + public AchievementReadSet[] Read { get; set; } + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] + public AchievementDateSet[] Date { get; set; } + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] + public byte[] Flags { get; set; } + + public readonly void GiveAll(DateTime t) { - /* - u32 CountAchievement[512]; - bool ReadAchievement[512][6]; - GSaveDate DateAchievement[512][6]; - _44c6787c NewAchievement[512]; - */ + for (int i = 0; i < Counts.Length; i++) + GiveAll(i, t); + } - public const int MaxCount = 512; - public const int SIZE = MaxCount * (4 + (6 * 1) + (6 * 4) + 1); - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] - public uint[] Counts { get; set; } - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] - public AchievementReadSet[] Read { get; set; } - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] - public AchievementDateSet[] Date { get; set; } - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] - public byte[] Flags { get; set; } - - public readonly void GiveAll(DateTime t) + public readonly void GiveAll(in int index, DateTime t) + { + if (!LifeSupportAchievement.List.TryGetValue(index, out var detail)) { - for (int i = 0; i < Counts.Length; i++) - GiveAll(i, t); + ClearAll(index); + return; } - public readonly void GiveAll(in int index, DateTime t) + var max = detail.MaxThreshold; + if (max != 0) + Counts[index] = Math.Max(Counts[index], max); + Flags[index] = 1; // visible + + for (int i = 0; i < detail.AchievementCount; i++) { - if (!LifeSupportAchievement.List.TryGetValue(index, out var detail)) - { - ClearAll(index); - return; - } + if (Read[index][i]) + continue; + if (!Date[index][i].IsEmpty) + continue; - var max = detail.MaxThreshold; - if (max != 0) - Counts[index] = Math.Max(Counts[index], max); - Flags[index] = 1; // visible - - for (int i = 0; i < detail.AchievementCount; i++) - { - if (Read[index][i]) - continue; - if (!Date[index][i].IsEmpty) - continue; - - Date[index][i] = t; - Read[index][i] = true; - t = t.AddDays(1); - } - } - - public readonly void ClearAll() - { - for (int i = 0; i < Counts.Length; i++) - ClearAll(i); - } - - public readonly void ClearAll(int index) - { - Read[index].Clear(); - Date[index].Clear(); - Flags[index] = 0; - Counts[index] = 0; + Date[index][i] = t; + Read[index][i] = true; + t = t.AddDays(1); } } - public struct AchievementReadSet + public readonly void ClearAll() { - public const int MaxCount = 6; - - [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = MaxCount)] - public bool[] Read { get; set; } - - public bool this[int index] - { - get => Read[index]; - set => Read[index] = value; - } - - public void Clear() - { - for (int i = 0; i < Read.Length; i++) - Read[i] = false; - } + for (int i = 0; i < Counts.Length; i++) + ClearAll(i); } - public struct AchievementDateSet + public readonly void ClearAll(int index) { - public const int MaxCount = 6; + Read[index].Clear(); + Date[index].Clear(); + Flags[index] = 0; + Counts[index] = 0; + } +} - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] - public GSaveDate[] Dates { get; set; } +public struct AchievementReadSet +{ + public const int MaxCount = 6; - public GSaveDate this[int index] - { - get => Dates[index]; - set => Dates[index] = value; - } + [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = MaxCount)] + public bool[] Read { get; set; } - public void Clear() - { - for (int i = 0; i < Dates.Length; i++) - Dates[i] = new GSaveDate(); - } + public bool this[int index] + { + get => Read[index]; + set => Read[index] = value; + } + + public void Clear() + { + for (int i = 0; i < Read.Length; i++) + Read[i] = false; + } +} + +public struct AchievementDateSet +{ + public const int MaxCount = 6; + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] + public GSaveDate[] Dates { get; set; } + + public GSaveDate this[int index] + { + get => Dates[index]; + set => Dates[index] = value; + } + + public void Clear() + { + for (int i = 0; i < Dates.Length; i++) + Dates[i] = new GSaveDate(); } } \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/AirportColor.cs b/NHSE.Core/Structures/Misc/AirportColor.cs index d528ed1..65ba8f5 100644 --- a/NHSE.Core/Structures/Misc/AirportColor.cs +++ b/NHSE.Core/Structures/Misc/AirportColor.cs @@ -1,13 +1,12 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Determines what color the airport structure will show up with in the overworld. +/// +public enum AirportColor : byte { - /// - /// Determines what color the airport structure will show up with in the overworld. - /// - public enum AirportColor : byte - { - Blue = 0, - Yellow = 1, - Orange = 2, - Green = 3, - } -} + Blue = 0, + Yellow = 1, + Orange = 2, + Green = 3, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveAudioInfo.cs b/NHSE.Core/Structures/Misc/GSaveAudioInfo.cs index 4e6e3b0..a929f03 100644 --- a/NHSE.Core/Structures/Misc/GSaveAudioInfo.cs +++ b/NHSE.Core/Structures/Misc/GSaveAudioInfo.cs @@ -1,18 +1,17 @@ using System.ComponentModel; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveAudioInfo { - [StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveAudioInfo - { - public const int SIZE = 0x4; + public const int SIZE = 0x4; - public short PlayingAudioMusicID { get; set; } - public sbyte Unknown { get; set; } + public short PlayingAudioMusicID { get; set; } + public sbyte Unknown { get; set; } - [field: MarshalAs(UnmanagedType.I1, SizeConst = 1)] - public bool IsShuffle { get; set; } - }; -} + [field: MarshalAs(UnmanagedType.I1, SizeConst = 1)] + public bool IsShuffle { get; set; } +}; \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveBBS.cs b/NHSE.Core/Structures/Misc/GSaveBBS.cs index faccc65..6bd4d48 100644 --- a/NHSE.Core/Structures/Misc/GSaveBBS.cs +++ b/NHSE.Core/Structures/Misc/GSaveBBS.cs @@ -4,77 +4,76 @@ // ReSharper disable MemberCanBePrivate.Global #pragma warning disable CS8618, CA1815, CA1819, IDE1006 -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential, Pack = 8)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveBulletinBoard { - [StructLayout(LayoutKind.Sequential, Pack = 8)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveBulletinBoard - { - public const int SIZE = 0xe0ae8; - public override string ToString() => $"{BuiltDate}: {Stock}"; + public const int SIZE = 0xe0ae8; + public override string ToString() => $"{BuiltDate}: {Stock}"; - public GSaveDate BuiltDate { get; set; } // @0x0 size 0x4, align 2 - public bool _3347e149 { get; set; } // @0x4 size 0x1, align 1 - public BulletinBoardStock Stock { get; set; } // @0x8 size 0xe0ad8, align 8 - public uint LatestUniqueId { get; set; } // @0xe0ae0 size 0x4, align 4 - } - - [StructLayout(LayoutKind.Sequential, Pack = 8)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct BulletinBoardStock - { - public const int SIZE = 0xe0ad8; - public const int MaxCount = 30; - public override string ToString() => "Bulletin Board"; - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] - public GSaveBBS[] Buffer { get; set; } // @0x0 size 0x77d0, align 8 - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] - public int[] IndexTable { get; set; } // @0xe0a60 size 0x4, align 4 - } - - [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveBBS - { - public const int SIZE = 0x77d0; - public override string ToString() => $"{Date}: {Body}"; - - public GSaveDate Date { get; set; } // @0x0 size 0x4, align 2 - - [field: MarshalAs(UnmanagedType.ByValTStr, SizeConst = 240)] - public string Body { get; set; } // @0x4 size 0x1e0, align 2 - - [field: MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)] - public string Footer { get; set; } // @0x1e4 size 0x60, align 2 - - public Handwriting HandWrite { get; set; } // @0x244 size 0x7538, align 4 - public GSavePlayerId PlayerId { get; set; } // @0x777c size 0x38, align 4 -#pragma warning disable IDE1006 // Naming Styles - public ushort _5d1fcb04 { get; set; } // @0x77b4 size 0x2, align 2 -#pragma warning restore IDE1006 // Naming Styles - public ushort DesignId { get; set; } // @0x77b6 size 0x2, align 2 - public ulong PopId { get; set; } // @0x77b8 size 0x8, align 8 - public ulong NsaId { get; set; } // @0x77c0 size 0x8, align 8 - public uint UniqueId { get; set; } // @0x77c8 size 0x4, align 4 - } - - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct Handwriting - { - public const int SIZE = 0x7538; - - public const int InkCount = 30_000; - public const int PaletteCount = 4; - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = InkCount)] - public byte[] Image { get; set; } - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = PaletteCount)] - public byte[] Palette { get; set; } - - public uint VerticesNum { get; set; } - } + public GSaveDate BuiltDate { get; set; } // @0x0 size 0x4, align 2 + public bool _3347e149 { get; set; } // @0x4 size 0x1, align 1 + public BulletinBoardStock Stock { get; set; } // @0x8 size 0xe0ad8, align 8 + public uint LatestUniqueId { get; set; } // @0xe0ae0 size 0x4, align 4 } + +[StructLayout(LayoutKind.Sequential, Pack = 8)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct BulletinBoardStock +{ + public const int SIZE = 0xe0ad8; + public const int MaxCount = 30; + public override string ToString() => "Bulletin Board"; + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] + public GSaveBBS[] Buffer { get; set; } // @0x0 size 0x77d0, align 8 + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] + public int[] IndexTable { get; set; } // @0xe0a60 size 0x4, align 4 +} + +[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveBBS +{ + public const int SIZE = 0x77d0; + public override string ToString() => $"{Date}: {Body}"; + + public GSaveDate Date { get; set; } // @0x0 size 0x4, align 2 + + [field: MarshalAs(UnmanagedType.ByValTStr, SizeConst = 240)] + public string Body { get; set; } // @0x4 size 0x1e0, align 2 + + [field: MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)] + public string Footer { get; set; } // @0x1e4 size 0x60, align 2 + + public Handwriting HandWrite { get; set; } // @0x244 size 0x7538, align 4 + public GSavePlayerId PlayerId { get; set; } // @0x777c size 0x38, align 4 +#pragma warning disable IDE1006 // Naming Styles + public ushort _5d1fcb04 { get; set; } // @0x77b4 size 0x2, align 2 +#pragma warning restore IDE1006 // Naming Styles + public ushort DesignId { get; set; } // @0x77b6 size 0x2, align 2 + public ulong PopId { get; set; } // @0x77b8 size 0x8, align 8 + public ulong NsaId { get; set; } // @0x77c0 size 0x8, align 8 + public uint UniqueId { get; set; } // @0x77c8 size 0x4, align 4 +} + +[StructLayout(LayoutKind.Sequential, Pack = 4)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct Handwriting +{ + public const int SIZE = 0x7538; + + public const int InkCount = 30_000; + public const int PaletteCount = 4; + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = InkCount)] + public byte[] Image { get; set; } + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = PaletteCount)] + public byte[] Palette { get; set; } + + public uint VerticesNum { get; set; } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveDate.cs b/NHSE.Core/Structures/Misc/GSaveDate.cs index 14947b9..12ad0e0 100644 --- a/NHSE.Core/Structures/Misc/GSaveDate.cs +++ b/NHSE.Core/Structures/Misc/GSaveDate.cs @@ -2,29 +2,28 @@ using System.ComponentModel; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential, Pack = 4)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveDate { - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveDate + public const int SIZE = 4; + public override string ToString() => $"{Year:0000}-{Month:00}-{Day:00}"; + + public ushort Year { get; set; } + public byte Month { get; set; } + public byte Day { get; set; } + + private GSaveDate(int year, int month, int day) { - public const int SIZE = 4; - public override string ToString() => $"{Year:0000}-{Month:00}-{Day:00}"; - - public ushort Year { get; set; } - public byte Month { get; set; } - public byte Day { get; set; } - - private GSaveDate(int year, int month, int day) - { - Year = (ushort) year; - Month = (byte) month; - Day = (byte) day; - } - - public bool IsEmpty => Year == 0 && Month == 0 && Day == 0; - - public static implicit operator GSaveDate(DateTime dt) => dt == DateTime.MinValue ? new GSaveDate() : new GSaveDate(dt.Year, dt.Month, dt.Day); - public static implicit operator DateTime(GSaveDate dt) => dt.IsEmpty ? DateTime.MinValue : new DateTime(dt.Year, dt.Month, dt.Day); + Year = (ushort) year; + Month = (byte) month; + Day = (byte) day; } -} + + public bool IsEmpty => Year == 0 && Month == 0 && Day == 0; + + public static implicit operator GSaveDate(DateTime dt) => dt == DateTime.MinValue ? new GSaveDate() : new GSaveDate(dt.Year, dt.Month, dt.Day); + public static implicit operator DateTime(GSaveDate dt) => dt.IsEmpty ? DateTime.MinValue : new DateTime(dt.Year, dt.Month, dt.Day); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveDateMD.cs b/NHSE.Core/Structures/Misc/GSaveDateMD.cs index 1485143..8639d72 100644 --- a/NHSE.Core/Structures/Misc/GSaveDateMD.cs +++ b/NHSE.Core/Structures/Misc/GSaveDateMD.cs @@ -2,30 +2,29 @@ using System.Runtime.InteropServices; #pragma warning disable CS8618, CA1815, CA1819, IDE1006 -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential, Pack = 1)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveDateMD { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveDateMD - { - public const int SIZE = 2; - public override string ToString() => $"{Month:00}-{Day:00}"; + public const int SIZE = 2; + public override string ToString() => $"{Month:00}-{Day:00}"; - public byte Month { get; set; } - public byte Day { get; set; } - } - - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct GSavePlayerHandleName - { - public const int SIZE = 0xA; - - public ushort ModifierId { get; set; } - public byte ModifierLevel { get; set; } - - public ushort NounId { get; set; } - public byte NounLevel { get; set; } - public byte NounGenderType { get; set; } - public byte _fa0a936b { get; set; } - }; + public byte Month { get; set; } + public byte Day { get; set; } } + +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct GSavePlayerHandleName +{ + public const int SIZE = 0xA; + + public ushort ModifierId { get; set; } + public byte ModifierLevel { get; set; } + + public ushort NounId { get; set; } + public byte NounLevel { get; set; } + public byte NounGenderType { get; set; } + public byte _fa0a936b { get; set; } +}; \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveFg.cs b/NHSE.Core/Structures/Misc/GSaveFg.cs index 25f9a62..19b1bf3 100644 --- a/NHSE.Core/Structures/Misc/GSaveFg.cs +++ b/NHSE.Core/Structures/Misc/GSaveFg.cs @@ -1,23 +1,22 @@ using System.Runtime.InteropServices; #pragma warning disable CS8618, CA1815, CA1819, IDE1006 -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential, Pack = 4)] +public class GSaveFg { - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public class GSaveFg - { - public const int SIZE = 0x928; - private const int _7b9816fbCount = 0x900; - private const int _e88f809dCount = 8; + public const int SIZE = 0x928; + private const int _7b9816fbCount = 0x900; + private const int _e88f809dCount = 8; - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = _7b9816fbCount)] - public byte[] _7b9816fb { get; set; } // @0x0 size 0x900, align 1 - public ushort SpecialityFruit { get; set; } // @0x900 size 0x2, align 2 - public ushort SisterFruit { get; set; } // @0x902 size 0x2, align 2 + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = _7b9816fbCount)] + public byte[] _7b9816fb { get; set; } // @0x0 size 0x900, align 1 + public ushort SpecialityFruit { get; set; } // @0x900 size 0x2, align 2 + public ushort SisterFruit { get; set; } // @0x902 size 0x2, align 2 - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = _e88f809dCount)] - public uint[] _e88f809d { get; set; } // @0x904 size 0x4, align 4 - public byte VillageFlower { get; set; } // @0x924 size 0x1, align 1 - public byte SpecialityFlower { get; set; } // @0x925 size 0x1, align 1 - } -} + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = _e88f809dCount)] + public uint[] _e88f809d { get; set; } // @0x904 size 0x4, align 4 + public byte VillageFlower { get; set; } // @0x924 size 0x1, align 1 + public byte SpecialityFlower { get; set; } // @0x925 size 0x1, align 1 +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveItemName.cs b/NHSE.Core/Structures/Misc/GSaveItemName.cs index b49c30b..92e056d 100644 --- a/NHSE.Core/Structures/Misc/GSaveItemName.cs +++ b/NHSE.Core/Structures/Misc/GSaveItemName.cs @@ -1,28 +1,27 @@ using System.ComponentModel; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveItemName { - [StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveItemName + public const int SIZE = 0x08; + public override string ToString() => UniqueID.ToString(); + + [field: FieldOffset(0x00)] public ushort UniqueID { get; set; } + [field: FieldOffset(0x02)] public byte SystemParam { get; set; } + [field: FieldOffset(0x03)] public byte AdditionalParam { get; set; } + [field: FieldOffset(0x04)] public int FreeParam { get; set; } + + public Item ToItem() => this.ToBytes().ToClass(); + + public void CopyFrom(Item item) { - public const int SIZE = 0x08; - public override string ToString() => UniqueID.ToString(); - - [field: FieldOffset(0x00)] public ushort UniqueID { get; set; } - [field: FieldOffset(0x02)] public byte SystemParam { get; set; } - [field: FieldOffset(0x03)] public byte AdditionalParam { get; set; } - [field: FieldOffset(0x04)] public int FreeParam { get; set; } - - public Item ToItem() => this.ToBytes().ToClass(); - - public void CopyFrom(Item item) - { - UniqueID = item.ItemId; - SystemParam = item.SystemParam; - AdditionalParam = item.AdditionalParam; - FreeParam = item.FreeParam; - } + UniqueID = item.ItemId; + SystemParam = item.SystemParam; + AdditionalParam = item.AdditionalParam; + FreeParam = item.FreeParam; } -} +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveLandId.cs b/NHSE.Core/Structures/Misc/GSaveLandId.cs index 66dd932..e185ad6 100644 --- a/NHSE.Core/Structures/Misc/GSaveLandId.cs +++ b/NHSE.Core/Structures/Misc/GSaveLandId.cs @@ -2,20 +2,19 @@ using System.Runtime.InteropServices; #pragma warning disable CS8618, CA1815, CA1819, IDE1006 -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveLandId { - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveLandId - { - public const int SIZE = 0x1C; - public override string ToString() => Name; + public const int SIZE = 0x1C; + public override string ToString() => Name; - public uint Id { get; set; } + public uint Id { get; set; } - [field: MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] - public string Name { get; set; } + [field: MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] + public string Name { get; set; } - public byte IslandRubyType { get; set; } - } -} + public byte IslandRubyType { get; set; } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSavePlayerBaseId.cs b/NHSE.Core/Structures/Misc/GSavePlayerBaseId.cs index d966d7a..87954ff 100644 --- a/NHSE.Core/Structures/Misc/GSavePlayerBaseId.cs +++ b/NHSE.Core/Structures/Misc/GSavePlayerBaseId.cs @@ -2,20 +2,19 @@ using System.Runtime.InteropServices; #pragma warning disable CS8618, CA1815, CA1819, IDE1006 -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSavePlayerBaseId { - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSavePlayerBaseId - { - public const int SIZE = 0x1C; - public override string ToString() => Name; + public const int SIZE = 0x1C; + public override string ToString() => Name; - public uint Id { get; set; } + public uint Id { get; set; } - [field: MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] - public string Name { get; set; } + [field: MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] + public string Name { get; set; } - public Gender Gender { get; set; } - } -} + public Gender Gender { get; set; } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSavePlayerId.cs b/NHSE.Core/Structures/Misc/GSavePlayerId.cs index 44bbf83..2fcfe21 100644 --- a/NHSE.Core/Structures/Misc/GSavePlayerId.cs +++ b/NHSE.Core/Structures/Misc/GSavePlayerId.cs @@ -1,16 +1,15 @@ using System.ComponentModel; using System.Runtime.InteropServices; -namespace NHSE.Core -{ - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSavePlayerId - { - public const int SIZE = 0x38; - public override string ToString() => $"{BaseId.Name}-{LandId.Name}"; +namespace NHSE.Core; - public GSaveLandId LandId { get; set; } - public GSavePlayerBaseId BaseId { get; set; } - } -} +[StructLayout(LayoutKind.Sequential, Pack = 4)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSavePlayerId +{ + public const int SIZE = 0x38; + public override string ToString() => $"{BaseId.Name}-{LandId.Name}"; + + public GSaveLandId LandId { get; set; } + public GSavePlayerBaseId BaseId { get; set; } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSavePlayerManpu.cs b/NHSE.Core/Structures/Misc/GSavePlayerManpu.cs index 0a8943b..b1d7a54 100644 --- a/NHSE.Core/Structures/Misc/GSavePlayerManpu.cs +++ b/NHSE.Core/Structures/Misc/GSavePlayerManpu.cs @@ -1,124 +1,123 @@ using System; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Original Reactions object from release +/// +[StructLayout(LayoutKind.Sequential, Pack = 1)] +public struct GSavePlayerManpu : IReactionStore { - /// - /// Original Reactions object from release - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct GSavePlayerManpu : IReactionStore - { - public const int SIZE = 0x88; - private const int MaxCount = 64; - private const int WheelCount = 8; - - /// - /// List of known Reaction IDs - /// - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] - public Reaction[] ManpuBit { get; set; } - - /// - /// Emotions that are currently bound to the Reaction Wheel. - /// - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = WheelCount)] - public Reaction[] UIList { get; set; } - - /// - /// Flags indicating if an Reaction (at the same index?) is newly learned or not. - /// - [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = MaxCount)] - public bool[] NewFlag { get; set; } - - public void AddMissingReactions() - { - var all = (Reaction[])Enum.GetValues(typeof(Reaction)); - foreach (var react in all) - AddReaction(react); - } - - // returns true if failed - public bool AddReaction(Reaction react) - { - if (react.ToString().StartsWith("UNUSED")) - return true; - - var index = Array.IndexOf(ManpuBit, react); - if (index >= 0) - return false; - - var empty = EmptyIndex; - if (empty < 0) - return true; - ManpuBit[empty] = react; - return false; - } - - private int EmptyIndex => Array.FindIndex(ManpuBit, z => z == 0); - } + public const int SIZE = 0x88; + private const int MaxCount = 64; + private const int WheelCount = 8; /// - /// Reactions object revised in v1.5.0 + /// List of known Reaction IDs /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct GSavePlayerManpu15 : IReactionStore + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] + public Reaction[] ManpuBit { get; set; } + + /// + /// Emotions that are currently bound to the Reaction Wheel. + /// + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = WheelCount)] + public Reaction[] UIList { get; set; } + + /// + /// Flags indicating if a Reaction (at the same index?) is newly learned or not. + /// + [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = MaxCount)] + public bool[] NewFlag { get; set; } + + public void AddMissingReactions() { - public const int SIZE = 0x208; - private const int MaxCount = 256; // up from 64 - private const int WheelCount = 8; + var all = Enum.GetValues(); + foreach (var react in all) + AddReaction(react); + } - /// - /// List of known Reaction IDs - /// - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] - public Reaction[] ManpuBit { get; set; } + // returns true if failed + public bool AddReaction(Reaction react) + { + if (react.ToString().StartsWith("UNUSED")) + return true; - /// - /// Emotions that are currently bound to the Reaction Wheel. - /// - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = WheelCount)] - public Reaction[] UIList { get; set; } - - /// - /// Flags indicating if an Reaction (at the same index?) is newly learned or not. - /// - [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = MaxCount)] - public bool[] NewFlag { get; set; } - - public void AddMissingReactions() - { - var all = (Reaction[])Enum.GetValues(typeof(Reaction)); - foreach (var react in all) - AddReaction(react); - } - - // returns true if failed - public bool AddReaction(Reaction react) - { - if (react.ToString().StartsWith("UNUSED")) - return true; - - var index = Array.IndexOf(ManpuBit, react); - if (index >= 0) - return false; - - var empty = EmptyIndex; - if (empty < 0) - return true; - ManpuBit[empty] = react; + var index = Array.IndexOf(ManpuBit, react); + if (index >= 0) return false; - } - private int EmptyIndex => Array.FindIndex(ManpuBit, z => z == 0); + var empty = EmptyIndex; + if (empty < 0) + return true; + ManpuBit[empty] = react; + return false; } - public interface IReactionStore - { - Reaction[] ManpuBit { get; set; } - Reaction[] UIList { get; set; } - bool[] NewFlag { get; set; } - bool AddReaction(Reaction react); - void AddMissingReactions(); - } + private readonly int EmptyIndex => Array.FindIndex(ManpuBit, z => z == 0); } + +/// +/// Reactions object revised in v1.5.0 +/// +[StructLayout(LayoutKind.Sequential, Pack = 1)] +public struct GSavePlayerManpu15 : IReactionStore +{ + public const int SIZE = 0x208; + private const int MaxCount = 256; // up from 64 + private const int WheelCount = 8; + + /// + /// List of known Reaction IDs + /// + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] + public Reaction[] ManpuBit { get; set; } + + /// + /// Emotions that are currently bound to the Reaction Wheel. + /// + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = WheelCount)] + public Reaction[] UIList { get; set; } + + /// + /// Flags indicating if a Reaction (at the same index?) is newly learned or not. + /// + [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = MaxCount)] + public bool[] NewFlag { get; set; } + + public void AddMissingReactions() + { + var all = Enum.GetValues(); + foreach (var react in all) + AddReaction(react); + } + + // returns true if failed + public bool AddReaction(Reaction react) + { + if (react.ToString().StartsWith("UNUSED")) + return true; + + var index = Array.IndexOf(ManpuBit, react); + if (index >= 0) + return false; + + var empty = EmptyIndex; + if (empty < 0) + return true; + ManpuBit[empty] = react; + return false; + } + + private readonly int EmptyIndex => Array.FindIndex(ManpuBit, z => z == 0); +} + +public interface IReactionStore +{ + Reaction[] ManpuBit { get; set; } + Reaction[] UIList { get; set; } + bool[] NewFlag { get; set; } + bool AddReaction(Reaction react); + void AddMissingReactions(); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveRoomFloorWall.cs b/NHSE.Core/Structures/Misc/GSaveRoomFloorWall.cs index 5805af0..2b61276 100644 --- a/NHSE.Core/Structures/Misc/GSaveRoomFloorWall.cs +++ b/NHSE.Core/Structures/Misc/GSaveRoomFloorWall.cs @@ -1,22 +1,21 @@ using System.ComponentModel; using System.Runtime.InteropServices; -namespace NHSE.Core -{ - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveRoomFloorWall - { - public const int SIZE = 0x24; +namespace NHSE.Core; - public GSaveItemName AccentWallItem { get; set; } // @0x0 size 0x8, align 4 - public GSaveItemName WallItem { get; set; } // @0x8 size 0x8, align 4 - public GSaveItemName FloorItem { get; set; } // @0x10 size 0x8, align 4 - public ushort AccentWallMyDesignID { get; set; } // @0x18 size 0x2, align 2 - public ushort WallMyDesignID { get; set; } // @0x1a size 0x2, align 2 - public ushort FloorMyDesignID { get; set; } // @0x1c size 0x2, align 2 - public byte AccentWallDirection { get; set; } // @0x1e size 0x1, align 1 - public byte InfoBit { get; set; } // @0x1f size 0x1, align 1 - public byte FloorDirection { get; set; } // @0x20 size 0x1, align 1 - } -} +[StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveRoomFloorWall +{ + public const int SIZE = 0x24; + + public GSaveItemName AccentWallItem { get; set; } // @0x0 size 0x8, align 4 + public GSaveItemName WallItem { get; set; } // @0x8 size 0x8, align 4 + public GSaveItemName FloorItem { get; set; } // @0x10 size 0x8, align 4 + public ushort AccentWallMyDesignID { get; set; } // @0x18 size 0x2, align 2 + public ushort WallMyDesignID { get; set; } // @0x1a size 0x2, align 2 + public ushort FloorMyDesignID { get; set; } // @0x1c size 0x2, align 2 + public byte AccentWallDirection { get; set; } // @0x1e size 0x1, align 1 + public byte InfoBit { get; set; } // @0x1f size 0x1, align 1 + public byte FloorDirection { get; set; } // @0x20 size 0x1, align 1 +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveTime.cs b/NHSE.Core/Structures/Misc/GSaveTime.cs index 61fea88..648faf2 100644 --- a/NHSE.Core/Structures/Misc/GSaveTime.cs +++ b/NHSE.Core/Structures/Misc/GSaveTime.cs @@ -1,26 +1,25 @@ -using System.Runtime.InteropServices; +using System; +using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] +public struct GSaveTime : IEquatable { - [StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] - public struct GSaveTime - { - public const int SIZE = 0x08; - [field: FieldOffset(0x00)] public ushort Year { get; set; } - [field: FieldOffset(0x02)] public byte Month { get; set; } - [field: FieldOffset(0x03)] public byte Day { get; set; } - [field: FieldOffset(0x04)] public byte Hour { get; set; } - [field: FieldOffset(0x05)] public byte Minute { get; set; } - [field: FieldOffset(0x06)] public byte Second { get; set; } + public const int SIZE = 0x08; + [field: FieldOffset(0x00)] public ushort Year { get; set; } + [field: FieldOffset(0x02)] public byte Month { get; set; } + [field: FieldOffset(0x03)] public byte Day { get; set; } + [field: FieldOffset(0x04)] public byte Hour { get; set; } + [field: FieldOffset(0x05)] public byte Minute { get; set; } + [field: FieldOffset(0x06)] public byte Second { get; set; } - // 0x07 unused, alignment + // 0x07 unused, alignment - public string TimeStamp => $"{Year:0000}-{Month:00}-{Day:00} {Hour:00}:{Minute:00}:{Second:00}"; - - public override int GetHashCode() => TimeStamp.GetHashCode(); - public override bool Equals(object obj) => obj is GSaveTime i && i.Equals(this); - public bool Equals(GSaveTime obj) => TimeStamp == obj.TimeStamp; - public static bool operator ==(GSaveTime left, GSaveTime right) => left.Equals(right); - public static bool operator !=(GSaveTime left, GSaveTime right) => !(left == right); - } -} + public readonly string TimeStamp => $"{Year:0000}-{Month:00}-{Day:00} {Hour:00}:{Minute:00}:{Second:00}"; + public readonly override int GetHashCode() => TimeStamp.GetHashCode(); + public readonly override bool Equals(object? obj) => obj is GSaveTime i && i.Equals(this); + public readonly bool Equals(GSaveTime obj) => TimeStamp == obj.TimeStamp; + public static bool operator ==(GSaveTime left, GSaveTime right) => left.Equals(right); + public static bool operator !=(GSaveTime left, GSaveTime right) => !(left == right); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/GSaveVisitorNpc.cs b/NHSE.Core/Structures/Misc/GSaveVisitorNpc.cs index 09f88ca..4ab8d5f 100644 --- a/NHSE.Core/Structures/Misc/GSaveVisitorNpc.cs +++ b/NHSE.Core/Structures/Misc/GSaveVisitorNpc.cs @@ -2,66 +2,65 @@ using System.Runtime.InteropServices; #pragma warning disable CS8618, CA1815, CA1819, IDE1006 -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential, Pack = 1)] +public class GSaveVisitorNpc { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public class GSaveVisitorNpc - { - public const int SIZE = 0x78; - private const int Days = 7; + public const int SIZE = 0x78; + private const int Days = 7; - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = Days)] - public VisitorNPC[] VisitorNPC { get; set; } + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = Days)] + public VisitorNPC[] VisitorNPC { get; set; } - public V3f CreatePos { get; set; } - public V3f _61e631dc { get; set; } + public V3f CreatePos { get; set; } + public V3f _61e631dc { get; set; } - [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = Days)] - public bool[] IsNormalLive { get; set; } + [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = Days)] + public bool[] IsNormalLive { get; set; } - [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = Days)] - public bool[] IsBirthdayLive { get; set; } + [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = Days)] + public bool[] IsBirthdayLive { get; set; } - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public byte[] gap_42; + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] gap_42; - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = Days)] - public VisitorNPC[] InitSchedule { get; set; } + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = Days)] + public VisitorNPC[] InitSchedule { get; set; } - [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = Days * 2)] - public bool[] _437619d8 { get; set; } + [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = Days * 2)] + public bool[] _437619d8 { get; set; } - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public byte[] gap_6e; + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] gap_6e; - public int DayWisp {get; set; } - public int DayCeleste { get; set; } - } - - // same as Vector3; not importing package - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct V3f - { - public float X { get; set; } - public float Y { get; set; } - public float Z { get; set; } - - public override string ToString() => $"({X},{Y},{Z})"; - } - - public enum VisitorNPC - { - None = 0, - Gulliver = 1, - Label = 2, - Saharah = 3, - Wisp = 4, - Mabel = 5, - CJ = 6, - Flick = 7, - Kicks = 8, - Leif = 9, - Redd = 10, - Gullivarrr = 11, - } + public int DayWisp {get; set; } + public int DayCeleste { get; set; } } + +// same as Vector3; not importing package +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct V3f +{ + public float X { get; set; } + public float Y { get; set; } + public float Z { get; set; } + + public override string ToString() => $"({X},{Y},{Z})"; +} + +public enum VisitorNPC +{ + None = 0, + Gulliver = 1, + Label = 2, + Saharah = 3, + Wisp = 4, + Mabel = 5, + CJ = 6, + Flick = 7, + Kicks = 8, + Leif = 9, + Redd = 10, + Gullivarrr = 11, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/Gender.cs b/NHSE.Core/Structures/Misc/Gender.cs index 7aae371..24b8b2c 100644 --- a/NHSE.Core/Structures/Misc/Gender.cs +++ b/NHSE.Core/Structures/Misc/Gender.cs @@ -1,11 +1,10 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Player gender toggle +/// +public enum Gender { - /// - /// Player gender toggle - /// - public enum Gender - { - Masculine = 0, - Feminine = 1, - } -} + Masculine = 0, + Feminine = 1, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/Hemisphere.cs b/NHSE.Core/Structures/Misc/Hemisphere.cs index 50f4a14..4c62317 100644 --- a/NHSE.Core/Structures/Misc/Hemisphere.cs +++ b/NHSE.Core/Structures/Misc/Hemisphere.cs @@ -1,8 +1,7 @@ -namespace NHSE.Core +namespace NHSE.Core; + +public enum Hemisphere { - public enum Hemisphere - { - Northern = 0, - Southern = 1, - } -} + Northern = 0, + Southern = 1, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/MapManager.cs b/NHSE.Core/Structures/Misc/MapManager.cs index ff32c97..7ef42f1 100644 --- a/NHSE.Core/Structures/Misc/MapManager.cs +++ b/NHSE.Core/Structures/Misc/MapManager.cs @@ -1,59 +1,59 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +public class MapManager : MapTerrainStructure { - public class MapManager : MapTerrainStructure + public readonly FieldItemManager Items; + + public int MapLayer { get; set; } // 0 or 1 + + public MapManager(MainSave sav) : base(sav) { - public readonly FieldItemManager Items; - - public int MapLayer { get; set; } // 0 or 1 - - public MapManager(MainSave sav) : base(sav) - { - Items = new FieldItemManager(sav); - } - - public FieldItemLayer CurrentLayer => MapLayer == 0 ? Items.Layer1 : Items.Layer2; - - public static void ClearDesignTiles(MainSave sav) - { - var tiles = sav.GetMapDesignTiles(); - for (int i = 0; i < tiles.Length; i++) - tiles[i] = MainSave.MapDesignNone; - sav.SetMapDesignTiles(tiles); - } - - public static byte[] ExportDesignTiles(MainSave sav) - { - var tiles = sav.GetMapDesignTiles(); - var result = new byte[tiles.Length * 2]; - Buffer.BlockCopy(tiles, 0, result, 0, result.Length); - return result; - } - - public static void ImportDesignTiles(MainSave sav, byte[] result) - { - var tiles = sav.GetMapDesignTiles(); - Buffer.BlockCopy(result, 0, tiles, 0, result.Length); - sav.SetMapDesignTiles(tiles); - } + Items = new FieldItemManager(sav); } - public class MapTerrainStructure + public FieldItemLayer CurrentLayer => MapLayer == 0 ? Items.Layer1 : Items.Layer2; + + public static void ClearDesignTiles(MainSave sav) { - public readonly TerrainLayer Terrain; - public readonly IReadOnlyList Buildings; + var tiles = sav.GetMapDesignTiles(); + for (int i = 0; i < tiles.Length; i++) + tiles[i] = MainSave.MapDesignNone; + sav.SetMapDesignTiles(tiles); + } - public uint PlazaX { get; set; } - public uint PlazaY { get; set; } + public static byte[] ExportDesignTiles(MainSave sav) + { + var tiles = sav.GetMapDesignTiles(); + var result = new byte[tiles.Length * 2]; + Buffer.BlockCopy(tiles, 0, result, 0, result.Length); + return result; + } - public MapTerrainStructure(MainSave sav) - { - Terrain = new TerrainLayer(sav.GetTerrainTiles(), sav.GetAcreBytes()); - Buildings = sav.Buildings; - PlazaX = sav.EventPlazaLeftUpX; - PlazaY = sav.EventPlazaLeftUpZ; - } + public static void ImportDesignTiles(MainSave sav, ReadOnlySpan result) + { + var tiles = sav.GetMapDesignTiles(); + MemoryMarshal.Cast(result).CopyTo(tiles); + sav.SetMapDesignTiles(tiles); } } + +public class MapTerrainStructure +{ + public readonly TerrainLayer Terrain; + public readonly IReadOnlyList Buildings; + + public uint PlazaX { get; set; } + public uint PlazaY { get; set; } + + public MapTerrainStructure(MainSave sav) + { + Terrain = new TerrainLayer(sav.GetTerrainTiles(), sav.GetAcreBytes()); + Buildings = sav.Buildings; + PlazaX = sav.EventPlazaLeftUpX; + PlazaY = sav.EventPlazaLeftUpZ; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/MapView.cs b/NHSE.Core/Structures/Misc/MapView.cs index 07c3f73..e49600d 100644 --- a/NHSE.Core/Structures/Misc/MapView.cs +++ b/NHSE.Core/Structures/Misc/MapView.cs @@ -1,108 +1,107 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +public class MapView { - public class MapView + private const int ViewInterval = 2; + public readonly MapManager Map; + + public int MapScale { get; } = 1; + public int AcreScale { get; } + public int TerrainScale => AcreScale * 2; + + // Top Left Anchor Coordinates + public int X { get; set; } + public int Y { get; set; } + + protected MapView(MapManager m, int scale = 16) { - private const int ViewInterval = 2; - public readonly MapManager Map; - - public int MapScale { get; } = 1; - public int AcreScale { get; } - public int TerrainScale => AcreScale * 2; - - // Top Left Anchor Coordinates - public int X { get; set; } - public int Y { get; set; } - - protected MapView(MapManager m, int scale = 16) - { - AcreScale = scale; - Map = m; - } - - public bool CanUp => Y != 0; - public bool CanDown => Y < Map.CurrentLayer.MaxHeight - Map.CurrentLayer.GridHeight; - public bool CanLeft => X != 0; - public bool CanRight => X < Map.CurrentLayer.MaxWidth - Map.CurrentLayer.GridWidth; - - public bool ArrowUp() - { - if (Y <= 0) - return false; - Y -= ViewInterval; - return true; - } - - public bool ArrowLeft() - { - if (X <= 0) - return false; - X -= ViewInterval; - return true; - } - - public bool ArrowRight() - { - if (X >= Map.CurrentLayer.MaxWidth - 2) - return false; - X += ViewInterval; - return true; - } - - public bool ArrowDown() - { - if (Y >= Map.CurrentLayer.MaxHeight - ViewInterval) - return false; - Y += ViewInterval; - return true; - } - - public bool SetViewTo(in int x, in int y) - { - var info = Map.CurrentLayer; - var newX = Math.Max(0, Math.Min(x, info.MaxWidth - info.GridWidth)); - var newY = Math.Max(0, Math.Min(y, info.MaxHeight - info.GridHeight)); - bool diff = X != newX || Y != newY; - X = newX; - Y = newY; - return diff; - } - - public void SetViewToAcre(in int acre) - { - var layer = Map.Items.Layer1; - layer.GetViewAnchorCoordinates(acre, out var x, out var y); - SetViewTo(x, y); - } - - public int ModifyFieldItems(Func action, in bool wholeMap) - { - var layer = Map.CurrentLayer; - return wholeMap - ? action(0, 0, layer.MaxWidth, layer.MaxHeight) - : action(X, Y, layer.GridWidth, layer.GridHeight); - } - - public int ReplaceFieldItems(Item oldItem, Item newItem, in bool wholeMap) - { - var layer = Map.CurrentLayer; - return wholeMap - ? layer.ReplaceAll(oldItem, newItem, 0, 0, layer.MaxWidth, layer.MaxHeight) - : layer.ReplaceAll(oldItem, newItem, X, Y, layer.GridWidth, layer.GridHeight); - } - - public void GetCursorCoordinates(in int mX, in int mY, out int x, out int y) - { - x = mX / MapScale; - y = mY / MapScale; - } - - public void GetViewAnchorCoordinates(int mX, int mY, out int x, out int y, bool centerReticle) - { - GetCursorCoordinates(mX, mY, out x, out y); - var layer = Map.Items.Layer1; - layer.GetViewAnchorCoordinates(ref x, ref y, centerReticle); - } + AcreScale = scale; + Map = m; } -} + + public bool CanUp => Y != 0; + public bool CanDown => Y < Map.CurrentLayer.MaxHeight - Map.CurrentLayer.GridHeight; + public bool CanLeft => X != 0; + public bool CanRight => X < Map.CurrentLayer.MaxWidth - Map.CurrentLayer.GridWidth; + + public bool ArrowUp() + { + if (Y <= 0) + return false; + Y -= ViewInterval; + return true; + } + + public bool ArrowLeft() + { + if (X <= 0) + return false; + X -= ViewInterval; + return true; + } + + public bool ArrowRight() + { + if (X >= Map.CurrentLayer.MaxWidth - 2) + return false; + X += ViewInterval; + return true; + } + + public bool ArrowDown() + { + if (Y >= Map.CurrentLayer.MaxHeight - ViewInterval) + return false; + Y += ViewInterval; + return true; + } + + public bool SetViewTo(in int x, in int y) + { + var info = Map.CurrentLayer; + var newX = Math.Max(0, Math.Min(x, info.MaxWidth - info.GridWidth)); + var newY = Math.Max(0, Math.Min(y, info.MaxHeight - info.GridHeight)); + bool diff = X != newX || Y != newY; + X = newX; + Y = newY; + return diff; + } + + public void SetViewToAcre(in int acre) + { + var layer = Map.Items.Layer1; + layer.GetViewAnchorCoordinates(acre, out var x, out var y); + SetViewTo(x, y); + } + + public int ModifyFieldItems(Func action, in bool wholeMap) + { + var layer = Map.CurrentLayer; + return wholeMap + ? action(0, 0, layer.MaxWidth, layer.MaxHeight) + : action(X, Y, layer.GridWidth, layer.GridHeight); + } + + public int ReplaceFieldItems(Item oldItem, Item newItem, in bool wholeMap) + { + var layer = Map.CurrentLayer; + return wholeMap + ? layer.ReplaceAll(oldItem, newItem, 0, 0, layer.MaxWidth, layer.MaxHeight) + : layer.ReplaceAll(oldItem, newItem, X, Y, layer.GridWidth, layer.GridHeight); + } + + public void GetCursorCoordinates(in int mX, in int mY, out int x, out int y) + { + x = mX / MapScale; + y = mY / MapScale; + } + + public void GetViewAnchorCoordinates(int mX, int mY, out int x, out int y, bool centerReticle) + { + GetCursorCoordinates(mX, mY, out x, out y); + var layer = Map.Items.Layer1; + layer.GetViewAnchorCoordinates(ref x, ref y, centerReticle); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/Museum.cs b/NHSE.Core/Structures/Misc/Museum.cs index 850aa96..3285372 100644 --- a/NHSE.Core/Structures/Misc/Museum.cs +++ b/NHSE.Core/Structures/Misc/Museum.cs @@ -1,30 +1,31 @@ using System; using System.Collections.Generic; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +public class Museum { - public class Museum + public const int SIZE = 0x3404; + public const int EntryCount = 1024; + + public readonly Memory Raw; + public Span Data => Raw.Span; + + public Museum(Memory data) => Raw = data; + + public int MuseumLevel { - public const int SIZE = 0x3404; - public const int EntryCount = 1024; - - public readonly byte[] Data; - - public Museum(byte[] data) => Data = data; - - public int MuseumLevel - { - get => BitConverter.ToInt32(Data, 0x00); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); - } - - public GSaveDate[] GetDates() => Data.Slice(0x0004, 0x1000).GetArrayStructure(GSaveDate.SIZE); - public void SetDates(IReadOnlyList value) => value.SetArrayStructure(GSaveDate.SIZE).CopyTo(Data, 4); - - public Item[] GetItems() => Data.Slice(0x1004, 0x2000).GetArray(Item.SIZE); - public void SetItems(IReadOnlyList value) => value.SetArray(Item.SIZE).CopyTo(Data, 0x1004); - - public byte[] GetPlayers() => Data.Slice(0x3004, 0x400); - public void SetPlayers(byte[] value) => value.CopyTo(Data, 0x3004); + get => ReadInt32LittleEndian(Data); + set => WriteInt32LittleEndian(Data, value); } -} + + public GSaveDate[] GetDates() => Data.Slice(0x0004, 0x1000).GetArrayStructure(GSaveDate.SIZE); + public void SetDates(ReadOnlySpan value) => value.SetArrayStructure(GSaveDate.SIZE).CopyTo(Data[4..]); + + public Item[] GetItems() => Data.Slice(0x1004, 0x2000).GetArray(Item.SIZE); + public void SetItems(IReadOnlyList value) => Item.SetArray(value).CopyTo(Data[0x1004..]); + + public byte[] GetPlayers() => Data.Slice(0x3004, 0x400).ToArray(); + public void SetPlayers(ReadOnlySpan value) => value.CopyTo(Data[0x3004..]); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/MuseumEditor.cs b/NHSE.Core/Structures/Misc/MuseumEditor.cs index f81840c..15a21f3 100644 --- a/NHSE.Core/Structures/Misc/MuseumEditor.cs +++ b/NHSE.Core/Structures/Misc/MuseumEditor.cs @@ -1,117 +1,119 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +public class MuseumEditor { - public class MuseumEditor + public readonly Museum Museum; + public readonly GSaveDate[] Dates; + public readonly Item[] Items; + public readonly byte[] Players; + + public MuseumEditor(Museum museum) { - public readonly Museum Museum; - public readonly GSaveDate[] Dates; - public readonly Item[] Items; - public readonly byte[] Players; + Museum = museum; + Dates = museum.GetDates(); + Items = museum.GetItems(); + Players = museum.GetPlayers(); + } - public MuseumEditor(Museum museum) + public void Save() + { + var museum = Museum; + museum.SetDates(Dates); + museum.SetItems(Items); + museum.SetPlayers(Players); + } + + public IEnumerable GetDonationSummary(GameStrings str) + { + for (int i = 0; i < Museum.EntryCount; i++) { - Museum = museum; - Dates = museum.GetDates(); - Items = museum.GetItems(); - Players = museum.GetPlayers(); - } + var item = Items[i]; + if (item.IsNone) + continue; - public void Save() - { - var museum = Museum; - museum.SetDates(Dates); - museum.SetItems(Items); - museum.SetPlayers(Players); - } - - public IEnumerable GetDonationSummary(GameStrings str) - { - for (int i = 0; i < Museum.EntryCount; i++) - { - var item = Items[i]; - if (item.IsNone) - continue; - - yield return GetDonationSummary(str, item, i); - } - } - - public string GetDonationSummary(GameStrings str, int index) => GetDonationSummary(str, Items[index], index); - - public string GetDonationText(GameStrings str, int index) => $"{Dates[index]}: {str.GetItemName(Items[index])}"; - - private string GetDonationSummary(GameStrings str, Item item, int index) - { - var date = Dates[index]; - var player = Players[index]; - - var name = str.GetItemName(item); - var result = $"On {date}, Player {player} donated a(n) {name}."; - return result; - } - - public int GiveAll(string[] englishNames, int interval = 20) - { - var items = new[] - { - GameLists.Art.Where(z => !englishNames[z].Contains('(')), // ignore forgeries - GameLists.Fish, - GameLists.Fossils, - GameLists.Bugs, - GameLists.Dive, - }.SelectMany(z => z).ToArray(); - - RandUtil.Shuffle(items); - return AddItems(items, interval); - } - - private int AddItems(IEnumerable items, int interval = 20) - { - var processed = Items.Select(z => z.ItemId).Where(z => z != Item.NONE).Distinct(); - var hashset = new HashSet(processed); - - var latestDate = Dates.Max(z => (DateTime)z); - int added = 0; - foreach (var id in items) - { - if (hashset.Contains(id)) - continue; - - if (added % interval == 0) - latestDate = latestDate.AddDays(1); - - int openIndex = GetFirstOpenIndex(); - - Dates[openIndex] = latestDate; - Items[openIndex] = new Item(id); - Players[openIndex] = 0; // first player - - added++; - } - - return added; - } - - private int GetFirstOpenIndex() => Array.FindIndex(Items, z => z.ItemId == Item.NONE); - - public void SortAll() - { - var lump = Enumerable.Range(0, Items.Length) - .Select(z => new {Index = z, Item = Items[z], Date = Dates[z], Player = Players[z]}) - .OrderBy(z => z.Date.IsEmpty) - .ThenBy(z => (DateTime)z.Date); - - int ctr = 0; - foreach (var x in lump) - { - Dates[ctr] = x.Date; - Items[ctr] = x.Item; - Players[ctr] = x.Player; - ctr++; - } + yield return GetDonationSummary(str, item, i); } } -} + + public string GetDonationSummary(GameStrings str, int index) => GetDonationSummary(str, Items[index], index); + + public string GetDonationText(GameStrings str, int index) => $"{Dates[index]}: {str.GetItemName(Items[index])}"; + + private string GetDonationSummary(GameStrings str, Item item, int index) + { + var date = Dates[index]; + var player = Players[index]; + + var name = str.GetItemName(item); + var result = $"On {date}, Player {player} donated a(n) {name}."; + return result; + } + + public int GiveAll(ReadOnlySpan englishNames, int interval = 20) + { + var list = new List(GameLists.Art.Length); + foreach (var item in GameLists.Art) + { + // ignore forgeries + if (!englishNames[item].Contains('(')) + list.Add(item); + } + list.AddRange(GameLists.Fish); + list.AddRange(GameLists.Fossils); + list.AddRange(GameLists.Bugs); + list.AddRange(GameLists.Dive); + RandUtil.Shuffle(list); + return AddItems(CollectionsMarshal.AsSpan(list), interval); + } + + private int AddItems(ReadOnlySpan items, int interval = 20) + { + var processed = Items.Select(z => z.ItemId).Where(z => z != Item.NONE).Distinct(); + var hashset = new HashSet(processed); + + var latestDate = Dates.Max(z => (DateTime)z); + int added = 0; + foreach (var id in items) + { + if (hashset.Contains(id)) + continue; + + if (added % interval == 0) + latestDate = latestDate.AddDays(1); + + int openIndex = GetFirstOpenIndex(); + + Dates[openIndex] = latestDate; + Items[openIndex] = new Item(id); + Players[openIndex] = 0; // first player + + added++; + } + + return added; + } + + private int GetFirstOpenIndex() => Array.FindIndex(Items, z => z.ItemId == Item.NONE); + + public void SortAll() + { + var lump = Enumerable.Range(0, Items.Length) + .Select(z => new {Index = z, Item = Items[z], Date = Dates[z], Player = Players[z]}) + .OrderBy(z => z.Date.IsEmpty) + .ThenBy(z => (DateTime)z.Date); + + int ctr = 0; + foreach (var x in lump) + { + Dates[ctr] = x.Date; + Items[ctr] = x.Item; + Players[ctr] = x.Player; + ctr++; + } + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/Reaction.cs b/NHSE.Core/Structures/Misc/Reaction.cs index 08db929..2e43487 100644 --- a/NHSE.Core/Structures/Misc/Reaction.cs +++ b/NHSE.Core/Structures/Misc/Reaction.cs @@ -1,94 +1,93 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Learned Emotions that can be used from the Reaction Wheel +/// +public enum Reaction : byte { - /// - /// Learned Emotions that can be used from the Reaction Wheel - /// - public enum Reaction : byte - { - None, - Happiness, // Smiling - Laughter, // Laughing - Joy, // HappyFlower - Love, // Love - Glee, // HappyDance - UNUSED_6, // Anger (Unused) - Aggravation, // Outraged - UNUSED_8, // Outrage (Unused) - Worry, // Worried - Sighing, // Sighing - Thought, // Thinking - Sadness, // SadSpiral - Distress, // Frantic - Sorrow, // Crying - Amazed, // Shocked - Surprise, // Aha - UNUSED_17, // Disbelief (Unused) - Shocked, // Surprised - Cold_Chill, // ColdChill - Fearful, // Shaking - Agreement, // Nodding - Inspiration, // IdeaBulb - Curiosity, // QuestionMark - Heartbreak, // BrokenHeart - Sleepy, // Sleepy - Bashfulness, // Blushing - Resignation, // OhGeez - Mischief, // Scheming - Delight, // Clapping - Sneezing, // Sneezing - Encouraging, // Cheering - Greetings, // Greeting - Pride, // SmugFace - UNUSED_34, // Sweating (Unused) - Smirking, // Grin - Sheepishness, // WrySmile - UNUSED_37, // Smile (Unused) - UNUSED_38, // Sunniness (Unused) - Shyness, // Hesitate - Disagreement, // Negative - Mistaken, // Oops - Flourish, // Dance - Daydreaming, // AbsentMindedness - Showmanship, // Shaki - Dozing, // Sleep - UNUSED_46, // Shrunk Funk Shuffle (Unused) - Intense, // Silent - Pleased, // Hello - UNUSED_49, // Distress without the hand movements? (Unused) - UNUSED_50, // Smiling and rubbing cheek (Unused) - UNUSED_51, // Poking hands together (Unused) - UNUSED_52, // Intense but frowning (Unused) - UNUSED_53, // Amazed with smaller particles (Unused) - Apologetic, // Apologize - Confident, // Assent - UNUSED_56, // Talking (Unused) - UNUSED_57, // Clapping with no expression (Makes you stand up if sitting down) (Unused) - Bewilderment, // Pardon - UNUSED_59, // Greetings with no sound or expression (Unused) + None, + Happiness, // Smiling + Laughter, // Laughing + Joy, // HappyFlower + Love, // Love + Glee, // HappyDance + UNUSED_6, // Anger (Unused) + Aggravation, // Outraged + UNUSED_8, // Outrage (Unused) + Worry, // Worried + Sighing, // Sighing + Thought, // Thinking + Sadness, // SadSpiral + Distress, // Frantic + Sorrow, // Crying + Amazed, // Shocked + Surprise, // Aha + UNUSED_17, // Disbelief (Unused) + Shocked, // Surprised + Cold_Chill, // ColdChill + Fearful, // Shaking + Agreement, // Nodding + Inspiration, // IdeaBulb + Curiosity, // QuestionMark + Heartbreak, // BrokenHeart + Sleepy, // Sleepy + Bashfulness, // Blushing + Resignation, // OhGeez + Mischief, // Scheming + Delight, // Clapping + Sneezing, // Sneezing + Encouraging, // Cheering + Greetings, // Greeting + Pride, // SmugFace + UNUSED_34, // Sweating (Unused) + Smirking, // Grin + Sheepishness, // WrySmile + UNUSED_37, // Smile (Unused) + UNUSED_38, // Sunniness (Unused) + Shyness, // Hesitate + Disagreement, // Negative + Mistaken, // Oops + Flourish, // Dance + Daydreaming, // AbsentMindedness + Showmanship, // Shaki + Dozing, // Sleep + UNUSED_46, // Shrunk Funk Shuffle (Unused) + Intense, // Silent + Pleased, // Hello + UNUSED_49, // Distress without the hand movements? (Unused) + UNUSED_50, // Smiling and rubbing cheek (Unused) + UNUSED_51, // Poking hands together (Unused) + UNUSED_52, // Intense but frowning (Unused) + UNUSED_53, // Amazed with smaller particles (Unused) + Apologetic, // Apologize + Confident, // Assent + UNUSED_56, // Talking (Unused) + UNUSED_57, // Clapping with no expression (Makes you stand up if sitting down) (Unused) + Bewilderment, // Pardon + UNUSED_59, // Greetings with no sound or expression (Unused) - Scare, // AddPrank - Haunt, // AddScaring - SitDown, // AddSitDown - Yoga, // AddYoga - HereYouGo, // AddHereYouGo - WorkOut, // AddGymnastics - TakeAPicture, // AddTakePictures - SniffSniff, // AddSmell - Tada, // AddPraise - WaveGoodbye, // AddWaveHands - Excited, // AddExcited + Scare, // AddPrank + Haunt, // AddScaring + SitDown, // AddSitDown + Yoga, // AddYoga + HereYouGo, // AddHereYouGo + WorkOut, // AddGymnastics + TakeAPicture, // AddTakePictures + SniffSniff, // AddSmell + Tada, // AddPraise + WaveGoodbye, // AddWaveHands + Excited, // AddExcited - Confetti, // (Festivale DLC) - Viva, // (Festivale DLC) - LetsGo, // (Festivale DLC) - FeelinIt, // (Festivale DLC) + Confetti, // (Festivale DLC) + Viva, // (Festivale DLC) + LetsGo, // (Festivale DLC) + FeelinIt, // (Festivale DLC) - UNUSED_75, // Gullivar about to come alive (Unused) - UNUSED_76, // Intense shake action (Unused) - UNUSED_77, // Literally the "roll safe" meme (google it) (Unused) - UNUSED_78, // Leave it to me! (Unused) - UNUSED_79, // K.K. Slider Sitting (Unused) - UNUSED_80, // K.K. nodding while sitting (Unused) - UNUSED_81, // K.K. thinking while sitting (Unused) - } -} + UNUSED_75, // Gullivar about to come alive (Unused) + UNUSED_76, // Intense shake action (Unused) + UNUSED_77, // Literally the "roll safe" meme (google it) (Unused) + UNUSED_78, // Leave it to me! (Unused) + UNUSED_79, // K.K. Slider Sitting (Unused) + UNUSED_80, // K.K. nodding while sitting (Unused) + UNUSED_81, // K.K. thinking while sitting (Unused) +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/RecipeBook.cs b/NHSE.Core/Structures/Misc/RecipeBook.cs index 956a3ad..e88b131 100644 --- a/NHSE.Core/Structures/Misc/RecipeBook.cs +++ b/NHSE.Core/Structures/Misc/RecipeBook.cs @@ -1,69 +1,70 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public class RecipeBook { - public class RecipeBook + private const int BitFlagArraySize = 0x100; + private const int BitFlagArrayCount = 4; + public const int SIZE = BitFlagArraySize * BitFlagArrayCount; + public const ushort RecipeCount = BitFlagArraySize * 8; + + private readonly Memory Raw; + private Span Data => Raw.Span; + public RecipeBook(Memory raw) => Raw = raw; + + public void Save(Span data) => Data.CopyTo(data); + + public bool GetIsKnown(int recipe) => FlagUtil.GetFlag(Data, 0 * BitFlagArraySize, recipe); + public void SetIsKnown(int recipe, bool value = true) => FlagUtil.SetFlag(Data, 0 * BitFlagArraySize, recipe, value); + + public bool GetIsMade(int recipe) => FlagUtil.GetFlag(Data, 1 * BitFlagArraySize, recipe); + public void SetIsMade(int recipe, bool value = true) => FlagUtil.SetFlag(Data, 1 * BitFlagArraySize, recipe, value); + + public bool GetIsNew(int recipe) => FlagUtil.GetFlag(Data, 2 * BitFlagArraySize, recipe); + public void SetIsNew(int recipe, bool value = true) => FlagUtil.SetFlag(Data, 2 * BitFlagArraySize, recipe, value); + + public bool GetIsFavorite(int recipe) => FlagUtil.GetFlag(Data, 3 * BitFlagArraySize, recipe); + public void SetIsFavorite(int recipe, bool value = true) => FlagUtil.SetFlag(Data, 3 * BitFlagArraySize, recipe, value); + + public void GiveAll(IReadOnlyDictionary recipes, bool isNew = true) { - private const int BitFlagArraySize = 0x100; - private const int BitFlagArrayCount = 4; - public const int SIZE = BitFlagArraySize * BitFlagArrayCount; - public const ushort RecipeCount = BitFlagArraySize * 8; - - private readonly byte[] Data; - public RecipeBook(byte[] data) => Data = data; - - public void Save(byte[] data, int offset) => Data.CopyTo(data, offset); - - public bool GetIsKnown(int recipe) => FlagUtil.GetFlag(Data, 0 * BitFlagArraySize, recipe); - public void SetIsKnown(int recipe, bool value = true) => FlagUtil.SetFlag(Data, 0 * BitFlagArraySize, recipe, value); - - public bool GetIsMade(int recipe) => FlagUtil.GetFlag(Data, 1 * BitFlagArraySize, recipe); - public void SetIsMade(int recipe, bool value = true) => FlagUtil.SetFlag(Data, 1 * BitFlagArraySize, recipe, value); - - public bool GetIsNew(int recipe) => FlagUtil.GetFlag(Data, 2 * BitFlagArraySize, recipe); - public void SetIsNew(int recipe, bool value = true) => FlagUtil.SetFlag(Data, 2 * BitFlagArraySize, recipe, value); - - public bool GetIsFavorite(int recipe) => FlagUtil.GetFlag(Data, 3 * BitFlagArraySize, recipe); - public void SetIsFavorite(int recipe, bool value = true) => FlagUtil.SetFlag(Data, 3 * BitFlagArraySize, recipe, value); - - public void GiveAll(IReadOnlyDictionary recipes, bool isNew = true) + foreach (var entry in recipes) { - foreach (var entry in recipes) - { - var index = entry.Key; - if (index is RecipeList.BridgeConstructionKit or RecipeList.CampsiteConstructionKit) - continue; + var index = entry.Key; + if (index is RecipeList.BridgeConstructionKit or RecipeList.CampsiteConstructionKit) + continue; - bool alreadyHave = GetIsKnown(index); - if (alreadyHave) - continue; + bool alreadyHave = GetIsKnown(index); + if (alreadyHave) + continue; - SetIsKnown(index); - SetIsNew(index, isNew); - } - } - - public void ClearAll() - { - for (int i = 0; i < RecipeCount; i++) - { - SetIsKnown(i, false); - SetIsNew(i, false); - SetIsMade(i, false); - SetIsFavorite(i, false); - } - } - - public void CraftAll() - { - for (int i = 0; i < RecipeCount; i++) - { - bool alreadyHave = GetIsKnown(i); - if (!alreadyHave) - continue; - SetIsMade(i); - SetIsNew(i, false); - } + SetIsKnown(index); + SetIsNew(index, isNew); } } -} + + public void ClearAll() + { + for (int i = 0; i < RecipeCount; i++) + { + SetIsKnown(i, false); + SetIsNew(i, false); + SetIsMade(i, false); + SetIsFavorite(i, false); + } + } + + public void CraftAll() + { + for (int i = 0; i < RecipeCount; i++) + { + bool alreadyHave = GetIsKnown(i); + if (!alreadyHave) + continue; + SetIsMade(i); + SetIsNew(i, false); + } + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Misc/ValueTypeTypeConverter.cs b/NHSE.Core/Structures/Misc/ValueTypeTypeConverter.cs index 2c5b136..dfca493 100644 --- a/NHSE.Core/Structures/Misc/ValueTypeTypeConverter.cs +++ b/NHSE.Core/Structures/Misc/ValueTypeTypeConverter.cs @@ -2,25 +2,29 @@ using System.Collections; using System.ComponentModel; -namespace NHSE.Core -{ - /// - /// Used for allowing a struct to be mutated in a PropertyGrid. - /// - public class ValueTypeTypeConverter : ExpandableObjectConverter - { - public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) => true; +namespace NHSE.Core; - public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues) +/// +/// Used for allowing a struct to be mutated in a PropertyGrid. +/// +public class ValueTypeTypeConverter : ExpandableObjectConverter +{ + public override bool GetCreateInstanceSupported(ITypeDescriptorContext? context) => true; + + public override object? CreateInstance(ITypeDescriptorContext? context, IDictionary propertyValues) + { + if (context?.PropertyDescriptor is not { } pd) + return null; + + var boxed = pd.GetValue(context.Instance); + foreach (DictionaryEntry entry in propertyValues) { - object boxed = context.PropertyDescriptor.GetValue(context.Instance); - foreach (DictionaryEntry entry in propertyValues) - { - var pi = context.PropertyDescriptor.PropertyType.GetProperty(entry.Key.ToString()); - if (pi?.CanWrite == true) - pi.SetValue(boxed, Convert.ChangeType(entry.Value, pi.PropertyType), null); - } - return boxed; + if (entry.Key.ToString() is not { } propName) + continue; + var pi = pd.PropertyType.GetProperty(propName); + if (pi?.CanWrite == true) + pi.SetValue(boxed, Convert.ChangeType(entry.Value, pi.PropertyType), null); } + return boxed; } } \ No newline at end of file diff --git a/NHSE.Core/Structures/RecipeList.cs b/NHSE.Core/Structures/RecipeList.cs index a197d48..56f7bb5 100644 --- a/NHSE.Core/Structures/RecipeList.cs +++ b/NHSE.Core/Structures/RecipeList.cs @@ -1,938 +1,937 @@ using System.Collections.Generic; -namespace NHSE.Core -{ - public static class RecipeList - { - public const int BridgeConstructionKit = 0x1CA; - public const int CampsiteConstructionKit = 0x1CD; +namespace NHSE.Core; - public static readonly IReadOnlyDictionary Recipes = new Dictionary - { - {0x006, 02596}, // juicy-apple TV - {0x009, 01263}, // pear wardrobe - {0x00A, 03068}, // flimsy axe - {0x00D, 01429}, // campfire - {0x00E, 01799}, // doghouse - {0x00F, 01913}, // wooden chair - {0x010, 00880}, // wooden bucket - {0x011, 02560}, // wooden chest - {0x012, 02605}, // wooden simple bed - {0x013, 03082}, // flimsy shovel - {0x014, 03083}, // flimsy watering can - {0x015, 03084}, // flimsy fishing rod - {0x016, 02376}, // flimsy net - {0x017, 01559}, // wooden-block bench - {0x018, 01561}, // wooden-block chest - {0x01A, 01565}, // wooden-block table - {0x01D, 02822}, // slingshot - {0x01E, 01753}, // aroma pot - {0x020, 00808}, // mush table - {0x021, 00739}, // tea table - {0x022, 01430}, // bonfire - {0x023, 03191}, // ironwood table - {0x024, 02754}, // simple well - {0x025, 02559}, // pot - {0x026, 03206}, // wooden-block toy - {0x029, 00333}, // birdhouse - {0x02A, 00331}, // birdbath - {0x02B, 00088}, // ringtoss - {0x02C, 00383}, // acoustic guitar - {0x02D, 00669}, // ukulele - {0x02E, 00710}, // bamboo bench - {0x030, 00729}, // garden rock - {0x031, 00730}, // tall garden rock - {0x033, 00805}, // mush lamp - {0x037, 00665}, // wave breaker - {0x038, 00975}, // fruit basket - {0x039, 01103}, // rocking chair - {0x03A, 01157}, // brick oven - {0x03B, 01170}, // swinging bench - {0x03C, 01189}, // tire stack - {0x03D, 01557}, // wooden-block bed - {0x03E, 01558}, // wooden-block bookshelf - {0x03F, 01625}, // iron garden bench - {0x040, 01626}, // iron garden chair - {0x041, 01627}, // iron garden table - {0x042, 01823}, // trash bags - {0x04D, 02319}, // drinking fountain - {0x04E, 02329}, // tire toy - {0x04F, 02553}, // iron frame - {0x050, 02586}, // natural garden chair - {0x051, 03065}, // gold bars - {0x052, 03122}, // mini DIY workbench - {0x053, 03193}, // ironwood chair - {0x054, 03194}, // ironwood low table - {0x055, 03195}, // ironwood cart - {0x056, 03196}, // ironwood dresser - {0x057, 03200}, // ironwood bed - {0x059, 03205}, // wooden-block stereo - {0x05A, 03208}, // wooden-block wall clock - {0x05B, 03270}, // ironwood kitchenette - {0x05C, 03271}, // ironwood cupboard - {0x05E, 03275}, // ironwood clock - {0x063, 03080}, // brick fence - {0x064, 03402}, // vertical-board fence - {0x065, 03403}, // bamboo lattice fence - {0x066, 00083}, // rocking horse - {0x067, 00343}, // tiki torch - {0x068, 03398}, // stone stool - {0x069, 03397}, // stone table - {0x06B, 02615}, // ladder - {0x06E, 04044}, // log extra-long sofa - {0x06F, 04043}, // log round table - {0x070, 04042}, // log bench - {0x071, 04035}, // log garden lounge - {0x072, 04036}, // log decorative shelves - {0x073, 04037}, // log wall-mounted clock - {0x074, 04038}, // log stool - {0x075, 04039}, // log chair - {0x076, 04040}, // log dining table - {0x077, 04041}, // log bed - {0x078, 04025}, // unglazed dish set - {0x079, 04027}, // floral swag - {0x07A, 03559}, // iron wall lamp - {0x07B, 03562}, // iron wall rack - {0x07C, 03509}, // garden bench - {0x07D, 03943}, // ironwood DIY workbench - {0x07E, 03560}, // iron worktable - {0x080, 03563}, // iron shelf - {0x082, 03772}, // golden candlestick - {0x083, 03810}, // golden dishes - {0x084, 03774}, // Libra scale - {0x085, 03473}, // golden seat - {0x088, 03808}, // mush log - {0x08A, 03806}, // mush partition - {0x08B, 03805}, // mush parasol - {0x08C, 03499}, // frozen arch - {0x08D, 03501}, // frozen sculpture - {0x08E, 03503}, // frozen chair - {0x08F, 03505}, // frozen counter - {0x091, 03504}, // frozen tree - {0x092, 03497}, // frozen table - {0x093, 03498}, // frozen partition - {0x094, 03500}, // frozen pillar - {0x095, 03502}, // frozen bed - {0x097, 03558}, // bamboo wall decoration - {0x098, 03658}, // bamboo basket - {0x099, 03554}, // bamboo candleholder - {0x09A, 03556}, // bamboo stopblock - {0x09B, 03551}, // bamboo shelf - {0x09D, 03553}, // bamboo partition - {0x09E, 03555}, // bamboo doll - {0x09F, 03557}, // bamboo floor lamp - {0x0A0, 02558}, // wooden-block chair - {0x0A1, 04011}, // cherry speakers - {0x0A2, 04012}, // cherry lamp - {0x0A3, 03684}, // coconut juice - {0x0A4, 00080}, // clackercart - {0x0A5, 01266}, // barrel - {0x0A6, 03692}, // plain wooden shop sign - {0x0A7, 03675}, // hay bed - {0x0A8, 03449}, // wooden stool - {0x0A9, 03445}, // standard umbrella stand - {0x0AA, 03438}, // wooden end table - {0x0AB, 00682}, // boomerang - {0x0AC, 03436}, // wooden wardrobe - {0x0AD, 03490}, // wooden waste bin - {0x0AE, 03683}, // plain sink - {0x0AF, 03977}, // shell arch - {0x0B0, 03978}, // shell partition - {0x0B1, 03979}, // shell stool - {0x0B2, 03980}, // shell table - {0x0B4, 03982}, // shell fountain - {0x0B5, 03983}, // shell bed - {0x0B6, 03984}, // shell lamp - {0x0B7, 04703}, // vaulting pole - {0x0B8, 03976}, // orange wall-mounted clock - {0x0B9, 03975}, // orange end table - {0x0BA, 04546}, // pear bed - {0x0BB, 04127}, // peach chair - {0x0BC, 04128}, // peach surprise box - {0x0BD, 04134}, // apple chair - {0x0BE, 00132}, // succulent plant - {0x0BF, 04549}, // fish bait - {0x0C0, 04073}, // classic pitcher - {0x0C1, 04124}, // wooden fish - {0x0C2, 04279}, // frozen-treat set - {0x0C3, 04393}, // old-fashioned washtub - {0x0C4, 01759}, // stack of books - {0x0C5, 01861}, // stacked magazines - {0x0C7, 04104}, // frying pan - {0x0C8, 05150}, // shell speaker - {0x0C9, 03439}, // wooden table - {0x0CA, 04090}, // spooky table - {0x0CB, 04066}, // illuminated tree - {0x0CC, 03406}, // beekeeper's hive - {0x0CD, 04083}, // spooky arch - {0x0CE, 04084}, // spooky scarecrow - {0x0CF, 04086}, // spooky tower - {0x0D0, 04087}, // spooky carriage - {0x0D1, 04088}, // spooky lantern - {0x0D2, 04089}, // spooky chair - {0x0D4, 04092}, // spooky lantern set - {0x0D5, 03588}, // signpost - {0x0D6, 03785}, // potted ivy - {0x0D7, 01058}, // music stand - {0x0D8, 00865}, // birdcage - {0x0D9, 00722}, // hearth - {0x0DA, 05320}, // ocarina - {0x0DB, 04376}, // shell wreath - {0x0DC, 04708}, // mush low stool - {0x0DD, 04726}, // mushroom wreath - {0x0DE, 04375}, // snowflake wreath - {0x0DF, 04378}, // fruit wreath - {0x0E0, 03396}, // natural garden table - {0x0E1, 04727}, // tree branch wreath - {0x0E2, 04377}, // ornament wreath - {0x0E3, 04293}, // cosmos wreath - {0x0E4, 05436}, // windflower wreath - {0x0E5, 05437}, // rose wreath - {0x0E6, 05466}, // pansy wreath - {0x0E7, 05467}, // mum wreath - {0x0E8, 05468}, // hyacinth wreath - {0x0E9, 01447}, // flying saucer - {0x0EA, 01054}, // moon - {0x0EB, 01439}, // asteroid - {0x0EC, 01445}, // astronaut suit - {0x0ED, 05096}, // hyacinth crown (No Variations) - {0x0EE, 05097}, // cool hyacinth crown (No Variations) - {0x0EF, 05098}, // purple hyacinth crown (No Variations) - {0x0F0, 05099}, // windflower crown (No Variations) - {0x0F1, 05100}, // cool windflower crown (No Variations) - {0x0F2, 05101}, // purple windflower crown (No Variations) - {0x0F3, 05102}, // tulip crown (No Variations) - {0x0F4, 05103}, // chic tulip crown (No Variations) - {0x0F5, 05104}, // dark tulip crown (No Variations) - {0x0F6, 05105}, // pansy crown (No Variations) - {0x0F7, 05106}, // cool pansy crown (No Variations) - {0x0F8, 05107}, // purple pansy crown (No Variations) - {0x0F9, 05108}, // cosmos crown (No Variations) - {0x0FA, 05109}, // lovely cosmos crown (No Variations) - {0x0FB, 05110}, // dark cosmos crown (No Variations) - {0x0FC, 05111}, // rose crown (No Variations) - {0x0FD, 05112}, // cute rose crown (No Variations) - {0x0FE, 05113}, // chic rose crown (No Variations) - {0x0FF, 05114}, // lily crown (No Variations) - {0x100, 05115}, // cute lily crown (No Variations) - {0x101, 05116}, // dark lily crown (No Variations) - {0x102, 05117}, // mum crown (No Variations) - {0x103, 05118}, // chic mum crown (No Variations) - {0x104, 05119}, // simple mum crown (No Variations) - {0x105, 04682}, // leaf (No Variations) - {0x106, 03472}, // golden toilet - {0x107, 01241}, // DIY workbench - {0x108, 02578}, // pitfall seed - {0x10A, 05212}, // stone fence - {0x10B, 04357}, // iron fence - {0x10C, 04350}, // country fence - {0x10D, 04349}, // corral fence - {0x10F, 02100}, // axe - {0x111, 03966}, // big festive tree - {0x112, 03991}, // festive tree - {0x115, 00144}, // manhole cover - {0x116, 05635}, // tiny library - {0x117, 05636}, // wooden-plank sign - {0x118, 02379}, // watering can - {0x119, 02099}, // shovel - {0x11A, 02377}, // fishing rod - {0x11B, 05784}, // net - {0x11C, 03618}, // cutting board - {0x11D, 05856}, // stone axe - {0x11E, 05528}, // starry wall - {0x120, 05516}, // ice flooring - {0x121, 05253}, // iceberg flooring - {0x122, 04905}, // autumn wall - {0x123, 05230}, // Jingle wall - {0x124, 05510}, // sci-fi wall - {0x125, 05505}, // ice wall - {0x126, 05500}, // starry-sky wall - {0x127, 05498}, // ski-slope wall - {0x128, 04865}, // honeycomb wall - {0x12A, 04820}, // gold-screen wall - {0x12B, 04894}, // golden wall - {0x12C, 04853}, // bamboo-grove wall - {0x12D, 05229}, // garbage-heap wall - {0x12E, 05662}, // iceberg wall - {0x12F, 04915}, // orange wall - {0x130, 04916}, // apple wall - {0x131, 04917}, // pear wall - {0x132, 04918}, // peach wall - {0x133, 04919}, // cherry wall - {0x134, 05164}, // mush wall - {0x135, 04858}, // wild-wood wall - {0x136, 04859}, // wooden-mosaic wall - {0x137, 04860}, // dark wooden-mosaic wall - {0x138, 04804}, // brown herringbone wall - {0x139, 04805}, // chocolate herringbone wall - {0x13A, 04844}, // stacked-wood wall - {0x13B, 04840}, // cabin wall - {0x13C, 04838}, // manga-library wall - {0x13D, 04837}, // classic-library wall - {0x13E, 05216}, // stone wall - {0x13F, 04911}, // wooden-knot wall - {0x140, 04904}, // modern wood wall - {0x141, 04947}, // sakura-wood wall - {0x142, 04833}, // bamboo wall - {0x143, 04855}, // snowflake wall - {0x144, 04813}, // rustic-stone wall - {0x145, 04801}, // steel-frame wall - {0x146, 05457}, // jungle wall - {0x167, 00677}, // deer scare - {0x168, 05670}, // tulip wreath - {0x169, 05751}, // pretty tulip wreath - {0x16A, 05771}, // dark tulip wreath - {0x16C, 05337}, // three-tiered snowperson - {0x16D, 03561}, // iron hanger stand - {0x16E, 05956}, // Aquarius urn - {0x16F, 05954}, // Aries rocking chair - {0x170, 05955}, // Virgo harp - {0x172, 05957}, // Capricorn ornament - {0x173, 05959}, // Cancer table - {0x174, 00891}, // holiday candle - {0x175, 01442}, // lunar rover - {0x176, 03689}, // sauna heater - {0x177, 06030}, // cherry-blossom bonsai - {0x178, 05958}, // Sagittarius arrow - {0x179, 05960}, // Gemini closet - {0x17A, 03340}, // deer decoration - {0x17B, 01443}, // satellite - {0x17C, 05962}, // Scorpio lamp - {0x17D, 01444}, // space shuttle - {0x17E, 03344}, // steamer-basket set - {0x17F, 04309}, // destinations signpost - {0x180, 05961}, // Taurus bathtub - {0x181, 05977}, // bamboo-shoot lamp - {0x182, 01440}, // lunar lander - {0x183, 05543}, // wooden-block stool - {0x184, 04067}, // tabletop festive tree - {0x185, 02326}, // water pump - {0x186, 01797}, // decoy duck - {0x187, 03773}, // terrarium - {0x188, 04074}, // illuminated reindeer - {0x189, 04075}, // gong - {0x18A, 03819}, // oil-barrel bathtub - {0x18B, 04078}, // barbell - {0x18C, 03775}, // hanging terrarium - {0x18D, 04093}, // bamboo drum - {0x18E, 05517}, // pan flute - {0x18F, 05963}, // Pisces lamp - {0x190, 04107}, // infused-water dispenser - {0x191, 04108}, // illuminated present - {0x192, 05970}, // firewood - {0x193, 01652}, // matryoshka - {0x194, 04125}, // wooden bookshelf - {0x195, 04130}, // coconut wall planter - {0x196, 04131}, // illuminated snowflakes - {0x197, 05964}, // Leo sculpture - {0x198, 03776}, // brick well - {0x199, 01441}, // rocket - {0x19A, 01111}, // outdoor bath - {0x19B, 05975}, // traditional balancing toy - {0x19C, 05973}, // log stakes - {0x19D, 01032}, // magazine rack - {0x19E, 06075}, // tree's bounty mobile - {0x19F, 06078}, // tree's bounty lamp - {0x1A0, 06079}, // tree's bounty little tree - {0x1A1, 06080}, // tree's bounty big tree - {0x1A2, 06032}, // cherry-blossom-petal pile - {0x1A3, 06031}, // cherry-blossom branches - {0x1A4, 05976}, // bamboo sphere - {0x1A5, 05978}, // bamboo lunch box - {0x1A6, 06033}, // outdoor picnic set - {0x1A7, 06081}, // tree's bounty arch - {0x1A8, 05979}, // bamboo noodle slide - {0x1A9, 06830}, // shell music box - {0x1AA, 06832}, // cherry-blossom clock - {0x1AB, 06831}, // blossom-viewing lantern - {0x1AD, 06826}, // nova light - {0x1AE, 06827}, // starry garland - {0x1B0, 06829}, // crescent-moon chair - {0x1B1, 06818}, // ornament mobile - {0x1B2, 05676}, // crewed spaceship - {0x1B3, 05931}, // jail bars - {0x1B4, 05972}, // wild log bench - {0x1B5, 03992}, // key holder - {0x1B6, 05641}, // lily wreath - {0x1B8, 05765}, // chic windflower wreath - {0x1B9, 05746}, // cool windflower wreath - {0x1BA, 05768}, // natural mum wreath - {0x1BB, 05749}, // fancy mum wreath - {0x1BC, 05764}, // chic cosmos wreath - {0x1BD, 05745}, // pretty cosmos wreath - {0x1BE, 05766}, // dark rose wreath - {0x1BF, 05772}, // blue rose wreath - {0x1C0, 05747}, // fancy rose wreath - {0x1C1, 05820}, // gold rose wreath - {0x1C2, 05767}, // cool pansy wreath - {0x1C3, 05748}, // snazzy pansy wreath - {0x1C4, 05769}, // purple hyacinth wreath - {0x1C5, 05750}, // cool hyacinth wreath - {0x1C6, 05770}, // dark lily wreath - {0x1C7, 05677}, // fancy lily wreath - {0x1C8, 06840}, // leaf umbrella - {0x1C9, 03229}, // clothesline - {0x1CA, 07211}, // bridge construction kit - {0x1CB, 07377}, // blue rose crown (No Variations) - {0x1CC, 07378}, // gold rose crown (No Variations) - {0x1CD, 05166}, // campsite construction kit - {0x1CE, 01750}, // document stack - {0x1CF, 04034}, // scattered papers - {0x1D0, 05719}, // fossil doorplate - {0x1D1, 05718}, // timber doorplate - {0x1D2, 05716}, // paw-print doorplate - {0x1D3, 04751}, // bone doorplate - {0x1D4, 04752}, // iron doorplate - {0x1D5, 05717}, // crest doorplate - {0x1D6, 05515}, // jungle flooring - {0x1D7, 05223}, // woodland wall - {0x1D8, 04999}, // honeycomb flooring - {0x1D9, 04986}, // money flooring - {0x1DA, 04797}, // basement flooring - {0x1DB, 05021}, // golden flooring - {0x1DC, 04990}, // colored-leaves flooring - {0x1DD, 05270}, // sci-fi flooring - {0x1DE, 04968}, // lunar surface - {0x1DF, 07204}, // cherry-blossom flooring - {0x1E0, 07205}, // cherry-blossom-trees wall - {0x1E2, 05269}, // galaxy flooring - {0x1E3, 04989}, // ski-slope flooring - {0x1E4, 07187}, // forest wall - {0x1E5, 04964}, // bamboo flooring - {0x1E6, 05236}, // garbage-heap flooring - {0x1E7, 04979}, // backyard lawn - {0x1E8, 07186}, // forest flooring - {0x1E9, 04960}, // steel flooring - {0x1EA, 04008}, // kettle bathtub - {0x1EB, 07134}, // wooden low table - {0x1EC, 07133}, // wooden mini table - {0x1ED, 07132}, // wooden double bed - {0x1EE, 07142}, // simple DIY workbench - {0x1EF, 07231}, // tulip surprise box - {0x1F0, 07160}, // cardboard table - {0x1F1, 07161}, // cardboard bed - {0x1F2, 07163}, // cardboard chair - {0x1F4, 07159}, // cardboard sofa - {0x1F5, 07230}, // cosmos shower - {0x1F6, 07137}, // wooden full-length mirror - {0x1F7, 07233}, // windflower fan - {0x1F8, 07045}, // recycled-can thumb piano - {0x1F9, 07232}, // mum cushion - {0x1FA, 07234}, // hyacinth lamp - {0x1FB, 07235}, // rose bed - {0x1FC, 07805}, // butter churn - {0x1FD, 07788}, // leaf campfire - {0x1FE, 07867}, // angled signpost - {0x1FF, 07409}, // cherry-blossom pond stone - {0x200, 07408}, // maple-leaf pond stone - {0x201, 07393}, // pond stone - {0x202, 07253}, // star clock - {0x203, 07236}, // lily record player - {0x204, 07237}, // pansy table - {0x206, 03446}, // western-style stone - {0x207, 07390}, // leaf stool - {0x208, 07452}, // raccoon figurine - {0x209, 07048}, // pile of zen cushions - {0x20B, 02544}, // star wand - {0x20C, 05083}, // hyacinth wand - {0x20D, 05084}, // windflower wand - {0x20E, 05085}, // tulip wand - {0x20F, 05091}, // pansy wand - {0x210, 05092}, // cosmos wand - {0x211, 05093}, // rose wand - {0x212, 05094}, // lily wand - {0x213, 05095}, // mums wand - {0x214, 07584}, // wand - {0x215, 07585}, // ice wand - {0x216, 07586}, // shell wand - {0x217, 07587}, // tree-branch wand - {0x218, 07588}, // mushroom wand - {0x219, 07589}, // cherry-blossom wand - {0x21A, 07590}, // bamboo wand - {0x21B, 07591}, // golden wand - {0x21C, 07592}, // iron wand - {0x21D, 07169}, // maple-leaf umbrella - {0x21E, 07327}, // apple rug - {0x21F, 07328}, // cherry rug - {0x220, 07330}, // orange rug - {0x221, 07331}, // peach rug - {0x222, 07332}, // pear rug - {0x224, 04351}, // log fence - {0x225, 04352}, // rope fence - {0x226, 04354}, // imperial fence - {0x227, 04355}, // block fence - {0x228, 04356}, // straw fence - {0x229, 04358}, // spiky fence - {0x22B, 05206}, // iron-and-stone fence - {0x22C, 05207}, // zen fence - {0x22D, 05208}, // large lattice fence - {0x22F, 05210}, // log-wall fence - {0x231, 05213}, // barbed-wire fence - {0x234, 05268}, // underwater flooring - {0x235, 05030}, // water flooring - {0x236, 04590}, // gold armor (No Variations) - {0x237, 02777}, // medicine - {0x238, 07317}, // zen-style stone - {0x239, 08825}, // golden casket - {0x23A, 07795}, // stone lion-dog - {0x23B, 08419}, // garden wagon - {0x23C, 08826}, // wooden table mirror - {0x23D, 09642}, // iron closet - {0x23E, 07258}, // modeling clay - {0x23F, 07259}, // palm-tree lamp - {0x240, 07261}, // trophy case - {0x241, 01504}, // giant teddy bear - {0x242, 09814}, // lucky gold cat - {0x243, 07454}, // wooden toolbox - {0x244, 07281}, // sleigh - {0x246, 00530}, // grass standee - {0x247, 00531}, // hedge standee - {0x248, 00532}, // mountain standee - {0x249, 00533}, // tree standee - {0x24A, 01023}, // pile of leaves - {0x24B, 04269}, // green-leaf pile - {0x24C, 04270}, // yellow-leaf pile - {0x24D, 04271}, // red-leaf pile - {0x24E, 10742}, // bamboo stool - {0x24F, 10743}, // bamboo speaker - {0x250, 03802}, // pine bonsai tree - {0x251, 03580}, // bonsai shelf - {0x252, 01509}, // robot hero - {0x253, 11261}, // golden gears - {0x254, 03617}, // stall - {0x256, 07247}, // silo - {0x257, 08031}, // fountain - {0x258, 07535}, // kettlebell - {0x259, 05941}, // golden dung beetle - {0x25A, 11260}, // golden arowana model - {0x25B, 04333}, // grass skirt (No Variations) - {0x25C, 05291}, // traditional straw coat (No Variations) - {0x25D, 08907}, // green grass skirt (No Variations) - {0x25E, 07254}, // straw umbrella hat (No Variations) - {0x25F, 05143}, // bamboo hat (No Variations) - {0x260, 07527}, // flower stand - {0x261, 03410}, // small cardboard boxes - {0x262, 03411}, // medium cardboard boxes - {0x263, 03412}, // large cardboard boxes - {0x264, 09838}, // cherry dress (No Variations) - {0x265, 09873}, // cherry hat (No Variations) - {0x266, 09949}, // cherry umbrella - {0x267, 09837}, // pear dress (No Variations) - {0x268, 09872}, // pear hat (No Variations) - {0x269, 09950}, // pear umbrella - {0x26A, 09839}, // peach dress (No Variations) - {0x26B, 09874}, // peach hat (No Variations) - {0x26C, 09947}, // peach umbrella - {0x26D, 09836}, // apple dress (No Variations) - {0x26E, 09871}, // apple hat (No Variations) - {0x26F, 09948}, // apple umbrella - {0x270, 05275}, // orange hat (No Variations) - {0x271, 06912}, // orange umbrella - {0x272, 03288}, // orange dress (No Variations) - {0x273, 07489}, // star pochette (No Variations) - {0x274, 09862}, // star head (No Variations) - {0x275, 09945}, // cherry-blossom umbrella - {0x276, 07490}, // cherry-blossom pochette (No Variations) - {0x277, 07491}, // maple-leaf pochette (No Variations) - {0x278, 07492}, // acorn pochette (No Variations) - {0x279, 07493}, // snowflake pochette (No Variations) - {0x27A, 07494}, // shellfish pochette (No Variations) - {0x27B, 07291}, // leaf mask (Green) - {0x27C, 07511}, // knitted-grass backpack (No Variations) - {0x27D, 08609}, // snowperson head (No Variations) - {0x27E, 07498}, // log pack (No Variations) - {0x280, 04588}, // iron armor (No Variations) - {0x281, 05334}, // knight's helmet (Gray) - {0x282, 05472}, // armor shoes (No Variations) - {0x283, 05524}, // gold-armor shoes (No Variations) - {0x284, 05346}, // gold helmet (Gold) - {0x285, 07506}, // basket pack (No Variations) - {0x286, 12206}, // flat garden rock - {0x287, 12208}, // mossy garden rock - {0x288, 07174}, // mush umbrella - {0x289, 05056}, // sakura-wood flooring - {0x28A, 12230}, // festive top set - {0x28B, 11943}, // stone tablet - {0x28C, 11941}, // stone arch - {0x28D, 00676}, // tall lantern - {0x28E, 11942}, // street piano - {0x28F, 01120}, // scarecrow - {0x290, 11711}, // simple wooden fence - {0x291, 11712}, // lattice fence - {0x292, 08179}, // golden net - {0x293, 08533}, // golden watering can - {0x294, 08574}, // golden shovel - {0x295, 08578}, // golden slingshot - {0x296, 08660}, // golden rod - {0x297, 09617}, // golden axe - {0x298, 12326}, // recycled boots (No Variations) - {0x299, 05508}, // underwater wall - {0x29A, 05661}, // tropical vista - {0x29B, 07239}, // starry-sands flooring - {0x29C, 07362}, // shell rug - {0x29D, 04970}, // sandy-beach flooring - {0x29E, 12332}, // natural square table - {0x29F, 11113}, // light bamboo rug - {0x2A0, 11114}, // dark bamboo rug - {0x2A1, 12439}, // earth-egg shell (No Variations) - {0x2A2, 12449}, // earth-egg outfit (No Variations) - {0x2A3, 12455}, // earth-egg shoes (No Variations) - {0x2A4, 12440}, // stone-egg shell (No Variations) - {0x2A5, 12450}, // stone-egg outfit (No Variations) - {0x2A6, 12456}, // stone-egg shoes (No Variations) - {0x2A7, 12441}, // leaf-egg shell (No Variations) - {0x2A8, 12451}, // leaf-egg outfit (No Variations) - {0x2A9, 12457}, // leaf-egg shoes (No Variations) - {0x2AA, 12442}, // wood-egg shell (No Variations) - {0x2AB, 12452}, // wood-egg outfit (No Variations) - {0x2AC, 12458}, // wood-egg shoes (No Variations) - {0x2AD, 12443}, // sky-egg shell (No Variations) - {0x2AE, 12453}, // sky-egg outfit (No Variations) - {0x2AF, 12459}, // sky-egg shoes (No Variations) - {0x2B0, 12444}, // water-egg shell (No Variations) - {0x2B1, 12454}, // water-egg outfit (No Variations) - {0x2B2, 12460}, // water-egg shoes (No Variations) - {0x2B3, 12446}, // egg party hat (No Variations) - {0x2B4, 12448}, // egg party dress (No Variations) - {0x2B5, 12445}, // Bunny Day crown (No Variations) - {0x2B6, 12447}, // Bunny Day bag (No Variations) - {0x2B7, 12398}, // Bunny Day arch - {0x2B8, 12412}, // wobbling Zipper toy - {0x2B9, 12413}, // Bunny Day lamp - {0x2BA, 12414}, // Bunny Day bed - {0x2BB, 12415}, // Bunny Day stool - {0x2BC, 12417}, // Bunny Day glowy garland - {0x2BD, 12418}, // Bunny Day wall clock - {0x2BE, 12419}, // Bunny Day merry balloons - {0x2BF, 12420}, // Bunny Day vanity - {0x2C0, 12421}, // Bunny Day festive balloons - {0x2C1, 12436}, // Bunny Day table - {0x2C2, 12437}, // Bunny Day wardrobe - {0x2C3, 12517}, // Bunny Day wreath - {0x2C4, 05231}, // Bunny Day wall - {0x2C5, 07546}, // Bunny Day rug - {0x2C6, 12423}, // Bunny Day flooring - {0x2C7, 12578}, // Bunny Day wand - {0x2C8, 12630}, // Bunny Day fence - {0x2C9, 12758}, // hedge - {0x2CA, 12894}, // wedding fence - {0x2CB, 12695}, // wedding wand - {0x2CC, 05607}, // King Tut mask (Gold) - {0x2CD, 12552}, // mermaid table - {0x2CE, 12553}, // mermaid shelf - {0x2CF, 12554}, // mermaid vanity - {0x2D0, 12555}, // mermaid screen - {0x2D1, 12556}, // mermaid lamp - {0x2D2, 12557}, // mermaid wall clock - {0x2D3, 12558}, // mermaid bed - {0x2D4, 12559}, // mermaid closet - {0x2D5, 12560}, // mermaid sofa - {0x2D6, 12561}, // mermaid dresser - {0x2D7, 12562}, // mermaid chair - {0x2D8, 12563}, // mermaid rug - {0x2D9, 12566}, // mermaid wall - {0x2DA, 12568}, // mermaid flooring - {0x2DC, 12951}, // spooky candy set - {0x2DD, 12949}, // spooky standing lamp - {0x2DE, 13222}, // spooky garland - {0x2DF, 13223}, // spooky table setting - {0x2E0, 13237}, // spooky wand - {0x2E1, 13275}, // spooky fence - {0x2E2, 13608}, // veggie basket - {0x2E4, 13447}, // Turkey Day garden stand - {0x2E5, 13448}, // Turkey Day hearth - {0x2E6, 13449}, // Turkey Day decorations - {0x2E7, 13450}, // Turkey Day chair - {0x2E9, 13453}, // Turkey Day table - {0x2EA, 07544}, // festive rug - {0x2EB, 13818}, // Turkey Day casserole - {0x2EC, 13819}, // Turkey Day wheat decor - {0x2ED, 13820}, // Turkey Day table setting - {0x2EE, 13244}, // gift pile - {0x2EF, 13792}, // festive wrapping paper - {0x2F0, 13603}, // falling-snow wall - {0x2F1, 12681}, // partition wall - {0x2F3, 03548}, // rainbow feather - {0x2F5, 12217}, // summer-shell rug - {0x2F6, 14019}, // vine hanging chair - {0x2F7, 13526}, // vine ladder set-up kit - {0x2F8, 13530}, // wooden ladder set-up kit - {0x2F9, 13534}, // iron ladder set-up kit - {0x2FA, 14017}, // cave - {0x2FB, 14018}, // ruined arch - {0x2FC, 13906}, // round vine rug - {0x2FD, 13874}, // glowing-moss ruins wall - {0x2FE, 13875}, // rope-net wall - {0x300, 13877}, // glowing-moss rug - {0x301, 13878}, // round glowing-moss rug - {0x302, 13879}, // glowing-moss flooring - {0x303, 13880}, // rope-net flooring - {0x304, 13881}, // glowing-moss cave wall - {0x305, 13019}, // glowing-moss forest wall - {0x306, 14239}, // shamrock wand - {0x308, 14278}, // mermaid fence - {0x309, 13895}, // tall concrete island counter - {0x30B, 13897}, // tall brick island counter - {0x30C, 13898}, // low concrete island counter - {0x30F, 13901}, // low brick island counter - {0x310, 13902}, // tall wooden island counter - {0x318, 14308}, // low simple island counter - {0x31A, 14310}, // tall simple island counter - {0x31D, 14313}, // low wooden island counter - {0x323, 14322}, // tall steel island counter - {0x325, 14324}, // low steel island counter - {0x32B, 14330}, // tall golden island counter - {0x32D, 14332}, // tall marble island counter - {0x32E, 14333}, // low golden island counter - {0x332, 14337}, // low marble island counter - {0x333, 14470}, // golden ladder set-up kit - {0x334, 14197}, // woven-vines hat (No Variations) - {0x335, 14202}, // vine crown (No Variations) - {0x336, 14248}, // vine outfit (No Variations) - {0x337, 14249}, // woven-vine pochette (No Variations) - {0x338, 01573}, // dharma - {0x339, 14487}, // golden dharma - {0x33A, 14489}, // mini golden dharma - {0x33B, 14207}, // glowing-moss stool - {0x33C, 14209}, // glowing-moss boulder - {0x33D, 14206}, // vine garland - {0x33E, 14192}, // giant vine - {0x33F, 14596}, // brick pillar - {0x340, 14597}, // marble pillar - {0x341, 14598}, // simple pillar - {0x342, 14599}, // steel pillar - {0x343, 14600}, // golden pillar - {0x344, 14601}, // wooden pillar - {0x345, 14602}, // concrete pillar - {0x346, 12335}, // acorn rug - {0x347, 12351}, // cherry-blossom rug - {0x349, 14187}, // stacked senmaizuke barrels - {0x34A, 14188}, // senmaizuke barrel - {0x34C, 13931}, // carrot potage - {0x34D, 13932}, // potato potage - {0x34E, 13933}, // bread gratin - {0x34F, 13934}, // orange pie - {0x350, 13935}, // peach pie - {0x351, 13936}, // pear pie - {0x352, 13937}, // cherry pie - {0x353, 13938}, // gnocchi di zucca - {0x354, 13939}, // gnocchi di patate - {0x355, 13940}, // gnocchi di carote - {0x356, 13941}, // pumpkin soup - {0x357, 13942}, // minestrone soup - {0x358, 13943}, // bamboo-shoot soup - {0x359, 13944}, // apple pie - {0x35A, 13945}, // seaweed soup - {0x35B, 13946}, // carrot cake - {0x35C, 13947}, // apple tart - {0x35D, 13948}, // veggie quiche - {0x35E, 13949}, // orange tart - {0x35F, 13950}, // mixed-fruits tart - {0x360, 13951}, // peach tart - {0x361, 13952}, // cherry tart - {0x362, 13953}, // pear tart - {0x363, 13957}, // mixed-fruits pie - {0x364, 13959}, // mixed-fruits sandwich - {0x365, 13960}, // coconut pudding - {0x366, 13961}, // pear jelly - {0x367, 13962}, // cherry jelly - {0x368, 13963}, // peach jelly - {0x369, 13964}, // mushroom crepe - {0x36A, 13965}, // seafood salad - {0x36B, 13966}, // fruit salad - {0x36C, 13967}, // orange jelly - {0x36D, 13968}, // salade de carottes râpées - {0x36E, 13969}, // poke - {0x36F, 13970}, // turnip salad - {0x370, 13971}, // apple jelly - {0x371, 13972}, // mushroom salad - {0x372, 13973}, // veggie crepe - {0x373, 13974}, // veggie sandwich - {0x374, 13975}, // mixed-fruits crepe - {0x375, 13976}, // salmon sandwich - {0x376, 13977}, // sugar crepe - {0x377, 13978}, // cookies - {0x378, 13979}, // orange pound cake - {0x379, 13980}, // pound cake - {0x37A, 13981}, // pumpkin pound cake - {0x37B, 13982}, // tomato juice - {0x37C, 13983}, // kabu ankake - {0x37D, 13984}, // carrot juice - {0x37E, 13985}, // coconut milk - {0x37F, 13986}, // pretzels - {0x380, 13987}, // frosted pretzels - {0x381, 13988}, // salad-stuffed tomato - {0x382, 13989}, // coconut cookies - {0x383, 13990}, // veggie cookies - {0x384, 13991}, // cherry smoothie - {0x385, 13992}, // thumbprint jam cookies - {0x386, 13993}, // frosted cookies - {0x387, 13994}, // flour - {0x388, 13995}, // pear smoothie - {0x389, 13996}, // whole-wheat flour - {0x38A, 13997}, // sugar - {0x38B, 13998}, // brown sugar - {0x38C, 13999}, // peach smoothie - {0x38D, 14000}, // apple smoothie - {0x38E, 14001}, // orange smoothie - {0x38F, 14002}, // brown-sugar pound cake - {0x390, 14003}, // sea-bass pie - {0x391, 14010}, // salad - {0x392, 14048}, // mushroom potage - {0x393, 14104}, // fish and chips - {0x394, 14105}, // french fries - {0x395, 14109}, // plain scones - {0x396, 14110}, // veggie cupcakes - {0x397, 14111}, // tomato bagel sandwich - {0x398, 14112}, // brown-sugar cupcakes - {0x399, 14113}, // carrot scones - {0x39A, 14114}, // pumpkin cupcakes - {0x39B, 14115}, // fruit scones - {0x39C, 14116}, // fruit cupcakes - {0x39D, 14117}, // pumpkin scones - {0x39E, 14118}, // plain cupcakes - {0x39F, 14119}, // salmon bagel sandwich - {0x3A0, 14120}, // squid-ink curry - {0x3A1, 14121}, // pumpkin curry - {0x3A2, 14122}, // carrot-tops curry - {0x3A3, 14123}, // mixed-fruits bagel sandwich - {0x3A4, 14124}, // tomato curry - {0x3A5, 14125}, // pumpkin bagel sandwich - {0x3A6, 14126}, // carrot bagel sandwich - {0x3A7, 14127}, // potato curry - {0x3A8, 14128}, // mushroom curry - {0x3A9, 14129}, // pancakes - {0x3AA, 14130}, // coconut pancakes - {0x3AB, 14131}, // potato galette - {0x3AC, 14132}, // fruit-topped pancakes - {0x3AD, 14161}, // pesce all'acqua pazza - {0x3AE, 14162}, // karei no nitsuke - {0x3AF, 14163}, // aji fry - {0x3B0, 14164}, // sautéed olive flounder - {0x3B1, 14165}, // grilled sea bass with herbs - {0x3B2, 14166}, // carpaccio di salmone - {0x3B3, 14167}, // carpaccio di marlin blu - {0x3B4, 14168}, // barred-knifejaw carpaccio - {0x3B5, 14169}, // orange marmalade - {0x3B6, 14170}, // peach jam - {0x3B7, 14171}, // pear jam - {0x3B8, 14172}, // carpaccio di capesante - {0x3B9, 14173}, // cherry jam - {0x3BA, 14174}, // pickled veggies - {0x3BB, 14175}, // tomato puree - {0x3BC, 14176}, // apple jam - {0x3BD, 14177}, // coconut oil - {0x3BE, 14178}, // anchoas al ajillo - {0x3BF, 14179}, // tomates al ajillo - {0x3C0, 14180}, // champiñones al ajillo - {0x3C1, 14181}, // sardines in oil - {0x3C2, 14182}, // pull-apart bread - {0x3C3, 14183}, // seafood ajillo - {0x3C4, 14185}, // jarred mushrooms - {0x3C5, 14186}, // jarred bamboo shoots - {0x3C6, 14465}, // baked potatoes - {0x3C7, 14466}, // pizza margherita - {0x3C8, 14696}, // seafood pizza - {0x3C9, 14697}, // fruit pizza - {0x3CA, 14698}, // mushroom pizza - {0x3CB, 13327}, // gratin - {0x3CC, 13328}, // clam chowder - {0x3CD, 13329}, // pumpkin pie - {0x3CE, 13330}, // olive-flounder meunière - {0x3CF, 12822}, // bread - {0x3D0, 12823}, // organic bread - {0x3D1, 12824}, // snack bread - {0x3D2, 12813}, // savory bread - {0x3D3, 12390}, // maple-leaf rug - {0x3D4, 14550}, // spooky tree - {0x3D5, 14551}, // spooky trick lamp - {0x3D6, 14542}, // spooky treats basket - {0x3D7, 12222}, // yellow star rug - {0x3D8, 12329}, // green bamboo mat - {0x3D9, 12330}, // yellow bamboo mat - {0x3DA, 12379}, // tree-stump rug - {0x3DB, 12399}, // light bamboo bath mat - {0x3DC, 12400}, // dark bamboo bath mat - {0x3DD, 12521}, // starry-skies rug - {0x3DE, 13662}, // ruined decorated pillar - {0x3DF, 14193}, // vine bench - {0x3E0, 14205}, // vine lamp - {0x3E1, 14210}, // hanging glowing moss - {0x3E2, 14211}, // glowing-moss wreath - {0x3E3, 14212}, // glowing-moss pond - {0x3E4, 14213}, // glowing-moss statue - {0x3E5, 14214}, // glowing-moss-jar shelves - {0x3E6, 14215}, // glow-in-the-dark stickers - {0x3E7, 14216}, // suspicious cauldron - {0x3E8, 14208}, // glowing-moss balloon - {0x3E9, 14604}, // glowing-moss jar - {0x3EA, 14199}, // glowing-moss hood (No Variations) - {0x3EB, 14198}, // glowing-moss pointed cap (No Variations) - {0x3EC, 14201}, // glowing-moss headband (No Variations) - {0x3ED, 14257}, // full-body glowing-moss suit (No Variations) - {0x3EE, 14259}, // glowing-moss dress (No Variations) - {0x3EF, 14755}, // green bamboo fence - {0x3F0, 14756}, // frozen fence - {0x3F1, 14757}, // bamboo-slats fence - {0x3F2, 14758}, // corrugated iron fence - {0x3F3, 14759}, // park fence - {0x3F4, 14728}, // ornament tree - {0x3F5, 14594}, // giant ornament - {0x3F6, 14593}, // ornament garland - {0x3F7, 14591}, // ornament table lamp - {0x3F8, 14552}, // spooky cookies - {0x3F9, 14613}, // ornament crown (No Variations) - {0x3FA, 14565}, // Roost sablé cookie - {0x3FB, 14478}, // golden plate armor - {0x3FC, 14479}, // golden piggy bank - {0x3FD, 14484}, // golden meter and pipes - {0x3FE, 14485}, // golden gear apparatus - {0x3FF, 14486}, // golden gear tower - {0x400, 14488}, // golden garden bunny - {0x401, 14490}, // golden urn - {0x402, 14491}, // golden wristwatch - {0x403, 14492}, // golden decorative plate - {0x404, 14481}, // golden vase - {0x405, 14482}, // golden altar - {0x406, 14483}, // golden bathtub - {0x407, 14480}, // gold-nugget mining car - {0x408, 14533}, // golden samurai suit - {0x409, 12840}, // spaghetti napolitan - {0x40A, 12838}, // spaghetti marinara - {0x40B, 12835}, // squid-ink spaghetti - {0x40C, 14645}, // foxtail - {0x40D, 14644}, // nice branch - {0x40E, 14716}, // cake salé - {0x40F, 14714}, // donation box - {0x410, 13496}, // stonework kitchen - {0x411, 14831}, // wooden storage shed - {0x412, 14592}, // wooden music box - {0x413, 14549}, // decayed tree - {0x414, 13572}, // frozen floor tiles - {0x415, 14882}, // ruined seat - {0x416, 13509}, // gear tower - {0x417, 13511}, // gear apparatus - {0x418, 13520}, // forbidden altar - {0x419, 12611}, // plate armor - {0x41A, 07154}, // wooden box - {0x41B, 12350}, // box-shaped seat - {0x41C, 12706}, // imperial pot - {0x41D, 13696}, // pile of cardboard boxes - {0x41E, 12349}, // project table - {0x41F, 13210}, // stacked shopping baskets - {0x420, 13606}, // stacked fish containers - {0x421, 13220}, // festival-lantern set - {0x422, 13580}, // skateboard wall rack - {0x423, 12709}, // carp on a cutting board - {0x424, 14887}, // ruined broken pillar - {0x425, 13666}, // pile of cash - {0x426, 00922}, // stacked bottle crates - {0x427, 00743}, // frozen mini snowperson - {0x42B, 13573}, // medium wooden partition - {0x42C, 13574}, // small wooden partition - {0x42D, 13751}, // open wooden shelves - {0x42E, 13588}, // tension-pole rack - {0x430, 13161}, // wooden field sign - }; - } -} +public static class RecipeList +{ + public const int BridgeConstructionKit = 0x1CA; + public const int CampsiteConstructionKit = 0x1CD; + + public static readonly IReadOnlyDictionary Recipes = new Dictionary + { + {0x006, 02596}, // juicy-apple TV + {0x009, 01263}, // pear wardrobe + {0x00A, 03068}, // flimsy axe + {0x00D, 01429}, // campfire + {0x00E, 01799}, // doghouse + {0x00F, 01913}, // wooden chair + {0x010, 00880}, // wooden bucket + {0x011, 02560}, // wooden chest + {0x012, 02605}, // wooden simple bed + {0x013, 03082}, // flimsy shovel + {0x014, 03083}, // flimsy watering can + {0x015, 03084}, // flimsy fishing rod + {0x016, 02376}, // flimsy net + {0x017, 01559}, // wooden-block bench + {0x018, 01561}, // wooden-block chest + {0x01A, 01565}, // wooden-block table + {0x01D, 02822}, // slingshot + {0x01E, 01753}, // aroma pot + {0x020, 00808}, // mush table + {0x021, 00739}, // tea table + {0x022, 01430}, // bonfire + {0x023, 03191}, // ironwood table + {0x024, 02754}, // simple well + {0x025, 02559}, // pot + {0x026, 03206}, // wooden-block toy + {0x029, 00333}, // birdhouse + {0x02A, 00331}, // birdbath + {0x02B, 00088}, // ringtoss + {0x02C, 00383}, // acoustic guitar + {0x02D, 00669}, // ukulele + {0x02E, 00710}, // bamboo bench + {0x030, 00729}, // garden rock + {0x031, 00730}, // tall garden rock + {0x033, 00805}, // mush lamp + {0x037, 00665}, // wave breaker + {0x038, 00975}, // fruit basket + {0x039, 01103}, // rocking chair + {0x03A, 01157}, // brick oven + {0x03B, 01170}, // swinging bench + {0x03C, 01189}, // tire stack + {0x03D, 01557}, // wooden-block bed + {0x03E, 01558}, // wooden-block bookshelf + {0x03F, 01625}, // iron garden bench + {0x040, 01626}, // iron garden chair + {0x041, 01627}, // iron garden table + {0x042, 01823}, // trash bags + {0x04D, 02319}, // drinking fountain + {0x04E, 02329}, // tire toy + {0x04F, 02553}, // iron frame + {0x050, 02586}, // natural garden chair + {0x051, 03065}, // gold bars + {0x052, 03122}, // mini DIY workbench + {0x053, 03193}, // ironwood chair + {0x054, 03194}, // ironwood low table + {0x055, 03195}, // ironwood cart + {0x056, 03196}, // ironwood dresser + {0x057, 03200}, // ironwood bed + {0x059, 03205}, // wooden-block stereo + {0x05A, 03208}, // wooden-block wall clock + {0x05B, 03270}, // ironwood kitchenette + {0x05C, 03271}, // ironwood cupboard + {0x05E, 03275}, // ironwood clock + {0x063, 03080}, // brick fence + {0x064, 03402}, // vertical-board fence + {0x065, 03403}, // bamboo lattice fence + {0x066, 00083}, // rocking horse + {0x067, 00343}, // tiki torch + {0x068, 03398}, // stone stool + {0x069, 03397}, // stone table + {0x06B, 02615}, // ladder + {0x06E, 04044}, // log extra-long sofa + {0x06F, 04043}, // log round table + {0x070, 04042}, // log bench + {0x071, 04035}, // log garden lounge + {0x072, 04036}, // log decorative shelves + {0x073, 04037}, // log wall-mounted clock + {0x074, 04038}, // log stool + {0x075, 04039}, // log chair + {0x076, 04040}, // log dining table + {0x077, 04041}, // log bed + {0x078, 04025}, // unglazed dish set + {0x079, 04027}, // floral swag + {0x07A, 03559}, // iron wall lamp + {0x07B, 03562}, // iron wall rack + {0x07C, 03509}, // garden bench + {0x07D, 03943}, // ironwood DIY workbench + {0x07E, 03560}, // iron worktable + {0x080, 03563}, // iron shelf + {0x082, 03772}, // golden candlestick + {0x083, 03810}, // golden dishes + {0x084, 03774}, // Libra scale + {0x085, 03473}, // golden seat + {0x088, 03808}, // mush log + {0x08A, 03806}, // mush partition + {0x08B, 03805}, // mush parasol + {0x08C, 03499}, // frozen arch + {0x08D, 03501}, // frozen sculpture + {0x08E, 03503}, // frozen chair + {0x08F, 03505}, // frozen counter + {0x091, 03504}, // frozen tree + {0x092, 03497}, // frozen table + {0x093, 03498}, // frozen partition + {0x094, 03500}, // frozen pillar + {0x095, 03502}, // frozen bed + {0x097, 03558}, // bamboo wall decoration + {0x098, 03658}, // bamboo basket + {0x099, 03554}, // bamboo candleholder + {0x09A, 03556}, // bamboo stopblock + {0x09B, 03551}, // bamboo shelf + {0x09D, 03553}, // bamboo partition + {0x09E, 03555}, // bamboo doll + {0x09F, 03557}, // bamboo floor lamp + {0x0A0, 02558}, // wooden-block chair + {0x0A1, 04011}, // cherry speakers + {0x0A2, 04012}, // cherry lamp + {0x0A3, 03684}, // coconut juice + {0x0A4, 00080}, // clackercart + {0x0A5, 01266}, // barrel + {0x0A6, 03692}, // plain wooden shop sign + {0x0A7, 03675}, // hay bed + {0x0A8, 03449}, // wooden stool + {0x0A9, 03445}, // standard umbrella stand + {0x0AA, 03438}, // wooden end table + {0x0AB, 00682}, // boomerang + {0x0AC, 03436}, // wooden wardrobe + {0x0AD, 03490}, // wooden waste bin + {0x0AE, 03683}, // plain sink + {0x0AF, 03977}, // shell arch + {0x0B0, 03978}, // shell partition + {0x0B1, 03979}, // shell stool + {0x0B2, 03980}, // shell table + {0x0B4, 03982}, // shell fountain + {0x0B5, 03983}, // shell bed + {0x0B6, 03984}, // shell lamp + {0x0B7, 04703}, // vaulting pole + {0x0B8, 03976}, // orange wall-mounted clock + {0x0B9, 03975}, // orange end table + {0x0BA, 04546}, // pear bed + {0x0BB, 04127}, // peach chair + {0x0BC, 04128}, // peach surprise box + {0x0BD, 04134}, // apple chair + {0x0BE, 00132}, // succulent plant + {0x0BF, 04549}, // fish bait + {0x0C0, 04073}, // classic pitcher + {0x0C1, 04124}, // wooden fish + {0x0C2, 04279}, // frozen-treat set + {0x0C3, 04393}, // old-fashioned washtub + {0x0C4, 01759}, // stack of books + {0x0C5, 01861}, // stacked magazines + {0x0C7, 04104}, // frying pan + {0x0C8, 05150}, // shell speaker + {0x0C9, 03439}, // wooden table + {0x0CA, 04090}, // spooky table + {0x0CB, 04066}, // illuminated tree + {0x0CC, 03406}, // beekeeper's hive + {0x0CD, 04083}, // spooky arch + {0x0CE, 04084}, // spooky scarecrow + {0x0CF, 04086}, // spooky tower + {0x0D0, 04087}, // spooky carriage + {0x0D1, 04088}, // spooky lantern + {0x0D2, 04089}, // spooky chair + {0x0D4, 04092}, // spooky lantern set + {0x0D5, 03588}, // signpost + {0x0D6, 03785}, // potted ivy + {0x0D7, 01058}, // music stand + {0x0D8, 00865}, // birdcage + {0x0D9, 00722}, // hearth + {0x0DA, 05320}, // ocarina + {0x0DB, 04376}, // shell wreath + {0x0DC, 04708}, // mush low stool + {0x0DD, 04726}, // mushroom wreath + {0x0DE, 04375}, // snowflake wreath + {0x0DF, 04378}, // fruit wreath + {0x0E0, 03396}, // natural garden table + {0x0E1, 04727}, // tree branch wreath + {0x0E2, 04377}, // ornament wreath + {0x0E3, 04293}, // cosmos wreath + {0x0E4, 05436}, // windflower wreath + {0x0E5, 05437}, // rose wreath + {0x0E6, 05466}, // pansy wreath + {0x0E7, 05467}, // mum wreath + {0x0E8, 05468}, // hyacinth wreath + {0x0E9, 01447}, // flying saucer + {0x0EA, 01054}, // moon + {0x0EB, 01439}, // asteroid + {0x0EC, 01445}, // astronaut suit + {0x0ED, 05096}, // hyacinth crown (No Variations) + {0x0EE, 05097}, // cool hyacinth crown (No Variations) + {0x0EF, 05098}, // purple hyacinth crown (No Variations) + {0x0F0, 05099}, // windflower crown (No Variations) + {0x0F1, 05100}, // cool windflower crown (No Variations) + {0x0F2, 05101}, // purple windflower crown (No Variations) + {0x0F3, 05102}, // tulip crown (No Variations) + {0x0F4, 05103}, // chic tulip crown (No Variations) + {0x0F5, 05104}, // dark tulip crown (No Variations) + {0x0F6, 05105}, // pansy crown (No Variations) + {0x0F7, 05106}, // cool pansy crown (No Variations) + {0x0F8, 05107}, // purple pansy crown (No Variations) + {0x0F9, 05108}, // cosmos crown (No Variations) + {0x0FA, 05109}, // lovely cosmos crown (No Variations) + {0x0FB, 05110}, // dark cosmos crown (No Variations) + {0x0FC, 05111}, // rose crown (No Variations) + {0x0FD, 05112}, // cute rose crown (No Variations) + {0x0FE, 05113}, // chic rose crown (No Variations) + {0x0FF, 05114}, // lily crown (No Variations) + {0x100, 05115}, // cute lily crown (No Variations) + {0x101, 05116}, // dark lily crown (No Variations) + {0x102, 05117}, // mum crown (No Variations) + {0x103, 05118}, // chic mum crown (No Variations) + {0x104, 05119}, // simple mum crown (No Variations) + {0x105, 04682}, // leaf (No Variations) + {0x106, 03472}, // golden toilet + {0x107, 01241}, // DIY workbench + {0x108, 02578}, // pitfall seed + {0x10A, 05212}, // stone fence + {0x10B, 04357}, // iron fence + {0x10C, 04350}, // country fence + {0x10D, 04349}, // corral fence + {0x10F, 02100}, // axe + {0x111, 03966}, // big festive tree + {0x112, 03991}, // festive tree + {0x115, 00144}, // manhole cover + {0x116, 05635}, // tiny library + {0x117, 05636}, // wooden-plank sign + {0x118, 02379}, // watering can + {0x119, 02099}, // shovel + {0x11A, 02377}, // fishing rod + {0x11B, 05784}, // net + {0x11C, 03618}, // cutting board + {0x11D, 05856}, // stone axe + {0x11E, 05528}, // starry wall + {0x120, 05516}, // ice flooring + {0x121, 05253}, // iceberg flooring + {0x122, 04905}, // autumn wall + {0x123, 05230}, // Jingle wall + {0x124, 05510}, // sci-fi wall + {0x125, 05505}, // ice wall + {0x126, 05500}, // starry-sky wall + {0x127, 05498}, // ski-slope wall + {0x128, 04865}, // honeycomb wall + {0x12A, 04820}, // gold-screen wall + {0x12B, 04894}, // golden wall + {0x12C, 04853}, // bamboo-grove wall + {0x12D, 05229}, // garbage-heap wall + {0x12E, 05662}, // iceberg wall + {0x12F, 04915}, // orange wall + {0x130, 04916}, // apple wall + {0x131, 04917}, // pear wall + {0x132, 04918}, // peach wall + {0x133, 04919}, // cherry wall + {0x134, 05164}, // mush wall + {0x135, 04858}, // wild-wood wall + {0x136, 04859}, // wooden-mosaic wall + {0x137, 04860}, // dark wooden-mosaic wall + {0x138, 04804}, // brown herringbone wall + {0x139, 04805}, // chocolate herringbone wall + {0x13A, 04844}, // stacked-wood wall + {0x13B, 04840}, // cabin wall + {0x13C, 04838}, // manga-library wall + {0x13D, 04837}, // classic-library wall + {0x13E, 05216}, // stone wall + {0x13F, 04911}, // wooden-knot wall + {0x140, 04904}, // modern wood wall + {0x141, 04947}, // sakura-wood wall + {0x142, 04833}, // bamboo wall + {0x143, 04855}, // snowflake wall + {0x144, 04813}, // rustic-stone wall + {0x145, 04801}, // steel-frame wall + {0x146, 05457}, // jungle wall + {0x167, 00677}, // deer scare + {0x168, 05670}, // tulip wreath + {0x169, 05751}, // pretty tulip wreath + {0x16A, 05771}, // dark tulip wreath + {0x16C, 05337}, // three-tiered snowperson + {0x16D, 03561}, // iron hanger stand + {0x16E, 05956}, // Aquarius urn + {0x16F, 05954}, // Aries rocking chair + {0x170, 05955}, // Virgo harp + {0x172, 05957}, // Capricorn ornament + {0x173, 05959}, // Cancer table + {0x174, 00891}, // holiday candle + {0x175, 01442}, // lunar rover + {0x176, 03689}, // sauna heater + {0x177, 06030}, // cherry-blossom bonsai + {0x178, 05958}, // Sagittarius arrow + {0x179, 05960}, // Gemini closet + {0x17A, 03340}, // deer decoration + {0x17B, 01443}, // satellite + {0x17C, 05962}, // Scorpio lamp + {0x17D, 01444}, // space shuttle + {0x17E, 03344}, // steamer-basket set + {0x17F, 04309}, // destinations signpost + {0x180, 05961}, // Taurus bathtub + {0x181, 05977}, // bamboo-shoot lamp + {0x182, 01440}, // lunar lander + {0x183, 05543}, // wooden-block stool + {0x184, 04067}, // tabletop festive tree + {0x185, 02326}, // water pump + {0x186, 01797}, // decoy duck + {0x187, 03773}, // terrarium + {0x188, 04074}, // illuminated reindeer + {0x189, 04075}, // gong + {0x18A, 03819}, // oil-barrel bathtub + {0x18B, 04078}, // barbell + {0x18C, 03775}, // hanging terrarium + {0x18D, 04093}, // bamboo drum + {0x18E, 05517}, // pan flute + {0x18F, 05963}, // Pisces lamp + {0x190, 04107}, // infused-water dispenser + {0x191, 04108}, // illuminated present + {0x192, 05970}, // firewood + {0x193, 01652}, // matryoshka + {0x194, 04125}, // wooden bookshelf + {0x195, 04130}, // coconut wall planter + {0x196, 04131}, // illuminated snowflakes + {0x197, 05964}, // Leo sculpture + {0x198, 03776}, // brick well + {0x199, 01441}, // rocket + {0x19A, 01111}, // outdoor bath + {0x19B, 05975}, // traditional balancing toy + {0x19C, 05973}, // log stakes + {0x19D, 01032}, // magazine rack + {0x19E, 06075}, // tree's bounty mobile + {0x19F, 06078}, // tree's bounty lamp + {0x1A0, 06079}, // tree's bounty little tree + {0x1A1, 06080}, // tree's bounty big tree + {0x1A2, 06032}, // cherry-blossom-petal pile + {0x1A3, 06031}, // cherry-blossom branches + {0x1A4, 05976}, // bamboo sphere + {0x1A5, 05978}, // bamboo lunch box + {0x1A6, 06033}, // outdoor picnic set + {0x1A7, 06081}, // tree's bounty arch + {0x1A8, 05979}, // bamboo noodle slide + {0x1A9, 06830}, // shell music box + {0x1AA, 06832}, // cherry-blossom clock + {0x1AB, 06831}, // blossom-viewing lantern + {0x1AD, 06826}, // nova light + {0x1AE, 06827}, // starry garland + {0x1B0, 06829}, // crescent-moon chair + {0x1B1, 06818}, // ornament mobile + {0x1B2, 05676}, // crewed spaceship + {0x1B3, 05931}, // jail bars + {0x1B4, 05972}, // wild log bench + {0x1B5, 03992}, // key holder + {0x1B6, 05641}, // lily wreath + {0x1B8, 05765}, // chic windflower wreath + {0x1B9, 05746}, // cool windflower wreath + {0x1BA, 05768}, // natural mum wreath + {0x1BB, 05749}, // fancy mum wreath + {0x1BC, 05764}, // chic cosmos wreath + {0x1BD, 05745}, // pretty cosmos wreath + {0x1BE, 05766}, // dark rose wreath + {0x1BF, 05772}, // blue rose wreath + {0x1C0, 05747}, // fancy rose wreath + {0x1C1, 05820}, // gold rose wreath + {0x1C2, 05767}, // cool pansy wreath + {0x1C3, 05748}, // snazzy pansy wreath + {0x1C4, 05769}, // purple hyacinth wreath + {0x1C5, 05750}, // cool hyacinth wreath + {0x1C6, 05770}, // dark lily wreath + {0x1C7, 05677}, // fancy lily wreath + {0x1C8, 06840}, // leaf umbrella + {0x1C9, 03229}, // clothesline + {0x1CA, 07211}, // bridge construction kit + {0x1CB, 07377}, // blue rose crown (No Variations) + {0x1CC, 07378}, // gold rose crown (No Variations) + {0x1CD, 05166}, // campsite construction kit + {0x1CE, 01750}, // document stack + {0x1CF, 04034}, // scattered papers + {0x1D0, 05719}, // fossil doorplate + {0x1D1, 05718}, // timber doorplate + {0x1D2, 05716}, // paw-print doorplate + {0x1D3, 04751}, // bone doorplate + {0x1D4, 04752}, // iron doorplate + {0x1D5, 05717}, // crest doorplate + {0x1D6, 05515}, // jungle flooring + {0x1D7, 05223}, // woodland wall + {0x1D8, 04999}, // honeycomb flooring + {0x1D9, 04986}, // money flooring + {0x1DA, 04797}, // basement flooring + {0x1DB, 05021}, // golden flooring + {0x1DC, 04990}, // colored-leaves flooring + {0x1DD, 05270}, // sci-fi flooring + {0x1DE, 04968}, // lunar surface + {0x1DF, 07204}, // cherry-blossom flooring + {0x1E0, 07205}, // cherry-blossom-trees wall + {0x1E2, 05269}, // galaxy flooring + {0x1E3, 04989}, // ski-slope flooring + {0x1E4, 07187}, // forest wall + {0x1E5, 04964}, // bamboo flooring + {0x1E6, 05236}, // garbage-heap flooring + {0x1E7, 04979}, // backyard lawn + {0x1E8, 07186}, // forest flooring + {0x1E9, 04960}, // steel flooring + {0x1EA, 04008}, // kettle bathtub + {0x1EB, 07134}, // wooden low table + {0x1EC, 07133}, // wooden mini table + {0x1ED, 07132}, // wooden double bed + {0x1EE, 07142}, // simple DIY workbench + {0x1EF, 07231}, // tulip surprise box + {0x1F0, 07160}, // cardboard table + {0x1F1, 07161}, // cardboard bed + {0x1F2, 07163}, // cardboard chair + {0x1F4, 07159}, // cardboard sofa + {0x1F5, 07230}, // cosmos shower + {0x1F6, 07137}, // wooden full-length mirror + {0x1F7, 07233}, // windflower fan + {0x1F8, 07045}, // recycled-can thumb piano + {0x1F9, 07232}, // mum cushion + {0x1FA, 07234}, // hyacinth lamp + {0x1FB, 07235}, // rose bed + {0x1FC, 07805}, // butter churn + {0x1FD, 07788}, // leaf campfire + {0x1FE, 07867}, // angled signpost + {0x1FF, 07409}, // cherry-blossom pond stone + {0x200, 07408}, // maple-leaf pond stone + {0x201, 07393}, // pond stone + {0x202, 07253}, // star clock + {0x203, 07236}, // lily record player + {0x204, 07237}, // pansy table + {0x206, 03446}, // western-style stone + {0x207, 07390}, // leaf stool + {0x208, 07452}, // raccoon figurine + {0x209, 07048}, // pile of zen cushions + {0x20B, 02544}, // star wand + {0x20C, 05083}, // hyacinth wand + {0x20D, 05084}, // windflower wand + {0x20E, 05085}, // tulip wand + {0x20F, 05091}, // pansy wand + {0x210, 05092}, // cosmos wand + {0x211, 05093}, // rose wand + {0x212, 05094}, // lily wand + {0x213, 05095}, // mums wand + {0x214, 07584}, // wand + {0x215, 07585}, // ice wand + {0x216, 07586}, // shell wand + {0x217, 07587}, // tree-branch wand + {0x218, 07588}, // mushroom wand + {0x219, 07589}, // cherry-blossom wand + {0x21A, 07590}, // bamboo wand + {0x21B, 07591}, // golden wand + {0x21C, 07592}, // iron wand + {0x21D, 07169}, // maple-leaf umbrella + {0x21E, 07327}, // apple rug + {0x21F, 07328}, // cherry rug + {0x220, 07330}, // orange rug + {0x221, 07331}, // peach rug + {0x222, 07332}, // pear rug + {0x224, 04351}, // log fence + {0x225, 04352}, // rope fence + {0x226, 04354}, // imperial fence + {0x227, 04355}, // block fence + {0x228, 04356}, // straw fence + {0x229, 04358}, // spiky fence + {0x22B, 05206}, // iron-and-stone fence + {0x22C, 05207}, // zen fence + {0x22D, 05208}, // large lattice fence + {0x22F, 05210}, // log-wall fence + {0x231, 05213}, // barbed-wire fence + {0x234, 05268}, // underwater flooring + {0x235, 05030}, // water flooring + {0x236, 04590}, // gold armor (No Variations) + {0x237, 02777}, // medicine + {0x238, 07317}, // zen-style stone + {0x239, 08825}, // golden casket + {0x23A, 07795}, // stone lion-dog + {0x23B, 08419}, // garden wagon + {0x23C, 08826}, // wooden table mirror + {0x23D, 09642}, // iron closet + {0x23E, 07258}, // modeling clay + {0x23F, 07259}, // palm-tree lamp + {0x240, 07261}, // trophy case + {0x241, 01504}, // giant teddy bear + {0x242, 09814}, // lucky gold cat + {0x243, 07454}, // wooden toolbox + {0x244, 07281}, // sleigh + {0x246, 00530}, // grass standee + {0x247, 00531}, // hedge standee + {0x248, 00532}, // mountain standee + {0x249, 00533}, // tree standee + {0x24A, 01023}, // pile of leaves + {0x24B, 04269}, // green-leaf pile + {0x24C, 04270}, // yellow-leaf pile + {0x24D, 04271}, // red-leaf pile + {0x24E, 10742}, // bamboo stool + {0x24F, 10743}, // bamboo speaker + {0x250, 03802}, // pine bonsai tree + {0x251, 03580}, // bonsai shelf + {0x252, 01509}, // robot hero + {0x253, 11261}, // golden gears + {0x254, 03617}, // stall + {0x256, 07247}, // silo + {0x257, 08031}, // fountain + {0x258, 07535}, // kettlebell + {0x259, 05941}, // golden dung beetle + {0x25A, 11260}, // golden arowana model + {0x25B, 04333}, // grass skirt (No Variations) + {0x25C, 05291}, // traditional straw coat (No Variations) + {0x25D, 08907}, // green grass skirt (No Variations) + {0x25E, 07254}, // straw umbrella hat (No Variations) + {0x25F, 05143}, // bamboo hat (No Variations) + {0x260, 07527}, // flower stand + {0x261, 03410}, // small cardboard boxes + {0x262, 03411}, // medium cardboard boxes + {0x263, 03412}, // large cardboard boxes + {0x264, 09838}, // cherry dress (No Variations) + {0x265, 09873}, // cherry hat (No Variations) + {0x266, 09949}, // cherry umbrella + {0x267, 09837}, // pear dress (No Variations) + {0x268, 09872}, // pear hat (No Variations) + {0x269, 09950}, // pear umbrella + {0x26A, 09839}, // peach dress (No Variations) + {0x26B, 09874}, // peach hat (No Variations) + {0x26C, 09947}, // peach umbrella + {0x26D, 09836}, // apple dress (No Variations) + {0x26E, 09871}, // apple hat (No Variations) + {0x26F, 09948}, // apple umbrella + {0x270, 05275}, // orange hat (No Variations) + {0x271, 06912}, // orange umbrella + {0x272, 03288}, // orange dress (No Variations) + {0x273, 07489}, // star pochette (No Variations) + {0x274, 09862}, // star head (No Variations) + {0x275, 09945}, // cherry-blossom umbrella + {0x276, 07490}, // cherry-blossom pochette (No Variations) + {0x277, 07491}, // maple-leaf pochette (No Variations) + {0x278, 07492}, // acorn pochette (No Variations) + {0x279, 07493}, // snowflake pochette (No Variations) + {0x27A, 07494}, // shellfish pochette (No Variations) + {0x27B, 07291}, // leaf mask (Green) + {0x27C, 07511}, // knitted-grass backpack (No Variations) + {0x27D, 08609}, // snowperson head (No Variations) + {0x27E, 07498}, // log pack (No Variations) + {0x280, 04588}, // iron armor (No Variations) + {0x281, 05334}, // knight's helmet (Gray) + {0x282, 05472}, // armor shoes (No Variations) + {0x283, 05524}, // gold-armor shoes (No Variations) + {0x284, 05346}, // gold helmet (Gold) + {0x285, 07506}, // basket pack (No Variations) + {0x286, 12206}, // flat garden rock + {0x287, 12208}, // mossy garden rock + {0x288, 07174}, // mush umbrella + {0x289, 05056}, // sakura-wood flooring + {0x28A, 12230}, // festive top set + {0x28B, 11943}, // stone tablet + {0x28C, 11941}, // stone arch + {0x28D, 00676}, // tall lantern + {0x28E, 11942}, // street piano + {0x28F, 01120}, // scarecrow + {0x290, 11711}, // simple wooden fence + {0x291, 11712}, // lattice fence + {0x292, 08179}, // golden net + {0x293, 08533}, // golden watering can + {0x294, 08574}, // golden shovel + {0x295, 08578}, // golden slingshot + {0x296, 08660}, // golden rod + {0x297, 09617}, // golden axe + {0x298, 12326}, // recycled boots (No Variations) + {0x299, 05508}, // underwater wall + {0x29A, 05661}, // tropical vista + {0x29B, 07239}, // starry-sands flooring + {0x29C, 07362}, // shell rug + {0x29D, 04970}, // sandy-beach flooring + {0x29E, 12332}, // natural square table + {0x29F, 11113}, // light bamboo rug + {0x2A0, 11114}, // dark bamboo rug + {0x2A1, 12439}, // earth-egg shell (No Variations) + {0x2A2, 12449}, // earth-egg outfit (No Variations) + {0x2A3, 12455}, // earth-egg shoes (No Variations) + {0x2A4, 12440}, // stone-egg shell (No Variations) + {0x2A5, 12450}, // stone-egg outfit (No Variations) + {0x2A6, 12456}, // stone-egg shoes (No Variations) + {0x2A7, 12441}, // leaf-egg shell (No Variations) + {0x2A8, 12451}, // leaf-egg outfit (No Variations) + {0x2A9, 12457}, // leaf-egg shoes (No Variations) + {0x2AA, 12442}, // wood-egg shell (No Variations) + {0x2AB, 12452}, // wood-egg outfit (No Variations) + {0x2AC, 12458}, // wood-egg shoes (No Variations) + {0x2AD, 12443}, // sky-egg shell (No Variations) + {0x2AE, 12453}, // sky-egg outfit (No Variations) + {0x2AF, 12459}, // sky-egg shoes (No Variations) + {0x2B0, 12444}, // water-egg shell (No Variations) + {0x2B1, 12454}, // water-egg outfit (No Variations) + {0x2B2, 12460}, // water-egg shoes (No Variations) + {0x2B3, 12446}, // egg party hat (No Variations) + {0x2B4, 12448}, // egg party dress (No Variations) + {0x2B5, 12445}, // Bunny Day crown (No Variations) + {0x2B6, 12447}, // Bunny Day bag (No Variations) + {0x2B7, 12398}, // Bunny Day arch + {0x2B8, 12412}, // wobbling Zipper toy + {0x2B9, 12413}, // Bunny Day lamp + {0x2BA, 12414}, // Bunny Day bed + {0x2BB, 12415}, // Bunny Day stool + {0x2BC, 12417}, // Bunny Day glowy garland + {0x2BD, 12418}, // Bunny Day wall clock + {0x2BE, 12419}, // Bunny Day merry balloons + {0x2BF, 12420}, // Bunny Day vanity + {0x2C0, 12421}, // Bunny Day festive balloons + {0x2C1, 12436}, // Bunny Day table + {0x2C2, 12437}, // Bunny Day wardrobe + {0x2C3, 12517}, // Bunny Day wreath + {0x2C4, 05231}, // Bunny Day wall + {0x2C5, 07546}, // Bunny Day rug + {0x2C6, 12423}, // Bunny Day flooring + {0x2C7, 12578}, // Bunny Day wand + {0x2C8, 12630}, // Bunny Day fence + {0x2C9, 12758}, // hedge + {0x2CA, 12894}, // wedding fence + {0x2CB, 12695}, // wedding wand + {0x2CC, 05607}, // King Tut mask (Gold) + {0x2CD, 12552}, // mermaid table + {0x2CE, 12553}, // mermaid shelf + {0x2CF, 12554}, // mermaid vanity + {0x2D0, 12555}, // mermaid screen + {0x2D1, 12556}, // mermaid lamp + {0x2D2, 12557}, // mermaid wall clock + {0x2D3, 12558}, // mermaid bed + {0x2D4, 12559}, // mermaid closet + {0x2D5, 12560}, // mermaid sofa + {0x2D6, 12561}, // mermaid dresser + {0x2D7, 12562}, // mermaid chair + {0x2D8, 12563}, // mermaid rug + {0x2D9, 12566}, // mermaid wall + {0x2DA, 12568}, // mermaid flooring + {0x2DC, 12951}, // spooky candy set + {0x2DD, 12949}, // spooky standing lamp + {0x2DE, 13222}, // spooky garland + {0x2DF, 13223}, // spooky table setting + {0x2E0, 13237}, // spooky wand + {0x2E1, 13275}, // spooky fence + {0x2E2, 13608}, // veggie basket + {0x2E4, 13447}, // Turkey Day garden stand + {0x2E5, 13448}, // Turkey Day hearth + {0x2E6, 13449}, // Turkey Day decorations + {0x2E7, 13450}, // Turkey Day chair + {0x2E9, 13453}, // Turkey Day table + {0x2EA, 07544}, // festive rug + {0x2EB, 13818}, // Turkey Day casserole + {0x2EC, 13819}, // Turkey Day wheat decor + {0x2ED, 13820}, // Turkey Day table setting + {0x2EE, 13244}, // gift pile + {0x2EF, 13792}, // festive wrapping paper + {0x2F0, 13603}, // falling-snow wall + {0x2F1, 12681}, // partition wall + {0x2F3, 03548}, // rainbow feather + {0x2F5, 12217}, // summer-shell rug + {0x2F6, 14019}, // vine hanging chair + {0x2F7, 13526}, // vine ladder set-up kit + {0x2F8, 13530}, // wooden ladder set-up kit + {0x2F9, 13534}, // iron ladder set-up kit + {0x2FA, 14017}, // cave + {0x2FB, 14018}, // ruined arch + {0x2FC, 13906}, // round vine rug + {0x2FD, 13874}, // glowing-moss ruins wall + {0x2FE, 13875}, // rope-net wall + {0x300, 13877}, // glowing-moss rug + {0x301, 13878}, // round glowing-moss rug + {0x302, 13879}, // glowing-moss flooring + {0x303, 13880}, // rope-net flooring + {0x304, 13881}, // glowing-moss cave wall + {0x305, 13019}, // glowing-moss forest wall + {0x306, 14239}, // shamrock wand + {0x308, 14278}, // mermaid fence + {0x309, 13895}, // tall concrete island counter + {0x30B, 13897}, // tall brick island counter + {0x30C, 13898}, // low concrete island counter + {0x30F, 13901}, // low brick island counter + {0x310, 13902}, // tall wooden island counter + {0x318, 14308}, // low simple island counter + {0x31A, 14310}, // tall simple island counter + {0x31D, 14313}, // low wooden island counter + {0x323, 14322}, // tall steel island counter + {0x325, 14324}, // low steel island counter + {0x32B, 14330}, // tall golden island counter + {0x32D, 14332}, // tall marble island counter + {0x32E, 14333}, // low golden island counter + {0x332, 14337}, // low marble island counter + {0x333, 14470}, // golden ladder set-up kit + {0x334, 14197}, // woven-vines hat (No Variations) + {0x335, 14202}, // vine crown (No Variations) + {0x336, 14248}, // vine outfit (No Variations) + {0x337, 14249}, // woven-vine pochette (No Variations) + {0x338, 01573}, // dharma + {0x339, 14487}, // golden dharma + {0x33A, 14489}, // mini golden dharma + {0x33B, 14207}, // glowing-moss stool + {0x33C, 14209}, // glowing-moss boulder + {0x33D, 14206}, // vine garland + {0x33E, 14192}, // giant vine + {0x33F, 14596}, // brick pillar + {0x340, 14597}, // marble pillar + {0x341, 14598}, // simple pillar + {0x342, 14599}, // steel pillar + {0x343, 14600}, // golden pillar + {0x344, 14601}, // wooden pillar + {0x345, 14602}, // concrete pillar + {0x346, 12335}, // acorn rug + {0x347, 12351}, // cherry-blossom rug + {0x349, 14187}, // stacked senmaizuke barrels + {0x34A, 14188}, // senmaizuke barrel + {0x34C, 13931}, // carrot potage + {0x34D, 13932}, // potato potage + {0x34E, 13933}, // bread gratin + {0x34F, 13934}, // orange pie + {0x350, 13935}, // peach pie + {0x351, 13936}, // pear pie + {0x352, 13937}, // cherry pie + {0x353, 13938}, // gnocchi di zucca + {0x354, 13939}, // gnocchi di patate + {0x355, 13940}, // gnocchi di carote + {0x356, 13941}, // pumpkin soup + {0x357, 13942}, // minestrone soup + {0x358, 13943}, // bamboo-shoot soup + {0x359, 13944}, // apple pie + {0x35A, 13945}, // seaweed soup + {0x35B, 13946}, // carrot cake + {0x35C, 13947}, // apple tart + {0x35D, 13948}, // veggie quiche + {0x35E, 13949}, // orange tart + {0x35F, 13950}, // mixed-fruits tart + {0x360, 13951}, // peach tart + {0x361, 13952}, // cherry tart + {0x362, 13953}, // pear tart + {0x363, 13957}, // mixed-fruits pie + {0x364, 13959}, // mixed-fruits sandwich + {0x365, 13960}, // coconut pudding + {0x366, 13961}, // pear jelly + {0x367, 13962}, // cherry jelly + {0x368, 13963}, // peach jelly + {0x369, 13964}, // mushroom crepe + {0x36A, 13965}, // seafood salad + {0x36B, 13966}, // fruit salad + {0x36C, 13967}, // orange jelly + {0x36D, 13968}, // salade de carottes râpées + {0x36E, 13969}, // poke + {0x36F, 13970}, // turnip salad + {0x370, 13971}, // apple jelly + {0x371, 13972}, // mushroom salad + {0x372, 13973}, // veggie crepe + {0x373, 13974}, // veggie sandwich + {0x374, 13975}, // mixed-fruits crepe + {0x375, 13976}, // salmon sandwich + {0x376, 13977}, // sugar crepe + {0x377, 13978}, // cookies + {0x378, 13979}, // orange pound cake + {0x379, 13980}, // pound cake + {0x37A, 13981}, // pumpkin pound cake + {0x37B, 13982}, // tomato juice + {0x37C, 13983}, // kabu ankake + {0x37D, 13984}, // carrot juice + {0x37E, 13985}, // coconut milk + {0x37F, 13986}, // pretzels + {0x380, 13987}, // frosted pretzels + {0x381, 13988}, // salad-stuffed tomato + {0x382, 13989}, // coconut cookies + {0x383, 13990}, // veggie cookies + {0x384, 13991}, // cherry smoothie + {0x385, 13992}, // thumbprint jam cookies + {0x386, 13993}, // frosted cookies + {0x387, 13994}, // flour + {0x388, 13995}, // pear smoothie + {0x389, 13996}, // whole-wheat flour + {0x38A, 13997}, // sugar + {0x38B, 13998}, // brown sugar + {0x38C, 13999}, // peach smoothie + {0x38D, 14000}, // apple smoothie + {0x38E, 14001}, // orange smoothie + {0x38F, 14002}, // brown-sugar pound cake + {0x390, 14003}, // sea-bass pie + {0x391, 14010}, // salad + {0x392, 14048}, // mushroom potage + {0x393, 14104}, // fish and chips + {0x394, 14105}, // french fries + {0x395, 14109}, // plain scones + {0x396, 14110}, // veggie cupcakes + {0x397, 14111}, // tomato bagel sandwich + {0x398, 14112}, // brown-sugar cupcakes + {0x399, 14113}, // carrot scones + {0x39A, 14114}, // pumpkin cupcakes + {0x39B, 14115}, // fruit scones + {0x39C, 14116}, // fruit cupcakes + {0x39D, 14117}, // pumpkin scones + {0x39E, 14118}, // plain cupcakes + {0x39F, 14119}, // salmon bagel sandwich + {0x3A0, 14120}, // squid-ink curry + {0x3A1, 14121}, // pumpkin curry + {0x3A2, 14122}, // carrot-tops curry + {0x3A3, 14123}, // mixed-fruits bagel sandwich + {0x3A4, 14124}, // tomato curry + {0x3A5, 14125}, // pumpkin bagel sandwich + {0x3A6, 14126}, // carrot bagel sandwich + {0x3A7, 14127}, // potato curry + {0x3A8, 14128}, // mushroom curry + {0x3A9, 14129}, // pancakes + {0x3AA, 14130}, // coconut pancakes + {0x3AB, 14131}, // potato galette + {0x3AC, 14132}, // fruit-topped pancakes + {0x3AD, 14161}, // pesce all'acqua pazza + {0x3AE, 14162}, // karei no nitsuke + {0x3AF, 14163}, // aji fry + {0x3B0, 14164}, // sautéed olive flounder + {0x3B1, 14165}, // grilled sea bass with herbs + {0x3B2, 14166}, // carpaccio di salmone + {0x3B3, 14167}, // carpaccio di marlin blu + {0x3B4, 14168}, // barred-knifejaw carpaccio + {0x3B5, 14169}, // orange marmalade + {0x3B6, 14170}, // peach jam + {0x3B7, 14171}, // pear jam + {0x3B8, 14172}, // carpaccio di capesante + {0x3B9, 14173}, // cherry jam + {0x3BA, 14174}, // pickled veggies + {0x3BB, 14175}, // tomato puree + {0x3BC, 14176}, // apple jam + {0x3BD, 14177}, // coconut oil + {0x3BE, 14178}, // anchoas al ajillo + {0x3BF, 14179}, // tomates al ajillo + {0x3C0, 14180}, // champiñones al ajillo + {0x3C1, 14181}, // sardines in oil + {0x3C2, 14182}, // pull-apart bread + {0x3C3, 14183}, // seafood ajillo + {0x3C4, 14185}, // jarred mushrooms + {0x3C5, 14186}, // jarred bamboo shoots + {0x3C6, 14465}, // baked potatoes + {0x3C7, 14466}, // pizza margherita + {0x3C8, 14696}, // seafood pizza + {0x3C9, 14697}, // fruit pizza + {0x3CA, 14698}, // mushroom pizza + {0x3CB, 13327}, // gratin + {0x3CC, 13328}, // clam chowder + {0x3CD, 13329}, // pumpkin pie + {0x3CE, 13330}, // olive-flounder meunière + {0x3CF, 12822}, // bread + {0x3D0, 12823}, // organic bread + {0x3D1, 12824}, // snack bread + {0x3D2, 12813}, // savory bread + {0x3D3, 12390}, // maple-leaf rug + {0x3D4, 14550}, // spooky tree + {0x3D5, 14551}, // spooky trick lamp + {0x3D6, 14542}, // spooky treats basket + {0x3D7, 12222}, // yellow star rug + {0x3D8, 12329}, // green bamboo mat + {0x3D9, 12330}, // yellow bamboo mat + {0x3DA, 12379}, // tree-stump rug + {0x3DB, 12399}, // light bamboo bath mat + {0x3DC, 12400}, // dark bamboo bath mat + {0x3DD, 12521}, // starry-skies rug + {0x3DE, 13662}, // ruined decorated pillar + {0x3DF, 14193}, // vine bench + {0x3E0, 14205}, // vine lamp + {0x3E1, 14210}, // hanging glowing moss + {0x3E2, 14211}, // glowing-moss wreath + {0x3E3, 14212}, // glowing-moss pond + {0x3E4, 14213}, // glowing-moss statue + {0x3E5, 14214}, // glowing-moss-jar shelves + {0x3E6, 14215}, // glow-in-the-dark stickers + {0x3E7, 14216}, // suspicious cauldron + {0x3E8, 14208}, // glowing-moss balloon + {0x3E9, 14604}, // glowing-moss jar + {0x3EA, 14199}, // glowing-moss hood (No Variations) + {0x3EB, 14198}, // glowing-moss pointed cap (No Variations) + {0x3EC, 14201}, // glowing-moss headband (No Variations) + {0x3ED, 14257}, // full-body glowing-moss suit (No Variations) + {0x3EE, 14259}, // glowing-moss dress (No Variations) + {0x3EF, 14755}, // green bamboo fence + {0x3F0, 14756}, // frozen fence + {0x3F1, 14757}, // bamboo-slats fence + {0x3F2, 14758}, // corrugated iron fence + {0x3F3, 14759}, // park fence + {0x3F4, 14728}, // ornament tree + {0x3F5, 14594}, // giant ornament + {0x3F6, 14593}, // ornament garland + {0x3F7, 14591}, // ornament table lamp + {0x3F8, 14552}, // spooky cookies + {0x3F9, 14613}, // ornament crown (No Variations) + {0x3FA, 14565}, // Roost sablé cookie + {0x3FB, 14478}, // golden plate armor + {0x3FC, 14479}, // golden piggy bank + {0x3FD, 14484}, // golden meter and pipes + {0x3FE, 14485}, // golden gear apparatus + {0x3FF, 14486}, // golden gear tower + {0x400, 14488}, // golden garden bunny + {0x401, 14490}, // golden urn + {0x402, 14491}, // golden wristwatch + {0x403, 14492}, // golden decorative plate + {0x404, 14481}, // golden vase + {0x405, 14482}, // golden altar + {0x406, 14483}, // golden bathtub + {0x407, 14480}, // gold-nugget mining car + {0x408, 14533}, // golden samurai suit + {0x409, 12840}, // spaghetti napolitan + {0x40A, 12838}, // spaghetti marinara + {0x40B, 12835}, // squid-ink spaghetti + {0x40C, 14645}, // foxtail + {0x40D, 14644}, // nice branch + {0x40E, 14716}, // cake salé + {0x40F, 14714}, // donation box + {0x410, 13496}, // stonework kitchen + {0x411, 14831}, // wooden storage shed + {0x412, 14592}, // wooden music box + {0x413, 14549}, // decayed tree + {0x414, 13572}, // frozen floor tiles + {0x415, 14882}, // ruined seat + {0x416, 13509}, // gear tower + {0x417, 13511}, // gear apparatus + {0x418, 13520}, // forbidden altar + {0x419, 12611}, // plate armor + {0x41A, 07154}, // wooden box + {0x41B, 12350}, // box-shaped seat + {0x41C, 12706}, // imperial pot + {0x41D, 13696}, // pile of cardboard boxes + {0x41E, 12349}, // project table + {0x41F, 13210}, // stacked shopping baskets + {0x420, 13606}, // stacked fish containers + {0x421, 13220}, // festival-lantern set + {0x422, 13580}, // skateboard wall rack + {0x423, 12709}, // carp on a cutting board + {0x424, 14887}, // ruined broken pillar + {0x425, 13666}, // pile of cash + {0x426, 00922}, // stacked bottle crates + {0x427, 00743}, // frozen mini snowperson + {0x42B, 13573}, // medium wooden partition + {0x42C, 13574}, // small wooden partition + {0x42D, 13751}, // open wooden shelves + {0x42E, 13588}, // tension-pole rack + {0x430, 13161}, // wooden field sign + }; +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Records/EventFlagHouse.cs b/NHSE.Core/Structures/Records/EventFlagHouse.cs index eea6471..4ff2e5a 100644 --- a/NHSE.Core/Structures/Records/EventFlagHouse.cs +++ b/NHSE.Core/Structures/Records/EventFlagHouse.cs @@ -1,59 +1,58 @@ using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public class EventFlagHouse : INamedValue { - public class EventFlagHouse : INamedValue + // these are actually unsigned + public readonly short DefaultValue; + public readonly short MaxValue; + + public ushort Index { get; } + public string Name { get; } + + public EventFlagHouse(short init, short max, ushort index, string name) { - // these are actually unsigned - public readonly short DefaultValue; - public readonly short MaxValue; + Name = name; + Index = index; + DefaultValue = init; + MaxValue = max; + } - public ushort Index { get; } - public string Name { get; } + public static readonly IReadOnlyDictionary List = new Dictionary + { + {0x001, new EventFlagHouse(0, 1 , 0001, "HouseOrder1" )}, // テント→6x6増築申込 + {0x002, new EventFlagHouse(0, 1 , 0002, "HouseOrder2" )}, // 6x6→8x8増築申込 + {0x003, new EventFlagHouse(0, 1 , 0003, "HouseOrder3" )}, // 8x8→8x8+奥増築申込 + {0x004, new EventFlagHouse(0, 1 , 0004, "HouseOrder4" )}, // 8x8+奥→8x8+奥左増築申込 + {0x005, new EventFlagHouse(0, 1 , 0005, "HouseOrder5" )}, // 8x8+奥左→8x8+奥左右増築申込 + {0x006, new EventFlagHouse(0, 1 , 0006, "HouseOrder6" )}, // 8x8+奥左右→2F増築申込 + {0x007, new EventFlagHouse(0, 1 , 0007, "HouseOrder7" )}, // 2F→地下増築申込 + {0x009, new EventFlagHouse(0, 10000, 0009, "CountHouseBuild" )}, // テントから家になって何日目か + {0x00A, new EventFlagHouse(0, 10000, 0010, "CountUnderGroundBuild" )}, // 地下室ができて何日目か + {0x00B, new EventFlagHouse(0, 10000, 0011, "CountHouseExtension" )}, // 最後に増築してからの日数 + }; - public EventFlagHouse(short init, short max, ushort index, string name) + private const string Unknown = "???"; + + public static string GetName(ushort index, short count, IReadOnlyDictionary str) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) { - Name = name; - Index = index; - DefaultValue = init; - MaxValue = max; + string name = val.Name; + if (str.TryGetValue(name, out var translated)) + name = translated; + return $"{index:00} - {name} = {count}"; } + return $"{index:00} - {Unknown} = {count}"; + } - public static readonly IReadOnlyDictionary List = new Dictionary - { - {0x001, new EventFlagHouse(0, 1 , 0001, "HouseOrder1" )}, // テント→6x6増築申込 - {0x002, new EventFlagHouse(0, 1 , 0002, "HouseOrder2" )}, // 6x6→8x8増築申込 - {0x003, new EventFlagHouse(0, 1 , 0003, "HouseOrder3" )}, // 8x8→8x8+奥増築申込 - {0x004, new EventFlagHouse(0, 1 , 0004, "HouseOrder4" )}, // 8x8+奥→8x8+奥左増築申込 - {0x005, new EventFlagHouse(0, 1 , 0005, "HouseOrder5" )}, // 8x8+奥左→8x8+奥左右増築申込 - {0x006, new EventFlagHouse(0, 1 , 0006, "HouseOrder6" )}, // 8x8+奥左右→2F増築申込 - {0x007, new EventFlagHouse(0, 1 , 0007, "HouseOrder7" )}, // 2F→地下増築申込 - {0x009, new EventFlagHouse(0, 10000, 0009, "CountHouseBuild" )}, // テントから家になって何日目か - {0x00A, new EventFlagHouse(0, 10000, 0010, "CountUnderGroundBuild" )}, // 地下室ができて何日目か - {0x00B, new EventFlagHouse(0, 10000, 0011, "CountHouseExtension" )}, // 最後に増築してからの日数 - }; - - private const string Unknown = "???"; - - public static string GetName(ushort index, short count, IReadOnlyDictionary str) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - { - string name = val.Name; - if (str.TryGetValue(name, out var translated)) - name = translated; - return $"{index:00} - {name} = {count}"; - } - return $"{index:00} - {Unknown} = {count}"; - } - - public static string GetName(ushort index, short count) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - return $"{index:00} - {val.Name} = {count}"; - return $"{index:00} - {Unknown} = {count}"; - } + public static string GetName(ushort index, short count) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + return $"{index:00} - {val.Name} = {count}"; + return $"{index:00} - {Unknown} = {count}"; } } \ No newline at end of file diff --git a/NHSE.Core/Structures/Records/EventFlagLand.cs b/NHSE.Core/Structures/Records/EventFlagLand.cs index aa667e1..8494f79 100644 --- a/NHSE.Core/Structures/Records/EventFlagLand.cs +++ b/NHSE.Core/Structures/Records/EventFlagLand.cs @@ -1,521 +1,520 @@ using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public class EventFlagLand : INamedValue { - public class EventFlagLand : INamedValue + // these are actually unsigned + public readonly short DefaultValue; + public readonly short MaxValue; + + public ushort Index { get; } + public string Name { get; } + + public EventFlagLand(short init, short max, ushort index, string name) { - // these are actually unsigned - public readonly short DefaultValue; - public readonly short MaxValue; - - public ushort Index { get; } - public string Name { get; } - - public EventFlagLand(short init, short max, ushort index, string name) - { - Name = name; - Index = index; - DefaultValue = init; - MaxValue = max; - } - - public static readonly IReadOnlyDictionary List = new Dictionary - { - {0x000, new EventFlagLand(0 , 1 , 0000, "TodayCreateVillage" )}, // 今日村作成されたか - {0x001, new EventFlagLand(0 , 1 , 0001, "TodayPlayerEmigrate" )}, // 今日プレイヤが移住してきたか? - {0x002, new EventFlagLand(0 , 1 , 0002, "TkkFirstLive" )}, // とたけけ|初ライブを行ったか - {0x003, new EventFlagLand(0 , 1 , 0003, "FinishiPC1Prologue" )}, // PC1の序盤プロローグ完了時にON - {0x004, new EventFlagLand(0 , 1 , 0004, "IsMovingConsultationToPlayer" )}, // NPCが引越相談をした - {0x005, new EventFlagLand(0 , 1 , 0005, "EnableMarketBuild" )}, // まめつぶ商店建築条件満たした - {0x006, new EventFlagLand(0 , 1 , 0006, "ValidateVillageSave" )}, // 村データが有効化された - {0x007, new EventFlagLand(0 , 5 , 0007, "FreeEChatTimes" )}, // 村で告知会話を聞いた回数 - {0x008, new EventFlagLand(0 , 5 , 0008, "FreeFChatTimes" )}, // 村でイベント会話を聞いた回数 - {0x00A, new EventFlagLand(0 , -1 , 0010, "RandomKey" )}, // ランダムキー - {0x00B, new EventFlagLand(0 , 1 , 0011, "DoneMuseumConstruction" )}, // 博物館建築工事完了 - {0x00C, new EventFlagLand(0 , 1 , 0012, "Prologue4BuiltPlayer" )}, // 序盤プレイヤーテント設置したか? - {0x00D, new EventFlagLand(0 , 1 , 0013, "Plorogue4BuiltMuseum" )}, // 博物館|フータテント予定地設置したか? - {0x00E, new EventFlagLand(0 , 1 , 0014, "Prologue4BuiltShop" )}, // 商店の工事看板設置したか? - {0x00F, new EventFlagLand(0 , 1 , 0015, "Prologue4BuiltNpcAN" )}, // 序盤ANテント設置したか? - {0x010, new EventFlagLand(0 , 1 , 0016, "Prologue4BuiltNpcHA" )}, // 序盤HAテント設置したか? - {0x011, new EventFlagLand(0 , 1 , 0017, "TodayStartTown1P" )}, // 1Pが村誕生させた初日か? - {0x012, new EventFlagLand(0 , 1 , 0018, "ShopItemSet" )}, // 商店に商品を置いてよいか? - {0x013, new EventFlagLand(0 , 1 , 0019, "VillageExtensionLevel2" )}, // 村の拡張段階2 - {0x014, new EventFlagLand(0 , 1 , 0020, "RcmGotSignboard" )}, // まめきちが看板を手に入れた - {0x015, new EventFlagLand(0 , 1 , 0021, "InstalledMarketTentSign" )}, // まめきちテントの看板が設置された - {0x016, new EventFlagLand(0 , 1 , 0022, "SandBankDisable" )}, // 中州判定が無効になったか? - {0x017, new EventFlagLand(0 , 1 , 0023, "MarketRemodelingFlag1" )}, // まめきちの店|テント→商店(小)改装決定 - {0x018, new EventFlagLand(0 , 1 , 0024, "MarketOpen1stDay1" )}, // まめきちの店|新装開店当日(商店) - {0x019, new EventFlagLand(0 , 9 , 0025, "SpotPrologueTimes" )}, // 序盤会話を呼んだ回数 - {0x01A, new EventFlagLand(0 , 20000, 0026, "PlazaDonationMoney" )}, // イベント広場寄付金額 - {0x01B, new EventFlagLand(0 , 20 , 0027, "PlazaDonationMaterial" )}, // イベント広場寄付素材数(ねんど) - {0x01C, new EventFlagLand(0 , 1 , 0028, "PlazaDonationFinish" )}, // イベント広場募金集まったか? - {0x01D, new EventFlagLand(0 , 1 , 0029, "EventPlazaBuilt" )}, // イベント広場完成 - {0x01E, new EventFlagLand(0 , 1 , 0030, "SzaGotGyroid" )}, // しずえがハニワくん入手した - {0x01F, new EventFlagLand(0 , 1 , 0031, "PlazaGyroidBuilt" )}, // イベント広場募金ハニワくん設置 - {0x020, new EventFlagLand(0 , 1 , 0032, "MuseumGrowupEnable1" )}, // 博物館成長条件1達成 - {0x021, new EventFlagLand(0 , 5 , 0033, "MuseumConstruction1" )}, // 博物館テント→工事中 - {0x022, new EventFlagLand(0 , 1 , 0034, "Museum2Built" )}, // 博物館①完成 - {0x023, new EventFlagLand(0 , 1 , 0035, "Museum2BuiltToday" )}, // 博物館(建物)①完成当日か? - {0x024, new EventFlagLand(0 , 5000 , 0036, "InsectNetHostCatchNumResult" )}, // 通信開始時にネットホストのプレイヤーが今まで捕まえたムシの数 - {0x025, new EventFlagLand(0 , 1 , 0037, "GlobalEventAvailable" )}, // グローバルイベント解禁 - {0x026, new EventFlagLand(0 , 1 , 0038, "InsectFesFinished" )}, // 島で2回目以降のムシとり大会?(ムシとり大会の日をまたいだ?) - {0x027, new EventFlagLand(0 , 1 , 0039, "MarketRemodelingFlag2" )}, // まめきちの店|商店(小)→倉庫 改装決定 - {0x028, new EventFlagLand(0 , 1 , 0040, "MarketOpen1stDay2" )}, // まめきちの店|新装開店当日(倉庫) - {0x029, new EventFlagLand(0 , 6 , 0041, "RcoMoveReservedKind" )}, // たぬきち|建物移設の予約種類判別カウンタ - {0x02A, new EventFlagLand(0 , 1 , 0042, "QuestReserveStart" )}, // クエスト予約解禁 - {0x02B, new EventFlagLand(0 , -1 , 0043, "VillageDaysCount" )}, // 村の経過日数 - {0x02C, new EventFlagLand(0 , 1 , 0044, "PeddlingAvailableSlo" )}, // 行商解禁済|レイジ - {0x02D, new EventFlagLand(0 , 1 , 0045, "MarketBuilt" )}, // まめつぶ商店が建った - {0x02E, new EventFlagLand(0 , 1 , 0046, "PeddingAvailableBoa" )}, // カブ解禁済|カブリバ - {0x02F, new EventFlagLand(0 , 1 , 0047, "MarketConstruction1" )}, // まめきちの店|テント→商店(小)工事中 - {0x030, new EventFlagLand(0 , 1 , 0048, "MarketConstruction2" )}, // まめきちの店||商店(小)→倉庫 工事中 - {0x031, new EventFlagLand(0 , 1 , 0049, "FirstKabuBuy" )}, // 島の誰かがカブを買ったことがある - {0x032, new EventFlagLand(0 , 1 , 0050, "FirstKabuPattern" )}, // 初回カブ価パターン適用済みフラグ - {0x033, new EventFlagLand(4 , 4 , 0051, "FoxArtStockCount" )}, // つねきち|美術品の在庫 - {0x034, new EventFlagLand(0 , 1 , 0052, "EventPlazaBuiltToday" )}, // イベント広場完成当日 - {0x035, new EventFlagLand(0 , 8 , 0053, "CountNnpcHouseSpaceSet" )}, // 建築予定地を確保し終えた数 - {0x036, new EventFlagLand(0 , 1 , 0054, "GlobalEventReady" )}, // グローバルイベント準備中 - {0x037, new EventFlagLand(0 , 6 , 0055, "BirthdayBbsVariation1" )}, // 誕生日の告知を掲示板に前回書き込んだときのバリエーション1人用 - {0x03A, new EventFlagLand(0 , 1 , 0058, "EnableBuildTownOffice" )}, // 役場建設条件が揃った - {0x03B, new EventFlagLand(0 , 1 , 0059, "BuiltTownOffice" )}, // 案内所完成 - {0x03C, new EventFlagLand(0 , 1 , 0060, "BuiltTownOfficeToday" )}, // 案内所完成当日 - {0x03D, new EventFlagLand(0 , 1 , 0061, "StartBuildingTownOffice" )}, // 役場建設&村長誘致開始可能 - {0x03E, new EventFlagLand(0 , 1111 , 0062, "SzaDonatedItemType" )}, // 役場建設用のアイテム寄贈状況(種類判別用) - {0x03F, new EventFlagLand(0 , 4 , 0063, "SzaDonatedItemCount" )}, // 役場建設用のアイテム寄贈状況(個数判別用) - {0x041, new EventFlagLand(0 , 1 , 0065, "IsNpcIncreased" )}, // NPCが1人でも引越してきたか? - {0x042, new EventFlagLand(0 , 1 , 0066, "MuseumBuilt" )}, // 博物館テントが建った - {0x043, new EventFlagLand(0 , 1 , 0067, "TailorBuilt" )}, // 仕立て屋|仕立て屋が建った - {0x044, new EventFlagLand(0 , 2 , 0068, "IslandKanaType" )}, // 『島』のルビ - {0x045, new EventFlagLand(0 , -1 , 0069, "TodayGlobalEventId" )}, // 今日行われるグローバルイベントのID - {0x046, new EventFlagLand(0 , -1 , 0070, "TodayRegionEventId" )}, // 今日行われるリージョンイベントのID - {0x047, new EventFlagLand(0 , 1 , 0071, "NoncompliantRegionCode" )}, // 非対応の地域設定でセーブしたか? - {0x048, new EventFlagLand(0 , 1 , 0072, "GstTalkAnyone" )}, // ゆうたろう|ゆうたろうと誰か話したことある? - {0x049, new EventFlagLand(0 , 1 , 0073, "OwlFoundFossil" )}, // フータに化石を見せたことがある - {0x04A, new EventFlagLand(0 , 1 , 0074, "MarketSellRecipeScoopStick" )}, // お店|ショボいスコップ、たかとびぼうレシピの店売りを解禁する - {0x04B, new EventFlagLand(0 , 1 , 0075, "TailorConstruction1" )}, // 仕立て屋|予定地→工事中 - {0x04C, new EventFlagLand(0 , 1 , 0076, "FishFesFinished" )}, // 島で2回目以降のつり大会?(つり大会の日をまたいだ?) - {0x04D, new EventFlagLand(0 , 1 , 0077, "HghStayMarket" )}, // きぬよ|商店に来訪中 - {0x04E, new EventFlagLand(0 , 1 , 0078, "EnableHghStayField" )}, // きぬよ|来訪NPCに選んでよいか? - {0x04F, new EventFlagLand(0 , 1 , 0079, "EnableTailorBuild" )}, // 仕立て屋|建築条件を満たした - {0x050, new EventFlagLand(0 , 1 , 0080, "TailorReserved" )}, // 仕立て屋|工事看板(予定地)が建った - {0x051, new EventFlagLand(0 , 1 , 0081, "TailorGetHousingkit" )}, // 仕立て屋|工事看板を受け取った - {0x052, new EventFlagLand(0 , 1 , 0082, "ReportedTaiorReserve" )}, // 仕立て屋|工事看板(予定地)建てたこと報告済み - {0x053, new EventFlagLand(0 , 99 , 0083, "CountTailorBuild" )}, // 仕立て屋|建築条件に関わるカウンタ - {0x054, new EventFlagLand(0 , 10 , 0084, "NNpcPhoneColorChangeCounter" )}, // 一般NPC|スマホ柄が汎用布地に変わるカウンタ - {0x055, new EventFlagLand(0 , 1 , 0085, "RcoEnableBuyHousingKit" )}, // たぬきち|売り土地を探すの選択肢解禁 - {0x056, new EventFlagLand(0 , 99 , 0086, "OpeningSeqBGMChangeCounter" )}, // 序盤シーケンス|BGM切替カウンタ - {0x060, new EventFlagLand(0 , 1 , 0096, "JohnnySitUpFlag" )}, // ジョニー|起きたかフラグ(海賊ジョニーでも使用) - {0x062, new EventFlagLand(0 , 1 , 0098, "AllowNpcInterestActivity" )}, // NPCの認識行動が許可されたか - {0x067, new EventFlagLand(0 , 1 , 0103, "RcoBuildCampsiteOngoing" )}, // たぬきち|キャンプ場設置の依頼を島の誰かが引き受けた - {0x068, new EventFlagLand(0 , 1 , 0104, "RcoBuildCampsiteComplete" )}, // たぬきち|キャンプ場設置の依頼で、誰かが予定地を建てた - {0x06A, new EventFlagLand(0 , 1 , 0106, "RcoMeetFirstVisitorRequest" )}, // たぬきち|1人目の客に会う依頼をしてくるようになる - {0x06B, new EventFlagLand(0 , 1 , 0107, "RcoMeetFirstVisitorOngoing" )}, // たぬきち|1人目の客に会う依頼を島の誰かが引き受けた - {0x06C, new EventFlagLand(0 , 1 , 0108, "RcoMeetFirstVisitorComplete" )}, // たぬきち|1人目のキャンプ客の移住希望の話を、島の誰かが聞いた - {0x06D, new EventFlagLand(0 , 1 , 0109, "RcoBuildFirstVisitorsHousingKitOngoing" )}, // たぬきち|1人目の客のハウジングキットの設置依頼を、島の誰かが受けた - {0x06E, new EventFlagLand(0 , 1 , 0110, "RcoBuildFirstVisitorsHousingKitComplete" )}, // たぬきち|1人目の客のハウジングキットを、島の誰かが設置した - {0x072, new EventFlagLand(15, 15 , 0114, "DonationAmountForMuseum" )}, // 博物館建設のために必要な寄贈の残り数 - {0x073, new EventFlagLand(0 , 1 , 0115, "OfficeConstruction1" )}, // 役場|工事中→役場 - {0x074, new EventFlagLand(0 , 1 , 0116, "JohnnyTalkAnyPlayerFlag" )}, // ジョニー|村の誰か話しかけたか(海賊ジョニー不使用) - {0x076, new EventFlagLand(0 , 1 , 0118, "TkkReturn" )}, // とたけけ|帰ったか? - {0x077, new EventFlagLand(0 , 1 , 0119, "FlightBalloonEnable" )}, // 空飛ぶ風船|発生してよいか? - {0x078, new EventFlagLand(0 , 1 , 0120, "ConfirmedFruit" )}, // フルーツの品種が特定された - {0x079, new EventFlagLand(0 , 1 , 0121, "RctInTent" )}, // つぶきち|たぬきちテントに帰る - {0x07A, new EventFlagLand(0 , 1 , 0122, "GstAppearField" )}, // ゆうたろう|村に出現する - {0x07B, new EventFlagLand(0 , 1 , 0123, "MuseumTentBuiltToday" )}, // 博物館テントオープン当日か? - {0x07C, new EventFlagLand(0 , 1 , 0124, "TailorBuiltToday" )}, // 仕立て屋オープン当日か? - {0x07D, new EventFlagLand(0 , 1 , 0125, "VillageExtensionLevel3" )}, // 村の拡張段階3 - {0x07E, new EventFlagLand(0 , 4 , 0126, "RcoBuildBridgeSlopeStatusCounter" )}, // たぬきち|橋/坂建設工事に関するカウンタ - {0x07F, new EventFlagLand(0 , 2 , 0127, "RcoMoveReservedAnyone" )}, // たぬきち|建物の移設予約カウンタ - {0x080, new EventFlagLand(0 , 1 , 0128, "HgcVisitFlagForTailor" )}, // 仕立て屋商品けってい用ことの来訪フラグ - {0x083, new EventFlagLand(0 , 1 , 0131, "RcoDeleteBridgeSlopeReservedAnyone" )}, // たぬきち|誰かが橋/坂の撤去を予約してる - {0x085, new EventFlagLand(0 , 1 , 0133, "RcoBuildBridgeSlopeSelector" )}, // たぬきち|現在の建設対象が橋/坂どちらか?0橋1坂 - {0x086, new EventFlagLand(0 , 1 , 0134, "RcoIslandRevitilizationRefuse" )}, // たぬきち|島おこし系クエスト断った - {0x087, new EventFlagLand(0 , 1 , 0135, "MessageBottleAvailable" )}, // メッセージボトル漂着が解禁 - {0x088, new EventFlagLand(0 , 1 , 0136, "ImmQ_A_GetHousing" )}, // 移住Quest|住宅A|ハウジングキットもらった - {0x089, new EventFlagLand(0 , 1 , 0137, "ImmQ_B_GetHousing" )}, // 移住Quest|住宅B|ハウジングキットもらった - {0x08A, new EventFlagLand(0 , 1 , 0138, "ImmQ_C_GetHousing" )}, // 移住Quest|住宅C|ハウジングキットもらった - {0x08B, new EventFlagLand(0 , 1 , 0139, "ImmQ_A_SetHousing" )}, // 移住Quest|住宅A|ハウジングキット設置した - {0x08C, new EventFlagLand(0 , 1 , 0140, "ImmQ_B_SetHousing" )}, // 移住Quest|住宅B|ハウジングキット設置した - {0x08D, new EventFlagLand(0 , 1 , 0141, "ImmQ_C_SetHousing" )}, // 移住Quest|住宅C|ハウジングキット設置した - {0x08E, new EventFlagLand(0 , 1 , 0142, "ImmQ_A_Interior1Donate" )}, // 移住Quest|住宅A|屋内家具1寄贈 - {0x08F, new EventFlagLand(0 , 1 , 0143, "ImmQ_B_Interior1Donate" )}, // 移住Quest|住宅B|屋内家具1寄贈 - {0x090, new EventFlagLand(0 , 1 , 0144, "ImmQ_C_Interior1Donate" )}, // 移住Quest|住宅C|屋内家具1寄贈 - {0x091, new EventFlagLand(0 , 1 , 0145, "ImmQ_A_Interior2Donate" )}, // 移住Quest|住宅A|屋内家具2寄贈 - {0x092, new EventFlagLand(0 , 1 , 0146, "ImmQ_B_Interior2Donate" )}, // 移住Quest|住宅B|屋内家具2寄贈 - {0x093, new EventFlagLand(0 , 1 , 0147, "ImmQ_C_Interior2Donate" )}, // 移住Quest|住宅C|屋内家具2寄贈 - {0x094, new EventFlagLand(0 , 1 , 0148, "ImmQ_A_Interior3Donate" )}, // 移住Quest|住宅A|屋内家具3寄贈 - {0x095, new EventFlagLand(0 , 1 , 0149, "ImmQ_B_Interior3Donate" )}, // 移住Quest|住宅B|屋内家具3寄贈 - {0x096, new EventFlagLand(0 , 1 , 0150, "ImmQ_C_Interior3Donate" )}, // 移住Quest|住宅C|屋内家具3寄贈 - {0x097, new EventFlagLand(0 , 1 , 0151, "ImmQ_A_Outdoor1Set" )}, // 移住Quest|住宅A|外置き家具1配置 - {0x098, new EventFlagLand(0 , 1 , 0152, "ImmQ_B_Outdoor1Set" )}, // 移住Quest|住宅B|外置き家具1配置 - {0x099, new EventFlagLand(0 , 1 , 0153, "ImmQ_C_Outdoor1Set" )}, // 移住Quest|住宅C|外置き家具1配置 - {0x09A, new EventFlagLand(0 , 1 , 0154, "ImmQ_A_Outdoor2Set" )}, // 移住Quest|住宅A|外置き家具2配置 - {0x09B, new EventFlagLand(0 , 1 , 0155, "ImmQ_B_Outdoor2Set" )}, // 移住Quest|住宅B|外置き家具2配置 - {0x09C, new EventFlagLand(0 , 1 , 0156, "ImmQ_C_Outdoor2Set" )}, // 移住Quest|住宅C|外置き家具2配置 - {0x09D, new EventFlagLand(0 , 1 , 0157, "ImmQ_A_Outdoor3Set" )}, // 移住Quest|住宅A|外置き家具3配置 - {0x09E, new EventFlagLand(0 , 1 , 0158, "ImmQ_B_Outdoor3Set" )}, // 移住Quest|住宅B|外置き家具3配置 - {0x09F, new EventFlagLand(0 , 1 , 0159, "ImmQ_C_Outdoor3Set" )}, // 移住Quest|住宅C|外置き家具3配置 - {0x0A0, new EventFlagLand(0 , 1 , 0160, "ImmQ_A_Complete" )}, // 移住Quest|住宅A|全工程完了 - {0x0A1, new EventFlagLand(0 , 1 , 0161, "ImmQ_B_Complete" )}, // 移住Quest|住宅B|全工程完了 - {0x0A2, new EventFlagLand(0 , 1 , 0162, "ImmQ_C_Complete" )}, // 移住Quest|住宅C|全工程完了 - {0x0A3, new EventFlagLand(0 , 1 , 0163, "ImmQ_A_Invited" )}, // 移住Quest|移住者A|勧誘した - {0x0A4, new EventFlagLand(0 , 1 , 0164, "ImmQ_B_Invited" )}, // 移住Quest|移住者B|勧誘した - {0x0A5, new EventFlagLand(0 , 1 , 0165, "ImmQ_C_Invited" )}, // 移住Quest|移住者C|勧誘した - {0x0A6, new EventFlagLand(0 , 1 , 0166, "RcmImmQuestOpen" )}, // たぬきち|移住Quest開始できる - {0x0A7, new EventFlagLand(0 , 1 , 0167, "RcmImmQuestRunning" )}, // たぬきち|移住Quest実施中 - {0x0A8, new EventFlagLand(0 , 1 , 0168, "RcmImmQuestComplete" )}, // たぬきち|移住Quest完了 - {0x0A9, new EventFlagLand(0 , 9 , 0169, "JohnnyRequirePartsNum" )}, // ジョニー|必要なパーツの個数(海賊ジョニー不使用) - {0x0AA, new EventFlagLand(0 , 1 , 0170, "ImmQ_A_InteriorDonateNow" )}, // 移住Quest|住宅A|屋内家具を今寄贈した - {0x0AB, new EventFlagLand(0 , 1 , 0171, "ImmQ_B_InteriorDonateNow" )}, // 移住Quest|住宅B|屋内家具の今寄贈した - {0x0AC, new EventFlagLand(0 , 1 , 0172, "ImmQ_C_InteriorDonateNow" )}, // 移住Quest|住宅C|屋内家具の今寄贈した - {0x0AD, new EventFlagLand(0 , 1 , 0173, "RcoRemoveBridgeSlopeSelector" )}, // たぬきち|現在の撤去対象が橋/坂どちらか?0橋1坂 - {0x0AE, new EventFlagLand(0 , 288 , 0174, "CeremonySlopeUnitX" )}, // セレモニ|坂建設位置X - {0x0AF, new EventFlagLand(0 , 256 , 0175, "CeremonySlopeUnitZ" )}, // セレモニ|坂建設位置Z - {0x0B0, new EventFlagLand(0 , 1 , 0176, "RcoNoticeBuildInfomationOffice" )}, // たぬきち|案内所建物建築のお知らせ可能 - {0x0B1, new EventFlagLand(0 , 1 , 0177, "CampSiteBuilt" )}, // キャンプ場が建った - {0x0B2, new EventFlagLand(0 , 1 , 0178, "RcoDeleteBridgeSlopeBuildPlayer" )}, // たぬきち|橋/坂予定地を建てたプレイヤーが削除された - {0x0B3, new EventFlagLand(0 , 100 , 0179, "VisitorPrayStarToday" )}, // 今日村に来たビジタが祈った回数 - {0x0B4, new EventFlagLand(0 , 1 , 0180, "AmiiboCampSiteCall" )}, // 今日amiiboを使ってキャンプ場にNPCを呼んだ - {0x0B5, new EventFlagLand(0 , 1 , 0181, "ImmQ_SetBridge" )}, // 移住Quest|橋の予定地が配置された - {0x0B6, new EventFlagLand(0 , 1 , 0182, "CampQuestInProgress" )}, // キャンプ家具クエスト進行中 - {0x0B7, new EventFlagLand(0 , 1 , 0183, "CampQuestClear" )}, // キャンプ家具クエストクリア済 - {0x0B9, new EventFlagLand(0 , 1 , 0185, "SzaTaled1stTimeAnyPlayer" )}, // 24時間BGMを案内所完成後用に切り替える - {0x0BA, new EventFlagLand(0 , 288 , 0186, "CeremonyBridgeUnitX" )}, // セレモニ|橋建設位置X - {0x0BB, new EventFlagLand(0 , 256 , 0187, "CeremonyBridgeUnitZ" )}, // セレモニ|橋建設位置Z - {0x0BC, new EventFlagLand(0 , 1 , 0188, "CeremonyBuildCampSite" )}, // セレモニ|セレモニ開催できる:キャンプ場 - {0x0BD, new EventFlagLand(0 , 1 , 0189, "CeremonyBuildTailor" )}, // セレモニ|廃止予定:置き換え可 - {0x0BE, new EventFlagLand(0 , 1 , 0190, "CeremonyBuildBridge" )}, // セレモニ|セレモニ開催できる:橋 - {0x0BF, new EventFlagLand(0 , 1 , 0191, "CeremonyBuildSlope" )}, // セレモニ|セレモニ開催できる:坂 - {0x0C0, new EventFlagLand(0 , 1 , 0192, "IslandDevQuestRunning" )}, // たぬきち|島の発展Quest実施中 - {0x0C1, new EventFlagLand(0 , 1 , 0193, "IslandDevQuestComplete" )}, // たぬきち|島の発展Quest完了 - {0x0C2, new EventFlagLand(0 , 10000, 0194, "CountTailorAfterBuild" )}, // 仕立て屋|オープンして何日目か - {0x0C3, new EventFlagLand(0 , 10000, 0195, "CountMuseumAfterBuild" )}, // 博物館|オープンして何日目か - {0x0C4, new EventFlagLand(0 , 10000, 0196, "CountMarket1AfterBuild" )}, // まめきちの店|小がオープンして何日目か - {0x0C5, new EventFlagLand(0 , 10000, 0197, "CountMarket2AfterBuild" )}, // まめきちの店|大がオープンして何日目か - {0x0C6, new EventFlagLand(0 , 10000, 0198, "CountOfficeAfterBuild" )}, // 案内所|オープンして何日目か - {0x0C7, new EventFlagLand(0 , 7 , 0199, "CountFirstBridgeAfterBuild" )}, // 初めての橋に言及する会話を表示できる残り日数 - {0x0C8, new EventFlagLand(0 , 7 , 0200, "CountFirstSlopeAfterBuild" )}, // 初めての坂に言及する会話を表示できる残り日数 - {0x0C9, new EventFlagLand(0 , 1 , 0201, "IslandEvaluationUnlock" )}, // しずえ|島の評価島全体で解禁 - {0x0CA, new EventFlagLand(0 , 1 , 0202, "IslandEvaluationClearTkkLive" )}, // しずえ|島の評価がとたけけライブ発生基準をクリアした - {0x0CB, new EventFlagLand(0 , 10 , 0203, "HaveHousingKitCount" )}, // たぬきち|島の住人が所持ているハウジングキットの数 - {0x0CC, new EventFlagLand(0 , 1 , 0204, "BridgeBuilt" )}, // 橋を作ったことがある - {0x0CD, new EventFlagLand(0 , 1 , 0205, "SlopeBuilt" )}, // 坂を作ったことがある - {0x0CE, new EventFlagLand(0 , 3 , 0206, "BeyRequireFishSize" )}, // 来訪新うおまさ|クエスト対象のサカナサイズ - {0x0CF, new EventFlagLand(0 , 1 , 0207, "TanuportAmiiboUnlock" )}, // タヌポート|amiibo関連機能を解禁 - {0x0D8, new EventFlagLand(0 , 1 , 0216, "SpnVisitMainField" )}, // パニエル|メインフィールドに出現 - {0x0D9, new EventFlagLand(0 , 1 , 0217, "ChangePlazaFtrToNormal" )}, // 広場の序盤配置家具を撤去 - {0x0DA, new EventFlagLand(0 , 1 , 0218, "SetPrologueBonfire" )}, // 序盤シーケンス|イベント用キャンプファイア設置 - {0x0DB, new EventFlagLand(0 , 1 , 0219, "ImmQ_A_OutdoorPattern" )}, // 移住Quest|住宅A|外置き家具パターンがAかBか? - {0x0DC, new EventFlagLand(0 , 1 , 0220, "ImmQ_B_OutdoorPattern" )}, // 移住Quest|住宅B|外置き家具パターンがAかBか? - {0x0DD, new EventFlagLand(0 , 1 , 0221, "ImmQ_C_OutdoorPattern" )}, // 移住Quest|住宅C|外置き家具パターンがAかBか? - {0x0DE, new EventFlagLand(0 , 1 , 0222, "TkkFirstLiveReserved" )}, // とたけけ|初ライブ当日か? - {0x0DF, new EventFlagLand(0 , 2 , 0223, "BirthdayBbsVariation2" )}, // 誕生日の告知を掲示板に前回書き込んだときのバリエーション2人用 - {0x0E0, new EventFlagLand(0 , 1 , 0224, "AllowNpcGroupActivity" )}, // NPCの広場行動(集団)が許可されたか - {0x0E1, new EventFlagLand(0 , 1 , 0225, "TanuportAmiiboCampUnlock" )}, // タヌポート|amiiboキャンプ場呼び出しが解禁可 - {0x0E2, new EventFlagLand(0 , 1 , 0226, "PickedUpMessageBottle" )}, // 最初のメッセージボトルが拾われた - {0x0E3, new EventFlagLand(0 , 10 , 0227, "CountAppE_RepTalk" )}, // 一般NPC島評判UP応援アプローチ発生(アイテムもらった)回数カウント - {0x0E4, new EventFlagLand(0 , 10 , 0228, "FlwLilyGrowCounter" )}, // スズラン|発生率決定カウンタ - {0x0E5, new EventFlagLand(0 , 1 , 0229, "FlwLilyFirstGrow" )}, // スズラン|島に発生したことがある? - {0x0E6, new EventFlagLand(0 , 1 , 0230, "CampFirstCamperVisit" )}, // キャンプ場|最初のキャンプ場客が滞在中か? - {0x0E7, new EventFlagLand(0 , 1 , 0231, "RcmShopMaterial_Wood" )}, // まめきち|木材提供済? - {0x0E8, new EventFlagLand(0 , 1 , 0232, "RcmShopMaterial_HardWood" )}, // まめきち|かたい木材提供済? - {0x0E9, new EventFlagLand(0 , 1 , 0233, "RcmShopMaterial_SoftWood" )}, // まめきち|やわらかい木材提供済? - {0x0EA, new EventFlagLand(0 , 1 , 0234, "RcmShopMaterial_Iron" )}, // まめきち|鉄鉱石提供済? - {0x0EB, new EventFlagLand(0 , 1 , 0235, "RcmShopMaterialComplete" )}, // まめきち|すべての資材が揃った - {0x0EC, new EventFlagLand(0 , 1 , 0236, "DailyQuestFivePointDay" )}, // 日課の5倍ポイントデーか? - {0x0ED, new EventFlagLand(0 , 1 , 0237, "ReportFirstCamperAboutSetHousing" )}, // キャンプ場|最初のキャンプ場客に家の予定地セットの報告した - {0x0EE, new EventFlagLand(0 , 1 , 0238, "RcoRcmTalkingAboutStoreMaterial" )}, // たぬきち&まめきち|商店建設資材の相談会話(初回)発生した - {0x0EF, new EventFlagLand(0 , 1 , 0239, "PAnnounceRcoCalling" )}, // 島内放送|放送中の入電イベント初回発生済 - {0x0F1, new EventFlagLand(0 , 1 , 0241, "PAnnounceCeremony1st" )}, // 島内放送|初めてセレモニーの告知した - {0x0F2, new EventFlagLand(0 , 1 , 0242, "PAnnounceCeremony1stToday" )}, // 島内放送|初めてセレモニーの告知入った当日のみON - {0x0F3, new EventFlagLand(0 , 1 , 0243, "CampSiteBuiltToday" )}, // キャンプ場が建った当日 - {0x0F4, new EventFlagLand(0 , 10000, 0244, "CountCampSiteAfterBuild" )}, // キャンプ場|オープンして何日目か - {0x0F5, new EventFlagLand(0 , 1 , 0245, "IslandLocalFruitApple" )}, // 島の特産フルーツがリンゴならON - {0x0F6, new EventFlagLand(0 , 1 , 0246, "IslandLocalFruitOrange" )}, // 島の特産フルーツがオレンジならON - {0x0F7, new EventFlagLand(0 , 1 , 0247, "IslandLocalFruitPear" )}, // 島の特産フルーツがナシならON - {0x0F8, new EventFlagLand(0 , 1 , 0248, "IslandLocalFruitPeach" )}, // 島の特産フルーツがモモならON - {0x0F9, new EventFlagLand(0 , 1 , 0249, "IslandLocalFruitCherry" )}, // 島の特産フルーツがサクランボならON - {0x0FA, new EventFlagLand(0 , 1 , 0250, "HghPeddlerPurchaceToday" )}, // きぬよ行商|今回の来訪で島の誰かが商品購入した? - {0x0FB, new EventFlagLand(0 , 1 , 0251, "PAnnounceKkProject" )}, // 島内放送|とたけけプロジェクトの予告発生した? - {0x0FC, new EventFlagLand(0 , 1 , 0252, "TownNewsHeardEventStarted" )}, // 島内放送|イベント開始済み村内放送を聞いた? - {0x0FD, new EventFlagLand(0 , 999 , 0253, "SzaIslandEvaluationBeforeLife" )}, // しずえ|島の環境:前回の「生活」ポイント - {0x0FE, new EventFlagLand(0 , 999 , 0254, "SzaIslandEvaluationBeforeNatural" )}, // しずえ|島の環境:前回の「自然」ポイント - {0x0FF, new EventFlagLand(0 , 5000 , 0255, "FishNetHostCatchNumResult" )}, // 通信開始時にネットホストのプレイヤーが今まで捕まえたサカナの数 - {0x100, new EventFlagLand(0 , 10 , 0256, "SzaIslandEvaluationBeforeDevelopment" )}, // しずえ|島の環境:前回の「発展」要素 - {0x101, new EventFlagLand(0 , 1 , 0257, "SzaIslandEvaluationTodayRankUpdate" )}, // しずえ|島の環境:今日のポイント更新したらON - {0x102, new EventFlagLand(0 , 1 , 0258, "SzaIslandEvaluationImprovementLifeToday" )}, // しずえ|島の環境:前回島内放送より「生活」ポイント向上 - {0x103, new EventFlagLand(0 , 1 , 0259, "SzaIslandEvaluationImprovementNaturalToday" )}, // しずえ|島の環境:前回島内放送より「自然」ポイント向上 - {0x104, new EventFlagLand(0 , 1 , 0260, "SzaIslandEvaluationImprovementDevelopToday" )}, // しずえ|島の環境:前回島内放送より発展要素が増えた - {0x105, new EventFlagLand(0 , 1 , 0261, "AppE_WelcomoMigrants_AN" )}, // AppE_WelcomoMigrants_AN発生した - {0x106, new EventFlagLand(0 , 1 , 0262, "AppE_WelcomoMigrants_HA" )}, // AppE_WelcomoMigrants_HA発生した - {0x107, new EventFlagLand(0 , 1 , 0263, "TkkFirstLiveSubPlayer" )}, // とたけけ|2人目以降のプレイヤーが初ライブを見られる? - {0x108, new EventFlagLand(0 , 1 , 0264, "PortableRadioControl" )}, // けいたいラジオ挙動制御用フラグ - {0x109, new EventFlagLand(0 , 1 , 0265, "Market2Built" )}, // まめつぶ商店が大になった - {0x10A, new EventFlagLand(0 , 1 , 0266, "OwlTentExplainFor1P" )}, // フータ|誰かに棒高跳び&スコップレシピ提供済 - {0x10B, new EventFlagLand(0 , 1 , 0267, "MuseumConstructionToday" )}, // 今日、博物館工事当日であるか? - {0x10C, new EventFlagLand(0 , 1 , 0268, "ShopUnlockAxe" )}, // お店|ショボいオノの店売りを解禁する - {0x10D, new EventFlagLand(0 , 1 , 0269, "FinishMuseumPreparation1stDay" )}, // フータ移住初日に博物館建築条件を達成した - {0x10E, new EventFlagLand(0 , 2 , 0270, "MushroomProbability" )}, // キノコ|発生確率決定フラグ - {0x10F, new EventFlagLand(0 , 3 , 0271, "NNpcContractProbablityAddPoint" )}, // 一般NPC|売地契約補正値 - {0x110, new EventFlagLand(0 , 1 , 0272, "TkkFirstLiveEnable" )}, // とたけけ|初ライブ解禁か? - {0x111, new EventFlagLand(0 , 1 , 0273, "ImmQClearNextDay" )}, // 移住Quest|クリアして1日経ったか? - {0x112, new EventFlagLand(0 , 1 , 0274, "TodayImmQNotClear" )}, // 移住Quest|今日の最初に移住クエスト未クリアだった? - {0x113, new EventFlagLand(0 , 1 , 0275, "NpcDIYScheduleSet" )}, // NPCのDIYスケジュールを決定したか - {0x114, new EventFlagLand(0 , 1 , 0276, "PAnnounceToday" )}, // 今日、村で島内放送が発生した - {0x115, new EventFlagLand(0 , 1 , 0277, "AirportOpen" )}, // 飛行場|オープンしたか? - {0x117, new EventFlagLand(0 , 1 , 0279, "AnyGlobalEventFinished" )}, // いずれかのグローバルイベント日をまたいだ? - {0x118, new EventFlagLand(0 , 1 , 0280, "LostPropertyFound" )}, // 島Pの誰かが落とし物を拾った - {0x119, new EventFlagLand(0 , 1 , 0281, "MuseumFossilComplete" )}, // 博物館_化石部屋コンプ済 - {0x11A, new EventFlagLand(0 , 1 , 0282, "InduceInMysteriTourIslandToday" )}, // 今日ミステリーツアー島で勧誘した - {0x11B, new EventFlagLand(0 , 1 , 0283, "Tutorial1PTentLightON" )}, // 1P島代表のテントの明かりをONにするか? - {0x11C, new EventFlagLand(0 , 9999 , 0284, "PynVisitYear" )}, // ぴょんたろうが来訪した年 - {0x11D, new EventFlagLand(0 , 1 , 0285, "PynVisitToday" )}, // ぴょんたろうが今日来訪NPCとして来訪する - {0x11E, new EventFlagLand(0 , -1 , 0286, "CatchInsectFesGetTotalNum" )}, // ムシ取り大会|全員のムシ取得数 - {0x11F, new EventFlagLand(0 , -1 , 0287, "CatchFishFesGetTotalNum" )}, // つり大会|全員のサカナ取得数 - {0x120, new EventFlagLand(0 , 1 , 0288, "JohnnyQuestFinishFlagIsland" )}, // ジョニー|その日に村で誰かがジョニーを助けたか?(海賊ジョニーでも使用) - {0x121, new EventFlagLand(0 , 10 , 0289, "CampRandomSelectMoveOutNpc" )}, // キャンプ場|ランダム選出転出NPCが何番目の住人か?(0:未抽選/抽選対象なし) - {0x122, new EventFlagLand(0 , 1 , 0290, "CampFireRemoved" )}, // 広場のキャンプファイアー撤去(実際の撤去とは連動してません) - {0x123, new EventFlagLand(0 , 1 , 0291, "WHEREAREN_HHDUnlock" )}, // ウェアラン諸島解禁 - {0x125, new EventFlagLand(0 , 1 , 0293, "UnlockEaster" )}, // BCATにてイースター解禁 - {0x126, new EventFlagLand(0 , 5 , 0294, "MuseumConstruction2" )}, // 博物館1→2(美術部屋追加)への工事中 - {0x127, new EventFlagLand(0 , 1 , 0295, "MuseumGrowupEnable2" )}, // 博物館2(美術部屋追加)への成長条件達成 - {0x130, new EventFlagLand(0 , 1 , 0304, "OwlWantsPainting" )}, // フータの絵画クエストを開始した - {0x131, new EventFlagLand(0 , 10 , 0305, "CampTodaySelectMoveOutNpc" )}, // キャンプ場|強制転出NPCが何番目の住人か?(0:未抽選/抽選対象なし) - {0x132, new EventFlagLand(0 , 1 , 0306, "Museum3Built" )}, // 博物館②(美術部屋追加)完成 - {0x133, new EventFlagLand(0 , 1 , 0307, "Museum3BuiltToday" )}, // 博物館②(美術部屋追加)完成当日か? - {0x134, new EventFlagLand(0 , 10000, 0308, "CountMuseum2AfterBuild" )}, // 博物館②(美術部屋追加)|オープンして何日目か - {0x135, new EventFlagLand(0 , 1 , 0309, "Museum2ConstructionToday" )}, // 今日、博物館②(美術部屋追加)工事当日であるか? - {0x136, new EventFlagLand(0 , 1 , 0310, "GrowUpAfterPatch1_1" )}, // 1.1適用して成長処理をした - {0x137, new EventFlagLand(0 , 1 , 0311, "GrowUpAfterPatch1_2" )}, // 1.2適用して成長処理をした - {0x138, new EventFlagLand(0 , 1 , 0312, "GrowUpAfterPatch1_3" )}, // 1.3適用して成長処理をした - {0x139, new EventFlagLand(0 , 1 , 0313, "GrowUpAfterPatch1_4" )}, // 1.4適用して成長処理をした - {0x13A, new EventFlagLand(0 , 1 , 0314, "GrowUpAfterPatch2_0" )}, // 2.0適用して成長処理をした - {0x13B, new EventFlagLand(0 , 1 , 0315, "EarthdaySloFirstVisit" )}, // アースデーの初回レイジを予約した - {0x13C, new EventFlagLand(0 , 1 , 0316, "OwlFoundDiveFish" )}, // フータ|誰かが海の幸を見せたことがある - {0x13D, new EventFlagLand(0 , 1 , 0317, "SloPeddlerPurchaceToday" )}, // レイジ行商|今回の来訪で島の誰かが商品購入した? - {0x13E, new EventFlagLand(0 , 1 , 0318, "FoxPreVisitToday" )}, // つねきちが今日事前来訪する - {0x13F, new EventFlagLand(0 , 1 , 0319, "AnyPlayerHouseBuilt" )}, // 住人の誰かのマイホームが1度でも建ったことがある - {0x140, new EventFlagLand(0 , 50 , 0320, "MuseumFishStampRackLotID1" )}, // 国際ミュージアム|1つ目のサカナのスタンプ台ID - {0x141, new EventFlagLand(0 , 50 , 0321, "MuseumFishStampRackLotID2" )}, // 国際ミュージアム|2つ目のサカナのスタンプ台ID - {0x142, new EventFlagLand(0 , 50 , 0322, "MuseumFishStampRackLotID3" )}, // 国際ミュージアム|3つ目のサカナのスタンプ台ID - {0x143, new EventFlagLand(0 , 50 , 0323, "MuseumInsectStampRackLotID1" )}, // 国際ミュージアム|1つ目のムシのスタンプ台ID - {0x144, new EventFlagLand(0 , 50 , 0324, "MuseumInsectStampRackLotID2" )}, // 国際ミュージアム|2つ目のムシのスタンプ台ID - {0x145, new EventFlagLand(0 , 50 , 0325, "MuseumInsectStampRackLotID3" )}, // 国際ミュージアム|3つ目のムシのスタンプ台ID - {0x146, new EventFlagLand(0 , 50 , 0326, "MuseumFossilStampRackLotID1" )}, // 国際ミュージアム|1つ目のかせきのスタンプ台ID - {0x147, new EventFlagLand(0 , 50 , 0327, "MuseumFossilStampRackLotID2" )}, // 国際ミュージアム|2つ目のかせきのスタンプ台ID - {0x148, new EventFlagLand(0 , 50 , 0328, "MuseumFossilStampRackLotID3" )}, // 国際ミュージアム|3つ目のかせきのスタンプ台ID - {0x149, new EventFlagLand(0 , 1 , 0329, "AOC_EventFlag_000" )}, // AOC同期フラグ| 000 Compass - {0x14A, new EventFlagLand(0 , 1 , 0330, "AOC_EventFlag_001" )}, // AOC同期フラグ| 001 NSO加入特典 - {0x14C, new EventFlagLand(0 , 1 , 0332, "FoxPreVisitReserve" )}, // 事前来訪つねきちを翌日に予約する - {0x14D, new EventFlagLand(0 , 1 , 0333, "FoxMovedToMarket" )}, // つねきち|来訪時にフィールドから船へ移動した - {0x14E, new EventFlagLand(0 , 1 , 0334, "FoxAndShipReserve" )}, // つねきち船+フィールドを予約する - {0x14F, new EventFlagLand(0 , 1 , 0335, "BCAT_EventFlag_002" )}, // 国際ミュージアム解禁 - {0x150, new EventFlagLand(0 , 1 , 0336, "BCAT_EventFlag_004" )}, // ハーベスト解禁 - {0x151, new EventFlagLand(0 , 1 , 0337, "BCAT_EventFlag_001" )}, // メーデー解禁 - {0x152, new EventFlagLand(0 , 1 , 0338, "BCAT_EventFlag_003" )}, // ジューンブライド解禁 - {0x157, new EventFlagLand(0 , 1 , 0343, "FoxPreVisit1Today" )}, // つねきち1回目の事前来訪当日 - {0x158, new EventFlagLand(0 , 1 , 0344, "FoxPreVisit2Today" )}, // つねきち2回目の事前来訪当日 - {0x159, new EventFlagLand(0 , 1 , 0345, "EarthdaySloFirstVisitToday" )}, // 今日がアースデーの初回レイジ来訪日 - {0x15A, new EventFlagLand(0 , 1 , 0346, "IsDreamingBed" )}, // ゆめみ用ベッドある? - {0x15B, new EventFlagLand(0 , 1 , 0347, "UnlockJuneBrideSeq" )}, // ゲーム進行的にジューンブライド解禁 - {0x15C, new EventFlagLand(0 , -1 , 0348, "RandomKey1" )}, // ランダムキー1 - {0x15D, new EventFlagLand(0 , -1 , 0349, "RandomKey2" )}, // ランダムキー2 - {0x15E, new EventFlagLand(0 , -1 , 0350, "RandomKey3" )}, // ランダムキー3 - {0x15F, new EventFlagLand(0 , -1 , 0351, "RandomKey4" )}, // ランダムキー4 - {0x160, new EventFlagLand(0 , 1 , 0352, "FoxPreVisitAlreadyBuyToday" )}, // つねきち|今日誰かが事前来訪中に美術品を買った - {0x161, new EventFlagLand(0 , 1 , 0353, "RcoHasResolvedMoveKitBug" )}, // いせつキットバグを解消したか - {0x162, new EventFlagLand(0 , 1 , 0354, "TapDreamEnable" )}, // ゆめみ|ゆめみ機能解禁か? - {0x165, new EventFlagLand(0 , 1 , 0357, "GulBVisitEnable" )}, // 海賊ジョニーが来訪する条件を満たしたか - {0x166, new EventFlagLand(0 , 200 , 0358, "PokiRate" )}, // x)ポキの両替レート - {0x167, new EventFlagLand(0 , 9999 , 0359, "FireworksAddBbsYear" )}, // 花火大会予告の掲示板書き込みをした年 - {0x16A, new EventFlagLand(0 , 1 , 0362, "EnableMyDream" )}, // ゆめみ|現在、自分の島の夢を提供中か? - {0x16B, new EventFlagLand(0 , 1 , 0363, "JohnnyInvisible" )}, // ジョニー非表示状態か - {0x16C, new EventFlagLand(0 , 1 , 0364, "DreamUploadPlayerHaveCreaterID" )}, // ゆめみ|夢の最終更新者がMyDesignショーケースの作者IDを持ってるか? - {0x16D, new EventFlagLand(0 , 5000 , 0365, "DiveFishNetHostCatchNumResult" )}, // 通信開始時にネットホストのプレイヤーが今までに捕まえた海の幸の数 - {0x16E, new EventFlagLand(0 , 9999 , 0366, "HalloweenSloVisitYear" )}, // ハロウィンの初回レイジを予約した年 - {0x16F, new EventFlagLand(0 , 1 , 0367, "HalloweenSloVisitToday" )}, // 今日がハロウィンのレイジ来訪日 - {0x171, new EventFlagLand(0 , 1 , 0369, "GrowUpAfterPatch1_5" )}, // 1.5適用して成長処理をした - {0x172, new EventFlagLand(0 , 1 , 0370, "NeedUpdatePassword" )}, // セーブデータ復元後のパスワード更新必要 - {0x173, new EventFlagLand(0 , 1 , 0371, "IsHalloweenLessThanThreeDays" )}, // ハロウィン3日前以内か? - {0x174, new EventFlagLand(0 , 1 , 0372, "GrowUpAfterPatch1_6" )}, // 1.6適用して成長処理をした - {0x175, new EventFlagLand(0 , 1 , 0373, "IslandProducedByPlayerMoving" )}, // プレイヤーだけ引越し|プレイヤーだけ引越しによって作られた島か? - {0x176, new EventFlagLand(0 , 1 , 0374, "EventObjFlag0" )}, // イベントオブジェフラグ0 - {0x179, new EventFlagLand(0 , 4 , 0377, "HarvestProgress" )}, // ハーベスト|完成した料理の数(島単位) - {0x17A, new EventFlagLand(0 , 1 , 0378, "PlayerMovingEnableShopMaterialCollect" )}, // プレイヤーだけ引越し|お店の資材集め解禁していいか? - {0x17B, new EventFlagLand(0 , 1 , 0379, "SecondPublicAnnouncement" )}, // 2回目島内放送の発生が必要か? - {0x17C, new EventFlagLand(0 , 1 , 0380, "HarvestAfterTerm" )}, // ハーベスト|アフター期間か? - {0x17D, new EventFlagLand(0 , 1 , 0381, "FinishTreasureQuestByRollback" )}, // 宝探しクエストが通信ロールバックで終了した - {0x17E, new EventFlagLand(0 , 1 , 0382, "HarvestHQDish1Island" )}, // ハーベスト|島の誰かが料理1クラムチャウダーの隠し食材納めた? - {0x17F, new EventFlagLand(0 , 1 , 0383, "HarvestHQDish2Island" )}, // ハーベスト|島の誰かが料理2パンプキンパイの隠し食材納めた? - {0x180, new EventFlagLand(0 , 1 , 0384, "HarvestHQDish3Island" )}, // ハーベスト|島の誰かが料理3グラタンの隠し食材納めた? - {0x181, new EventFlagLand(0 , 1 , 0385, "HarvestHQDish4Island" )}, // ハーベスト|島の誰かが料理4サカナのムニエルの隠し食材納めた? - {0x182, new EventFlagLand(0 , 1 , 0386, "IsDisclosedMyDream" )}, // ゆめみ|現在、自分の島の夢をおまかせに公開中か? - {0x183, new EventFlagLand(0 , 22 , 0387, "HarvestTukIngredient2_2" )}, // ハーベスト|必要食材2-2 - {0x184, new EventFlagLand(0 , 22 , 0388, "HarvestTukIngredient3_1" )}, // ハーベスト|必要食材3-1 - {0x185, new EventFlagLand(0 , 22 , 0389, "HarvestTukIngredient3_2" )}, // ハーベスト|必要食材3-2 - {0x186, new EventFlagLand(0 , 22 , 0390, "HarvestTukIngredient4_2" )}, // ハーベスト|必要食材4-2 - {0x187, new EventFlagLand(0 , 22 , 0391, "HarvestTukHideIngredient2_1" )}, // ハーベスト|隠し食材2-1 - {0x188, new EventFlagLand(0 , 22 , 0392, "HarvestTukHideIngredient2_2" )}, // ハーベスト|隠し食材2-2 - {0x189, new EventFlagLand(0 , 5 , 0393, "ReputaionMyIsland" )}, // ゆめみ|現在の自分の島の評判値 - {0x18C, new EventFlagLand(0 , 9999 , 0396, "LastPlayXmasYear" )}, // 最後にプレイしたクリスマスの年 - {0x18D, new EventFlagLand(0 , 1 , 0397, "ShopSelectChristmasFtr" )}, // クリスマスおもちゃ家具抽選を今日したか - {0x18E, new EventFlagLand(0 , 1 , 0398, "IsUploadDisclosedMyDream" )}, // ゆめみ|オマカセ公開で初回更新しなかったか? - {0x18F, new EventFlagLand(0 , 1 , 0399, "TkkFirstLiveNow" )}, // とたけけ|初ライブステージか? - {0x190, new EventFlagLand(0 , 1 , 0400, "ChristmasFtrFirstRound" )}, // クリスマス|おもちゃ家具の商品抽選が1巡したか - {0x191, new EventFlagLand(0 , 9999 , 0401, "HarvestFestivalAddBbsYear" )}, // ハーベストフェスティバル予告の掲示板書き込みをした年 - {0x192, new EventFlagLand(0 , 1 , 0402, "GrowUpAfterPatch1_7" )}, // 1.7適用して成長処理をした - {0x193, new EventFlagLand(0 , 9999 , 0403, "XmasEveAddBbsYear" )}, // クリスマス予告の掲示板書き込みをした年 - {0x194, new EventFlagLand(0 , 1 , 0404, "BCAT_EventFlag_005" )}, // クリスマス準備期間解禁 - {0x195, new EventFlagLand(0 , -1 , 0405, "RandomKey5" )}, // ランダムキー5 - {0x196, new EventFlagLand(0 , 1 , 0406, "ShopSocksFlag" )}, // かべかけソックス当選済み - {0x197, new EventFlagLand(0 , -1 , 0407, "ShopHeartChocoSelect" )}, // ハートのチョコレート抽選済みカラバリ - {0x198, new EventFlagLand(0 , -1 , 0408, "ShopHeartFlowerSelect" )}, // ハートのバラブーケ抽選済みカラバリ - {0x199, new EventFlagLand(0 , -1 , 0409, "RandomKey6" )}, // ランダムキー6 - {0x19A, new EventFlagLand(0 , -1 , 0410, "RandomKey7" )}, // ランダムキー7 - {0x19B, new EventFlagLand(0 , -1 , 0411, "RandomKey8" )}, // ランダムキー8 - {0x19C, new EventFlagLand(0 , 1 , 0412, "BCAT_EventFlag_006" )}, // クリスマスイブ解禁 - {0x19D, new EventFlagLand(0 , 1 , 0413, "BCAT_EventFlag_007" )}, // カーニバル本番、バレンタイン本番解禁 - {0x19E, new EventFlagLand(0 , 1 , 0414, "BCAT_EventFlag_008" )}, // マリオコラボ解禁 - {0x19F, new EventFlagLand(0 , 1 , 0415, "GrowUpAfterPatch1_8" )}, // 1.8適用して成長処理をした - {0x1A0, new EventFlagLand(0 , 1 , 0416, "GrowUpAfterPatch1_9" )}, // 1.9適用して成長処理をした - {0x1A1, new EventFlagLand(0 , -1 , 0417, "RandomKey9" )}, // ランダムキー9 - {0x1A2, new EventFlagLand(0 , 1 , 0418, "BCAT_EventFlag_009" )}, // イースター2年目準備解禁 - {0x1A3, new EventFlagLand(0 , 9999 , 0419, "ValentineAddBbsYear" )}, // バレンタイン予告の掲示板書き込みをした年 - {0x1A4, new EventFlagLand(0 , 9999 , 0420, "CarnivalAddBbsYear" )}, // カーニバル予告の掲示板書き込みをした年 - {0x1A5, new EventFlagLand(0 , 1 , 0421, "CarnivalNpcFeatherColorDecided" )}, // カーニバル|NPCが欲しがる羽の色決定済み - {0x1A6, new EventFlagLand(0 , 1 , 0422, "CarnivalEventPlazaNpcWander" )}, // カーニバル|広場行動NPCがぶらつくか - {0x1AD, new EventFlagLand(0 , 1 , 0429, "BCAT_EventFlag_010" )}, // イースター2年目本番解禁 - {0x1AE, new EventFlagLand(0 , -1 , 0430, "RandomKey10" )}, // ランダムキー10 - {0x1B5, new EventFlagLand(0 , 1 , 0437, "AOC_EventFlag_002" )}, // AOC同期フラグ| 002 1.9.0NSO加入特典 - {0x1B6, new EventFlagLand(0 , 1 , 0438, "BCAT_EventFlag_011" )}, // ジューンブライド2年目解禁 - {0x1B7, new EventFlagLand(0 , -1 , 0439, "RandomKey11" )}, // ランダムキー11 - {0x1B8, new EventFlagLand(0 , 50 , 0440, "MuseumArtStampRackLotID1" )}, // 国際ミュージアム|1つ目の美術品のスタンプ台ID - {0x1B9, new EventFlagLand(0 , 50 , 0441, "MuseumArtStampRackLotID2" )}, // 国際ミュージアム|2つ目の美術品のスタンプ台ID - {0x1BA, new EventFlagLand(0 , 50 , 0442, "MuseumArtStampRackLotID3" )}, // 国際ミュージアム|3つ目の美術品のスタンプ台ID - {0x1BB, new EventFlagLand(0 , 1 , 0443, "v200_Enabled_ChangeRegulation" )}, // 条例が解禁した - {0x1BC, new EventFlagLand(0 , 1 , 0444, "RegulationType1" )}, // 美しい島条例発動中 - {0x1BD, new EventFlagLand(0 , 1 , 0445, "RegulationType2" )}, // 朝活条例発動中 - {0x1BE, new EventFlagLand(0 , 1 , 0446, "RegulationType3" )}, // 夜活条例発動中 - {0x1BF, new EventFlagLand(0 , 1 , 0447, "RegulationType4" )}, // 景気アップ条例発動中 - {0x1C0, new EventFlagLand(0 , 5 , 0448, "ReserveRegulation" )}, // 予約中の条例 - {0x1C1, new EventFlagLand(0 , 5 , 0449, "TodayChangeRegulation" )}, // 今日変更した条例 - {0x1C2, new EventFlagLand(0 , 1 , 0450, "MuseumCafeConstruction_1_Confirm" )}, // 博物館カフェ増築|①工事決定(翌朝工事へ) - {0x1C3, new EventFlagLand(0 , 1 , 0451, "GyroidCommuneFlag" )}, // チャリティーハニワくん|目標額を達成した? - {0x1C4, new EventFlagLand(0 , 8 , 0452, "GyroidCommuneDonationCount" )}, // チャリティーハニワくん|今日どのハニワくんが目標額達成した? - {0x1C5, new EventFlagLand(0 , 1 , 0453, "GyroidCommuneOtherFlag" )}, // チャリティーハニワくん|目標額を達成したハニワがいる? - {0x1C6, new EventFlagLand(0 , -1 , 0454, "WeedCount" )}, // 村全体に生えている雑草の本数 - {0x1C7, new EventFlagLand(0 , 1 , 0455, "MuseumCafeConstruction_2_ConstructionDay" )}, // 博物館カフェ増築|②工事当日(今日一日工事状態) - {0x1C8, new EventFlagLand(0 , 2 , 0456, "CommuneSloDonation" )}, // コミューン島レイジ用募金状態 - {0x1C9, new EventFlagLand(0 , 2 , 0457, "CommuneCmlDonation" )}, // コミューン島レローラン用募金状態 - {0x1CA, new EventFlagLand(0 , 2 , 0458, "CommuneFoxDonation" )}, // コミューン島つねきち用募金状態 - {0x1CB, new EventFlagLand(0 , 2 , 0459, "CommuneBptDonation" )}, // コミューン島ハッケミィ用募金状態 - {0x1CC, new EventFlagLand(0 , 2 , 0460, "CommuneSkkDonation" )}, // コミューン島シャンク用募金状態 - {0x1CD, new EventFlagLand(0 , 2 , 0461, "CommuneAlpDonation" )}, // コミューン島リサカイゾー用募金状態 - {0x1CE, new EventFlagLand(0 , 1 , 0462, "MuseumCafeConstruction_3_OpenDay" )}, // 博物館カフェ増築|③オープン当日 - {0x1CF, new EventFlagLand(0 , 1 , 0463, "MuseumCafeConstruction_4_Opened" )}, // 博物館カフェ増築|④オープン済(当日含む) - {0x1D0, new EventFlagLand(0 , 10000, 0464, "MuseumCafeConstruction_5_OpenDaysCount" )}, // 博物館カフェ増築|⑤オープンして何日目か(初日は1) - {0x1D1, new EventFlagLand(0 , 1 , 0465, "ReserveCommuneSloOpenEvent" )}, // コミューン島レイジ開店イベント予約 - {0x1D2, new EventFlagLand(0 , 1 , 0466, "EventObjFlag1" )}, // イベントオブジェフラグ1 - {0x1D3, new EventFlagLand(0 , 1 , 0467, "EventObjFlag2" )}, // イベントオブジェフラグ2 - {0x1D4, new EventFlagLand(0 , 5 , 0468, "MuseumConstruction3" )}, // 博物館2→3(カフェ増築)への工事中 - {0x1D5, new EventFlagLand(0 , 1 , 0469, "CommuneExpanded" )}, // コミューン|コミューン島が拡張した - {0x1D6, new EventFlagLand(0 , 1 , 0470, "ReserveCommuneCmlOpenEvent" )}, // コミューン島ローラン開店イベント予約 - {0x1D7, new EventFlagLand(0 , 1 , 0471, "ReserveCommuneFoxOpenEvent" )}, // コミューン島つねきち開店イベント予約 - {0x1D8, new EventFlagLand(0 , 1 , 0472, "ReserveCommuneBptOpenEvent" )}, // コミューン島ハッケミィ開店イベント予約 - {0x1D9, new EventFlagLand(0 , 1 , 0473, "ReserveCommuneSkkOpenEvent" )}, // コミューン島シャンク開店イベント予約 - {0x1DA, new EventFlagLand(0 , 1 , 0474, "ReserveCommuneAlpOpenEvent" )}, // コミューン島リサカイゾー開店イベント予約 - {0x1DB, new EventFlagLand(0 , -1 , 0475, "MuseumCafeAmiiboCustomer" )}, // 喫茶ハトの巣|Amiiboで呼び出したNPC - {0x1DC, new EventFlagLand(0 , 1 , 0476, "SloWeedingFlag" )}, // レイジ|今日草むしりサービス頼んだ? - {0x1DD, new EventFlagLand(0 , 1 , 0477, "GrowUpAfterPatch1_10" )}, // 1.10適用して成長処理をした - {0x1DE, new EventFlagLand(0 , 1 , 0478, "GrowUpAfterPatch1_11" )}, // 1.11適用して成長処理をした - {0x1DF, new EventFlagLand(0 , 2 , 0479, "RadioGymnasticsBbsFlag" )}, // ラジオ体操の掲示板書き込みをした? - {0x1E0, new EventFlagLand(0 , 1 , 0480, "BCAT_EventFlag_012" )}, // ハロウィン2年目解禁 - {0x1E1, new EventFlagLand(0 , -1 , 0481, "RandomKey12" )}, // ランダムキー12 - {0x1E2, new EventFlagLand(0 , 1 , 0482, "CompleteCommuneExpandEvent" )}, // コミューン|コミューン島が拡張したイベントを誰かが完了したか - {0x1E3, new EventFlagLand(0 , 9999 , 0483, "MayDayAddBbsYear" )}, // メーデー予告の掲示板書き込みをした年 - {0x1E4, new EventFlagLand(0 , -1 , 0484, "MuseumCafeCheckedTimeZone" )}, // 喫茶ハトの巣|ランダム来訪一般NPCチェックした時間帯 - {0x1E5, new EventFlagLand(0 , 3 , 0485, "MuseumCafeRandomVisitSp_hgs" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(あさみ) - {0x1E6, new EventFlagLand(0 , 3 , 0486, "MuseumCafeRandomVisitSp_hgh" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(きぬよ) - {0x1E7, new EventFlagLand(0 , 3 , 0487, "MuseumCafeRandomVisitSp_doc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ロドリー) - {0x1E8, new EventFlagLand(0 , 3 , 0488, "MuseumCafeRandomVisitSp_boc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ウリ) - {0x1E9, new EventFlagLand(0 , 3 , 0489, "MuseumCafeRandomVisitSp_mol" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(リセットさん) - {0x1EA, new EventFlagLand(0 , 3 , 0490, "MuseumCafeRandomVisitSp_mob" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ラケットさん) - {0x1EB, new EventFlagLand(0 , 3 , 0491, "MuseumCafeRandomVisitSp_tkkA" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(とたけけ) - {0x1EC, new EventFlagLand(0 , 3 , 0492, "MuseumCafeRandomVisitSp_skk" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(シャンク) - {0x1ED, new EventFlagLand(0 , 3 , 0493, "MuseumCafeRandomVisitSp_cml" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ローラン) - {0x1EE, new EventFlagLand(0 , 3 , 0494, "MuseumCafeRandomVisitSp_hgc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ことの) - {0x1EF, new EventFlagLand(0 , 3 , 0495, "MuseumCafeRandomVisitSp_slo" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(レイジ) - {0x1F0, new EventFlagLand(0 , 3 , 0496, "MuseumCafeRandomVisitSp_ows" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(フーコ) - {0x1F1, new EventFlagLand(0 , 3 , 0497, "MuseumCafeRandomVisitSp_chy" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(レックス) - {0x1F2, new EventFlagLand(0 , 3 , 0498, "MuseumCafeRandomVisitSp_bey" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ジャスティン) - {0x1F3, new EventFlagLand(0 , 1 , 0499, "BCAT_EventFlag_013" )}, // サンクスギビング、ブラックフライデー解禁 - {0x1F4, new EventFlagLand(0 , -1 , 0500, "RandomKey13" )}, // ランダムキー13 - {0x1F5, new EventFlagLand(0 , 2 , 0501, "CommuneTtlDonation" )}, // コミューン島コトブキ用募金状態 - {0x1F6, new EventFlagLand(0 , 1 , 0502, "ReserveCommuneTtlOpenEvent" )}, // コミューン島コトブキ開店イベント予約 - {0x1F7, new EventFlagLand(0 , 1 , 0503, "UnlockGyroidMainField" )}, // ハニワの自然発生が解禁されているか? - {0x1F8, new EventFlagLand(0 , 1 , 0504, "EventObjFlag3" )}, // イベントオブジェフラグ3 - {0x1F9, new EventFlagLand(0 , 9999 , 0505, "HalloweenAddBbsYear" )}, // ハロウィン予告の掲示板書き込みをした年 - {0x1FA, new EventFlagLand(0 , 1 , 0506, "Museum2BuiltSkippedMuseum1" )}, // 博物館①をスキップして博物館②が建った - {0x1FB, new EventFlagLand(0 , 1 , 0507, "FoxAndShipReserveVer2" )}, // つねきち船+フィールドを予約する(Ver2.0.0) - {0x1FC, new EventFlagLand(0 , 1 , 0508, "EverChangedRegulation" )}, // 条例変更直前に発動中の条例があったか? - {0x1FD, new EventFlagLand(0 , 1 , 0509, "ExistIllminations" )}, // 成長処理時点で電飾付の木が一本以上存在しているか? - {0x1FE, new EventFlagLand(0 , 1 , 0510, "ExistSakura" )}, // 成長処理時点で村に桜の木が存在するか? - {0x1FF, new EventFlagLand(0 , 1 , 0511, "ExistBanboo" )}, // 成長処理時点で村に竹の成木が存在するか? - {0x200, new EventFlagLand(0 , 1 , 0512, "ExistOak" )}, // 成長処理時点で村に成木の広葉樹が存在するか? - {0x201, new EventFlagLand(0 , 1 , 0513, "ExistCedar" )}, // 成長処理時点で村に成木の針葉樹が存在するか? - {0x202, new EventFlagLand(0 , 2 , 0514, "FoxCommuneArtStockCount" )}, // つねきち|コミューンで購入されたの美術品の数 - {0x203, new EventFlagLand(0 , 1 , 0515, "PlacementRadioGymnastics" )}, // ラジオ体操用ラジカセ設置 - {0x204, new EventFlagLand(0 , 100 , 0516, "FoxCommuneRealRate" )}, // つねきち|コミューンで美術品を本物に差し替える確率 - {0x205, new EventFlagLand(0 , 2 , 0517, "FoxCommuneRealNum" )}, // つねきち|コミューンで本物の美術品を並べた回数 - {0x206, new EventFlagLand(0 , 3 , 0518, "CatalogShopBigCount" )}, // カタログショッピングで大型の連続ハズレカウント - {0x208, new EventFlagLand(0 , 1 , 0520, "CoffeTakeout" )}, // 喫茶ハトの巣|島の誰かがコーヒーの持ち帰り解禁された? - {0x209, new EventFlagLand(0 , 1 , 0521, "MuseumPosterflagbug" )}, // フータ/博物館コンプポスター|ムシのポスター購入を解禁した? - {0x20A, new EventFlagLand(0 , 1 , 0522, "MuseumPosterflagfish" )}, // フータ/博物館コンプポスター|サカナのポスター購入を解禁した? - {0x20B, new EventFlagLand(0 , 1 , 0523, "MuseumPosterflagfossil" )}, // フータ/博物館コンプポスター|化石のポスター購入を解禁した? - {0x20C, new EventFlagLand(0 , 1 , 0524, "MuseumPosterflagpainting" )}, // フータ/博物館コンプポスター|美術品のポスター購入を解禁した? - {0x20D, new EventFlagLand(0 , 1 , 0525, "MuseumPosterflagsea" )}, // フータ/博物館コンプポスター|海の幸のポスター購入を解禁した? - {0x20E, new EventFlagLand(0 , 1 , 0526, "MuseumPosterTodayflagbug" )}, // フータ/博物館コンプポスター|ムシのポスター送った? - {0x20F, new EventFlagLand(0 , 1 , 0527, "MuseumPosterTodayflagfish" )}, // フータ/博物館コンプポスター|サカナのポスター送った? - {0x210, new EventFlagLand(0 , 1 , 0528, "MuseumPosterTodayflagfossil" )}, // フータ/博物館コンプポスター|かせきのポスター送った? - {0x211, new EventFlagLand(0 , 1 , 0529, "MuseumPosterTodayflagpainting" )}, // フータ/博物館コンプポスター|美術品のポスター送った? - {0x212, new EventFlagLand(0 , 1 , 0530, "MuseumPosterTodayflagsea" )}, // フータ/博物館コンプポスター|海の幸のポスター送った? - {0x213, new EventFlagLand(0 , 1 , 0531, "SzaChangeSymbol" )}, // しずえ|誰かが旗のデザイン変えた? - {0x214, new EventFlagLand(0 , 5 , 0532, "GotFakeArts" )}, // Tips|島全体で贋作購入した個数 - {0x215, new EventFlagLand(0 , 1 , 0533, "VisitGulAFlag" )}, // ジョニーが来訪したフラグ - {0x216, new EventFlagLand(0 , 1 , 0534, "EnableBlackFriday" )}, // ゲーム進行的にブラックフライデー解禁 - {0x217, new EventFlagLand(0 , 1 , 0535, "KppTourStart" )}, // 島内放送|島の誰かにかっぺいツアー開始告知をした - {0x218, new EventFlagLand(0 , 1 , 0536, "KppTourStartToday" )}, // 島内放送|今日が、初めて島の誰かにかっぺいツアー開始告知をした当日 - {0x219, new EventFlagLand(0 , 1 , 0537, "RcoUnlockBridgeSlopePlus2" )}, // たぬきち|橋、坂を追加で2つ作れるようになった? - {0x21A, new EventFlagLand(0 , 1 , 0538, "UnlockCommuneExpandedBGM" )}, // コミューン島|コミューン島拡張BGMが解禁済みか? - {0x21B, new EventFlagLand(0 , 1 , 0539, "CommuneFoxShopGenuine" )}, // コミューン島|つねきちの店で今週本物が並んだ - {0x21C, new EventFlagLand(0 , 1 , 0540, "CommuneSloOpenToday" )}, // コミューン島レイジ開店当日 - {0x21D, new EventFlagLand(0 , 1 , 0541, "UnlockBuyRecipePitfallSeed" )}, // お店|おとしあなのタネのレシピの店売りを解禁するか? - {0x21E, new EventFlagLand(0 , 10 , 0542, "GrowHaniwaPieceNum" )}, // Tips|ハニワのかけらがハニワに成長した個数 - {0x21F, new EventFlagLand(0 , 1 , 0543, "UnlockSzaResetHouse" )}, // しずえ|NPCの家リセット解禁(家コーデが村の誰かのところで解禁) - {0x220, new EventFlagLand(0 , 1 , 0544, "RcoTipsDisableNoticeLoginBonus" )}, // Tips|タヌポートログボ出すの禁止か?(工事当日&大晦日にON) - }; - - private const string Unknown = "???"; - - public static string GetName(ushort index, short count, IReadOnlyDictionary str) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - { - string name = val.Name; - if (str.TryGetValue(name, out var translated)) - name = translated; - return $"{index:00} - {name} = {count}"; - } - return $"{index:00} - {Unknown} = {count}"; - } - - public static string GetName(ushort index, short count) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - return $"{index:00} - {val.Name} = {count}"; - return $"{index:00} - {Unknown} = {count}"; - } + Name = name; + Index = index; + DefaultValue = init; + MaxValue = max; } -} + + public static readonly IReadOnlyDictionary List = new Dictionary + { + {0x000, new EventFlagLand(0 , 1 , 0000, "TodayCreateVillage" )}, // 今日村作成されたか + {0x001, new EventFlagLand(0 , 1 , 0001, "TodayPlayerEmigrate" )}, // 今日プレイヤが移住してきたか? + {0x002, new EventFlagLand(0 , 1 , 0002, "TkkFirstLive" )}, // とたけけ|初ライブを行ったか + {0x003, new EventFlagLand(0 , 1 , 0003, "FinishiPC1Prologue" )}, // PC1の序盤プロローグ完了時にON + {0x004, new EventFlagLand(0 , 1 , 0004, "IsMovingConsultationToPlayer" )}, // NPCが引越相談をした + {0x005, new EventFlagLand(0 , 1 , 0005, "EnableMarketBuild" )}, // まめつぶ商店建築条件満たした + {0x006, new EventFlagLand(0 , 1 , 0006, "ValidateVillageSave" )}, // 村データが有効化された + {0x007, new EventFlagLand(0 , 5 , 0007, "FreeEChatTimes" )}, // 村で告知会話を聞いた回数 + {0x008, new EventFlagLand(0 , 5 , 0008, "FreeFChatTimes" )}, // 村でイベント会話を聞いた回数 + {0x00A, new EventFlagLand(0 , -1 , 0010, "RandomKey" )}, // ランダムキー + {0x00B, new EventFlagLand(0 , 1 , 0011, "DoneMuseumConstruction" )}, // 博物館建築工事完了 + {0x00C, new EventFlagLand(0 , 1 , 0012, "Prologue4BuiltPlayer" )}, // 序盤プレイヤーテント設置したか? + {0x00D, new EventFlagLand(0 , 1 , 0013, "Plorogue4BuiltMuseum" )}, // 博物館|フータテント予定地設置したか? + {0x00E, new EventFlagLand(0 , 1 , 0014, "Prologue4BuiltShop" )}, // 商店の工事看板設置したか? + {0x00F, new EventFlagLand(0 , 1 , 0015, "Prologue4BuiltNpcAN" )}, // 序盤ANテント設置したか? + {0x010, new EventFlagLand(0 , 1 , 0016, "Prologue4BuiltNpcHA" )}, // 序盤HAテント設置したか? + {0x011, new EventFlagLand(0 , 1 , 0017, "TodayStartTown1P" )}, // 1Pが村誕生させた初日か? + {0x012, new EventFlagLand(0 , 1 , 0018, "ShopItemSet" )}, // 商店に商品を置いてよいか? + {0x013, new EventFlagLand(0 , 1 , 0019, "VillageExtensionLevel2" )}, // 村の拡張段階2 + {0x014, new EventFlagLand(0 , 1 , 0020, "RcmGotSignboard" )}, // まめきちが看板を手に入れた + {0x015, new EventFlagLand(0 , 1 , 0021, "InstalledMarketTentSign" )}, // まめきちテントの看板が設置された + {0x016, new EventFlagLand(0 , 1 , 0022, "SandBankDisable" )}, // 中州判定が無効になったか? + {0x017, new EventFlagLand(0 , 1 , 0023, "MarketRemodelingFlag1" )}, // まめきちの店|テント→商店(小)改装決定 + {0x018, new EventFlagLand(0 , 1 , 0024, "MarketOpen1stDay1" )}, // まめきちの店|新装開店当日(商店) + {0x019, new EventFlagLand(0 , 9 , 0025, "SpotPrologueTimes" )}, // 序盤会話を呼んだ回数 + {0x01A, new EventFlagLand(0 , 20000, 0026, "PlazaDonationMoney" )}, // イベント広場寄付金額 + {0x01B, new EventFlagLand(0 , 20 , 0027, "PlazaDonationMaterial" )}, // イベント広場寄付素材数(ねんど) + {0x01C, new EventFlagLand(0 , 1 , 0028, "PlazaDonationFinish" )}, // イベント広場募金集まったか? + {0x01D, new EventFlagLand(0 , 1 , 0029, "EventPlazaBuilt" )}, // イベント広場完成 + {0x01E, new EventFlagLand(0 , 1 , 0030, "SzaGotGyroid" )}, // しずえがハニワくん入手した + {0x01F, new EventFlagLand(0 , 1 , 0031, "PlazaGyroidBuilt" )}, // イベント広場募金ハニワくん設置 + {0x020, new EventFlagLand(0 , 1 , 0032, "MuseumGrowupEnable1" )}, // 博物館成長条件1達成 + {0x021, new EventFlagLand(0 , 5 , 0033, "MuseumConstruction1" )}, // 博物館テント→工事中 + {0x022, new EventFlagLand(0 , 1 , 0034, "Museum2Built" )}, // 博物館①完成 + {0x023, new EventFlagLand(0 , 1 , 0035, "Museum2BuiltToday" )}, // 博物館(建物)①完成当日か? + {0x024, new EventFlagLand(0 , 5000 , 0036, "InsectNetHostCatchNumResult" )}, // 通信開始時にネットホストのプレイヤーが今まで捕まえたムシの数 + {0x025, new EventFlagLand(0 , 1 , 0037, "GlobalEventAvailable" )}, // グローバルイベント解禁 + {0x026, new EventFlagLand(0 , 1 , 0038, "InsectFesFinished" )}, // 島で2回目以降のムシとり大会?(ムシとり大会の日をまたいだ?) + {0x027, new EventFlagLand(0 , 1 , 0039, "MarketRemodelingFlag2" )}, // まめきちの店|商店(小)→倉庫 改装決定 + {0x028, new EventFlagLand(0 , 1 , 0040, "MarketOpen1stDay2" )}, // まめきちの店|新装開店当日(倉庫) + {0x029, new EventFlagLand(0 , 6 , 0041, "RcoMoveReservedKind" )}, // たぬきち|建物移設の予約種類判別カウンタ + {0x02A, new EventFlagLand(0 , 1 , 0042, "QuestReserveStart" )}, // クエスト予約解禁 + {0x02B, new EventFlagLand(0 , -1 , 0043, "VillageDaysCount" )}, // 村の経過日数 + {0x02C, new EventFlagLand(0 , 1 , 0044, "PeddlingAvailableSlo" )}, // 行商解禁済|レイジ + {0x02D, new EventFlagLand(0 , 1 , 0045, "MarketBuilt" )}, // まめつぶ商店が建った + {0x02E, new EventFlagLand(0 , 1 , 0046, "PeddingAvailableBoa" )}, // カブ解禁済|カブリバ + {0x02F, new EventFlagLand(0 , 1 , 0047, "MarketConstruction1" )}, // まめきちの店|テント→商店(小)工事中 + {0x030, new EventFlagLand(0 , 1 , 0048, "MarketConstruction2" )}, // まめきちの店||商店(小)→倉庫 工事中 + {0x031, new EventFlagLand(0 , 1 , 0049, "FirstKabuBuy" )}, // 島の誰かがカブを買ったことがある + {0x032, new EventFlagLand(0 , 1 , 0050, "FirstKabuPattern" )}, // 初回カブ価パターン適用済みフラグ + {0x033, new EventFlagLand(4 , 4 , 0051, "FoxArtStockCount" )}, // つねきち|美術品の在庫 + {0x034, new EventFlagLand(0 , 1 , 0052, "EventPlazaBuiltToday" )}, // イベント広場完成当日 + {0x035, new EventFlagLand(0 , 8 , 0053, "CountNnpcHouseSpaceSet" )}, // 建築予定地を確保し終えた数 + {0x036, new EventFlagLand(0 , 1 , 0054, "GlobalEventReady" )}, // グローバルイベント準備中 + {0x037, new EventFlagLand(0 , 6 , 0055, "BirthdayBbsVariation1" )}, // 誕生日の告知を掲示板に前回書き込んだときのバリエーション1人用 + {0x03A, new EventFlagLand(0 , 1 , 0058, "EnableBuildTownOffice" )}, // 役場建設条件が揃った + {0x03B, new EventFlagLand(0 , 1 , 0059, "BuiltTownOffice" )}, // 案内所完成 + {0x03C, new EventFlagLand(0 , 1 , 0060, "BuiltTownOfficeToday" )}, // 案内所完成当日 + {0x03D, new EventFlagLand(0 , 1 , 0061, "StartBuildingTownOffice" )}, // 役場建設&村長誘致開始可能 + {0x03E, new EventFlagLand(0 , 1111 , 0062, "SzaDonatedItemType" )}, // 役場建設用のアイテム寄贈状況(種類判別用) + {0x03F, new EventFlagLand(0 , 4 , 0063, "SzaDonatedItemCount" )}, // 役場建設用のアイテム寄贈状況(個数判別用) + {0x041, new EventFlagLand(0 , 1 , 0065, "IsNpcIncreased" )}, // NPCが1人でも引越してきたか? + {0x042, new EventFlagLand(0 , 1 , 0066, "MuseumBuilt" )}, // 博物館テントが建った + {0x043, new EventFlagLand(0 , 1 , 0067, "TailorBuilt" )}, // 仕立て屋|仕立て屋が建った + {0x044, new EventFlagLand(0 , 2 , 0068, "IslandKanaType" )}, // 『島』のルビ + {0x045, new EventFlagLand(0 , -1 , 0069, "TodayGlobalEventId" )}, // 今日行われるグローバルイベントのID + {0x046, new EventFlagLand(0 , -1 , 0070, "TodayRegionEventId" )}, // 今日行われるリージョンイベントのID + {0x047, new EventFlagLand(0 , 1 , 0071, "NoncompliantRegionCode" )}, // 非対応の地域設定でセーブしたか? + {0x048, new EventFlagLand(0 , 1 , 0072, "GstTalkAnyone" )}, // ゆうたろう|ゆうたろうと誰か話したことある? + {0x049, new EventFlagLand(0 , 1 , 0073, "OwlFoundFossil" )}, // フータに化石を見せたことがある + {0x04A, new EventFlagLand(0 , 1 , 0074, "MarketSellRecipeScoopStick" )}, // お店|ショボいスコップ、たかとびぼうレシピの店売りを解禁する + {0x04B, new EventFlagLand(0 , 1 , 0075, "TailorConstruction1" )}, // 仕立て屋|予定地→工事中 + {0x04C, new EventFlagLand(0 , 1 , 0076, "FishFesFinished" )}, // 島で2回目以降のつり大会?(つり大会の日をまたいだ?) + {0x04D, new EventFlagLand(0 , 1 , 0077, "HghStayMarket" )}, // きぬよ|商店に来訪中 + {0x04E, new EventFlagLand(0 , 1 , 0078, "EnableHghStayField" )}, // きぬよ|来訪NPCに選んでよいか? + {0x04F, new EventFlagLand(0 , 1 , 0079, "EnableTailorBuild" )}, // 仕立て屋|建築条件を満たした + {0x050, new EventFlagLand(0 , 1 , 0080, "TailorReserved" )}, // 仕立て屋|工事看板(予定地)が建った + {0x051, new EventFlagLand(0 , 1 , 0081, "TailorGetHousingkit" )}, // 仕立て屋|工事看板を受け取った + {0x052, new EventFlagLand(0 , 1 , 0082, "ReportedTaiorReserve" )}, // 仕立て屋|工事看板(予定地)建てたこと報告済み + {0x053, new EventFlagLand(0 , 99 , 0083, "CountTailorBuild" )}, // 仕立て屋|建築条件に関わるカウンタ + {0x054, new EventFlagLand(0 , 10 , 0084, "NNpcPhoneColorChangeCounter" )}, // 一般NPC|スマホ柄が汎用布地に変わるカウンタ + {0x055, new EventFlagLand(0 , 1 , 0085, "RcoEnableBuyHousingKit" )}, // たぬきち|売り土地を探すの選択肢解禁 + {0x056, new EventFlagLand(0 , 99 , 0086, "OpeningSeqBGMChangeCounter" )}, // 序盤シーケンス|BGM切替カウンタ + {0x060, new EventFlagLand(0 , 1 , 0096, "JohnnySitUpFlag" )}, // ジョニー|起きたかフラグ(海賊ジョニーでも使用) + {0x062, new EventFlagLand(0 , 1 , 0098, "AllowNpcInterestActivity" )}, // NPCの認識行動が許可されたか + {0x067, new EventFlagLand(0 , 1 , 0103, "RcoBuildCampsiteOngoing" )}, // たぬきち|キャンプ場設置の依頼を島の誰かが引き受けた + {0x068, new EventFlagLand(0 , 1 , 0104, "RcoBuildCampsiteComplete" )}, // たぬきち|キャンプ場設置の依頼で、誰かが予定地を建てた + {0x06A, new EventFlagLand(0 , 1 , 0106, "RcoMeetFirstVisitorRequest" )}, // たぬきち|1人目の客に会う依頼をしてくるようになる + {0x06B, new EventFlagLand(0 , 1 , 0107, "RcoMeetFirstVisitorOngoing" )}, // たぬきち|1人目の客に会う依頼を島の誰かが引き受けた + {0x06C, new EventFlagLand(0 , 1 , 0108, "RcoMeetFirstVisitorComplete" )}, // たぬきち|1人目のキャンプ客の移住希望の話を、島の誰かが聞いた + {0x06D, new EventFlagLand(0 , 1 , 0109, "RcoBuildFirstVisitorsHousingKitOngoing" )}, // たぬきち|1人目の客のハウジングキットの設置依頼を、島の誰かが受けた + {0x06E, new EventFlagLand(0 , 1 , 0110, "RcoBuildFirstVisitorsHousingKitComplete" )}, // たぬきち|1人目の客のハウジングキットを、島の誰かが設置した + {0x072, new EventFlagLand(15, 15 , 0114, "DonationAmountForMuseum" )}, // 博物館建設のために必要な寄贈の残り数 + {0x073, new EventFlagLand(0 , 1 , 0115, "OfficeConstruction1" )}, // 役場|工事中→役場 + {0x074, new EventFlagLand(0 , 1 , 0116, "JohnnyTalkAnyPlayerFlag" )}, // ジョニー|村の誰か話しかけたか(海賊ジョニー不使用) + {0x076, new EventFlagLand(0 , 1 , 0118, "TkkReturn" )}, // とたけけ|帰ったか? + {0x077, new EventFlagLand(0 , 1 , 0119, "FlightBalloonEnable" )}, // 空飛ぶ風船|発生してよいか? + {0x078, new EventFlagLand(0 , 1 , 0120, "ConfirmedFruit" )}, // フルーツの品種が特定された + {0x079, new EventFlagLand(0 , 1 , 0121, "RctInTent" )}, // つぶきち|たぬきちテントに帰る + {0x07A, new EventFlagLand(0 , 1 , 0122, "GstAppearField" )}, // ゆうたろう|村に出現する + {0x07B, new EventFlagLand(0 , 1 , 0123, "MuseumTentBuiltToday" )}, // 博物館テントオープン当日か? + {0x07C, new EventFlagLand(0 , 1 , 0124, "TailorBuiltToday" )}, // 仕立て屋オープン当日か? + {0x07D, new EventFlagLand(0 , 1 , 0125, "VillageExtensionLevel3" )}, // 村の拡張段階3 + {0x07E, new EventFlagLand(0 , 4 , 0126, "RcoBuildBridgeSlopeStatusCounter" )}, // たぬきち|橋/坂建設工事に関するカウンタ + {0x07F, new EventFlagLand(0 , 2 , 0127, "RcoMoveReservedAnyone" )}, // たぬきち|建物の移設予約カウンタ + {0x080, new EventFlagLand(0 , 1 , 0128, "HgcVisitFlagForTailor" )}, // 仕立て屋商品けってい用ことの来訪フラグ + {0x083, new EventFlagLand(0 , 1 , 0131, "RcoDeleteBridgeSlopeReservedAnyone" )}, // たぬきち|誰かが橋/坂の撤去を予約してる + {0x085, new EventFlagLand(0 , 1 , 0133, "RcoBuildBridgeSlopeSelector" )}, // たぬきち|現在の建設対象が橋/坂どちらか?0橋1坂 + {0x086, new EventFlagLand(0 , 1 , 0134, "RcoIslandRevitilizationRefuse" )}, // たぬきち|島おこし系クエスト断った + {0x087, new EventFlagLand(0 , 1 , 0135, "MessageBottleAvailable" )}, // メッセージボトル漂着が解禁 + {0x088, new EventFlagLand(0 , 1 , 0136, "ImmQ_A_GetHousing" )}, // 移住Quest|住宅A|ハウジングキットもらった + {0x089, new EventFlagLand(0 , 1 , 0137, "ImmQ_B_GetHousing" )}, // 移住Quest|住宅B|ハウジングキットもらった + {0x08A, new EventFlagLand(0 , 1 , 0138, "ImmQ_C_GetHousing" )}, // 移住Quest|住宅C|ハウジングキットもらった + {0x08B, new EventFlagLand(0 , 1 , 0139, "ImmQ_A_SetHousing" )}, // 移住Quest|住宅A|ハウジングキット設置した + {0x08C, new EventFlagLand(0 , 1 , 0140, "ImmQ_B_SetHousing" )}, // 移住Quest|住宅B|ハウジングキット設置した + {0x08D, new EventFlagLand(0 , 1 , 0141, "ImmQ_C_SetHousing" )}, // 移住Quest|住宅C|ハウジングキット設置した + {0x08E, new EventFlagLand(0 , 1 , 0142, "ImmQ_A_Interior1Donate" )}, // 移住Quest|住宅A|屋内家具1寄贈 + {0x08F, new EventFlagLand(0 , 1 , 0143, "ImmQ_B_Interior1Donate" )}, // 移住Quest|住宅B|屋内家具1寄贈 + {0x090, new EventFlagLand(0 , 1 , 0144, "ImmQ_C_Interior1Donate" )}, // 移住Quest|住宅C|屋内家具1寄贈 + {0x091, new EventFlagLand(0 , 1 , 0145, "ImmQ_A_Interior2Donate" )}, // 移住Quest|住宅A|屋内家具2寄贈 + {0x092, new EventFlagLand(0 , 1 , 0146, "ImmQ_B_Interior2Donate" )}, // 移住Quest|住宅B|屋内家具2寄贈 + {0x093, new EventFlagLand(0 , 1 , 0147, "ImmQ_C_Interior2Donate" )}, // 移住Quest|住宅C|屋内家具2寄贈 + {0x094, new EventFlagLand(0 , 1 , 0148, "ImmQ_A_Interior3Donate" )}, // 移住Quest|住宅A|屋内家具3寄贈 + {0x095, new EventFlagLand(0 , 1 , 0149, "ImmQ_B_Interior3Donate" )}, // 移住Quest|住宅B|屋内家具3寄贈 + {0x096, new EventFlagLand(0 , 1 , 0150, "ImmQ_C_Interior3Donate" )}, // 移住Quest|住宅C|屋内家具3寄贈 + {0x097, new EventFlagLand(0 , 1 , 0151, "ImmQ_A_Outdoor1Set" )}, // 移住Quest|住宅A|外置き家具1配置 + {0x098, new EventFlagLand(0 , 1 , 0152, "ImmQ_B_Outdoor1Set" )}, // 移住Quest|住宅B|外置き家具1配置 + {0x099, new EventFlagLand(0 , 1 , 0153, "ImmQ_C_Outdoor1Set" )}, // 移住Quest|住宅C|外置き家具1配置 + {0x09A, new EventFlagLand(0 , 1 , 0154, "ImmQ_A_Outdoor2Set" )}, // 移住Quest|住宅A|外置き家具2配置 + {0x09B, new EventFlagLand(0 , 1 , 0155, "ImmQ_B_Outdoor2Set" )}, // 移住Quest|住宅B|外置き家具2配置 + {0x09C, new EventFlagLand(0 , 1 , 0156, "ImmQ_C_Outdoor2Set" )}, // 移住Quest|住宅C|外置き家具2配置 + {0x09D, new EventFlagLand(0 , 1 , 0157, "ImmQ_A_Outdoor3Set" )}, // 移住Quest|住宅A|外置き家具3配置 + {0x09E, new EventFlagLand(0 , 1 , 0158, "ImmQ_B_Outdoor3Set" )}, // 移住Quest|住宅B|外置き家具3配置 + {0x09F, new EventFlagLand(0 , 1 , 0159, "ImmQ_C_Outdoor3Set" )}, // 移住Quest|住宅C|外置き家具3配置 + {0x0A0, new EventFlagLand(0 , 1 , 0160, "ImmQ_A_Complete" )}, // 移住Quest|住宅A|全工程完了 + {0x0A1, new EventFlagLand(0 , 1 , 0161, "ImmQ_B_Complete" )}, // 移住Quest|住宅B|全工程完了 + {0x0A2, new EventFlagLand(0 , 1 , 0162, "ImmQ_C_Complete" )}, // 移住Quest|住宅C|全工程完了 + {0x0A3, new EventFlagLand(0 , 1 , 0163, "ImmQ_A_Invited" )}, // 移住Quest|移住者A|勧誘した + {0x0A4, new EventFlagLand(0 , 1 , 0164, "ImmQ_B_Invited" )}, // 移住Quest|移住者B|勧誘した + {0x0A5, new EventFlagLand(0 , 1 , 0165, "ImmQ_C_Invited" )}, // 移住Quest|移住者C|勧誘した + {0x0A6, new EventFlagLand(0 , 1 , 0166, "RcmImmQuestOpen" )}, // たぬきち|移住Quest開始できる + {0x0A7, new EventFlagLand(0 , 1 , 0167, "RcmImmQuestRunning" )}, // たぬきち|移住Quest実施中 + {0x0A8, new EventFlagLand(0 , 1 , 0168, "RcmImmQuestComplete" )}, // たぬきち|移住Quest完了 + {0x0A9, new EventFlagLand(0 , 9 , 0169, "JohnnyRequirePartsNum" )}, // ジョニー|必要なパーツの個数(海賊ジョニー不使用) + {0x0AA, new EventFlagLand(0 , 1 , 0170, "ImmQ_A_InteriorDonateNow" )}, // 移住Quest|住宅A|屋内家具を今寄贈した + {0x0AB, new EventFlagLand(0 , 1 , 0171, "ImmQ_B_InteriorDonateNow" )}, // 移住Quest|住宅B|屋内家具の今寄贈した + {0x0AC, new EventFlagLand(0 , 1 , 0172, "ImmQ_C_InteriorDonateNow" )}, // 移住Quest|住宅C|屋内家具の今寄贈した + {0x0AD, new EventFlagLand(0 , 1 , 0173, "RcoRemoveBridgeSlopeSelector" )}, // たぬきち|現在の撤去対象が橋/坂どちらか?0橋1坂 + {0x0AE, new EventFlagLand(0 , 288 , 0174, "CeremonySlopeUnitX" )}, // セレモニ|坂建設位置X + {0x0AF, new EventFlagLand(0 , 256 , 0175, "CeremonySlopeUnitZ" )}, // セレモニ|坂建設位置Z + {0x0B0, new EventFlagLand(0 , 1 , 0176, "RcoNoticeBuildInfomationOffice" )}, // たぬきち|案内所建物建築のお知らせ可能 + {0x0B1, new EventFlagLand(0 , 1 , 0177, "CampSiteBuilt" )}, // キャンプ場が建った + {0x0B2, new EventFlagLand(0 , 1 , 0178, "RcoDeleteBridgeSlopeBuildPlayer" )}, // たぬきち|橋/坂予定地を建てたプレイヤーが削除された + {0x0B3, new EventFlagLand(0 , 100 , 0179, "VisitorPrayStarToday" )}, // 今日村に来たビジタが祈った回数 + {0x0B4, new EventFlagLand(0 , 1 , 0180, "AmiiboCampSiteCall" )}, // 今日amiiboを使ってキャンプ場にNPCを呼んだ + {0x0B5, new EventFlagLand(0 , 1 , 0181, "ImmQ_SetBridge" )}, // 移住Quest|橋の予定地が配置された + {0x0B6, new EventFlagLand(0 , 1 , 0182, "CampQuestInProgress" )}, // キャンプ家具クエスト進行中 + {0x0B7, new EventFlagLand(0 , 1 , 0183, "CampQuestClear" )}, // キャンプ家具クエストクリア済 + {0x0B9, new EventFlagLand(0 , 1 , 0185, "SzaTaled1stTimeAnyPlayer" )}, // 24時間BGMを案内所完成後用に切り替える + {0x0BA, new EventFlagLand(0 , 288 , 0186, "CeremonyBridgeUnitX" )}, // セレモニ|橋建設位置X + {0x0BB, new EventFlagLand(0 , 256 , 0187, "CeremonyBridgeUnitZ" )}, // セレモニ|橋建設位置Z + {0x0BC, new EventFlagLand(0 , 1 , 0188, "CeremonyBuildCampSite" )}, // セレモニ|セレモニ開催できる:キャンプ場 + {0x0BD, new EventFlagLand(0 , 1 , 0189, "CeremonyBuildTailor" )}, // セレモニ|廃止予定:置き換え可 + {0x0BE, new EventFlagLand(0 , 1 , 0190, "CeremonyBuildBridge" )}, // セレモニ|セレモニ開催できる:橋 + {0x0BF, new EventFlagLand(0 , 1 , 0191, "CeremonyBuildSlope" )}, // セレモニ|セレモニ開催できる:坂 + {0x0C0, new EventFlagLand(0 , 1 , 0192, "IslandDevQuestRunning" )}, // たぬきち|島の発展Quest実施中 + {0x0C1, new EventFlagLand(0 , 1 , 0193, "IslandDevQuestComplete" )}, // たぬきち|島の発展Quest完了 + {0x0C2, new EventFlagLand(0 , 10000, 0194, "CountTailorAfterBuild" )}, // 仕立て屋|オープンして何日目か + {0x0C3, new EventFlagLand(0 , 10000, 0195, "CountMuseumAfterBuild" )}, // 博物館|オープンして何日目か + {0x0C4, new EventFlagLand(0 , 10000, 0196, "CountMarket1AfterBuild" )}, // まめきちの店|小がオープンして何日目か + {0x0C5, new EventFlagLand(0 , 10000, 0197, "CountMarket2AfterBuild" )}, // まめきちの店|大がオープンして何日目か + {0x0C6, new EventFlagLand(0 , 10000, 0198, "CountOfficeAfterBuild" )}, // 案内所|オープンして何日目か + {0x0C7, new EventFlagLand(0 , 7 , 0199, "CountFirstBridgeAfterBuild" )}, // 初めての橋に言及する会話を表示できる残り日数 + {0x0C8, new EventFlagLand(0 , 7 , 0200, "CountFirstSlopeAfterBuild" )}, // 初めての坂に言及する会話を表示できる残り日数 + {0x0C9, new EventFlagLand(0 , 1 , 0201, "IslandEvaluationUnlock" )}, // しずえ|島の評価島全体で解禁 + {0x0CA, new EventFlagLand(0 , 1 , 0202, "IslandEvaluationClearTkkLive" )}, // しずえ|島の評価がとたけけライブ発生基準をクリアした + {0x0CB, new EventFlagLand(0 , 10 , 0203, "HaveHousingKitCount" )}, // たぬきち|島の住人が所持ているハウジングキットの数 + {0x0CC, new EventFlagLand(0 , 1 , 0204, "BridgeBuilt" )}, // 橋を作ったことがある + {0x0CD, new EventFlagLand(0 , 1 , 0205, "SlopeBuilt" )}, // 坂を作ったことがある + {0x0CE, new EventFlagLand(0 , 3 , 0206, "BeyRequireFishSize" )}, // 来訪新うおまさ|クエスト対象のサカナサイズ + {0x0CF, new EventFlagLand(0 , 1 , 0207, "TanuportAmiiboUnlock" )}, // タヌポート|amiibo関連機能を解禁 + {0x0D8, new EventFlagLand(0 , 1 , 0216, "SpnVisitMainField" )}, // パニエル|メインフィールドに出現 + {0x0D9, new EventFlagLand(0 , 1 , 0217, "ChangePlazaFtrToNormal" )}, // 広場の序盤配置家具を撤去 + {0x0DA, new EventFlagLand(0 , 1 , 0218, "SetPrologueBonfire" )}, // 序盤シーケンス|イベント用キャンプファイア設置 + {0x0DB, new EventFlagLand(0 , 1 , 0219, "ImmQ_A_OutdoorPattern" )}, // 移住Quest|住宅A|外置き家具パターンがAかBか? + {0x0DC, new EventFlagLand(0 , 1 , 0220, "ImmQ_B_OutdoorPattern" )}, // 移住Quest|住宅B|外置き家具パターンがAかBか? + {0x0DD, new EventFlagLand(0 , 1 , 0221, "ImmQ_C_OutdoorPattern" )}, // 移住Quest|住宅C|外置き家具パターンがAかBか? + {0x0DE, new EventFlagLand(0 , 1 , 0222, "TkkFirstLiveReserved" )}, // とたけけ|初ライブ当日か? + {0x0DF, new EventFlagLand(0 , 2 , 0223, "BirthdayBbsVariation2" )}, // 誕生日の告知を掲示板に前回書き込んだときのバリエーション2人用 + {0x0E0, new EventFlagLand(0 , 1 , 0224, "AllowNpcGroupActivity" )}, // NPCの広場行動(集団)が許可されたか + {0x0E1, new EventFlagLand(0 , 1 , 0225, "TanuportAmiiboCampUnlock" )}, // タヌポート|amiiboキャンプ場呼び出しが解禁可 + {0x0E2, new EventFlagLand(0 , 1 , 0226, "PickedUpMessageBottle" )}, // 最初のメッセージボトルが拾われた + {0x0E3, new EventFlagLand(0 , 10 , 0227, "CountAppE_RepTalk" )}, // 一般NPC島評判UP応援アプローチ発生(アイテムもらった)回数カウント + {0x0E4, new EventFlagLand(0 , 10 , 0228, "FlwLilyGrowCounter" )}, // スズラン|発生率決定カウンタ + {0x0E5, new EventFlagLand(0 , 1 , 0229, "FlwLilyFirstGrow" )}, // スズラン|島に発生したことがある? + {0x0E6, new EventFlagLand(0 , 1 , 0230, "CampFirstCamperVisit" )}, // キャンプ場|最初のキャンプ場客が滞在中か? + {0x0E7, new EventFlagLand(0 , 1 , 0231, "RcmShopMaterial_Wood" )}, // まめきち|木材提供済? + {0x0E8, new EventFlagLand(0 , 1 , 0232, "RcmShopMaterial_HardWood" )}, // まめきち|かたい木材提供済? + {0x0E9, new EventFlagLand(0 , 1 , 0233, "RcmShopMaterial_SoftWood" )}, // まめきち|やわらかい木材提供済? + {0x0EA, new EventFlagLand(0 , 1 , 0234, "RcmShopMaterial_Iron" )}, // まめきち|鉄鉱石提供済? + {0x0EB, new EventFlagLand(0 , 1 , 0235, "RcmShopMaterialComplete" )}, // まめきち|すべての資材が揃った + {0x0EC, new EventFlagLand(0 , 1 , 0236, "DailyQuestFivePointDay" )}, // 日課の5倍ポイントデーか? + {0x0ED, new EventFlagLand(0 , 1 , 0237, "ReportFirstCamperAboutSetHousing" )}, // キャンプ場|最初のキャンプ場客に家の予定地セットの報告した + {0x0EE, new EventFlagLand(0 , 1 , 0238, "RcoRcmTalkingAboutStoreMaterial" )}, // たぬきち&まめきち|商店建設資材の相談会話(初回)発生した + {0x0EF, new EventFlagLand(0 , 1 , 0239, "PAnnounceRcoCalling" )}, // 島内放送|放送中の入電イベント初回発生済 + {0x0F1, new EventFlagLand(0 , 1 , 0241, "PAnnounceCeremony1st" )}, // 島内放送|初めてセレモニーの告知した + {0x0F2, new EventFlagLand(0 , 1 , 0242, "PAnnounceCeremony1stToday" )}, // 島内放送|初めてセレモニーの告知入った当日のみON + {0x0F3, new EventFlagLand(0 , 1 , 0243, "CampSiteBuiltToday" )}, // キャンプ場が建った当日 + {0x0F4, new EventFlagLand(0 , 10000, 0244, "CountCampSiteAfterBuild" )}, // キャンプ場|オープンして何日目か + {0x0F5, new EventFlagLand(0 , 1 , 0245, "IslandLocalFruitApple" )}, // 島の特産フルーツがリンゴならON + {0x0F6, new EventFlagLand(0 , 1 , 0246, "IslandLocalFruitOrange" )}, // 島の特産フルーツがオレンジならON + {0x0F7, new EventFlagLand(0 , 1 , 0247, "IslandLocalFruitPear" )}, // 島の特産フルーツがナシならON + {0x0F8, new EventFlagLand(0 , 1 , 0248, "IslandLocalFruitPeach" )}, // 島の特産フルーツがモモならON + {0x0F9, new EventFlagLand(0 , 1 , 0249, "IslandLocalFruitCherry" )}, // 島の特産フルーツがサクランボならON + {0x0FA, new EventFlagLand(0 , 1 , 0250, "HghPeddlerPurchaceToday" )}, // きぬよ行商|今回の来訪で島の誰かが商品購入した? + {0x0FB, new EventFlagLand(0 , 1 , 0251, "PAnnounceKkProject" )}, // 島内放送|とたけけプロジェクトの予告発生した? + {0x0FC, new EventFlagLand(0 , 1 , 0252, "TownNewsHeardEventStarted" )}, // 島内放送|イベント開始済み村内放送を聞いた? + {0x0FD, new EventFlagLand(0 , 999 , 0253, "SzaIslandEvaluationBeforeLife" )}, // しずえ|島の環境:前回の「生活」ポイント + {0x0FE, new EventFlagLand(0 , 999 , 0254, "SzaIslandEvaluationBeforeNatural" )}, // しずえ|島の環境:前回の「自然」ポイント + {0x0FF, new EventFlagLand(0 , 5000 , 0255, "FishNetHostCatchNumResult" )}, // 通信開始時にネットホストのプレイヤーが今まで捕まえたサカナの数 + {0x100, new EventFlagLand(0 , 10 , 0256, "SzaIslandEvaluationBeforeDevelopment" )}, // しずえ|島の環境:前回の「発展」要素 + {0x101, new EventFlagLand(0 , 1 , 0257, "SzaIslandEvaluationTodayRankUpdate" )}, // しずえ|島の環境:今日のポイント更新したらON + {0x102, new EventFlagLand(0 , 1 , 0258, "SzaIslandEvaluationImprovementLifeToday" )}, // しずえ|島の環境:前回島内放送より「生活」ポイント向上 + {0x103, new EventFlagLand(0 , 1 , 0259, "SzaIslandEvaluationImprovementNaturalToday" )}, // しずえ|島の環境:前回島内放送より「自然」ポイント向上 + {0x104, new EventFlagLand(0 , 1 , 0260, "SzaIslandEvaluationImprovementDevelopToday" )}, // しずえ|島の環境:前回島内放送より発展要素が増えた + {0x105, new EventFlagLand(0 , 1 , 0261, "AppE_WelcomoMigrants_AN" )}, // AppE_WelcomoMigrants_AN発生した + {0x106, new EventFlagLand(0 , 1 , 0262, "AppE_WelcomoMigrants_HA" )}, // AppE_WelcomoMigrants_HA発生した + {0x107, new EventFlagLand(0 , 1 , 0263, "TkkFirstLiveSubPlayer" )}, // とたけけ|2人目以降のプレイヤーが初ライブを見られる? + {0x108, new EventFlagLand(0 , 1 , 0264, "PortableRadioControl" )}, // けいたいラジオ挙動制御用フラグ + {0x109, new EventFlagLand(0 , 1 , 0265, "Market2Built" )}, // まめつぶ商店が大になった + {0x10A, new EventFlagLand(0 , 1 , 0266, "OwlTentExplainFor1P" )}, // フータ|誰かに棒高跳び&スコップレシピ提供済 + {0x10B, new EventFlagLand(0 , 1 , 0267, "MuseumConstructionToday" )}, // 今日、博物館工事当日であるか? + {0x10C, new EventFlagLand(0 , 1 , 0268, "ShopUnlockAxe" )}, // お店|ショボいオノの店売りを解禁する + {0x10D, new EventFlagLand(0 , 1 , 0269, "FinishMuseumPreparation1stDay" )}, // フータ移住初日に博物館建築条件を達成した + {0x10E, new EventFlagLand(0 , 2 , 0270, "MushroomProbability" )}, // キノコ|発生確率決定フラグ + {0x10F, new EventFlagLand(0 , 3 , 0271, "NNpcContractProbablityAddPoint" )}, // 一般NPC|売地契約補正値 + {0x110, new EventFlagLand(0 , 1 , 0272, "TkkFirstLiveEnable" )}, // とたけけ|初ライブ解禁か? + {0x111, new EventFlagLand(0 , 1 , 0273, "ImmQClearNextDay" )}, // 移住Quest|クリアして1日経ったか? + {0x112, new EventFlagLand(0 , 1 , 0274, "TodayImmQNotClear" )}, // 移住Quest|今日の最初に移住クエスト未クリアだった? + {0x113, new EventFlagLand(0 , 1 , 0275, "NpcDIYScheduleSet" )}, // NPCのDIYスケジュールを決定したか + {0x114, new EventFlagLand(0 , 1 , 0276, "PAnnounceToday" )}, // 今日、村で島内放送が発生した + {0x115, new EventFlagLand(0 , 1 , 0277, "AirportOpen" )}, // 飛行場|オープンしたか? + {0x117, new EventFlagLand(0 , 1 , 0279, "AnyGlobalEventFinished" )}, // いずれかのグローバルイベント日をまたいだ? + {0x118, new EventFlagLand(0 , 1 , 0280, "LostPropertyFound" )}, // 島Pの誰かが落とし物を拾った + {0x119, new EventFlagLand(0 , 1 , 0281, "MuseumFossilComplete" )}, // 博物館_化石部屋コンプ済 + {0x11A, new EventFlagLand(0 , 1 , 0282, "InduceInMysteriTourIslandToday" )}, // 今日ミステリーツアー島で勧誘した + {0x11B, new EventFlagLand(0 , 1 , 0283, "Tutorial1PTentLightON" )}, // 1P島代表のテントの明かりをONにするか? + {0x11C, new EventFlagLand(0 , 9999 , 0284, "PynVisitYear" )}, // ぴょんたろうが来訪した年 + {0x11D, new EventFlagLand(0 , 1 , 0285, "PynVisitToday" )}, // ぴょんたろうが今日来訪NPCとして来訪する + {0x11E, new EventFlagLand(0 , -1 , 0286, "CatchInsectFesGetTotalNum" )}, // ムシ取り大会|全員のムシ取得数 + {0x11F, new EventFlagLand(0 , -1 , 0287, "CatchFishFesGetTotalNum" )}, // つり大会|全員のサカナ取得数 + {0x120, new EventFlagLand(0 , 1 , 0288, "JohnnyQuestFinishFlagIsland" )}, // ジョニー|その日に村で誰かがジョニーを助けたか?(海賊ジョニーでも使用) + {0x121, new EventFlagLand(0 , 10 , 0289, "CampRandomSelectMoveOutNpc" )}, // キャンプ場|ランダム選出転出NPCが何番目の住人か?(0:未抽選/抽選対象なし) + {0x122, new EventFlagLand(0 , 1 , 0290, "CampFireRemoved" )}, // 広場のキャンプファイアー撤去(実際の撤去とは連動してません) + {0x123, new EventFlagLand(0 , 1 , 0291, "WHEREAREN_HHDUnlock" )}, // ウェアラン諸島解禁 + {0x125, new EventFlagLand(0 , 1 , 0293, "UnlockEaster" )}, // BCATにてイースター解禁 + {0x126, new EventFlagLand(0 , 5 , 0294, "MuseumConstruction2" )}, // 博物館1→2(美術部屋追加)への工事中 + {0x127, new EventFlagLand(0 , 1 , 0295, "MuseumGrowupEnable2" )}, // 博物館2(美術部屋追加)への成長条件達成 + {0x130, new EventFlagLand(0 , 1 , 0304, "OwlWantsPainting" )}, // フータの絵画クエストを開始した + {0x131, new EventFlagLand(0 , 10 , 0305, "CampTodaySelectMoveOutNpc" )}, // キャンプ場|強制転出NPCが何番目の住人か?(0:未抽選/抽選対象なし) + {0x132, new EventFlagLand(0 , 1 , 0306, "Museum3Built" )}, // 博物館②(美術部屋追加)完成 + {0x133, new EventFlagLand(0 , 1 , 0307, "Museum3BuiltToday" )}, // 博物館②(美術部屋追加)完成当日か? + {0x134, new EventFlagLand(0 , 10000, 0308, "CountMuseum2AfterBuild" )}, // 博物館②(美術部屋追加)|オープンして何日目か + {0x135, new EventFlagLand(0 , 1 , 0309, "Museum2ConstructionToday" )}, // 今日、博物館②(美術部屋追加)工事当日であるか? + {0x136, new EventFlagLand(0 , 1 , 0310, "GrowUpAfterPatch1_1" )}, // 1.1適用して成長処理をした + {0x137, new EventFlagLand(0 , 1 , 0311, "GrowUpAfterPatch1_2" )}, // 1.2適用して成長処理をした + {0x138, new EventFlagLand(0 , 1 , 0312, "GrowUpAfterPatch1_3" )}, // 1.3適用して成長処理をした + {0x139, new EventFlagLand(0 , 1 , 0313, "GrowUpAfterPatch1_4" )}, // 1.4適用して成長処理をした + {0x13A, new EventFlagLand(0 , 1 , 0314, "GrowUpAfterPatch2_0" )}, // 2.0適用して成長処理をした + {0x13B, new EventFlagLand(0 , 1 , 0315, "EarthdaySloFirstVisit" )}, // アースデーの初回レイジを予約した + {0x13C, new EventFlagLand(0 , 1 , 0316, "OwlFoundDiveFish" )}, // フータ|誰かが海の幸を見せたことがある + {0x13D, new EventFlagLand(0 , 1 , 0317, "SloPeddlerPurchaceToday" )}, // レイジ行商|今回の来訪で島の誰かが商品購入した? + {0x13E, new EventFlagLand(0 , 1 , 0318, "FoxPreVisitToday" )}, // つねきちが今日事前来訪する + {0x13F, new EventFlagLand(0 , 1 , 0319, "AnyPlayerHouseBuilt" )}, // 住人の誰かのマイホームが1度でも建ったことがある + {0x140, new EventFlagLand(0 , 50 , 0320, "MuseumFishStampRackLotID1" )}, // 国際ミュージアム|1つ目のサカナのスタンプ台ID + {0x141, new EventFlagLand(0 , 50 , 0321, "MuseumFishStampRackLotID2" )}, // 国際ミュージアム|2つ目のサカナのスタンプ台ID + {0x142, new EventFlagLand(0 , 50 , 0322, "MuseumFishStampRackLotID3" )}, // 国際ミュージアム|3つ目のサカナのスタンプ台ID + {0x143, new EventFlagLand(0 , 50 , 0323, "MuseumInsectStampRackLotID1" )}, // 国際ミュージアム|1つ目のムシのスタンプ台ID + {0x144, new EventFlagLand(0 , 50 , 0324, "MuseumInsectStampRackLotID2" )}, // 国際ミュージアム|2つ目のムシのスタンプ台ID + {0x145, new EventFlagLand(0 , 50 , 0325, "MuseumInsectStampRackLotID3" )}, // 国際ミュージアム|3つ目のムシのスタンプ台ID + {0x146, new EventFlagLand(0 , 50 , 0326, "MuseumFossilStampRackLotID1" )}, // 国際ミュージアム|1つ目のかせきのスタンプ台ID + {0x147, new EventFlagLand(0 , 50 , 0327, "MuseumFossilStampRackLotID2" )}, // 国際ミュージアム|2つ目のかせきのスタンプ台ID + {0x148, new EventFlagLand(0 , 50 , 0328, "MuseumFossilStampRackLotID3" )}, // 国際ミュージアム|3つ目のかせきのスタンプ台ID + {0x149, new EventFlagLand(0 , 1 , 0329, "AOC_EventFlag_000" )}, // AOC同期フラグ| 000 Compass + {0x14A, new EventFlagLand(0 , 1 , 0330, "AOC_EventFlag_001" )}, // AOC同期フラグ| 001 NSO加入特典 + {0x14C, new EventFlagLand(0 , 1 , 0332, "FoxPreVisitReserve" )}, // 事前来訪つねきちを翌日に予約する + {0x14D, new EventFlagLand(0 , 1 , 0333, "FoxMovedToMarket" )}, // つねきち|来訪時にフィールドから船へ移動した + {0x14E, new EventFlagLand(0 , 1 , 0334, "FoxAndShipReserve" )}, // つねきち船+フィールドを予約する + {0x14F, new EventFlagLand(0 , 1 , 0335, "BCAT_EventFlag_002" )}, // 国際ミュージアム解禁 + {0x150, new EventFlagLand(0 , 1 , 0336, "BCAT_EventFlag_004" )}, // ハーベスト解禁 + {0x151, new EventFlagLand(0 , 1 , 0337, "BCAT_EventFlag_001" )}, // メーデー解禁 + {0x152, new EventFlagLand(0 , 1 , 0338, "BCAT_EventFlag_003" )}, // ジューンブライド解禁 + {0x157, new EventFlagLand(0 , 1 , 0343, "FoxPreVisit1Today" )}, // つねきち1回目の事前来訪当日 + {0x158, new EventFlagLand(0 , 1 , 0344, "FoxPreVisit2Today" )}, // つねきち2回目の事前来訪当日 + {0x159, new EventFlagLand(0 , 1 , 0345, "EarthdaySloFirstVisitToday" )}, // 今日がアースデーの初回レイジ来訪日 + {0x15A, new EventFlagLand(0 , 1 , 0346, "IsDreamingBed" )}, // ゆめみ用ベッドある? + {0x15B, new EventFlagLand(0 , 1 , 0347, "UnlockJuneBrideSeq" )}, // ゲーム進行的にジューンブライド解禁 + {0x15C, new EventFlagLand(0 , -1 , 0348, "RandomKey1" )}, // ランダムキー1 + {0x15D, new EventFlagLand(0 , -1 , 0349, "RandomKey2" )}, // ランダムキー2 + {0x15E, new EventFlagLand(0 , -1 , 0350, "RandomKey3" )}, // ランダムキー3 + {0x15F, new EventFlagLand(0 , -1 , 0351, "RandomKey4" )}, // ランダムキー4 + {0x160, new EventFlagLand(0 , 1 , 0352, "FoxPreVisitAlreadyBuyToday" )}, // つねきち|今日誰かが事前来訪中に美術品を買った + {0x161, new EventFlagLand(0 , 1 , 0353, "RcoHasResolvedMoveKitBug" )}, // いせつキットバグを解消したか + {0x162, new EventFlagLand(0 , 1 , 0354, "TapDreamEnable" )}, // ゆめみ|ゆめみ機能解禁か? + {0x165, new EventFlagLand(0 , 1 , 0357, "GulBVisitEnable" )}, // 海賊ジョニーが来訪する条件を満たしたか + {0x166, new EventFlagLand(0 , 200 , 0358, "PokiRate" )}, // x)ポキの両替レート + {0x167, new EventFlagLand(0 , 9999 , 0359, "FireworksAddBbsYear" )}, // 花火大会予告の掲示板書き込みをした年 + {0x16A, new EventFlagLand(0 , 1 , 0362, "EnableMyDream" )}, // ゆめみ|現在、自分の島の夢を提供中か? + {0x16B, new EventFlagLand(0 , 1 , 0363, "JohnnyInvisible" )}, // ジョニー非表示状態か + {0x16C, new EventFlagLand(0 , 1 , 0364, "DreamUploadPlayerHaveCreaterID" )}, // ゆめみ|夢の最終更新者がMyDesignショーケースの作者IDを持ってるか? + {0x16D, new EventFlagLand(0 , 5000 , 0365, "DiveFishNetHostCatchNumResult" )}, // 通信開始時にネットホストのプレイヤーが今までに捕まえた海の幸の数 + {0x16E, new EventFlagLand(0 , 9999 , 0366, "HalloweenSloVisitYear" )}, // ハロウィンの初回レイジを予約した年 + {0x16F, new EventFlagLand(0 , 1 , 0367, "HalloweenSloVisitToday" )}, // 今日がハロウィンのレイジ来訪日 + {0x171, new EventFlagLand(0 , 1 , 0369, "GrowUpAfterPatch1_5" )}, // 1.5適用して成長処理をした + {0x172, new EventFlagLand(0 , 1 , 0370, "NeedUpdatePassword" )}, // セーブデータ復元後のパスワード更新必要 + {0x173, new EventFlagLand(0 , 1 , 0371, "IsHalloweenLessThanThreeDays" )}, // ハロウィン3日前以内か? + {0x174, new EventFlagLand(0 , 1 , 0372, "GrowUpAfterPatch1_6" )}, // 1.6適用して成長処理をした + {0x175, new EventFlagLand(0 , 1 , 0373, "IslandProducedByPlayerMoving" )}, // プレイヤーだけ引越し|プレイヤーだけ引越しによって作られた島か? + {0x176, new EventFlagLand(0 , 1 , 0374, "EventObjFlag0" )}, // イベントオブジェフラグ0 + {0x179, new EventFlagLand(0 , 4 , 0377, "HarvestProgress" )}, // ハーベスト|完成した料理の数(島単位) + {0x17A, new EventFlagLand(0 , 1 , 0378, "PlayerMovingEnableShopMaterialCollect" )}, // プレイヤーだけ引越し|お店の資材集め解禁していいか? + {0x17B, new EventFlagLand(0 , 1 , 0379, "SecondPublicAnnouncement" )}, // 2回目島内放送の発生が必要か? + {0x17C, new EventFlagLand(0 , 1 , 0380, "HarvestAfterTerm" )}, // ハーベスト|アフター期間か? + {0x17D, new EventFlagLand(0 , 1 , 0381, "FinishTreasureQuestByRollback" )}, // 宝探しクエストが通信ロールバックで終了した + {0x17E, new EventFlagLand(0 , 1 , 0382, "HarvestHQDish1Island" )}, // ハーベスト|島の誰かが料理1クラムチャウダーの隠し食材納めた? + {0x17F, new EventFlagLand(0 , 1 , 0383, "HarvestHQDish2Island" )}, // ハーベスト|島の誰かが料理2パンプキンパイの隠し食材納めた? + {0x180, new EventFlagLand(0 , 1 , 0384, "HarvestHQDish3Island" )}, // ハーベスト|島の誰かが料理3グラタンの隠し食材納めた? + {0x181, new EventFlagLand(0 , 1 , 0385, "HarvestHQDish4Island" )}, // ハーベスト|島の誰かが料理4サカナのムニエルの隠し食材納めた? + {0x182, new EventFlagLand(0 , 1 , 0386, "IsDisclosedMyDream" )}, // ゆめみ|現在、自分の島の夢をおまかせに公開中か? + {0x183, new EventFlagLand(0 , 22 , 0387, "HarvestTukIngredient2_2" )}, // ハーベスト|必要食材2-2 + {0x184, new EventFlagLand(0 , 22 , 0388, "HarvestTukIngredient3_1" )}, // ハーベスト|必要食材3-1 + {0x185, new EventFlagLand(0 , 22 , 0389, "HarvestTukIngredient3_2" )}, // ハーベスト|必要食材3-2 + {0x186, new EventFlagLand(0 , 22 , 0390, "HarvestTukIngredient4_2" )}, // ハーベスト|必要食材4-2 + {0x187, new EventFlagLand(0 , 22 , 0391, "HarvestTukHideIngredient2_1" )}, // ハーベスト|隠し食材2-1 + {0x188, new EventFlagLand(0 , 22 , 0392, "HarvestTukHideIngredient2_2" )}, // ハーベスト|隠し食材2-2 + {0x189, new EventFlagLand(0 , 5 , 0393, "ReputaionMyIsland" )}, // ゆめみ|現在の自分の島の評判値 + {0x18C, new EventFlagLand(0 , 9999 , 0396, "LastPlayXmasYear" )}, // 最後にプレイしたクリスマスの年 + {0x18D, new EventFlagLand(0 , 1 , 0397, "ShopSelectChristmasFtr" )}, // クリスマスおもちゃ家具抽選を今日したか + {0x18E, new EventFlagLand(0 , 1 , 0398, "IsUploadDisclosedMyDream" )}, // ゆめみ|オマカセ公開で初回更新しなかったか? + {0x18F, new EventFlagLand(0 , 1 , 0399, "TkkFirstLiveNow" )}, // とたけけ|初ライブステージか? + {0x190, new EventFlagLand(0 , 1 , 0400, "ChristmasFtrFirstRound" )}, // クリスマス|おもちゃ家具の商品抽選が1巡したか + {0x191, new EventFlagLand(0 , 9999 , 0401, "HarvestFestivalAddBbsYear" )}, // ハーベストフェスティバル予告の掲示板書き込みをした年 + {0x192, new EventFlagLand(0 , 1 , 0402, "GrowUpAfterPatch1_7" )}, // 1.7適用して成長処理をした + {0x193, new EventFlagLand(0 , 9999 , 0403, "XmasEveAddBbsYear" )}, // クリスマス予告の掲示板書き込みをした年 + {0x194, new EventFlagLand(0 , 1 , 0404, "BCAT_EventFlag_005" )}, // クリスマス準備期間解禁 + {0x195, new EventFlagLand(0 , -1 , 0405, "RandomKey5" )}, // ランダムキー5 + {0x196, new EventFlagLand(0 , 1 , 0406, "ShopSocksFlag" )}, // かべかけソックス当選済み + {0x197, new EventFlagLand(0 , -1 , 0407, "ShopHeartChocoSelect" )}, // ハートのチョコレート抽選済みカラバリ + {0x198, new EventFlagLand(0 , -1 , 0408, "ShopHeartFlowerSelect" )}, // ハートのバラブーケ抽選済みカラバリ + {0x199, new EventFlagLand(0 , -1 , 0409, "RandomKey6" )}, // ランダムキー6 + {0x19A, new EventFlagLand(0 , -1 , 0410, "RandomKey7" )}, // ランダムキー7 + {0x19B, new EventFlagLand(0 , -1 , 0411, "RandomKey8" )}, // ランダムキー8 + {0x19C, new EventFlagLand(0 , 1 , 0412, "BCAT_EventFlag_006" )}, // クリスマスイブ解禁 + {0x19D, new EventFlagLand(0 , 1 , 0413, "BCAT_EventFlag_007" )}, // カーニバル本番、バレンタイン本番解禁 + {0x19E, new EventFlagLand(0 , 1 , 0414, "BCAT_EventFlag_008" )}, // マリオコラボ解禁 + {0x19F, new EventFlagLand(0 , 1 , 0415, "GrowUpAfterPatch1_8" )}, // 1.8適用して成長処理をした + {0x1A0, new EventFlagLand(0 , 1 , 0416, "GrowUpAfterPatch1_9" )}, // 1.9適用して成長処理をした + {0x1A1, new EventFlagLand(0 , -1 , 0417, "RandomKey9" )}, // ランダムキー9 + {0x1A2, new EventFlagLand(0 , 1 , 0418, "BCAT_EventFlag_009" )}, // イースター2年目準備解禁 + {0x1A3, new EventFlagLand(0 , 9999 , 0419, "ValentineAddBbsYear" )}, // バレンタイン予告の掲示板書き込みをした年 + {0x1A4, new EventFlagLand(0 , 9999 , 0420, "CarnivalAddBbsYear" )}, // カーニバル予告の掲示板書き込みをした年 + {0x1A5, new EventFlagLand(0 , 1 , 0421, "CarnivalNpcFeatherColorDecided" )}, // カーニバル|NPCが欲しがる羽の色決定済み + {0x1A6, new EventFlagLand(0 , 1 , 0422, "CarnivalEventPlazaNpcWander" )}, // カーニバル|広場行動NPCがぶらつくか + {0x1AD, new EventFlagLand(0 , 1 , 0429, "BCAT_EventFlag_010" )}, // イースター2年目本番解禁 + {0x1AE, new EventFlagLand(0 , -1 , 0430, "RandomKey10" )}, // ランダムキー10 + {0x1B5, new EventFlagLand(0 , 1 , 0437, "AOC_EventFlag_002" )}, // AOC同期フラグ| 002 1.9.0NSO加入特典 + {0x1B6, new EventFlagLand(0 , 1 , 0438, "BCAT_EventFlag_011" )}, // ジューンブライド2年目解禁 + {0x1B7, new EventFlagLand(0 , -1 , 0439, "RandomKey11" )}, // ランダムキー11 + {0x1B8, new EventFlagLand(0 , 50 , 0440, "MuseumArtStampRackLotID1" )}, // 国際ミュージアム|1つ目の美術品のスタンプ台ID + {0x1B9, new EventFlagLand(0 , 50 , 0441, "MuseumArtStampRackLotID2" )}, // 国際ミュージアム|2つ目の美術品のスタンプ台ID + {0x1BA, new EventFlagLand(0 , 50 , 0442, "MuseumArtStampRackLotID3" )}, // 国際ミュージアム|3つ目の美術品のスタンプ台ID + {0x1BB, new EventFlagLand(0 , 1 , 0443, "v200_Enabled_ChangeRegulation" )}, // 条例が解禁した + {0x1BC, new EventFlagLand(0 , 1 , 0444, "RegulationType1" )}, // 美しい島条例発動中 + {0x1BD, new EventFlagLand(0 , 1 , 0445, "RegulationType2" )}, // 朝活条例発動中 + {0x1BE, new EventFlagLand(0 , 1 , 0446, "RegulationType3" )}, // 夜活条例発動中 + {0x1BF, new EventFlagLand(0 , 1 , 0447, "RegulationType4" )}, // 景気アップ条例発動中 + {0x1C0, new EventFlagLand(0 , 5 , 0448, "ReserveRegulation" )}, // 予約中の条例 + {0x1C1, new EventFlagLand(0 , 5 , 0449, "TodayChangeRegulation" )}, // 今日変更した条例 + {0x1C2, new EventFlagLand(0 , 1 , 0450, "MuseumCafeConstruction_1_Confirm" )}, // 博物館カフェ増築|①工事決定(翌朝工事へ) + {0x1C3, new EventFlagLand(0 , 1 , 0451, "GyroidCommuneFlag" )}, // チャリティーハニワくん|目標額を達成した? + {0x1C4, new EventFlagLand(0 , 8 , 0452, "GyroidCommuneDonationCount" )}, // チャリティーハニワくん|今日どのハニワくんが目標額達成した? + {0x1C5, new EventFlagLand(0 , 1 , 0453, "GyroidCommuneOtherFlag" )}, // チャリティーハニワくん|目標額を達成したハニワがいる? + {0x1C6, new EventFlagLand(0 , -1 , 0454, "WeedCount" )}, // 村全体に生えている雑草の本数 + {0x1C7, new EventFlagLand(0 , 1 , 0455, "MuseumCafeConstruction_2_ConstructionDay" )}, // 博物館カフェ増築|②工事当日(今日一日工事状態) + {0x1C8, new EventFlagLand(0 , 2 , 0456, "CommuneSloDonation" )}, // コミューン島レイジ用募金状態 + {0x1C9, new EventFlagLand(0 , 2 , 0457, "CommuneCmlDonation" )}, // コミューン島レローラン用募金状態 + {0x1CA, new EventFlagLand(0 , 2 , 0458, "CommuneFoxDonation" )}, // コミューン島つねきち用募金状態 + {0x1CB, new EventFlagLand(0 , 2 , 0459, "CommuneBptDonation" )}, // コミューン島ハッケミィ用募金状態 + {0x1CC, new EventFlagLand(0 , 2 , 0460, "CommuneSkkDonation" )}, // コミューン島シャンク用募金状態 + {0x1CD, new EventFlagLand(0 , 2 , 0461, "CommuneAlpDonation" )}, // コミューン島リサカイゾー用募金状態 + {0x1CE, new EventFlagLand(0 , 1 , 0462, "MuseumCafeConstruction_3_OpenDay" )}, // 博物館カフェ増築|③オープン当日 + {0x1CF, new EventFlagLand(0 , 1 , 0463, "MuseumCafeConstruction_4_Opened" )}, // 博物館カフェ増築|④オープン済(当日含む) + {0x1D0, new EventFlagLand(0 , 10000, 0464, "MuseumCafeConstruction_5_OpenDaysCount" )}, // 博物館カフェ増築|⑤オープンして何日目か(初日は1) + {0x1D1, new EventFlagLand(0 , 1 , 0465, "ReserveCommuneSloOpenEvent" )}, // コミューン島レイジ開店イベント予約 + {0x1D2, new EventFlagLand(0 , 1 , 0466, "EventObjFlag1" )}, // イベントオブジェフラグ1 + {0x1D3, new EventFlagLand(0 , 1 , 0467, "EventObjFlag2" )}, // イベントオブジェフラグ2 + {0x1D4, new EventFlagLand(0 , 5 , 0468, "MuseumConstruction3" )}, // 博物館2→3(カフェ増築)への工事中 + {0x1D5, new EventFlagLand(0 , 1 , 0469, "CommuneExpanded" )}, // コミューン|コミューン島が拡張した + {0x1D6, new EventFlagLand(0 , 1 , 0470, "ReserveCommuneCmlOpenEvent" )}, // コミューン島ローラン開店イベント予約 + {0x1D7, new EventFlagLand(0 , 1 , 0471, "ReserveCommuneFoxOpenEvent" )}, // コミューン島つねきち開店イベント予約 + {0x1D8, new EventFlagLand(0 , 1 , 0472, "ReserveCommuneBptOpenEvent" )}, // コミューン島ハッケミィ開店イベント予約 + {0x1D9, new EventFlagLand(0 , 1 , 0473, "ReserveCommuneSkkOpenEvent" )}, // コミューン島シャンク開店イベント予約 + {0x1DA, new EventFlagLand(0 , 1 , 0474, "ReserveCommuneAlpOpenEvent" )}, // コミューン島リサカイゾー開店イベント予約 + {0x1DB, new EventFlagLand(0 , -1 , 0475, "MuseumCafeAmiiboCustomer" )}, // 喫茶ハトの巣|Amiiboで呼び出したNPC + {0x1DC, new EventFlagLand(0 , 1 , 0476, "SloWeedingFlag" )}, // レイジ|今日草むしりサービス頼んだ? + {0x1DD, new EventFlagLand(0 , 1 , 0477, "GrowUpAfterPatch1_10" )}, // 1.10適用して成長処理をした + {0x1DE, new EventFlagLand(0 , 1 , 0478, "GrowUpAfterPatch1_11" )}, // 1.11適用して成長処理をした + {0x1DF, new EventFlagLand(0 , 2 , 0479, "RadioGymnasticsBbsFlag" )}, // ラジオ体操の掲示板書き込みをした? + {0x1E0, new EventFlagLand(0 , 1 , 0480, "BCAT_EventFlag_012" )}, // ハロウィン2年目解禁 + {0x1E1, new EventFlagLand(0 , -1 , 0481, "RandomKey12" )}, // ランダムキー12 + {0x1E2, new EventFlagLand(0 , 1 , 0482, "CompleteCommuneExpandEvent" )}, // コミューン|コミューン島が拡張したイベントを誰かが完了したか + {0x1E3, new EventFlagLand(0 , 9999 , 0483, "MayDayAddBbsYear" )}, // メーデー予告の掲示板書き込みをした年 + {0x1E4, new EventFlagLand(0 , -1 , 0484, "MuseumCafeCheckedTimeZone" )}, // 喫茶ハトの巣|ランダム来訪一般NPCチェックした時間帯 + {0x1E5, new EventFlagLand(0 , 3 , 0485, "MuseumCafeRandomVisitSp_hgs" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(あさみ) + {0x1E6, new EventFlagLand(0 , 3 , 0486, "MuseumCafeRandomVisitSp_hgh" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(きぬよ) + {0x1E7, new EventFlagLand(0 , 3 , 0487, "MuseumCafeRandomVisitSp_doc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ロドリー) + {0x1E8, new EventFlagLand(0 , 3 , 0488, "MuseumCafeRandomVisitSp_boc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ウリ) + {0x1E9, new EventFlagLand(0 , 3 , 0489, "MuseumCafeRandomVisitSp_mol" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(リセットさん) + {0x1EA, new EventFlagLand(0 , 3 , 0490, "MuseumCafeRandomVisitSp_mob" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ラケットさん) + {0x1EB, new EventFlagLand(0 , 3 , 0491, "MuseumCafeRandomVisitSp_tkkA" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(とたけけ) + {0x1EC, new EventFlagLand(0 , 3 , 0492, "MuseumCafeRandomVisitSp_skk" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(シャンク) + {0x1ED, new EventFlagLand(0 , 3 , 0493, "MuseumCafeRandomVisitSp_cml" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ローラン) + {0x1EE, new EventFlagLand(0 , 3 , 0494, "MuseumCafeRandomVisitSp_hgc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ことの) + {0x1EF, new EventFlagLand(0 , 3 , 0495, "MuseumCafeRandomVisitSp_slo" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(レイジ) + {0x1F0, new EventFlagLand(0 , 3 , 0496, "MuseumCafeRandomVisitSp_ows" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(フーコ) + {0x1F1, new EventFlagLand(0 , 3 , 0497, "MuseumCafeRandomVisitSp_chy" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(レックス) + {0x1F2, new EventFlagLand(0 , 3 , 0498, "MuseumCafeRandomVisitSp_bey" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC(ジャスティン) + {0x1F3, new EventFlagLand(0 , 1 , 0499, "BCAT_EventFlag_013" )}, // サンクスギビング、ブラックフライデー解禁 + {0x1F4, new EventFlagLand(0 , -1 , 0500, "RandomKey13" )}, // ランダムキー13 + {0x1F5, new EventFlagLand(0 , 2 , 0501, "CommuneTtlDonation" )}, // コミューン島コトブキ用募金状態 + {0x1F6, new EventFlagLand(0 , 1 , 0502, "ReserveCommuneTtlOpenEvent" )}, // コミューン島コトブキ開店イベント予約 + {0x1F7, new EventFlagLand(0 , 1 , 0503, "UnlockGyroidMainField" )}, // ハニワの自然発生が解禁されているか? + {0x1F8, new EventFlagLand(0 , 1 , 0504, "EventObjFlag3" )}, // イベントオブジェフラグ3 + {0x1F9, new EventFlagLand(0 , 9999 , 0505, "HalloweenAddBbsYear" )}, // ハロウィン予告の掲示板書き込みをした年 + {0x1FA, new EventFlagLand(0 , 1 , 0506, "Museum2BuiltSkippedMuseum1" )}, // 博物館①をスキップして博物館②が建った + {0x1FB, new EventFlagLand(0 , 1 , 0507, "FoxAndShipReserveVer2" )}, // つねきち船+フィールドを予約する(Ver2.0.0) + {0x1FC, new EventFlagLand(0 , 1 , 0508, "EverChangedRegulation" )}, // 条例変更直前に発動中の条例があったか? + {0x1FD, new EventFlagLand(0 , 1 , 0509, "ExistIllminations" )}, // 成長処理時点で電飾付の木が一本以上存在しているか? + {0x1FE, new EventFlagLand(0 , 1 , 0510, "ExistSakura" )}, // 成長処理時点で村に桜の木が存在するか? + {0x1FF, new EventFlagLand(0 , 1 , 0511, "ExistBanboo" )}, // 成長処理時点で村に竹の成木が存在するか? + {0x200, new EventFlagLand(0 , 1 , 0512, "ExistOak" )}, // 成長処理時点で村に成木の広葉樹が存在するか? + {0x201, new EventFlagLand(0 , 1 , 0513, "ExistCedar" )}, // 成長処理時点で村に成木の針葉樹が存在するか? + {0x202, new EventFlagLand(0 , 2 , 0514, "FoxCommuneArtStockCount" )}, // つねきち|コミューンで購入されたの美術品の数 + {0x203, new EventFlagLand(0 , 1 , 0515, "PlacementRadioGymnastics" )}, // ラジオ体操用ラジカセ設置 + {0x204, new EventFlagLand(0 , 100 , 0516, "FoxCommuneRealRate" )}, // つねきち|コミューンで美術品を本物に差し替える確率 + {0x205, new EventFlagLand(0 , 2 , 0517, "FoxCommuneRealNum" )}, // つねきち|コミューンで本物の美術品を並べた回数 + {0x206, new EventFlagLand(0 , 3 , 0518, "CatalogShopBigCount" )}, // カタログショッピングで大型の連続ハズレカウント + {0x208, new EventFlagLand(0 , 1 , 0520, "CoffeTakeout" )}, // 喫茶ハトの巣|島の誰かがコーヒーの持ち帰り解禁された? + {0x209, new EventFlagLand(0 , 1 , 0521, "MuseumPosterflagbug" )}, // フータ/博物館コンプポスター|ムシのポスター購入を解禁した? + {0x20A, new EventFlagLand(0 , 1 , 0522, "MuseumPosterflagfish" )}, // フータ/博物館コンプポスター|サカナのポスター購入を解禁した? + {0x20B, new EventFlagLand(0 , 1 , 0523, "MuseumPosterflagfossil" )}, // フータ/博物館コンプポスター|化石のポスター購入を解禁した? + {0x20C, new EventFlagLand(0 , 1 , 0524, "MuseumPosterflagpainting" )}, // フータ/博物館コンプポスター|美術品のポスター購入を解禁した? + {0x20D, new EventFlagLand(0 , 1 , 0525, "MuseumPosterflagsea" )}, // フータ/博物館コンプポスター|海の幸のポスター購入を解禁した? + {0x20E, new EventFlagLand(0 , 1 , 0526, "MuseumPosterTodayflagbug" )}, // フータ/博物館コンプポスター|ムシのポスター送った? + {0x20F, new EventFlagLand(0 , 1 , 0527, "MuseumPosterTodayflagfish" )}, // フータ/博物館コンプポスター|サカナのポスター送った? + {0x210, new EventFlagLand(0 , 1 , 0528, "MuseumPosterTodayflagfossil" )}, // フータ/博物館コンプポスター|かせきのポスター送った? + {0x211, new EventFlagLand(0 , 1 , 0529, "MuseumPosterTodayflagpainting" )}, // フータ/博物館コンプポスター|美術品のポスター送った? + {0x212, new EventFlagLand(0 , 1 , 0530, "MuseumPosterTodayflagsea" )}, // フータ/博物館コンプポスター|海の幸のポスター送った? + {0x213, new EventFlagLand(0 , 1 , 0531, "SzaChangeSymbol" )}, // しずえ|誰かが旗のデザイン変えた? + {0x214, new EventFlagLand(0 , 5 , 0532, "GotFakeArts" )}, // Tips|島全体で贋作購入した個数 + {0x215, new EventFlagLand(0 , 1 , 0533, "VisitGulAFlag" )}, // ジョニーが来訪したフラグ + {0x216, new EventFlagLand(0 , 1 , 0534, "EnableBlackFriday" )}, // ゲーム進行的にブラックフライデー解禁 + {0x217, new EventFlagLand(0 , 1 , 0535, "KppTourStart" )}, // 島内放送|島の誰かにかっぺいツアー開始告知をした + {0x218, new EventFlagLand(0 , 1 , 0536, "KppTourStartToday" )}, // 島内放送|今日が、初めて島の誰かにかっぺいツアー開始告知をした当日 + {0x219, new EventFlagLand(0 , 1 , 0537, "RcoUnlockBridgeSlopePlus2" )}, // たぬきち|橋、坂を追加で2つ作れるようになった? + {0x21A, new EventFlagLand(0 , 1 , 0538, "UnlockCommuneExpandedBGM" )}, // コミューン島|コミューン島拡張BGMが解禁済みか? + {0x21B, new EventFlagLand(0 , 1 , 0539, "CommuneFoxShopGenuine" )}, // コミューン島|つねきちの店で今週本物が並んだ + {0x21C, new EventFlagLand(0 , 1 , 0540, "CommuneSloOpenToday" )}, // コミューン島レイジ開店当日 + {0x21D, new EventFlagLand(0 , 1 , 0541, "UnlockBuyRecipePitfallSeed" )}, // お店|おとしあなのタネのレシピの店売りを解禁するか? + {0x21E, new EventFlagLand(0 , 10 , 0542, "GrowHaniwaPieceNum" )}, // Tips|ハニワのかけらがハニワに成長した個数 + {0x21F, new EventFlagLand(0 , 1 , 0543, "UnlockSzaResetHouse" )}, // しずえ|NPCの家リセット解禁(家コーデが村の誰かのところで解禁) + {0x220, new EventFlagLand(0 , 1 , 0544, "RcoTipsDisableNoticeLoginBonus" )}, // Tips|タヌポートログボ出すの禁止か?(工事当日&大晦日にON) + }; + + private const string Unknown = "???"; + + public static string GetName(ushort index, short count, IReadOnlyDictionary str) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + { + string name = val.Name; + if (str.TryGetValue(name, out var translated)) + name = translated; + return $"{index:00} - {name} = {count}"; + } + return $"{index:00} - {Unknown} = {count}"; + } + + public static string GetName(ushort index, short count) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + return $"{index:00} - {val.Name} = {count}"; + return $"{index:00} - {Unknown} = {count}"; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Records/EventFlagPlayer.cs b/NHSE.Core/Structures/Records/EventFlagPlayer.cs index 2d7a2b0..292037e 100644 --- a/NHSE.Core/Structures/Records/EventFlagPlayer.cs +++ b/NHSE.Core/Structures/Records/EventFlagPlayer.cs @@ -1,1554 +1,1553 @@ using System.Collections.Generic; // ReSharper disable StringLiteralTypo -namespace NHSE.Core +namespace NHSE.Core; + +public class EventFlagPlayer : INamedValue { - public class EventFlagPlayer : INamedValue + // these are actually unsigned + public readonly short DefaultValue; + public readonly short MaxValue; + + public ushort Index { get; } + public string Name { get; } + + public EventFlagPlayer(short init, short max, ushort index, string name) { - // these are actually unsigned - public readonly short DefaultValue; - public readonly short MaxValue; - - public ushort Index { get; } - public string Name { get; } - - public EventFlagPlayer(short init, short max, ushort index, string name) - { - Name = name; - Index = index; - DefaultValue = init; - MaxValue = max; - } - - public static readonly IReadOnlyDictionary List = new Dictionary - { - {0x002, new EventFlagPlayer(0 , 9 , 0002, "PrologueNpcHintCount" )}, // NPCの序盤ヒントをいくつまで聞いたか - {0x003, new EventFlagPlayer(0 , 31 , 0003, "TotakekeLiveCount" )}, // とたけけライブを聴いた回数 - {0x008, new EventFlagPlayer(0 , 1 , 0008, "JohnnyQuestStartFlag" )}, // ジョニークエスト開始フラグ(海賊ジョニーは別フラグ) - {0x009, new EventFlagPlayer(0 , 1 , 0009, "JohnnyQuestFinishFlag" )}, // ジョニークエスト完了フラグ(海賊ジョニーは別フラグ) - {0x00A, new EventFlagPlayer(0 , 8 , 0010, "JonnyTalkCount" )}, // 寝ているジョニーに話しかけた回数(海賊ジョニー共用) - {0x00B, new EventFlagPlayer(0 , 1 , 0011, "HasPlayedTreasureHunt" )}, // 宝探しクエストをした事がある - {0x00D, new EventFlagPlayer(0 , 1 , 0013, "ShizueCmnExplanationTowntune" )}, // しずえ|メロ説明聞いたか? - {0x00E, new EventFlagPlayer(0 , 1 , 0014, "ShizueCmnExplanationTownflag" )}, // しずえ|村の旗説明聞いたか? - {0x00F, new EventFlagPlayer(0 , 1 , 0015, "ShizueCmnExplanationComplaint" )}, // しずえ|『村民のこと』の説明聞いたか? - {0x011, new EventFlagPlayer(0 , 1 , 0017, "FutaTalkedWhenAsleep" )}, // フータ|寝てる時に話かけたことがある? - {0x012, new EventFlagPlayer(0 , 1 , 0018, "FutaExplanationDonationComp" )}, // フータ|博物館コンプの報告を受けたか? - {0x013, new EventFlagPlayer(0 , 1 , 0019, "FutaTalkedInMuseumToday" )}, // フータ|博物館内で今日会話した? - {0x014, new EventFlagPlayer(0 , 1 , 0020, "FutaHeardCommentary" )}, // フータ|コレってなに?で解説聞いた? - {0x015, new EventFlagPlayer(0 , 1 , 0021, "FutaReadyForMuseum" )}, // フータ|博物館建設条件達成の報告聞いた? - {0x016, new EventFlagPlayer(0 , 1 , 0022, "FutaReadyForMuseumToday" )}, // フータ|今日博物館の条件達成した当日か? - {0x017, new EventFlagPlayer(0 , 1 , 0023, "KaburibaTalkTodayFlag" )}, // ウリ|今日すでに会話した? - {0x018, new EventFlagPlayer(0 , 1 , 0024, "KaburibaTalkBeforeFlag" )}, // ウリ|今までに会話したことある? - {0x019, new EventFlagPlayer(0 , 1 , 0025, "KaburibaBuyKabuTodayFlag" )}, // ウリ|今日カブ買った? - {0x01A, new EventFlagPlayer(0 , 1 , 0026, "KinuyoTalkBoforeFlag" )}, // きぬよ|今までに会話したことある? - {0x01B, new EventFlagPlayer(0 , 1 , 0027, "KinuyoTalkTodayFlag" )}, // きぬよ|今日すでに会話した?(来訪用) - {0x01D, new EventFlagPlayer(0 , 1 , 0029, "SkkTalkBeforeFlag" )}, // シャンク|今までに会話したことある? - {0x01F, new EventFlagPlayer(0 , 1 , 0031, "ReijiTalkBeforeFlag" )}, // レイジ|今までに会話したことある?(面識ある?) - {0x021, new EventFlagPlayer(0 , 1 , 0033, "RollanTalkTodayFlag" )}, // ローラン|今日すでに会話した? - {0x022, new EventFlagPlayer(0 , 3 , 0034, "RollanBuyLargeCount" )}, // ローラン|今日ラグ大を買った枚数 - {0x023, new EventFlagPlayer(0 , 3 , 0035, "RollanBuyMediumCount" )}, // ローラン|今日ラグ中を買った枚数 - {0x024, new EventFlagPlayer(0 , 3 , 0036, "RollanBuySmallCount" )}, // ローラン|今日ラグ小を買った枚数 - {0x025, new EventFlagPlayer(0 , 1 , 0037, "RcmTalkBeforeFlag" )}, // まめきち|店内で会話したことある? - {0x026, new EventFlagPlayer(0 , 1 , 0038, "RcmTookReqMarket" )}, // まめきち|商店設置場所決め依頼された - {0x027, new EventFlagPlayer(0 , 1 , 0039, "RcmDeclinedMarketReq" )}, // まめきち|商店設置場所決め依頼を断ったことある - {0x028, new EventFlagPlayer(0 , 1 , 0040, "DoneCharacterCreation" )}, // キャラメイク完了 - {0x029, new EventFlagPlayer(0 , 1 , 0041, "RcmNoTurnipSellToday" )}, // まめきち|カブ買取不可の説明今日受けた? - {0x02C, new EventFlagPlayer(0 , 1 , 0044, "ValidatePlayerSaveFlag" )}, // プレイヤーセーブデータが有効化された - {0x02D, new EventFlagPlayer(0 , 1 , 0045, "MakeVillagePlayerFlag" )}, // 村民代表か? - {0x02E, new EventFlagPlayer(0 , 1 , 0046, "PrologueDone1stTalkAtPlaza" )}, // 1P序盤|広場での最初の会話終わった? - {0x02F, new EventFlagPlayer(0 , 1 , 0047, "HighAndLowPlayed" )}, // ミニゲームのハイ&ローをプレイした事がある - {0x030, new EventFlagPlayer(0 , 1 , 0048, "HappyHomeMission1" )}, // HHA/ハッピーホームでミッション1をクリヤーした - {0x033, new EventFlagPlayer(0 , 1 , 0051, "OccurrenceCoinStone" )}, // コイン岩を発生させたか - {0x034, new EventFlagPlayer(0 , 1 , 0052, "HappyHomeMission2" )}, // HHA/ハッピーホームでミッション2をクリヤーした - {0x035, new EventFlagPlayer(0 , 1 , 0053, "SeoRejectFlag" )}, // ラコスケ|ホタテ渡すの断った? - {0x036, new EventFlagPlayer(0 , 1 , 0054, "HappyHomeMission3" )}, // HHA/ハッピーホームでミッション3をクリヤーした - {0x03B, new EventFlagPlayer(0 , 999 , 0059, "CatchFishFesCount" )}, // つり大会|保持している大会ポイント - {0x03C, new EventFlagPlayer(0 , 999 , 0060, "CatchInsectFesCount" )}, // ムシとり大会|保持している大会ポイント - {0x03D, new EventFlagPlayer(0 , 1 , 0061, "PlayerPocketUIEnable" )}, // プレイヤー|ポケットUI解禁 - {0x03E, new EventFlagPlayer(0 , 1 , 0062, "PlayerMainUImenuEnable" )}, // プレイヤー|メイン(スマホ)UI解禁 - {0x03F, new EventFlagPlayer(0 , 1 , 0063, "Prologue4AfterBuiltPcTent" )}, // たぬきち|自宅テント設営後に話した? - {0x040, new EventFlagPlayer(0 , 1 , 0064, "RcoHearedWhatShouldIAsk" )}, // たぬきち|『何聞けばいい?』を聞いた - {0x042, new EventFlagPlayer(0 , 1 , 0066, "Prologue4OwlNoMuseum" )}, // フータ|博物館設営前に話した? - {0x043, new EventFlagPlayer(0 , 1 , 0067, "Prologue4OwlGetTent" )}, // フータ|テントを受け取ったか? - {0x044, new EventFlagPlayer(0 , 1 , 0068, "Prologue4OwlBuiltMuseum" )}, // フータ|のテント設営後に話した? - {0x045, new EventFlagPlayer(0 , 1 , 0069, "Prologue4RcmNoShop" )}, // まめきち|商店設営前に話した? - {0x046, new EventFlagPlayer(0 , 1 , 0070, "Prologue4RcmGetTent" )}, // まめきち|お店の工事看板を受け取ったか? - {0x047, new EventFlagPlayer(0 , 1 , 0071, "Prologue4RcmBuiltShop" )}, // まめきち|お店の工事看板設営後に話した? - {0x048, new EventFlagPlayer(0 , 1 , 0072, "Prologue4HaNoTent" )}, // 初期HA|テント設営前に話した? - {0x049, new EventFlagPlayer(0 , 1 , 0073, "Prologue4HaGetTent" )}, // 初期HA|テントを受け取ったか? - {0x04A, new EventFlagPlayer(0 , 1 , 0074, "Prologue4HaBuiltTent" )}, // 初期HA|テント設営後に話した? - {0x04B, new EventFlagPlayer(0 , 1 , 0075, "Prologue4AnNoTent" )}, // 初期AN|テント設営前に話した? - {0x04C, new EventFlagPlayer(0 , 1 , 0076, "Prologue4AnGetTent" )}, // 初期AN|テントを受け取ったか? - {0x04D, new EventFlagPlayer(0 , 1 , 0077, "Prologue4AnBuiltTent" )}, // 初期AN|テント設営後に話した? - {0x04E, new EventFlagPlayer(0 , 1 , 0078, "BirthdayNGavePresentFlag" )}, // NPC誕生日|ホストにプレゼントを渡した? - {0x04F, new EventFlagPlayer(0 , 1 , 0079, "BirthdayPCandleFlag" )}, // プレイヤー誕生日|ローソク吹き消した? - {0x050, new EventFlagPlayer(0 , 1 , 0080, "BirthdayPNotPresentFlag" )}, // プレイヤー誕生日|プレゼントもらえなかった? - {0x052, new EventFlagPlayer(0 , 1 , 0082, "SickQuestFirst" )}, // 病気クエストをクリアしたことがあるか? - {0x053, new EventFlagPlayer(0 , 1 , 0083, "TotakekeTalkBeforeFlag" )}, // とたけけ|今までに会話したことある? - {0x054, new EventFlagPlayer(0 , 1 , 0084, "JohnnyTalkBeforeFlag" )}, // ジョニー|今までに会話したことある?(海賊ジョニーは別フラグ) - {0x055, new EventFlagPlayer(0 , 1 , 0085, "KotonoTalkBeforeFlag" )}, // ことの|今までに会話したことある? - {0x056, new EventFlagPlayer(0 , 1 , 0086, "RollanTalkBeforeFlag" )}, // ローラン|今までに会話したことある? - {0x058, new EventFlagPlayer(0 , 1 , 0088, "TunekichiTalkBefore" )}, // つねきち|今までに会話したことある? - {0x059, new EventFlagPlayer(0 , 128 , 0089, "KotonoQuestCount" )}, // ことの|ことのとの親密度 - {0x05A, new EventFlagPlayer(0 , 1 , 0090, "KotonoQuestStartFlag" )}, // ことの|クエスト開始 - {0x05B, new EventFlagPlayer(0 , 1 , 0091, "KotonoQuestClearFlag" )}, // ことの|クエスト完了 - {0x05C, new EventFlagPlayer(0 , 1 , 0092, "KotonoQuestRefuseFlag" )}, // ことの|クエスト断った? - {0x05D, new EventFlagPlayer(0 , 1 , 0093, "MainmenuEncyclopedia" )}, // スマホUI|図鑑解禁 - {0x05E, new EventFlagPlayer(0 , 1 , 0094, "MainmenuMap" )}, // スマホUI|マップ解禁 - {0x05F, new EventFlagPlayer(0 , 1 , 0095, "MainmenuMydesign" )}, // スマホUI|マイデザイン解禁 - {0x060, new EventFlagPlayer(0 , 1 , 0096, "MainmenuBank" )}, // スマホUI|モバイルバンク解禁 - {0x061, new EventFlagPlayer(0 , 1 , 0097, "RcmTalked1P1stday" )}, // まめきち|1Pが初日にテントで会話した? - {0x062, new EventFlagPlayer(0 , 1 , 0098, "HappyHomeMission4" )}, // HHA/ハッピーホームでミッション4をクリヤーした - {0x063, new EventFlagPlayer(0 , 1 , 0099, "RcoHeardDetailDIYtrial" )}, // たぬきち|DIY体験の材料の説明聞いた? - {0x064, new EventFlagPlayer(0 , 1 , 0100, "SzaTaled1stTime" )}, // しずえ|役場内で会話したことがあるか? - {0x065, new EventFlagPlayer(0 , 1 , 0101, "HappyHomeMission5" )}, // HHA/ハッピーホームでミッション5をクリヤーした - {0x066, new EventFlagPlayer(0 , 1 , 0102, "HappyHomeMission6" )}, // HHA/ハッピーホームでミッション6をクリヤーした - {0x06B, new EventFlagPlayer(0 , 1 , 0107, "OdekakeTutorial" )}, // 空港|モーリー|おでかけ初回説明済? - {0x06C, new EventFlagPlayer(0 , 1 , 0108, "OdekakeTutorialKeyword" )}, // 空港|モーリー|おでかけあいことばマッチメイク初回説明済? - {0x06E, new EventFlagPlayer(0 , 1 , 0110, "RcoGotWorkingwear" )}, // たぬきち|アルバイトの服もらった? - {0x06F, new EventFlagPlayer(0 , 1 , 0111, "RcoHeardWorkExplain1" )}, // たぬきち|1つ目の仕事内容聞いた? - {0x070, new EventFlagPlayer(0 , 1 , 0112, "RcoHeardWorkExplain2" )}, // たぬきち|2つ目の仕事内容聞いた? - {0x071, new EventFlagPlayer(0 , 1 , 0113, "RcoFinishMakingAxe" )}, // たぬきち|チュートリアル斧作り終えた? - {0x072, new EventFlagPlayer(0 , 1 , 0114, "OdekakeFirstTalk" )}, // 空港|モーリー|おでかけ初めて話しかけた? - {0x073, new EventFlagPlayer(0 , 1 , 0115, "OdekakeFirstOpenGate" )}, // 空港|モーリー|おでかけ始めて改札を開けた説明済? - {0x07E, new EventFlagPlayer(0 , 1 , 0126, "SzaGotDiyRecipe001" )}, // しずえ|しずえDIYレシピ1もらった? - {0x07F, new EventFlagPlayer(0 , 1 , 0127, "OwlGotDiyRecipe001" )}, // フータ|フータDIYレシピ1もらった? - {0x080, new EventFlagPlayer(0 , 1 , 0128, "TownNewsHeard1st" )}, // 村内放送|村内放送を聞いた事がある? - {0x083, new EventFlagPlayer(0 , 1 , 0131, "GyroidPlazaTalk1st" )}, // 募金ハニワくん|広場募金ハニワくんと話した? - {0x084, new EventFlagPlayer(0 , 1 , 0132, "PlayerLoanRepaying" )}, // ローン返済中? - {0x085, new EventFlagPlayer(0 , 1 , 0133, "PlayerLoanFinish1st" )}, // ローン完済した? - {0x086, new EventFlagPlayer(0 , 1 , 0134, "RcoHeardRemodel1" )}, // 増築提案受けた? - {0x087, new EventFlagPlayer(0 , 1 , 0135, "UsedCoinStone" )}, // コイン岩を使ったか - {0x088, new EventFlagPlayer(0 , 1 , 0136, "OwlFinished1stTalk" )}, // フータ|初対面挨拶したか? - {0x089, new EventFlagPlayer(0 , 1 , 0137, "OwlTalkDuringConst1" )}, // フータ|テント→博物館工事中に会話したか? - {0x08A, new EventFlagPlayer(0 , 1 , 0138, "OwlDonationDone" )}, // フータ|博物館(テント)で寄贈したことある? - {0x08B, new EventFlagPlayer(0 , 1 , 0139, "Owl1stTalkMuseum1" )}, // フータ|博物館①完成後の挨拶した? - {0x08C, new EventFlagPlayer(0 , 1 , 0140, "EnableEmoticonUI" )}, // 漫符UI解禁 - {0x08D, new EventFlagPlayer(0 , 1 , 0141, "RcoDoneDIYmyself" )}, // たぬきち|たぬきちテント内で自分でDIYしたことがある? - {0x08E, new EventFlagPlayer(0 , 1 , 0142, "RcoOrderedHouseBuilt" )}, // たぬきち|家建築申し込み当日? - {0x08F, new EventFlagPlayer(0 , 1 , 0143, "RcmHeardAboutRenual" )}, // まめきち|改装告知聞いた? - {0x090, new EventFlagPlayer(0 , 1 , 0144, "RcmHeardAboutNewOpen1" )}, // まめきち|新装開店の案内聞いた?(商店・小) - {0x091, new EventFlagPlayer(0 , 1 , 0145, "RcmHeardAboutNewOpen2" )}, // まめきち|新装開店の案内聞いた?(商店・大) - {0x096, new EventFlagPlayer(0 , 1 , 0150, "ChmTalkRuleFirst" )}, // [大会]レックス|初回ルール説明聞いたか? - {0x097, new EventFlagPlayer(0 , 1 , 0151, "ChmQuestFinish" )}, // [大会]レックス|結果発表あるか? - {0x099, new EventFlagPlayer(0 , 1 , 0153, "ChmTalkPoint_BeforeEv" )}, // [大会]レックス|受付前、ポイント交換のお誘い聞いた? - {0x09A, new EventFlagPlayer(0 , 1 , 0154, "ChmTalkFirst_EvQuestFinish" )}, // [大会]レックス|今日大会クエストしたか? - {0x09B, new EventFlagPlayer(0 , 1 , 0155, "ChmTalkFirst_AfterEv" )}, // [大会]レックス|受付終了後、初回会話聞いた? - {0x09C, new EventFlagPlayer(0 , 1 , 0156, "RcoGotDonationRewardFlower" )}, // たぬきち|虫魚提供報酬の花をもらった当日? - {0x09F, new EventFlagPlayer(0 , 1 , 0159, "TownNewsHeardTownHallOpenFlag" )}, // 村内放送|案内所が建った告知(しずえ引継ぎ)を聞いた? - {0x0A0, new EventFlagPlayer(0 , 1 , 0160, "TownNewsHeardShopOpen1Flag" )}, // 村内放送|商店の新装開店告知を聞いた?(商店・小) - {0x0A1, new EventFlagPlayer(0 , 1 , 0161, "TownNewsHeardShopOpen2Flag" )}, // 村内放送|商店の新装開店告知を聞いた?(商店・大) - {0x0A3, new EventFlagPlayer(0 , 1 , 0163, "TownNewsHeardMuseumOpenFlag" )}, // 村内放送|博物館建物が建った告知を聞いた? - {0x0A5, new EventFlagPlayer(0 , 1 , 0165, "TownNewsHeardMuseumCafeOpenFlag" )}, // 村内放送|ミュージアムカフェのオープン告知を聞いた? - {0x0A6, new EventFlagPlayer(0 , 1 , 0166, "MarvelAtCockroarchToday" )}, // ゴキブリに驚いた - {0x0A7, new EventFlagPlayer(0 , 1 , 0167, "GstTalkBefore" )}, // ゆうたろう|今までに会話したことある? - {0x0A8, new EventFlagPlayer(0 , 1 , 0168, "GstQuestStartFlag" )}, // ゆうたろう|クエスト発生中? - {0x0A9, new EventFlagPlayer(0 , 1 , 0169, "GstQuestClearFlag" )}, // ゆうたろう|今日クエストクリアした? - {0x0AA, new EventFlagPlayer(0 , 1 , 0170, "GstQuestBreakFlag" )}, // ゆうたろう|一度クエスト発生させてゲーム終了した? - {0x0AB, new EventFlagPlayer(0 , 1 , 0171, "MainmenuRecipe" )}, // スマホUI|レシピ解禁 - {0x0AC, new EventFlagPlayer(0 , 1 , 0172, "PurchaseBoxUseTodayFlag" )}, // 時間外買取BOX|今日すでに利用した? - {0x0B1, new EventFlagPlayer(0 , 1 , 0177, "TownNewsHeardEventOpen" )}, // 村内放送|イベント開始時の村内放送を聞いたことがある? - {0x0B2, new EventFlagPlayer(0 , 1 , 0178, "PostHasNewMessage" )}, // ポスト|新着メッセージカードがある? - {0x0B4, new EventFlagPlayer(0 , 1 , 0180, "EnablePcTownDecoration" )}, // フィールド家具配置解禁 - {0x0B5, new EventFlagPlayer(1 , 1 , 0181, "KaburibaConditionFlag" )}, // ウリ|プレイヤーが住む前から来訪していた? - {0x0B6, new EventFlagPlayer(0 , 1 , 0182, "SzaHeardSonkatsuExplain" )}, // しずえ|村活のことの説明聞いた? - {0x0B7, new EventFlagPlayer(0 , 1 , 0183, "SzaHeardMuraokoshiExplain" )}, // しずえ|村おこしのことの説明聞いた? - {0x0B8, new EventFlagPlayer(0 , 1 , 0184, "SzaHeardAboutHousingKit" )}, // たぬきち|土地確保解禁の説明聞いた? - {0x0BA, new EventFlagPlayer(0 , 1 , 0186, "SeoFirstFlag" )}, // ラコスケ|ホタテを渡したことある? - {0x0BF, new EventFlagPlayer(0 , 1 , 0191, "FoxTalkTodayFlag" )}, // つねきち|今日本島に来訪したつねきちと会話した? - {0x0C0, new EventFlagPlayer(0 , 1 , 0192, "FoxBuyTodayFlag" )}, // つねきち|今日いなりマーケットで買い物した? - {0x0C1, new EventFlagPlayer(0 , 1 , 0193, "FoxBuyArtTodayFlag" )}, // つねきち|今日いなりマーケットで美術品買った? - {0x0C2, new EventFlagPlayer(0 , 1 , 0194, "TownNewsHeardEventSpaceOpenFlag" )}, // 村内放送|村内放送でイベント広場が完成した告知を聞いた? - {0x0C3, new EventFlagPlayer(0 , 1 , 0195, "PcDidNotKnowKK" )}, // プレイヤー|序盤にとたけけ知らないと答えた - {0x0C4, new EventFlagPlayer(0 , 1 , 0196, "RcoAfterHouseRemodel" )}, // たぬきち|家増築後の説明発生する? - {0x0C6, new EventFlagPlayer(0 , 1 , 0198, "HeardAboutBuildingTownOffice" )}, // しずえ|役場建設開始の説明聞いた? - {0x0C7, new EventFlagPlayer(0 , 1 , 0199, "PgeTalkTodayFlag" )}, // マスター|今日すでに会話した? - {0x0C8, new EventFlagPlayer(0 , 1 , 0200, "PgeItemGetFirstFlag" )}, // マスター|今日アイテムもらった? - {0x0C9, new EventFlagPlayer(0 , 50 , 0201, "PgeRegularCount" )}, // マスター|常連度 - {0x0CA, new EventFlagPlayer(0 , 1 , 0202, "PgeTalkValentineFlag" )}, // マスター|今日バレンタインでコーヒー飲んだ? - {0x0CB, new EventFlagPlayer(0 , 1 , 0203, "PgeTalkBirthdayFlag" )}, // マスター|今日誕生日などイベント系の会話した? - {0x0CD, new EventFlagPlayer(0 , 1 , 0205, "RcoFenceShoppingExplain" )}, // たぬきち|柵購入の説明を受けたことがある? - {0x0CE, new EventFlagPlayer(0 , 1 , 0206, "Ttl1stmet" )}, // コトブキ|初対面会話済か? - {0x0CF, new EventFlagPlayer(1 , 5 , 0207, "PcTownmakeLv" )}, // プレイヤーの村づくりライセンスレベル - {0x0D0, new EventFlagPlayer(0 , 1 , 0208, "PcUpgradeTownmakeToday" )}, // 今日上級村づくりライセンスを入手したか? - {0x0D1, new EventFlagPlayer(0 , 1 , 0209, "PcHousingLoanFinish" )}, // 住宅ローン完全終了 - {0x0D2, new EventFlagPlayer(0 , 1 , 0210, "PgeCoffeeTodayFlag" )}, // マスター|今日コーヒーかホットチョコレート注文した? - {0x0D3, new EventFlagPlayer(0 , 1 , 0211, "RcoGetTvForCongratsHouse" )}, // たぬきち|新築祝いもらった? - {0x0D4, new EventFlagPlayer(0 , 1 , 0212, "RcoItemFullForTv" )}, // たぬきち|新築祝いもらう時アイテムいっぱいだった - {0x0D7, new EventFlagPlayer(0 , 1 , 0215, "PlayerEnableEating" )}, // プレイヤー|『食べる』解禁 - {0x0D8, new EventFlagPlayer(0 , 1 , 0216, "PlayerStungByBee" )}, // プレイヤー|ハチにさされたか? - {0x0D9, new EventFlagPlayer(0 , 1 , 0217, "GetEmoticonTodayFlag" )}, // 今日すでに漫符を入手した? - {0x0DA, new EventFlagPlayer(0 , 1 , 0218, "BevTalkRuleFirst" )}, // [大会]ジャスティン|初回ルール説明聞いたか? - {0x0DB, new EventFlagPlayer(0 , 1 , 0219, "BevQuestFinish" )}, // [大会]ジャスティン|結果発表あるか? - {0x0DD, new EventFlagPlayer(0 , 1 , 0221, "BevTalkPoint_BeforeEv" )}, // [大会]ジャスティン|受付前ポイント交換のお誘い聞いた? - {0x0DE, new EventFlagPlayer(0 , 1 , 0222, "BevTalkFirst_EvQuestFinish" )}, // [大会]ジャスティン|今日クエストしたか? - {0x0DF, new EventFlagPlayer(0 , 1 , 0223, "BevTalkFirst_AfterEv" )}, // [大会]ジャスティン|受付終了後、初回会話聞いた? - {0x0E9, new EventFlagPlayer(0 , 1 , 0233, "TutorialFinishAndPast1day" )}, // 序盤シーケンス終了後1日以上経過 - {0x0EA, new EventFlagPlayer(0 , 1 , 0234, "HasGottenToolChangeStick" )}, // 変身ステッキを入手したことがあるか? - {0x0EB, new EventFlagPlayer(0 , 1 , 0235, "GetBirthdayTable" )}, // 今年バースデーテーブルを貰った - {0x0EC, new EventFlagPlayer(0 , 1 , 0236, "GetBirthdayCandle" )}, // 今年バースデーキャンドルを貰った - {0x0ED, new EventFlagPlayer(0 , 1 , 0237, "GetBirthdayHat" )}, // 今年バースデーハットを貰った - {0x0EE, new EventFlagPlayer(0 , 1 , 0238, "GetBirthdayBoard" )}, // 今年バースデーボードを貰った - {0x0EF, new EventFlagPlayer(0 , 1 , 0239, "GetBirthdaySunglasses" )}, // 今年バースデーサングラスを貰った - {0x0F6, new EventFlagPlayer(0 , 1 , 0246, "MainUiClockEnable" )}, // SYS|時計表示ON - {0x0F7, new EventFlagPlayer(0 , 1 , 0247, "PrologueAfterBuiltTentTalk" )}, // 序盤|テント設営後の広場会話終わった - {0x0F8, new EventFlagPlayer(0 , 1 , 0248, "PrologueForCampfire1" )}, // 序盤|キャンプ材料集めの話聞いた(1) - {0x0F9, new EventFlagPlayer(0 , 1 , 0249, "PlayerPickupEnable" )}, // SYS|プレイヤー|拾う(Y)解禁 - {0x0FA, new EventFlagPlayer(0 , 1 , 0250, "HaveTownFruit4CampFire" )}, // 序盤|特産果物揃った状態でたぬきちに話しかけた - {0x0FB, new EventFlagPlayer(0 , 1 , 0251, "PrologueForCampfire2" )}, // 序盤|キャンプ材料集めの話聞いた(2) - {0x0FC, new EventFlagPlayer(0 , 1 , 0252, "SzaTalkBeforeCountdown" )}, // しずえ|年越し前に話した? - {0x0FD, new EventFlagPlayer(0 , 1 , 0253, "SzaTalkAfterCountdown" )}, // しずえ|年越し後に話した? - {0x0FE, new EventFlagPlayer(0 , 1 , 0254, "SzaGotNewYearHat" )}, // しずえ|スティックライトもらった? - {0x0FF, new EventFlagPlayer(0 , 1 , 0255, "SzaGotCracker" )}, // たぬきち|クラッカーもらった? - {0x100, new EventFlagPlayer(0 , 1 , 0256, "PrologueStartedCampfire" )}, // プロローグ|キャンプファイヤー開始 - {0x101, new EventFlagPlayer(0 , 1 , 0257, "AllowPcTentEntering" )}, // 〔序盤〕プレイヤー自宅テント入場解禁 - {0x102, new EventFlagPlayer(0 , 1 , 0258, "TkkTalkToday" )}, // とたけけ|今日すでに会話した? - {0x103, new EventFlagPlayer(0 , 1 , 0259, "TkkLiveToday" )}, // とたけけ|今日ライブを聴いた? - {0x104, new EventFlagPlayer(0 , 1 , 0260, "PcMaingameStart" )}, // プロローグ終了~本番ゲーム開始~ - {0x105, new EventFlagPlayer(0 , 1 , 0261, "TkkGetMusicToday" )}, // とたけけ|今日ミュージックをもらった? - {0x106, new EventFlagPlayer(0 , 100 , 0262, "MoveNpcTradeSkipCount" )}, // 引越交換処理スキップカウント - {0x107, new EventFlagPlayer(0 , 1 , 0263, "RcoTalked1stAfterPrologue" )}, // たぬきち|序盤終了後初会話した? - {0x108, new EventFlagPlayer(0 , 1 , 0264, "RcmTalked1stAfterPrologue" )}, // まめきち|序盤終了後初会話した? - {0x109, new EventFlagPlayer(0 , 1 , 0265, "RcoTentAdviceCanceled" )}, // たぬきち|テントのアドバイスキャンセルしたことある - {0x10A, new EventFlagPlayer(0 , 1 , 0266, "RcoHeardAboutMyhome" )}, // たぬきち|『お家のこと』初めて聞いた? - {0x10B, new EventFlagPlayer(0 , 1 , 0267, "PlayerFirstShootDownBalloon" )}, // 風船を初めて撃ち落とした? - {0x10C, new EventFlagPlayer(0 , 1 , 0268, "PrologueFinishTkkDream" )}, // 序盤|とたけけの夢終了 - {0x10D, new EventFlagPlayer(0 , 1 , 0269, "RcoPaid1stCharge" )}, // たぬきち|移住費用支払い完了 - {0x10E, new EventFlagPlayer(0 , 1 , 0270, "RcoTentEnableDIYtrial" )}, // たぬきち|DIY体験選択肢解禁 - {0x10F, new EventFlagPlayer(0 , 1 , 0271, "RcoDIYtrialOngoing" )}, // たぬきち|DIY体験中 - {0x110, new EventFlagPlayer(0 , 1 , 0272, "RcoDIYtrialGetMaterial" )}, // たぬきち|DIY体験中に材料揃った状態でたぬきちに話しかけた - {0x111, new EventFlagPlayer(0 , 1 , 0273, "RcoTentDonation" )}, // たぬきち|たぬきちに虫魚預けたことある - {0x112, new EventFlagPlayer(0 , 1 , 0274, "RcoTentDonatinDeclined" )}, // たぬきち|たぬきちに虫魚預けるのを断ったことある - {0x113, new EventFlagPlayer(0 , 1 , 0275, "EnableBuildMuseumTent" )}, // 博物館テント設置条件満たした - {0x114, new EventFlagPlayer(0 , 1 , 0276, "RcoTookRequestMuseum" )}, // たぬきち|博物館テント設置場所決め依頼された - {0x115, new EventFlagPlayer(0 , 1 , 0277, "DecidedMuseumTentPlace" )}, // 博物館テント設営場所確定した - {0x116, new EventFlagPlayer(0 , 1 , 0278, "RcoDeclinedMuseumReq" )}, // たぬきち|博物館設置場所決め依頼を断ったことある - {0x11C, new EventFlagPlayer(0 , 1 , 0284, "RcmDeclinedQuestReq" )}, // まめきち|商店建築の材料集め依頼を断ったことがある - {0x11D, new EventFlagPlayer(0 , 1 , 0285, "RcmTookQuestReq" )}, // まめきち|商店建築の材料集め依頼された - {0x11E, new EventFlagPlayer(0 , 1 , 0286, "JohnnyAnotherPlayerClearFlag" )}, // ジョニー|クエスト発生後に他のプレイヤーがクリアした?(海賊ジョニーは別フラグ) - {0x124, new EventFlagPlayer(0 , 1 , 0292, "NnpcFinishHintTalk" )}, // NPCの序盤ヒント会話を聞き終えた - {0x12A, new EventFlagPlayer(0 , 11 , 0298, "HgsCloseness" )}, // あさみ|あさみとの親密度 - {0x12B, new EventFlagPlayer(0 , 1 , 0299, "HgsTalkTodayFlag" )}, // あさみ|今日すでに会話した? - {0x12C, new EventFlagPlayer(0 , 3 , 0300, "NnpcApproachNoEmoticonCount" )}, // アプローチ会話|漫符入手会話を見ないまま経過したプレイ日数 - {0x12D, new EventFlagPlayer(0 , 1 , 0301, "HgsAllowAddFriendship" )}, // あさみ|親密度加算許可 - {0x12F, new EventFlagPlayer(0 , 1 , 0303, "MainmenuCall" )}, // スマホUI|住人呼び出し解禁 - {0x130, new EventFlagPlayer(0 , 1 , 0304, "EmergencyEscapeExplain" )}, // 緊急脱出|説明聞いた - {0x132, new EventFlagPlayer(0 , 1 , 0306, "HHAGradeMailFlag" )}, // HHA|評価の手紙送付ON? - {0x133, new EventFlagPlayer(0 , 1 , 0307, "EnableSmatDeviceNortification" )}, // スマホUI|通知機能有効化 - {0x134, new EventFlagPlayer(0 , 1 , 0308, "CatchFishFes_Bonus" )}, // つり大会|到達ボーナスある? - {0x135, new EventFlagPlayer(0 , 1 , 0309, "CatchFishFes_CooperativeBonus" )}, // つり大会|通信ボーナスある? - {0x136, new EventFlagPlayer(0 , 1 , 0310, "CatchInsectFes_Bonus" )}, // ムシとり大会|到達ボーナスある? - {0x137, new EventFlagPlayer(0 , 1 , 0311, "CatchInsectFes_CooperativeBonus" )}, // ムシとり大会|通信ボーナスある? - {0x138, new EventFlagPlayer(0 , 1 , 0312, "LookNpcHouseVisitNpc" )}, // 他のNPCの家に訪問中のNPCを見た - {0x139, new EventFlagPlayer(0 , 1 , 0313, "MainmenuFriendList" )}, // スマホUI|フレンドリスト解禁 - {0x13A, new EventFlagPlayer(1 , 1 , 0314, "FriendListMainSwitch" )}, // フレンドリストUI|メインスイッチ - {0x13B, new EventFlagPlayer(0 , 1 , 0315, "SnowmanGotDay1Flag" )}, // ゆきだるま|今日すでに1日目の報酬もらった? - {0x13C, new EventFlagPlayer(0 , 1 , 0316, "SnowmanGotDay2Flag" )}, // ゆきだるま|今日すでに2日目の報酬もらった? - {0x13D, new EventFlagPlayer(0 , 1 , 0317, "SnowmanGotDay3Flag" )}, // ゆきだるま|今日すでに3日目の報酬もらった? - {0x13E, new EventFlagPlayer(0 , 1 , 0318, "SnowmanGotDay4Flag" )}, // ゆきだるま|今日すでに4日目の報酬もらった? - {0x13F, new EventFlagPlayer(0 , 1 , 0319, "MainmenuOnlineShopping" )}, // スマホUI|カタログショッピング解禁 - {0x140, new EventFlagPlayer(0 , 1 , 0320, "MainmenuRndDailyQuest" )}, // スマホUI|マイレージ+解禁 - {0x141, new EventFlagPlayer(0 , 1 , 0321, "MainmenuAchievement" )}, // スマホUI|実績(たぬきマイル)解禁 - {0x143, new EventFlagPlayer(0 , 1 , 0323, "SnowmanBuildFlag" )}, // ゆきだるま|作ったことある? - {0x144, new EventFlagPlayer(0 , 1 , 0324, "SnowmanFirstBuildTodayFlag" )}, // ゆきだるま|今日初めてゆきだるまを作った? - {0x146, new EventFlagPlayer(0 , 1 , 0326, "ObjRcoMachineCheck1st" )}, // OBJ|たぬポートにアクセスしたことがある? - {0x148, new EventFlagPlayer(0 , 100 , 0328, "ReservedNpcGroupActivityMorning" )}, // 朝の時間帯にNPCの集団行動が予約されているか - {0x149, new EventFlagPlayer(0 , 100 , 0329, "ReservedNpcGroupActivityNoon" )}, // 昼の時間帯にNPCの集団行動が予約されているか - {0x14A, new EventFlagPlayer(0 , 100 , 0330, "ReservedNpcGroupActivityEvening" )}, // 夕方の時間帯にNPCの集団行動が予約されているか - {0x14B, new EventFlagPlayer(0 , 100 , 0331, "ReservedNpcGroupActivityNignt" )}, // 夜の時間帯にNPCの集団行動が予約されているか - {0x14D, new EventFlagPlayer(0 , 1 , 0333, "RcoMoveHouseReserved" )}, // たぬきち|プレイヤ家の引越しを予約しているか - {0x14E, new EventFlagPlayer(0 , 1 , 0334, "RcoChangeHouseDesignReserved" )}, // たぬきち|家外観変更の予約をしているか - {0x14F, new EventFlagPlayer(0 , 1 , 0335, "RcoMoveNpcHouseFacilityReserved" )}, // たぬきち|NPC家か施設の移設を予約しているか - {0x151, new EventFlagPlayer(0 , 1 , 0337, "PlayerSonkatsuQuestEnable" )}, // SYS|マイレージ+のカウント処理解禁 - {0x152, new EventFlagPlayer(0 , 1 , 0338, "RcoMoveShopReserved" )}, // たぬきち|お店の移設を予約している - {0x153, new EventFlagPlayer(0 , 1 , 0339, "RcoMoveMuseumReserved" )}, // たぬきち|博物館の移設を予約している - {0x154, new EventFlagPlayer(0 , 1 , 0340, "RcoMoveTailorReserved" )}, // たぬきち|仕立て屋の移設を予約している - {0x155, new EventFlagPlayer(0 , 1 , 0341, "ChyDaily_TalkFirst" )}, // レックス|面識ある?(大会、来訪共通) - {0x157, new EventFlagPlayer(0 , 1 , 0343, "BeyDaily_TalkFirst" )}, // ジャスティン|面識ある?(大会、来訪共通) - {0x158, new EventFlagPlayer(0 , 1 , 0344, "BeyDaily_QuestClear" )}, // ジャスティン|来訪クエスト達成会話聞いた? - {0x159, new EventFlagPlayer(0 , 1 , 0345, "AccessLostPropertyBox1st" )}, // 落とし物BOX|アクセスしたことがあるか? - {0x15A, new EventFlagPlayer(0 , 1 , 0346, "Mobile1stBoot_Camera" )}, // スマホアプリ初起動|カメラ - {0x15B, new EventFlagPlayer(0 , 1 , 0347, "Mobile1stBoot_MilageProgram" )}, // スマホアプリ初起動|たぬきマイレージ - {0x15C, new EventFlagPlayer(0 , 1 , 0348, "Mobile1stBoot_MilagePlus" )}, // スマホアプリ初起動|マイレージプラス - {0x15D, new EventFlagPlayer(0 , 1 , 0349, "Mobile1stBoot_Encyclopedia" )}, // スマホアプリ初起動|いきもの図鑑 - {0x15E, new EventFlagPlayer(0 , 1 , 0350, "Mobile1stBoot_DIYrecipe" )}, // スマホアプリ初起動|DIYレシピ - {0x15F, new EventFlagPlayer(0 , 1 , 0351, "Mobile1stBoot_OnlineShopping" )}, // スマホアプリ初起動|たぬきショッピング - {0x161, new EventFlagPlayer(0 , 1 , 0353, "Mobile1stBoot_Mydesign" )}, // スマホアプリ初起動|マイデザイン - {0x162, new EventFlagPlayer(0 , 1 , 0354, "Mobile1stBoot_SharePlay" )}, // スマホアプリ初起動|住人呼び出し - {0x163, new EventFlagPlayer(0 , 1 , 0355, "Mobile1stBoot_BestFriend" )}, // スマホアプリ初起動|ベストフレンド - {0x164, new EventFlagPlayer(0 , 1 , 0356, "Mobile1stBoot_Passport" )}, // スマホアプリ初起動|パスポート - {0x165, new EventFlagPlayer(0 , 1 , 0357, "Mobile1stBoot_Map" )}, // スマホアプリ初起動|マップ - {0x167, new EventFlagPlayer(0 , 1 , 0359, "Mobile1stBoot_SOS" )}, // スマホアプリ初起動|SOS - {0x168, new EventFlagPlayer(0 , 1 , 0360, "RctTalkBeforeFalg" )}, // つぶきち|オートセーブ解禁以降、会話したことあるか? - {0x169, new EventFlagPlayer(0 , 255 , 0361, "AmountHeardPublicAnnouncement" )}, // 島内放送を聞いた回数 - {0x16A, new EventFlagPlayer(0 , 1 , 0362, "SzaTalkAboutOfficeService" )}, // しずえ|案内所で工事ライセンスの説明聞いた? - {0x16B, new EventFlagPlayer(0 , 1 , 0363, "SzaFlowerQuestClear" )}, // しずえ|花を渡すおつかいをクリアした? - {0x16C, new EventFlagPlayer(0 , 1 , 0364, "RcoTalkAboutBuildBridge" )}, // xたぬきち|橋建設について説明受けた - {0x16D, new EventFlagPlayer(0 , 1 , 0365, "RcoTalkAboutBuildSlope" )}, // xたぬきち|坂建設について説明受けた - {0x16E, new EventFlagPlayer(0 , 1 , 0366, "RcoTalkAboutDeleteBridgeSlope" )}, // たぬきち|橋坂撤去について説明受けた - {0x16F, new EventFlagPlayer(0 , 1 , 0367, "RcoBuildBridgeReserved" )}, // xたぬきち|今日、橋建設を予約済み - {0x170, new EventFlagPlayer(0 , 1 , 0368, "RcoBuildSlopeReserved" )}, // xたぬきち|今日、坂建設を予約済み - {0x171, new EventFlagPlayer(0 , 1 , 0369, "RcoDeleteBridgeSlopeReserved" )}, // xたぬきち|今日、橋撤去を予約済み - {0x172, new EventFlagPlayer(0 , 1 , 0370, "RcoDeleteSlopeReserved" )}, // xたぬきち|今日、坂撤去を予約済み - {0x173, new EventFlagPlayer(0 , 1 , 0371, "OwlShowFossilMyself" )}, // フータ|化石発見の報告を受けた - {0x174, new EventFlagPlayer(0 , 1 , 0372, "RcmShowHardWood" )}, // まめきち|かたいもくざいを見せた - {0x175, new EventFlagPlayer(0 , 1 , 0373, "RcoTalkAfterMuseumTent" )}, // たぬきち|博物館テント設置場所決め後会話発動させる? - {0x176, new EventFlagPlayer(0 , 1 , 0374, "PlayerGotHardWood" )}, // プレイヤー|かたいもくざいを拾ったことがある - {0x177, new EventFlagPlayer(0 , 1 , 0375, "RcmSellCampingStuffReaction" )}, // まめきち|序盤に支給品を売却しようとした反応発生 - {0x178, new EventFlagPlayer(0 , 1 , 0376, "OBJRcoMachineChkPlusEnable" )}, // OBJ|たぬポートにプラス会員になった後話しかけた - {0x179, new EventFlagPlayer(0 , 8 , 0377, "SysCountOpenedToolManual" )}, // 道具の説明の解禁数カウント - {0x17A, new EventFlagPlayer(0 , 1 , 0378, "RcoHeardThanksForBuiltOwlTent" )}, // たぬきち|ヒントでフータテント設営お礼聞いた - {0x17C, new EventFlagPlayer(0 , 1 , 0380, "AnnouncementOwlMovedIn" )}, // 島内放送|フータ移住開始のアナウンス聞いた? - {0x17D, new EventFlagPlayer(0 , 1 , 0381, "RcmTalkAboutCupboard" )}, // まめきち|戸棚を調べて説明を受けた - {0x17E, new EventFlagPlayer(0 , 2 , 0382, "RcoDonateStatus" )}, // ×たぬきち|テント内フロー分岐用 0:DIY~ 1:生き物~ 2:(なし) - {0x17F, new EventFlagPlayer(0 , 1 , 0383, "RcoGotLoginBonusToday" )}, // タヌポート|今日ログインボーナス獲得済? - {0x180, new EventFlagPlayer(0 , 7 , 0384, "RcoMachineDailyLoginDays" )}, // タヌポート|連続ログインカウント - {0x181, new EventFlagPlayer(0 , 1 , 0385, "RcoMachineDailyLoginCheck" )}, // タヌポート|連続ログインチェック - {0x182, new EventFlagPlayer(0 , 1 , 0386, "RcoMachineEnableExchange" )}, // タヌポート|マイル交換開始の説明聞いた? - {0x183, new EventFlagPlayer(0 , 16 , 0387, "JohnnyPartsCount" )}, // ジョニー|渡したパーツの個数(海賊ジョニーは別フラグ) - {0x184, new EventFlagPlayer(0 , 9 , 0388, "BeyDaily_QuestCount" )}, // ジャスティン|指定サイズの魚を釣り上げた回数 - {0x185, new EventFlagPlayer(0 , 1 , 0389, "TalkRumorPActionTodayAnyone" )}, // 今日RumorP_Action(現在プレイヤー)を聞いたか? - {0x186, new EventFlagPlayer(0 , 1 , 0390, "TalkRumorPFavoriteTodayAnyone" )}, // 今日誰かにRumorP_Favoriteを聞いたか? - {0x188, new EventFlagPlayer(0 , 1 , 0392, "IsToolShortcutManualOpen" )}, // 道具ショートカット説明解禁済か? - {0x189, new EventFlagPlayer(0 , 1 , 0393, "RcoMachineExplainAboutPlaneTicket" )}, // タヌポート|マイル航空券の説明聞いた? - {0x18A, new EventFlagPlayer(0 , 1 , 0394, "DodExplainAboutMysteryTour" )}, // モーリー|ミステリーツアーの説明聞いた? - {0x18E, new EventFlagPlayer(0 , 1 , 0398, "IsGetMessageBottle" )}, // プレイヤ|今日メッセージボトルを拾った - {0x18F, new EventFlagPlayer(0 , 1 , 0399, "DodFirstTalkAfterPlusEnable" )}, // モーリー|初会話したのはマイレージ+解禁後? - {0x190, new EventFlagPlayer(0 , 1 , 0400, "ImmQHousingKitGetFirst" )}, // たぬきち|ハウジングキット初めてもらった - {0x191, new EventFlagPlayer(0 , 1 , 0401, "ImmQFirstExplain" )}, // たぬきち|移住クエストの最初の説明聞いた - {0x192, new EventFlagPlayer(0 , 1 , 0402, "ImmQRunningForPlayer" )}, // たぬきち|自身が移住クエスト実施中か - {0x193, new EventFlagPlayer(0 , 1 , 0403, "DodUseFirstFreeTour" )}, // モーリー|ミステリーツアーの初回無料権使った? - {0x194, new EventFlagPlayer(0 , 1 , 0404, "AppUrgentEscapeUseToday" )}, // 緊急脱出|本日利用した - {0x195, new EventFlagPlayer(0 , 1 , 0405, "AppUrgentEscapeNoPayment" )}, // 緊急脱出|前回、マイル支払ってない - {0x196, new EventFlagPlayer(0 , 1 , 0406, "ImmQSetHousingAbyMySelf" )}, // たぬきち|移住クエスト自分でハウジングA置いた - {0x197, new EventFlagPlayer(0 , 1 , 0407, "ImmQSetHousingBbyMySelf" )}, // たぬきち|移住クエスト自分でハウジングB置いた - {0x198, new EventFlagPlayer(0 , 1 , 0408, "ImmQSetHousingCbyMySelf" )}, // たぬきち|移住クエスト自分でハウジングC置いた - {0x199, new EventFlagPlayer(0 , 1 , 0409, "ImmQSetOutdoorAbyMySelf" )}, // たぬきち|移住クエスト自分で外置き家具A置いた - {0x19A, new EventFlagPlayer(0 , 1 , 0410, "ImmQSetOutdoorBbyMySelf" )}, // たぬきち|移住クエスト自分で外置き家具B置いた - {0x19B, new EventFlagPlayer(0 , 1 , 0411, "ImmQSetOutdoorCbyMySelf" )}, // たぬきち|移住クエスト自分で外置き家具C置いた - {0x19C, new EventFlagPlayer(0 , 1 , 0412, "RcoHeardNoticeOfficeBuild" )}, // たぬきち|案内所建物建築予告聞いた - {0x19F, new EventFlagPlayer(0 , 1 , 0415, "RcoTalkBeforeCountdown" )}, // たぬきち|年越し前に話した? - {0x1A0, new EventFlagPlayer(0 , 1 , 0416, "RcoTalkAfterCountdown" )}, // たぬきち|年越し後に話した? - {0x1A1, new EventFlagPlayer(0 , 1 , 0417, "ChyDaily_TalkFirstDay" )}, // レックス|今回の来訪中に話したか? - {0x1A2, new EventFlagPlayer(0 , 1 , 0418, "ChyDaily_SellCount" )}, // レックス|買取総数(今回計算含む)/未使用 - {0x1A3, new EventFlagPlayer(0 , 1 , 0419, "ChyDaily_SellFirst" )}, // レックス|今日買取した? - {0x1A6, new EventFlagPlayer(0 , 1 , 0422, "NetIsRegistHomeLand" )}, // 通信|独自サーバに島登録したか? - {0x1A7, new EventFlagPlayer(0 , 1 , 0423, "FriendListNotifyUpdate" )}, // フレンドリスト|更新要求通知 - {0x1A8, new EventFlagPlayer(0 , 1 , 0424, "FriendListNotifyLook" )}, // スマホUI|ベストフレンドリストアイコン用更新通知 - {0x1A9, new EventFlagPlayer(0 , 100 , 0425, "CatchFishContinueCount" )}, // つり|逃げられずに釣り上げた回数 - {0x1AA, new EventFlagPlayer(0 , 1 , 0426, "FriendMailSendEnable" )}, // メッセージカード|フレンドへの送信解禁 - {0x1AC, new EventFlagPlayer(0 , 1 , 0428, "BeyDaily_TalkFirstDay" )}, // ジャスティン|今回の来訪中に話した? - {0x1AE, new EventFlagPlayer(0 , 20 , 0430, "PrayStarToday" )}, // 今日祈った回数 - {0x1AF, new EventFlagPlayer(0 , 40 , 0431, "StarPieceGrowCount" )}, // 星素材発生カウンタ - {0x1B0, new EventFlagPlayer(0 , 1 , 0432, "BeyDaily_QuestStart" )}, // ジャスティン|クエスト申し込みした? - {0x1B1, new EventFlagPlayer(0 , 1 , 0433, "KinuyoChkMydesginFlag" )}, // きぬよ|仕立て屋のマイデザインチェックしたことある? - {0x1B3, new EventFlagPlayer(0 , 1 , 0435, "HgsGotCloth" )}, // あさみ|汎用布地もらったことある? - {0x1B4, new EventFlagPlayer(0 , 100 , 0436, "RcmDeliver_00" )}, // まめきち|商店建設クエストでかたいもくざいを渡した数 - {0x1B6, new EventFlagPlayer(0 , 1 , 0438, "HasTalkedAllVillagerToday" )}, // 今日全ての住民NPCと話したか? - {0x1B7, new EventFlagPlayer(0 , 1 , 0439, "AmiiboPhoneTalkFirst" )}, // amiiboフォン+と話したことがあるか? - {0x1B8, new EventFlagPlayer(0 , 1 , 0440, "PrintServiceExplain" )}, // タヌポートでポスター販売開始の案内聞いたか? - {0x1B9, new EventFlagPlayer(0 , 3 , 0441, "SendPuromaidoCount" )}, // 今日プリントしたブロマイドの数 - {0x1BA, new EventFlagPlayer(0 , 1 , 0442, "KinuyoTalkInTailorFlag" )}, // きぬよ|仕立て屋で会話したことある? - {0x1BB, new EventFlagPlayer(0 , 1 , 0443, "KinuyoForcesTalkTodayFlag" )}, // きぬよ|今日仕立て屋で入店時の強制会話した? - {0x1BC, new EventFlagPlayer(0 , 1 , 0444, "KinuyoForcedTalk2TodayFlag" )}, // きぬよ|今日仕立て屋で退店時の強制会話した? - {0x1BD, new EventFlagPlayer(0 , 999 , 0445, "ChyEvent_TotalPoint" )}, // [大会]レックス|ムシとり大会累計ポイント - {0x1BE, new EventFlagPlayer(0 , 999 , 0446, "BeyEvent_TotalPoint" )}, // [大会]ジャスティン|つり大会累計ポイント - {0x1BF, new EventFlagPlayer(0 , 1 , 0447, "ChyEvent_GetTrophyGold" )}, // [大会]レックス|トロフィ金もらったか? - {0x1C0, new EventFlagPlayer(0 , 1 , 0448, "ChyEvent_GetTrophySilver" )}, // [大会]レックス|トロフィ銀もらったか? - {0x1C1, new EventFlagPlayer(0 , 1 , 0449, "ChyEvent_GetTrophyCopper" )}, // [大会]レックス|トロフィ銅もらったか? - {0x1C2, new EventFlagPlayer(0 , 1 , 0450, "BeyEvent_GetTrophyGold" )}, // [大会]ジャスティン|トロフィ金もらったか? - {0x1C3, new EventFlagPlayer(0 , 1 , 0451, "BeyEvent_GetTrophySilver" )}, // [大会]ジャスティン|トロフィ銀もらったか? - {0x1C4, new EventFlagPlayer(0 , 1 , 0452, "BeyEvent_GetTrophyCopper" )}, // [大会]ジャスティン|トロフィ銅もらったか? - {0x1C5, new EventFlagPlayer(0 , 1 , 0453, "PurchaseBoxUseOnceFlag" )}, // 時間外買取BOX|自分の島で調べたことがある? - {0x1C6, new EventFlagPlayer(0 , 1 , 0454, "BeyDaily_ReqObj" )}, // ジャスティン|サカナOBJ申込した? - {0x1C7, new EventFlagPlayer(0 , 1 , 0455, "ChyDaily_ReqObj" )}, // レックス|ムシOBJ申込した? - {0x1C8, new EventFlagPlayer(0 , 1 , 0456, "BeyDaily_ExplainReqObj_First" )}, // ジャスティン|サカナOBJ初回説明聞いた? - {0x1C9, new EventFlagPlayer(0 , 1 , 0457, "ChyDaily_ExplainReqObj_First" )}, // レックス|ムシOBJ初回説明聞いた? - {0x1CB, new EventFlagPlayer(0 , 1 , 0459, "KinuyoTailorBuildFlag" )}, // きぬよ|仕立て屋の場所決めたプレイヤー? - {0x1CC, new EventFlagPlayer(0 , 1 , 0460, "BirthdayPToldlPartySharePlay" )}, // プレイヤー誕生日|NPCから誕生会の案内聞いた? - {0x1CD, new EventFlagPlayer(0 , 1 , 0461, "TalkSnpcTodayAnyone" )}, // 今日誰かにSnpcを聞いたか? - {0x1CE, new EventFlagPlayer(0 , 1 , 0462, "RcmForcedTalkTodayFlag" )}, // まめきち|今日お店で入店時の強制会話した? - {0x1CF, new EventFlagPlayer(0 , 1 , 0463, "RcmForcedTalk2TodayFlag" )}, // まめきち|今日お店で退店時の強制会話した? - {0x1D0, new EventFlagPlayer(0 , 1 , 0464, "KinuyoMetShopFlag" )}, // きぬよ|商店で会った? - {0x1D1, new EventFlagPlayer(0 , 1 , 0465, "ImmQGetHousingFullItem" )}, // たぬきち|ハウジングキットもらうとき、持ち物いっぱいだった - {0x1D2, new EventFlagPlayer(0 , 1 , 0466, "TownNewsReserve" )}, // 村内放送|村内放送予約フラグ - {0x1D3, new EventFlagPlayer(0 , 1 , 0467, "BeyDaily_ExolainQ_First" )}, // ジャスティン|初回クエスト説明聞いた? - {0x1D4, new EventFlagPlayer(0 , 1 , 0468, "ImmQHeardClearInfoA" )}, // たぬきち|移住クエストAをクリアした旨を聞いたことがある - {0x1D5, new EventFlagPlayer(0 , 1 , 0469, "ImmQHeardClearInfoB" )}, // たぬきち|移住クエストBをクリアした旨を聞いたことがある - {0x1D6, new EventFlagPlayer(0 , 1 , 0470, "ImmQHeardClearInfoC" )}, // たぬきち|移住クエストCをクリアした旨を聞いたことがある - {0x1D7, new EventFlagPlayer(0 , 1 , 0471, "ImmQHeardNoticeRemoveFtr" )}, // たぬきち|聞いていない移住クエストクリアの告知がある? - {0x1D8, new EventFlagPlayer(0 , 1 , 0472, "RcoImmQClear1QuestToday" )}, // たぬきち|今日、移住クエストの1工程を既にクリアしてる - {0x1D9, new EventFlagPlayer(0 , 1 , 0473, "ImmQTalkRcoHaveBridgeKit" )}, // たぬきち|まるたのはしキット持った状態で会話した - {0x1DA, new EventFlagPlayer(0 , 1 , 0474, "ImmQTalkRcoBridgeKitSet" )}, // たぬきち|まるたのはしキットを設置したお礼会話発動させる? - {0x1DB, new EventFlagPlayer(0 , 1 , 0475, "ImmQSetBridgeKitMySelf" )}, // たぬきち|まるたのはしキットを自分自身が設置した - {0x1DC, new EventFlagPlayer(0 , 1 , 0476, "ImmQTalkRcoBridgeComplete" )}, // たぬきち|まるたのはしが完成してから会話した - {0x1DD, new EventFlagPlayer(0 , 1 , 0477, "ImmQTalkAboutPrize" )}, // たぬきち|移住クエスト報酬会話した - {0x1DE, new EventFlagPlayer(0 , 1 , 0478, "ImmQGetQuestPrize" )}, // たぬきち|移住クエストの報酬もらった - {0x1DF, new EventFlagPlayer(0 , 1 , 0479, "ChyDaily_AnnounceEvent" )}, // レックス|ムシとり大会予告聞いた? - {0x1E0, new EventFlagPlayer(0 , 1 , 0480, "BeyDaily_AnnounceEvent" )}, // ジャスティン|つり大会予告聞いた? - {0x1E1, new EventFlagPlayer(0 , 1 , 0481, "CampInvite" )}, // キャンプ場に誘った - {0x1E2, new EventFlagPlayer(0 , 1 , 0482, "CampFirstTalk" )}, // キャンパーNPCとの初回会話を済ませた - {0x1E3, new EventFlagPlayer(0 , 1 , 0483, "CampQuestAccept" )}, // キャンプ家具クエストを受注した - {0x1E4, new EventFlagPlayer(0 , 1 , 0484, "CampQuestRecipiFailed" )}, // キャンプ家具クエストのレシピを受け取れなかった - {0x1E5, new EventFlagPlayer(0 , 1 , 0485, "CampQuestRejected" )}, // キャンプ家具クエストを断った - {0x1E6, new EventFlagPlayer(0 , 1 , 0486, "CampGameGetRare" )}, // キャンプゲームでレア枠アイテムを入手した - {0x1E8, new EventFlagPlayer(0 , 1 , 0488, "Camp_InduceFailFlag" )}, // キャンプ|勧誘失敗フラグ - {0x1EA, new EventFlagPlayer(0 , 1 , 0490, "Camp_InduceFailSameNpcLiving" )}, // キャンプ|勧誘失敗理由|同名NPCが村に住んでいる - {0x1EB, new EventFlagPlayer(0 , 1 , 0491, "Camp_InduceFailSameNpcMoveIn" )}, // キャンプ|勧誘失敗理由|同名NPCが転入確定状態 - {0x1EC, new EventFlagPlayer(0 , 1 , 0492, "Camp_InduceFailVillagerMax" )}, // キャンプ|勧誘失敗理由|住人数が既に上限 - {0x1ED, new EventFlagPlayer(0 , 1 , 0493, "Camp_InduceFailSellPlaceNothing" )}, // キャンプ|勧誘失敗理由|売り土地が無い - {0x1EE, new EventFlagPlayer(0 , 1 , 0494, "CalendarEventAchievementFinish" )}, // カレンダーイベントの実績を今日カウントした - {0x1EF, new EventFlagPlayer(0 , 1 , 0495, "RollanGotWallpaperFlag" )}, // ローラン|今日かべがみひきかえた? - {0x1F0, new EventFlagPlayer(0 , 1 , 0496, "RollanGotCarpetFlag" )}, // ローラン|今日ゆかひきかえた? - {0x1F7, new EventFlagPlayer(0 , 1 , 0503, "ImmQTakeFruit" )}, // たぬきち|移住クエストで今日果物もらった - {0x1F8, new EventFlagPlayer(0 , 1 , 0504, "ImmQTakeRemakeKit" )}, // xたぬきち|移住クエストで今日リメイクキットもらった - {0x1F9, new EventFlagPlayer(0 , 1 , 0505, "ImmQBridgeMadeinRcoTent" )}, // たぬきち|はしキットをたぬきちテントで作った - {0x1FA, new EventFlagPlayer(0 , 1 , 0506, "IslandDevQuestShowCampKit" )}, // たぬきち|キャンプ場よていちキットをたぬきちに見せた - {0x1FB, new EventFlagPlayer(0 , 1 , 0507, "IslandDevQuestCampMadeRcotent" )}, // たぬきち|キャンプ場よていちキットを案内所で作った - {0x1FC, new EventFlagPlayer(0 , 1 , 0508, "IslandDevQuestTalkAfterCampSet" )}, // たぬきち|キャンプ場よていちキットをセットしてから会話した - {0x1FD, new EventFlagPlayer(0 , 1 , 0509, "IslandDevQuestCampSetMySelf" )}, // たぬきち|キャンプ場よていちキットを自身で設置した - {0x1FF, new EventFlagPlayer(0 , 1 , 0511, "IslandDevQuestGetRecipeCampKit" )}, // たぬきち|キャンプ場よていちキットのレシピを受け取った - {0x200, new EventFlagPlayer(0 , 1 , 0512, "IslandDevQuestOrderFirstCamperMyself" )}, // たぬきち|1人目のキャンプ客から移住の相談を自身が受けた - {0x201, new EventFlagPlayer(0 , 1 , 0513, "MainmenuConstructLicense" )}, // スマホUI|造成ライセンスアプリ解禁 - {0x202, new EventFlagPlayer(0 , 1 , 0514, "FirstPlayAfterOfficeBuiltFlag" )}, // 案内所の建物が完成したあとのプレイ初日? - {0x203, new EventFlagPlayer(0 , 1 , 0515, "FirstPlayAfterShopBuiltFlag" )}, // 商店が完成したあとのプレイ初日? - {0x204, new EventFlagPlayer(0 , 1 , 0516, "FirstPlayAfterShopBuilt2Flag" )}, // 商店を拡張したあとのプレイ初日? - {0x205, new EventFlagPlayer(0 , 1 , 0517, "FirstPlayAfterMuseumTentFlag" )}, // フータのテントが完成したあとのプレイ初日? - {0x206, new EventFlagPlayer(0 , 1 , 0518, "FirstPlayAfterMuseumBuiltFlag" )}, // 博物館が完成したあとのプレイ初日? - {0x207, new EventFlagPlayer(0 , 1 , 0519, "FirstPlayAfterTailorBuiltFlag" )}, // 仕立て屋が完成したあとのプレイ初日? - {0x208, new EventFlagPlayer(0 , 1 , 0520, "SzaHeardTodayIslandEvaluation" )}, // しずえ|今日の島の評価を聞いた - {0x209, new EventFlagPlayer(0 , 1 , 0521, "IslandEvaluationUnlockMyself" )}, // しずえ|自分自身が島の評価を解禁した - {0x20A, new EventFlagPlayer(0 , 1 , 0522, "SzaHeardAboutIslandEvaluation" )}, // しずえ|島の評価に関する説明を聞いた - {0x20B, new EventFlagPlayer(0 , 1 , 0523, "ConstructionWorkToday" )}, // 工事ライセンス|説明を見た - {0x20C, new EventFlagPlayer(0 , 1 , 0524, "PlayToday" )}, // 今日プレイした - {0x20D, new EventFlagPlayer(0 , 1 , 0525, "TalkFreeIPresentTodayAnyone" )}, // 今日誰かにFreeI_Presentを聞いたか? - {0x20E, new EventFlagPlayer(0 , 1 , 0526, "IslandDevQuestTalkAfterBuildCamp" )}, // たぬきち|キャンプ場が完成してから会話した - {0x20F, new EventFlagPlayer(0 , 1 , 0527, "IslandDevQuestTalkAboutFirstCamper" )}, // たぬきち|1人目のキャンプ客に会いに行く依頼を自身が受けた - {0x210, new EventFlagPlayer(0 , 1 , 0528, "GetHousingKitForFirstCamper" )}, // たぬきち|1人目のキャンプ客用のハウジングキット受け取った - {0x211, new EventFlagPlayer(0 , 1 , 0529, "ItemFullHousingKitForFirstCamper" )}, // たぬきち|1人目のキャンプ客用のキット、持ち物いっぱいで受取失敗した - {0x212, new EventFlagPlayer(0 , 1 , 0530, "SetHousingKitForFirstCamper" )}, // たぬきち|1人目のキャンプ客用のハウジングキットを、自らセットした - {0x214, new EventFlagPlayer(0 , 6 , 0532, "ChyDaily_InsectSellNum" )}, // レックス|今回の来訪中に買取した数 - {0x216, new EventFlagPlayer(0 , 1 , 0534, "SharePlayGuideDone" )}, // おすそわけプレイの解説ダイアログを見た - {0x217, new EventFlagPlayer(0 , 1 , 0535, "CommuneIslandAvailable" )}, // パニエル|コミューン島に招待された - {0x218, new EventFlagPlayer(0 , 1 , 0536, "VisitedCommune" )}, // コミューン島に上陸したことがある - {0x21A, new EventFlagPlayer(0 , 1 , 0538, "ChyEvent_TalkTrophyGold" )}, // [大会]レックス|金トロフィ会話した? - {0x21B, new EventFlagPlayer(0 , 1 , 0539, "ChyEvent_TalkTrophySilver" )}, // [大会]レックス|銀トロフィ会話した? - {0x21C, new EventFlagPlayer(0 , 1 , 0540, "ChyEvent_TalkTrophyCopper" )}, // [大会]レックス|銅トロフィ会話した? - {0x21D, new EventFlagPlayer(0 , 1 , 0541, "BeyEvent_TalkTrophyGold" )}, // [大会]ジャスティン|金トロフィ会話した? - {0x21E, new EventFlagPlayer(0 , 1 , 0542, "BeyEvent_TalkTrophySilver" )}, // [大会]ジャスティン|銀トロフィ会話した? - {0x21F, new EventFlagPlayer(0 , 1 , 0543, "BeyEvent_TalkTrophyCopper" )}, // [大会]ジャスティン|銅トロフィ会話した? - {0x220, new EventFlagPlayer(0 , 1 , 0544, "SpnFirstTalkedAtCommuneIsland" )}, // パニエル|コミューン島で初回会話した? - {0x222, new EventFlagPlayer(0 , 1 , 0546, "AppUrgentEscapeCallToday" )}, // 緊急脱出|本日電話した - {0x223, new EventFlagPlayer(0 , 1 , 0547, "KotonoGotSampleFlag" )}, // ことの|サンプルもらった? - {0x224, new EventFlagPlayer(0 , 1 , 0548, "KotonoGotTicketFlag" )}, // ことの|ひきかえけんもらったことある? - {0x225, new EventFlagPlayer(0 , 1 , 0549, "OwsFirstTalk" )}, // フーコ|面識ある? - {0x226, new EventFlagPlayer(0 , 1 , 0550, "OwsTalkedToday" )}, // フーコ|今日会話した? - {0x22A, new EventFlagPlayer(0 , 1 , 0554, "OwsPresentFirstRecipe" )}, // フーコ|最初のレシピもらった? - {0x22B, new EventFlagPlayer(0 , 1 , 0555, "SpnPhotoStudioGuideDone" )}, // パニエル|撮影スタジオの説明を聞いた - {0x22C, new EventFlagPlayer(0 , 1 , 0556, "GetBirthdayCake" )}, // 今年バースデーケーキをもらった - {0x22D, new EventFlagPlayer(0 , 1 , 0557, "GetBirthdayFloorParty" )}, // 今年パーティのゆかをもらった - {0x22E, new EventFlagPlayer(0 , 1 , 0558, "GetBirthdayWallParty" )}, // 今年パーティのかべがみをもらった - {0x22F, new EventFlagPlayer(0 , 1 , 0559, "AddHairStyle1" )}, // 『ポップなヘアアレンジ』解禁 - {0x230, new EventFlagPlayer(0 , 1 , 0560, "AddHairStyle2" )}, // 『クールなヘアアレンジ』解禁 - {0x231, new EventFlagPlayer(0 , 1 , 0561, "AddHairStyle3" )}, // 寝ぐせ解禁 - {0x232, new EventFlagPlayer(0 , 1 , 0562, "TanuportAmiiboBromideUnlock" )}, // タヌポート|amiibo ブロマイド機能を解禁 - {0x233, new EventFlagPlayer(0 , 1 , 0563, "AddHairColor" )}, // タヌポート|追加ヘアカラー解禁 - {0x234, new EventFlagPlayer(0 , 1 , 0564, "EnableDiyRemake" )}, // DIY作業台|リメイク解禁 - {0x235, new EventFlagPlayer(0 , 1 , 0565, "GetLicenseGrdStone" )}, // 工事ライセンス|道路工事:石だたみ解禁 - {0x236, new EventFlagPlayer(0 , 1 , 0566, "GetLicenseGrdBrick" )}, // 工事ライセンス|道路工事:レンガの道解禁 - {0x237, new EventFlagPlayer(0 , 1 , 0567, "GetLicenseGrdDarkSoil" )}, // 工事ライセンス|道路工事:畑の道解禁 - {0x238, new EventFlagPlayer(0 , 1 , 0568, "GetLicenseGrdStonePattern" )}, // 工事ライセンス|道路工事:おうぎの石だたみ解禁 - {0x239, new EventFlagPlayer(0 , 1 , 0569, "GetLicenseGrdSand" )}, // 工事ライセンス|道路工事:すなの道解禁 - {0x23A, new EventFlagPlayer(0 , 1 , 0570, "GetLicenseGrdTile" )}, // 工事ライセンス|道路工事:テラコッタタイル解禁 - {0x23B, new EventFlagPlayer(0 , 1 , 0571, "GetLicenseGrdWood" )}, // 工事ライセンス|道路工事:くみ木の道解禁 - {0x23C, new EventFlagPlayer(0 , 1 , 0572, "GetLicenseRiver" )}, // 工事ライセンス|河川工事解禁 - {0x23D, new EventFlagPlayer(0 , 1 , 0573, "GetLicenseCliff" )}, // 工事ライセンス|崖工事解禁 - {0x23E, new EventFlagPlayer(0 , 1 , 0574, "EquipLicenseHelmet" )}, // 工事ライセンス|装備状態 - {0x240, new EventFlagPlayer(0 , 1 , 0576, "OwsPresentTodayRecipe" )}, // フーコ|今日レシピ(または素材)もらった? - {0x241, new EventFlagPlayer(0 , 1 , 0577, "OwsPresentThisZodiacRecipe" )}, // フーコ|今月の星座レシピもらった - {0x242, new EventFlagPlayer(1 , 12 , 0578, "OwsThisZodiac" )}, // フーコ|最後に遊んだ日の星座 - {0x243, new EventFlagPlayer(0 , 1 , 0579, "NewYearPlayReportSend" )}, // カウントダウンのプレイレポートを送った - {0x244, new EventFlagPlayer(0 , 1 , 0580, "RctOutsideHintToday" )}, // 今日、屋外ヒントつぶきちと会話した - {0x245, new EventFlagPlayer(0 , 1 , 0581, "DecideShopArea" )}, // お店の建設場所を決定した - {0x246, new EventFlagPlayer(0 , 1 , 0582, "HeardEatingHintAtShop" )}, // お店で「食べる」ヒント聞いた - {0x248, new EventFlagPlayer(0 , 1 , 0584, "KinuyoExplainFittingRoomFlag" )}, // きぬよ|試着室の説明聞いたことある? - {0x249, new EventFlagPlayer(0 , 1 , 0585, "HasLookMyHouseExplain" )}, // 家の機能説明ダイアログを見たことがある? - {0x24A, new EventFlagPlayer(0 , 1 , 0586, "TownNewsHeardRemakeTrialFlag" )}, // 村内放送|リメイク体験開催のお知らせを聞いた? - {0x24B, new EventFlagPlayer(0 , 1 , 0587, "RcoEnableRemakeTrial" )}, // たぬきち|リメイク体験選択肢解禁 - {0x24C, new EventFlagPlayer(0 , 1 , 0588, "RcoRemakeTrialOngoing" )}, // たぬきち|リメイク体験中 - {0x24D, new EventFlagPlayer(0 , 1 , 0589, "RcoRemakeTrialGetFurniture" )}, // たぬきち|リメイク体験中に必要な家具を持った状態でたぬきちに話しかけた - {0x24F, new EventFlagPlayer(0 , 1 , 0591, "RcoTalkAboutRemakeTrial" )}, // たぬきち|リメイク体験会のお誘い会話発動させるか? - {0x250, new EventFlagPlayer(0 , 1 , 0592, "RcoStayMyHouseImmQClear" )}, // たぬきち|移住クエストクリアで自宅前にくるか? - {0x251, new EventFlagPlayer(0 , 5 , 0593, "1stPresentHatType" )}, // (1P)初期HAからもらった帽子タイプは? - {0x253, new EventFlagPlayer(0 , 1 , 0595, "DodHeardAboutMileTravelTicket" )}, // モーリー|たぬきちから預かったマイル旅行券の説明聞いたか? - {0x255, new EventFlagPlayer(0 , 1 , 0597, "DocMysterytourExplain1st" )}, // ロドリー|ミステリーツアー初上陸で説明聞いた? - {0x256, new EventFlagPlayer(0 , 3 , 0598, "CampGameClear" )}, // キャンプゲームクリア回数 - {0x257, new EventFlagPlayer(0 , 1 , 0599, "RctTnx4CollectingMaterials" )}, // つぶきち|資材集め協力のお礼を聞いた? - {0x258, new EventFlagPlayer(0 , 1 , 0600, "RctTnx4CollectingMaterials2" )}, // つぶきち|資材集め終了のお礼を聞いた? - {0x259, new EventFlagPlayer(0 , 1 , 0601, "RctTnx4ConfirmingStorePlace" )}, // つぶきち|店の場所決め終了のお礼を聞いた? - {0x25A, new EventFlagPlayer(0 , 1 , 0602, "RcoFinishAdvice" )}, // たぬきち|アドバイス終了? - {0x25B, new EventFlagPlayer(5 , 5 , 0603, "RumorPFavoriteProgressDays" )}, // RumorP_Favoriteを聞いてからの経過日数 - {0x25C, new EventFlagPlayer(0 , 1 , 0604, "PAnnounceExplainCeremony" )}, // 島内放送|セレモニーの説明入った? - {0x25D, new EventFlagPlayer(0 , 1 , 0605, "PAnnounceTailorBuilt" )}, // 島内放送|仕立て屋オープンの話聞いた? - {0x25E, new EventFlagPlayer(0 , 1 , 0606, "RctHintCongratsMyhome" )}, // つぶきち|マイホームのお祝いを聞いた? - {0x25F, new EventFlagPlayer(0 , 1 , 0607, "PAnnounceCampsite" )}, // 島内放送|キャンプ場オープンの話聞いた? - {0x260, new EventFlagPlayer(0 , 1 , 0608, "PAnnounceHeardOfficeRenual" )}, // 島内放送|案内所改装の話聞いた? - {0x261, new EventFlagPlayer(0 , 1 , 0609, "RcoFirstTalkNewOffice" )}, // たぬきち|案内所建物初会話聞いた? - {0x262, new EventFlagPlayer(0 , 1 , 0610, "ItemRingEnable" )}, // アイテムリング解禁 - {0x263, new EventFlagPlayer(0 , 1 , 0611, "RcoTalkAboutOfficeWork" )}, // たぬきち|案内所での業務内容聞いた? - {0x264, new EventFlagPlayer(0 , 1 , 0612, "TwinTurnipExplanation" )}, // まめつぶからカブ価と高額買取品の説明聞いた? - {0x265, new EventFlagPlayer(0 , 1 , 0613, "HeldCeremonyMarket1" )}, // セレモニ|商店(小)を開いた - {0x266, new EventFlagPlayer(0 , 1 , 0614, "HeldCeremonyMarket2" )}, // セレモニ|商店(大)を開いた - {0x267, new EventFlagPlayer(0 , 1 , 0615, "HerdCeremonyOffice" )}, // セレモニ|案内所を開いた - {0x268, new EventFlagPlayer(0 , 1 , 0616, "HeldCeremonyMuseum" )}, // セレモニ|博物館を開いた - {0x269, new EventFlagPlayer(0 , 1 , 0617, "HeldCeremonyTailor" )}, // セレモニ|仕立て屋を開いた - {0x26A, new EventFlagPlayer(0 , 1 , 0618, "HeldCeremonyCampSite" )}, // セレモニ|キャンプ場を開いた - {0x26B, new EventFlagPlayer(0 , 1 , 0619, "HeldCeremonyBridge" )}, // セレモニ|橋を開いた - {0x26C, new EventFlagPlayer(0 , 1 , 0620, "HeldCeremonySlope" )}, // セレモニ|坂を開いた - {0x26D, new EventFlagPlayer(0 , 1 , 0621, "HghPeddlerPurchaceToday" )}, // きぬよ行商|今回の来訪で商品購入した - {0x26E, new EventFlagPlayer(0 , 1 , 0622, "RollanBuyWallpaperCount" )}, // ローラン|今日フシギなかべがみを買った? - {0x26F, new EventFlagPlayer(0 , 1 , 0623, "RollanBuyCarpetCount" )}, // ローラン|今日フシギなゆかを買った? - {0x270, new EventFlagPlayer(0 , 1 , 0624, "RcoTalkAboutMoveBuilding" )}, // たぬきち|建物移設の説明した - {0x271, new EventFlagPlayer(0 , 1 , 0625, "UseMigrantHousingKit1st" )}, // 移住クエ用ハウジングキットを初めて使用しようとした - {0x272, new EventFlagPlayer(0 , 1 , 0626, "RcoHeardLadderExplain" )}, // たぬきち|電話ではしごの説明を聞いた - {0x273, new EventFlagPlayer(0 , 1 , 0627, "RcoReciveMigrantEvPhone1st" )}, // たぬきち|移住クエ予定地設置後初めての電話かかってきた - {0x274, new EventFlagPlayer(0 , 1 , 0628, "SzaTalkAboutIncresePopulation" )}, // しずえ|島の評判:人口8人突破報告を聞いた - {0x275, new EventFlagPlayer(0 , 1 , 0629, "RcoMoveCampSiteReserved" )}, // たぬきち|キャンプ場の移設を予約している - {0x276, new EventFlagPlayer(0 , 1 , 0630, "SkkPurchaseToday" )}, // シャンク|今回の来訪で商品購入した - {0x277, new EventFlagPlayer(0 , 1 , 0631, "SkkTalkTodayFlag" )}, // シャンク|今日会話した? - {0x278, new EventFlagPlayer(0 , 1 , 0632, "TkkFirstLiveJoined" )}, // とたけけ|初ライブに自身が参加した? - {0x279, new EventFlagPlayer(0 , 1 , 0633, "FirstPlayAfterPlayerMake" )}, // このプレイヤを作った初日? - {0x27A, new EventFlagPlayer(0 , 1 , 0634, "RcoMigrantProgressTalk1st" )}, // たぬきち|移住クエ経過強制会話を聞いたことがある? - {0x27B, new EventFlagPlayer(0 , 1 , 0635, "DodTodayFlightMileGet" )}, // モーリー|今日のおでかけマイルもらった - {0x27C, new EventFlagPlayer(0 , 1 , 0636, "PAnnouceHeardRemakeWsNewsToday" )}, // 島内放送|今日リメイクワークショップの案内聞いた - {0x27D, new EventFlagPlayer(0 , 1 , 0637, "HghGetTailorHousingKit" )}, // きぬよ|自分が仕立て屋予定地キット受け取った - {0x27E, new EventFlagPlayer(0 , 1 , 0638, "SzaTalkAboutIncreseHousingKit" )}, // しずえ|島の評判:ハウジングキット含め8軒突破報告を聞いた - {0x27F, new EventFlagPlayer(0 , 1 , 0639, "HghHeardRequestHousingKit" )}, // きぬよ|仕立て屋の場所探しの依頼を聞いた - {0x280, new EventFlagPlayer(0 , 1 , 0640, "HghEndRequestHousingKit" )}, // きぬよ|仕立て屋の場所探しの話が完結した - {0x281, new EventFlagPlayer(0 , 1 , 0641, "OfficeSzaIntroduction" )}, // 案内所|強制会話で直接しずえの紹介受けた - {0x282, new EventFlagPlayer(0 , 1 , 0642, "PAnnouceHeardKkProject" )}, // 島内放送|とたけけプロジェクトの予告発生した? - {0x283, new EventFlagPlayer(0 , 1 , 0643, "RcoHeardAboutKkProject1st" )}, // たぬきち|けけプロジェクトの存在を聞いた? - {0x284, new EventFlagPlayer(0 , 1 , 0644, "GetLicenseGrdMydesign" )}, // 工事ライセンス|道路工事:マイデザイン地面貼り工事解禁 - {0x285, new EventFlagPlayer(0 , 1 , 0645, "RcoHeardAbout1stCamperToday" )}, // たぬきち|初キャンパーの話と勧誘依頼を今日聞いた? - {0x286, new EventFlagPlayer(0 , 1 , 0646, "RcoHeardAboutEvaluationStart" )}, // たぬきち|評価開始前の会話を聞いた? - {0x287, new EventFlagPlayer(0 , 1 , 0647, "RcoHeardAboutEvalutationDetail" )}, // たぬきち|評価の詳細を聞いた? - {0x288, new EventFlagPlayer(0 , 1 , 0648, "RcoAwaitingExplanation" )}, // たぬきち|お願い聞いてねと頼まれてる状態? - {0x289, new EventFlagPlayer(0 , 1 , 0649, "SzaHeardAboutEvaluationDetail" )}, // しずえ|村の評判の詳細説明を聞いた? - {0x28A, new EventFlagPlayer(0 , 1 , 0650, "PopDiyGoldFromStoneToday" )}, // 今日、岩から金鉱石を出した? - {0x28B, new EventFlagPlayer(0 , 1 , 0651, "BeyEvent_TalkFirst" )}, // [大会]ジャスティン|つり大会の日に会話したか? - {0x28C, new EventFlagPlayer(0 , 10 , 0652, "AppUrgentEscapeMobCounter" )}, // 緊急脱出|ラケットさん出現カウンター - {0x28D, new EventFlagPlayer(0 , 1 , 0653, "AppUrgentEscapeTodayShiftMob" )}, // 緊急脱出|今日の当番はラケットさん - {0x28E, new EventFlagPlayer(0 , 1 , 0654, "GotMedicineRecipe" )}, // (NPCから)おくすりのレシピをもらった - {0x28F, new EventFlagPlayer(0 , 1 , 0655, "MessageCardPayment" )}, // メッセージカードの代金を支払っているか - {0x290, new EventFlagPlayer(0 , 1 , 0656, "PlayerHalfAsleepDemoFlag" )}, // 寝ぼけデモフラグ - {0x291, new EventFlagPlayer(0 , 1 , 0657, "ChyEvent_TalkFirst" )}, // [大会]レックス|ムシとり大会の日に会話をしたか? - {0x292, new EventFlagPlayer(0 , 1 , 0658, "RcoWallFtrRemoveHouseRemodel" )}, // たぬきち|家増築時に壁掛け家具の撤去が発生した? - {0x293, new EventFlagPlayer(0 , 1 , 0659, "LegacyMyDesignDLEnable" )}, // Blanco|3DSマイデザインのダウンロード解禁 - {0x294, new EventFlagPlayer(0 , 1 , 0660, "Got2ndLoach" )}, // 2匹目のドジョウ - {0x295, new EventFlagPlayer(0 , 1 , 0661, "PlayReportDaily" )}, // デイリープレイレポート - {0x296, new EventFlagPlayer(0 , 1 , 0662, "UseCloset" )}, // クロゼット機能を利用したことがある - {0x297, new EventFlagPlayer(0 , 1 , 0663, "RemakeWs_TalkWhenItemFull" )}, // リメイク体験会で持ち物いっぱいを指摘された - {0x299, new EventFlagPlayer(0 , 1 , 0665, "ImmQCompleteDemo" )}, // 移住クエスト|クリア時の単独デモを見たか? - {0x29A, new EventFlagPlayer(0 , 1 , 0666, "DodSelectCommune1st" )}, // モーリー|コミューン島に行くを選んだことがある - {0x29B, new EventFlagPlayer(0 , 1 , 0667, "SpnTalkAtHomelandToday" )}, // パニエル|自分の島で会話して招待された当日か? - {0x29C, new EventFlagPlayer(0 , 1 , 0668, "SpnTalkAtCommuneToday" )}, // パニエル|今日コミューン島で会話したか? - {0x29D, new EventFlagPlayer(0 , 1 , 0669, "UpgradePocket30" )}, // 持ち物欄が30に拡張された - {0x29E, new EventFlagPlayer(0 , 1 , 0670, "UpgradePocket40" )}, // 持ち物欄が40に拡張された - {0x29F, new EventFlagPlayer(0 , 20 , 0671, "IllegalReportCount" )}, // 通報回数 - {0x2A0, new EventFlagPlayer(0 , 1 , 0672, "SellPocket40" )}, // 持ち物欄を40にするアイテムを陳列するか? - {0x2A1, new EventFlagPlayer(0 , 1 , 0673, "BeyDaily_GetDemo_Clear" )}, // 来訪クエスト達成時ゲットデモを見たか? - {0x2A2, new EventFlagPlayer(0 , 1 , 0674, "OpenDIYRecipeEtcCategory" )}, // DIYレシピ・作業台|タブカテゴリ【その他】解禁 - {0x2A3, new EventFlagPlayer(0 , 1 , 0675, "RcoBuildBridgeSlopeMyself" )}, // たぬきち|今、橋/坂建設を申し込んでいるのが自分? - {0x2A4, new EventFlagPlayer(0 , 1 , 0676, "RcoRemoveBridgeSlopeMyself" )}, // たぬきち|今、橋/坂撤去を申し込んでいるのが自分? - {0x2A5, new EventFlagPlayer(0 , 1 , 0677, "RcoTalkAboutBuildBridgeSlope" )}, // たぬきち|橋/坂建築について説明受けた - {0x2A6, new EventFlagPlayer(0 , 1 , 0678, "RcoTalkAboutHaniwa" )}, // たぬきち|募金集めのハニワについて説明受けた - {0x2A7, new EventFlagPlayer(0 , 1 , 0679, "PAnnounceHintRnd" )}, // 村内放送|ヒント発生制御用フラグ - {0x2A8, new EventFlagPlayer(0 , 1 , 0680, "PickUpFirst" )}, // Yボタン「ひろう」が可能な状態だが、ものを拾ったことがない - {0x2A9, new EventFlagPlayer(0 , 1 , 0681, "StandByGameStartPhoneCall" )}, // 電話デモ|ゲーム開始時入電するか? - {0x2AA, new EventFlagPlayer(0 , 1 , 0682, "StandByPhoneCallPrintService" )}, // 電話デモ|プリントサービス入電するか? - {0x2AB, new EventFlagPlayer(0 , 1 , 0683, "StandByPhoneCallSharePlay" )}, // 電話デモ|おすそわけ解禁入電するか? - {0x2AC, new EventFlagPlayer(0 , 1 , 0684, "StandByPhoneCallPurchaseBox" )}, // 電話デモ|買取BOX入金電話するか? - {0x2AD, new EventFlagPlayer(0 , 3 , 0685, "HeardAboutFreeDKeywordA" )}, // 肩書会話|今日同じ島のPの肩書会話を聞いた? - {0x2AE, new EventFlagPlayer(0 , 3 , 0686, "HeardAboutFreeDKeywordB" )}, // 肩書会話|今日他の島のPの肩書会話を聞いた? - {0x2AF, new EventFlagPlayer(0 , 3 , 0687, "HeardAboutFreeDKeywordC" )}, // 肩書会話|今日訪問先のPの肩書会話を聞いた? - {0x2B0, new EventFlagPlayer(0 , 1 , 0688, "RcoMoveSomeBuiding" )}, // たぬきち|なにかの建物の移設を依頼しているか? - {0x2B1, new EventFlagPlayer(0 , 1 , 0689, "BuiltMyHome" )}, // マイホームが建った - {0x2B2, new EventFlagPlayer(0 , 1 , 0690, "RcoMoveHousingSetSomeBuild" )}, // たぬきち|移設用のハウジングキット設置した - {0x2B4, new EventFlagPlayer(0 , 1 , 0692, "SzaIslandEvaluation5star1st" )}, // しずえ|島の評価で初めて5つ星とった - {0x2B5, new EventFlagPlayer(0 , 1 , 0693, "JohnnySitUpBeforeFlag" )}, // ジョニー|今までに起こしたことある?(海賊ジョニーは別フラグ) - {0x2B6, new EventFlagPlayer(0 , 1 , 0694, "CampFirstTalk_FirstVisitor" )}, // キャンパーNPCとの初回会話を済ませた(初回キャンパー用) - {0x2B7, new EventFlagPlayer(0 , 1 , 0695, "BocAllowAddBuyCount" )}, // ウリ|カブ購入回数加算許可 - {0x2B8, new EventFlagPlayer(0 , 10 , 0696, "BocBuyCount" )}, // ウリ|カブ購入回数 - {0x2B9, new EventFlagPlayer(0 , 300 , 0697, "BocBuyNumCount" )}, // ウリ|カブ購入個数 - {0x2BD, new EventFlagPlayer(0 , 10 , 0701, "EmoticonLastLearnVillagerIndex" )}, // 最後に漫符を教わったNPCの住人番号 - {0x2BE, new EventFlagPlayer(0 , 1 , 0702, "MainmenuUnlockMydesingPro" )}, // スマホUI|PROデザイン解禁 - {0x2BF, new EventFlagPlayer(0 , 255 , 0703, "HeardCurrentPlayerActivityInfo" )}, // 今回の行動に関する噂話を聞いたプレイヤーの情報 - {0x2C0, new EventFlagPlayer(0 , 255 , 0704, "HeardPreviousPlayerActivityInfo" )}, // 前回の行動に関する噂話を聞いたプレイヤーの情報 - {0x2C1, new EventFlagPlayer(0 , 9999, 0705, "DodPresentCounter" )}, // 飛行場|ノベルティ用搭乗回数 - {0x2C2, new EventFlagPlayer(0 , 3 , 0706, "DodPresentCounterToday" )}, // 飛行場|今日の搭乗回数カウンタ - {0x2C3, new EventFlagPlayer(0 , 1 , 0707, "DodSingleFlightToday" )}, // 飛行場|今日ツアー島、パニー島に行ったか? - {0x2C4, new EventFlagPlayer(0 , 20 , 0708, "DodPresentSendCounter" )}, // 飛行場|ノベルティ入手カウンタ - {0x2C5, new EventFlagPlayer(-1, -1 , 0709, "BDayMsgSenderSNpcUniqueID0" )}, // バースデーメッセージを送ったSNpcのユニークID - {0x2C6, new EventFlagPlayer(-1, -1 , 0710, "BDayMsgSenderSNpcUniqueID1" )}, // バースデーメッセージを送ったSNpcのユニークID - {0x2C7, new EventFlagPlayer(-1, -1 , 0711, "BDayMsgSenderNNpcUniqueID0" )}, // バースデーメッセージを送ったNNpcのユニークID - {0x2C8, new EventFlagPlayer(-1, -1 , 0712, "BDayMsgSenderNNpcUniqueID1" )}, // バースデーメッセージを送ったNNpcのユニークID - {0x2C9, new EventFlagPlayer(0 , -1 , 0713, "BDayMsgRandomSead" )}, // バースデーメッセージの内容を決定する乱数のシード値 - {0x2CA, new EventFlagPlayer(0 , 1 , 0714, "UnlockMyDesignProCategory" )}, // スマホUI|PROデザインのタブカテゴリ解禁 - {0x2D5, new EventFlagPlayer(0 , 30 , 0725, "BalloonShootCountToday" )}, // 今日風船をいくつ撃ったか? - {0x2D6, new EventFlagPlayer(0 , 1 , 0726, "ContributedBuildBridgeorSlope" )}, // セレモニ|橋か坂の建設に貢献した - {0x2D7, new EventFlagPlayer(0 , 1 , 0727, "ContributedTodaysCeremonyBridgeorSlope" )}, // セレモニ|今日の橋か坂のセレモニーに貢献した - {0x2D8, new EventFlagPlayer(0 , 1 , 0728, "Mobile1stBootAfterUnlockPro_Mydesign" )}, // プロ編集解禁後スマホアプリ初起動|マイデザイン - {0x2D9, new EventFlagPlayer(0 , 1 , 0729, "TkkBirthdayMessageFlag" )}, // とたけけ|バースデーメッセージ送った? - {0x2DA, new EventFlagPlayer(0 , 1 , 0730, "TalkFirstCamperAfterSetHousing" )}, // たぬきち|1人目のキャンプ客とハウジングキットセット後会話した - {0x2DB, new EventFlagPlayer(0 , 1 , 0731, "TalkFirstCamperAfterRequestSetHousing" )}, // たぬきち|1人目のキャンプ客とハウジングキット設置依頼後会話した - {0x2DC, new EventFlagPlayer(0 , 1 , 0732, "NnpcAppE_Rep_OccuredToday" )}, // NNPC_ApproachE_IslandReputationが今日発生した - {0x2DD, new EventFlagPlayer(0 , 10 , 0733, "SzaPAAccidentCounter" )}, // 村内放送|しずえがハッとするイベント発生カウンタ - {0x2DF, new EventFlagPlayer(0 , 1 , 0735, "SzaIslandEvaluationTalkAbout1Star" )}, // しずえ|島の環境:ゆうたろうからの感想を見たことがある - {0x2E0, new EventFlagPlayer(0 , 1 , 0736, "SzaIslandEvaluationHeardToday" )}, // しずえ|島の環境を今日聞いた - {0x2E4, new EventFlagPlayer(0 , 1 , 0740, "DailyQuestFivePointDay" )}, // 日課の5倍ポイントデーか? - {0x2E5, new EventFlagPlayer(0 , 1 , 0741, "DailyQuestFirstFivePoint" )}, // 日課の初回5倍ポイント使用済みか? - {0x2E6, new EventFlagPlayer(0 , 3 , 0742, "DailyQuestFivePointMiss" )}, // 日課ポイント5倍デーはずれ回数 - {0x2E7, new EventFlagPlayer(0 , -1 , 0743, "DailyQuestFivePointQuest" )}, // 日課ポイント5倍対象ユニークID - {0x2E8, new EventFlagPlayer(0 , 1 , 0744, "DailyQuestFirstFivePointToday" )}, // 今日日課の初回5倍ポイントが選ばれているか? - {0x2E9, new EventFlagPlayer(0 , 1 , 0745, "DailyQuestFivePointSelect" )}, // 日課ポイント5倍デー抽選済みフラグ - {0x2EA, new EventFlagPlayer(0 , 1 , 0746, "AppE_WelcomoMigrants_Occured" )}, // AppE_WelcomeMigrantsが発生した - {0x2EB, new EventFlagPlayer(0 , 999 , 0747, "BeyEvent_ResultGetFish" )}, // [大会]つり大会|(結果発表用)捕まえたサカナ数 - {0x2EC, new EventFlagPlayer(0 , 999 , 0748, "ChyEvent_ResultGetInsect" )}, // [大会]ムシとり大会|(結果発表用)捕まえたムシ数 - {0x2ED, new EventFlagPlayer(0 , 1 , 0749, "KotonoKateTalkFlag" )}, // ことの|ケイトの説明聞いたことある? - {0x2EE, new EventFlagPlayer(0 , 999 , 0750, "BeyEvent_ResultGetPoint" )}, // [大会]つり大会|(結果発表用)獲得したポイント - {0x2EF, new EventFlagPlayer(0 , 999 , 0751, "ChyEvent_ResultGetPoint" )}, // [大会]ムシとり大会|(結果発表用)獲得したポイント - {0x2F0, new EventFlagPlayer(0 , 1 , 0752, "PhoneCallByRcm" )}, // 電話デモ|まめきちの入電受けたことある - {0x2F1, new EventFlagPlayer(0 , 1 , 0753, "PhoneCallByRct" )}, // 電話デモ|つぶきちの入電受けたことある - {0x2F2, new EventFlagPlayer(0 , 1 , 0754, "ThisPCcreatedbeforeOfficeUpgrading" )}, // 案内所がテントのうちに作成されたプレイヤーか? - {0x2F3, new EventFlagPlayer(0 , 1 , 0755, "RcoMachineAmiiboCamperUnlock" )}, // タヌポート|amiiboキャンパー勧誘機能解禁 - {0x2F4, new EventFlagPlayer(0 , 1 , 0756, "ObjRcoMachineHeardExplanation" )}, // タヌポート|たぬきちの最初の説明を聞いた? - {0x2F5, new EventFlagPlayer(0 , 1 , 0757, "OwlHeardInsectExplanation" )}, // フータ|寄贈経由でムシの解説を聞いたことがある? - {0x2F6, new EventFlagPlayer(0 , 1 , 0758, "OwlEverDonatedInsect" )}, // フータ|自分がムシを寄贈したことがある - {0x2F7, new EventFlagPlayer(0 , 1 , 0759, "2P_CreatedAfterOwlMoving" )}, // フータのテント完成以降に作られたプレイヤー - {0x2F8, new EventFlagPlayer(0 , 1 , 0760, "OwlGotDiyRecipe" )}, // フータからテントでDIYレシピもらったか? - {0x2F9, new EventFlagPlayer(0 , 1 , 0761, "RcoTalkAboutMoveMyHome" )}, // たぬきち|自宅の移設の解禁情報を聞いた? - {0x2FA, new EventFlagPlayer(0 , 1 , 0762, "RcoPAnnounceMuseumSP" )}, // 島内放送|フータ移住アナウンスで寄贈完了のことを聞いた? - {0x2FB, new EventFlagPlayer(0 , 1 , 0763, "PAnnounceHeardMarketUpgradeInfo" )}, // 島内放送|商店小→大の改装決定のアナウンスを聞いた?(たぬきち) - {0x2FC, new EventFlagPlayer(0 , 1 , 0764, "PAnnounceHeardMarketUpgradeInfoSza" )}, // 島内放送|商店小→大の改装決定のアナウンスを聞いた?(しずえ) - {0x2FD, new EventFlagPlayer(0 , 1 , 0765, "NoticeAboutLicenseRiver" )}, // 工事ライセンス|河川工事解禁して初起動した? - {0x2FE, new EventFlagPlayer(0 , 1 , 0766, "NoticeAboutLicenseCliff" )}, // 工事ライセンス|崖工事解禁して初起動した? - {0x2FF, new EventFlagPlayer(0 , 1 , 0767, "OdekakeFirstInternet" )}, // 空港|モーリー|おでかけ初めてインターネットの島を選択 - {0x300, new EventFlagPlayer(0 , 1 , 0768, "UploadProfileGrowupDaily" )}, // 成長処理でプロフィールアップロードを行ったか? - {0x301, new EventFlagPlayer(0 , 30 , 0769, "GoldenBalloonCount" )}, // 金の風船発生条件カウンタ - {0x302, new EventFlagPlayer(0 , 200 , 0770, "GoldenAxeLearningCount" )}, // 金のオノレシピひらめきカウンタ - {0x303, new EventFlagPlayer(0 , 3 , 0771, "LastUseLicense" )}, // 工事ライセンス|最後に使ったライセンスをできるだけ記憶する - {0x304, new EventFlagPlayer(0 , 1 , 0772, "GoldenRodRecipeSent" )}, // 金のつりざおレシピ投函済か? - {0x305, new EventFlagPlayer(0 , 1 , 0773, "GoldenNetRecipeSent" )}, // 金のあみレシピ投函済か? - {0x306, new EventFlagPlayer(0 , 1 , 0774, "CompleteFish" )}, // サカナコンプリート済か? - {0x307, new EventFlagPlayer(0 , 1 , 0775, "CompleteInsects" )}, // ムシコンプリート済か? - {0x308, new EventFlagPlayer(0 , 1 , 0776, "Experienced3starEvaluation" )}, // 3つ星以下の島の評価を聞いたことがある - {0x309, new EventFlagPlayer(0 , 20 , 0777, "CountGotTrash" )}, // ゴミを釣り上げて入手した回数カウント - {0x30A, new EventFlagPlayer(0 , 10 , 0778, "CountGotTrash_Can" )}, // あきかんを釣り上げて入手した回数カウント - {0x30B, new EventFlagPlayer(0 , 10 , 0779, "CountGotTrash_Tire" )}, // タイヤを釣り上げて入手した回数カウント - {0x30C, new EventFlagPlayer(0 , 50 , 0780, "JohnnyHelpCount" )}, // ジョニー|助けた回数(海賊ジョニーは別フラグ) - {0x30D, new EventFlagPlayer(0 , 1 , 0781, "CatchtFesBox_Valid" )}, // ムシサカナBOXの中身をキープ - {0x30E, new EventFlagPlayer(0 , 1 , 0782, "TreasurePlayerWin" )}, // 宝探しプレイヤー勝利 - {0x30F, new EventFlagPlayer(0 , 1 , 0783, "PAnnounce_SummerShell" )}, // 島内放送|季節素材告知_夏_なつのかいがら - {0x310, new EventFlagPlayer(0 , 1 , 0784, "PAnnounce_AutumnNuts" )}, // 島内放送|季節素材告知_秋_木の実 - {0x311, new EventFlagPlayer(0 , 1 , 0785, "UploadPlayerProfileIllegal" )}, // アップロードしたプレイヤープロフィールがNG扱いに - {0x312, new EventFlagPlayer(0 , 1 , 0786, "PAnnounce_AutumnMushroom" )}, // 島内放送|季節素材告知_秋_キノコ - {0x313, new EventFlagPlayer(0 , 1 , 0787, "PAnnounce_WinterSnowFlake" )}, // 島内放送|季節素材告知_冬_雪の結晶 - {0x314, new EventFlagPlayer(0 , 1 , 0788, "PAnnounce_WinterSnowball" )}, // 島内放送|季節素材告知_冬_雪だるま - {0x315, new EventFlagPlayer(0 , 1 , 0789, "PAnnounce_WinterOrnament" )}, // 島内放送|季節素材告知_冬_オーナメント - {0x316, new EventFlagPlayer(0 , 1 , 0790, "NotStartImmQByDIYDisable" )}, // 移住クエスト|DIY未修得で移住クエストを始められない - {0x317, new EventFlagPlayer(0 , 1 , 0791, "PAnnounce_AutumnRedLeaf" )}, // 島内放送|季節素材告知_秋_もみじ - {0x318, new EventFlagPlayer(0 , 1 , 0792, "PAnnounce_SpringSakura" )}, // 島内放送|季節素材告知_春_桜の花びら - {0x319, new EventFlagPlayer(0 , 1 , 0793, "PAnnounce_SpringBamboo" )}, // 島内放送|季節素材告知_春_春の若竹 - {0x31A, new EventFlagPlayer(0 , 1 , 0794, "RcoHeardInviteRemakeWS" )}, // たぬきち|リメイク体験会のお誘い会話聞いた - {0x31C, new EventFlagPlayer(0 , 1 , 0796, "KinuyoPROdesginFlag" )}, // きぬよ|PROデザインの説明聞いたことある? - {0x31D, new EventFlagPlayer(0 , 1 , 0797, "NoticeAboutMydesingOnWorkBench" )}, // 作業台|マイデザインリメイク選んで説明ダイアログ見た - {0x31E, new EventFlagPlayer(0 , -1 , 0798, "LatestMysteryTourUniqueID" )}, // 最後に選出したミステリーツアーのユニークID - {0x31F, new EventFlagPlayer(0 , 1 , 0799, "OwlMultiDonateExplain" )}, // フータ|複数鑑定&コレって何説明聞いた? - {0x320, new EventFlagPlayer(0 , 1 , 0800, "StandByPhoneCallIslandCreater" )}, // 電話デモ|島クリエイタの解禁入電するか? - {0x321, new EventFlagPlayer(0 , -1 , 0801, "PastDaysFromLastPlay" )}, // 最後にプレイした日から今日の成長処理までの経過日数 - {0x322, new EventFlagPlayer(0 , 1 , 0802, "UncollectedTreasure" )}, // 宝未回収で終了 - {0x323, new EventFlagPlayer(0 , 1 , 0803, "VisitMysteryTourID11" )}, // ID: 11のミステリーツアー島にその日行ったことがある - {0x324, new EventFlagPlayer(0 , 1 , 0804, "VisitMysteryTourID12" )}, // ID: 12のミステリーツアー島にその日行ったことがある - {0x325, new EventFlagPlayer(0 , 1 , 0805, "VisitMysteryTourID13" )}, // ID: 13のミステリーツアー島にその日行ったことがある - {0x326, new EventFlagPlayer(0 , 1 , 0806, "VisitMysteryTourID14" )}, // ID: 14のミステリーツアー島にその日行ったことがある - {0x327, new EventFlagPlayer(0 , 1 , 0807, "VisitMysteryTourID16" )}, // ID: 16のミステリーツアー島にその日行ったことがある - {0x328, new EventFlagPlayer(0 , 1 , 0808, "VisitMysteryTourID17" )}, // ID: 17のミステリーツアー島にその日行ったことがある - {0x329, new EventFlagPlayer(0 , 1 , 0809, "VisitMysteryTourID19" )}, // ID: 19のミステリーツアー島にその日行ったことがある - {0x32A, new EventFlagPlayer(0 , 1 , 0810, "VisitMysteryTourID21" )}, // ID: 21のミステリーツアー島にその日行ったことがある - {0x32B, new EventFlagPlayer(0 , 1 , 0811, "VisitMysteryTourID24" )}, // ID: 24のミステリーツアー島にその日行ったことがある - {0x32C, new EventFlagPlayer(0 , 1 , 0812, "FriendMailGuideRetentionPeriod" )}, // メッセージカード|サーバ保持期間に関する説明を見たか? - {0x32D, new EventFlagPlayer(0 , 1 , 0813, "StandByRcoVisitMyHomeAfterTkkFirstLive" )}, // たぬきち|とたけけライブ後の自宅訪問するか? - {0x32E, new EventFlagPlayer(0 , 1 , 0814, "SpnTalkBeforeGotHouseToday" )}, // パニエル|家ないプレイヤー(ホスト)が島で今日会話した - {0x32F, new EventFlagPlayer(0 , 1 , 0815, "TodayGrowUp" )}, // 今日成長処理済みか - {0x330, new EventFlagPlayer(0 , 32 , 0816, "KotonoQuestClearCount" )}, // ことの|クリアした回数 - {0x331, new EventFlagPlayer(0 , 1 , 0817, "PhotoStudioUseCantCallAmiibo" )}, // 撮影スタジオ|呼べないamiiboを使った - {0x332, new EventFlagPlayer(0 , 1 , 0818, "ChyDaily_ObjEntry1" )}, // レックス(来訪)|OBJ申込(1回目)した - {0x333, new EventFlagPlayer(0 , 1 , 0819, "ChyDaily_ObjEntry2" )}, // レックス(来訪)|OBJ申込(2回目)した - {0x334, new EventFlagPlayer(0 , 1 , 0820, "ChyDaily_ObjEntry3" )}, // レックス(来訪)|OBJ申込(3回目)した - {0x335, new EventFlagPlayer(0 , 1 , 0821, "BeyDaily_ObjEntry1" )}, // ジャスティン(来訪)|OBJ申込(1回目)した - {0x336, new EventFlagPlayer(0 , 1 , 0822, "BeyDaily_ObjEntry2" )}, // ジャスティン(来訪)|OBJ申込(2回目)した - {0x337, new EventFlagPlayer(0 , 1 , 0823, "BeyDaily_ObjEntry3" )}, // ジャスティン(来訪)|OBJ申込(3回目)した - {0x338, new EventFlagPlayer(0 , 1 , 0824, "BeyDaily_TalkAlways1" )}, // ジャスティン(来訪)|OBJ申込後雑談①聞いた - {0x339, new EventFlagPlayer(0 , 1 , 0825, "BeyDaily_TalkAlways2" )}, // ジャスティン(来訪)|OBJ申込後雑談②聞いた - {0x33A, new EventFlagPlayer(0 , 1 , 0826, "BeyDaily_TalkAlways3" )}, // ジャスティン(来訪)|OBJ申込後雑談③聞いた - {0x33B, new EventFlagPlayer(0 , 1 , 0827, "CampQuestRecipeGet" )}, // キャンプ家具クエストでレシピを貰った - {0x33C, new EventFlagPlayer(0 , 1 , 0828, "Mobile1stBoot_IslandCreater" )}, // スマホアプリ初起動|島クリエイター - {0x33D, new EventFlagPlayer(0 , 1 , 0829, "Closet_Explain_ChangeStick" )}, // タンスで変身ステッキの説明を聞いた - {0x33E, new EventFlagPlayer(0 , 1 , 0830, "TkkFirstLiveToday" )}, // とたけけ|今日初めてライブを聴いた? - {0x33F, new EventFlagPlayer(0 , 1 , 0831, "1stBootIslandCreaterCleanService" )}, // 島クリエイター|お片付けサービスの説明聞いた - {0x340, new EventFlagPlayer(0 , 1 , 0832, "MarketBuiltMyVillage" )}, // 自分の村のお店が開店した - {0x341, new EventFlagPlayer(0 , 1 , 0833, "Mobile1stBootUnlockCantEditMydesign" )}, // 編集不可デザイン保存後スマホアプリ初起動|マイデザイン - {0x342, new EventFlagPlayer(0 , 1 , 0834, "DodHeardAboutIslandCreator" )}, // モーリー|島クリエイター強制解除されたことある? - {0x343, new EventFlagPlayer(0 , 5 , 0835, "SzaBeforeIslandEvaluation" )}, // しずえ|前回聞いた島の評判(1~5) - {0x344, new EventFlagPlayer(0 , 1 , 0836, "PAnnouceProcessDoneToday" )}, // 村内放送のProcess処理を今日行ったか? - {0x345, new EventFlagPlayer(0 , 1 , 0837, "ImprovePlayerProfile" )}, // NG扱いとなったプレイヤープロフィールが修正されたか? - {0x346, new EventFlagPlayer(0 , 1 , 0838, "EnableInviteMoveoutNPC" )}, // よその島の引っ越し状態のNPCを勧誘可能か? - {0x348, new EventFlagPlayer(0 , 1 , 0840, "TodayMainGrowUp" )}, // 今日メインプレイヤーとして成長処理済みか - {0x349, new EventFlagPlayer(0 , 1 , 0841, "SzaTalkAtOfficeToday" )}, // しずえ|案内所で今日話しかけたか? - {0x34A, new EventFlagPlayer(0 , 1 , 0842, "MainmenuChatLog" )}, // スマホUI|チャットログ解禁 - {0x34B, new EventFlagPlayer(0 , 1 , 0843, "Mobile1stBoot_ChatLog" )}, // スマホアプリ初起動|チャットログ - {0x34C, new EventFlagPlayer(0 , 1 , 0844, "Activate_WebService" )}, // Blanco解禁 - {0x34D, new EventFlagPlayer(0 , 1 , 0845, "MyDesignExchangeFirstAccess" )}, // マイデザイン交換端末|初回アクセス - {0x34E, new EventFlagPlayer(0 , 1 , 0846, "MyDesignExchangeUploadOnce" )}, // マイデザイン交換端末|一度でも投稿したか? - {0x34F, new EventFlagPlayer(0 , 1 , 0847, "OhirakiRollbackTutorial" )}, // 通信|緊急おひらきによるロールバックの説明をしたか? - {0x350, new EventFlagPlayer(0 , 1 , 0848, "SzaTalkFirstNotOffice" )}, // しずえ|案内所以外で初めて会話した - {0x351, new EventFlagPlayer(0 , 1 , 0849, "Talk1stCamperMultiplay" )}, // キャンプ場|通信中に最初のキャンパーと会話したか? - {0x352, new EventFlagPlayer(0 , 20 , 0850, "EasterTodayRecipeRandomGenerateNum" )}, // イースター|今日のランダム出現レシピ数 - {0x353, new EventFlagPlayer(0 , 1 , 0851, "ObjRcoMachineHeardFenceRecipe" )}, // タヌポート|たぬきちに柵レシピ解禁の話聞いた?(2P専用) - {0x354, new EventFlagPlayer(0 , 100 , 0852, "WinningProbabilityOfEasterEggGroundRecipe" )}, // じめんのたまご関連のレシピの抽選確率 - {0x355, new EventFlagPlayer(0 , 100 , 0853, "WinningProbabilityOfEasterEggRockRecipe" )}, // いわのたまご関連のレシピの抽選確率 - {0x356, new EventFlagPlayer(0 , 100 , 0854, "WinningProbabilityOfEasterEggLeafRecipe" )}, // はっぱのたまご関連のレシピの抽選確率 - {0x357, new EventFlagPlayer(0 , 100 , 0855, "WinningProbabilityOfEasterEggForestRecipe" )}, // もりのたまご関連のレシピの抽選確率 - {0x358, new EventFlagPlayer(0 , 100 , 0856, "WinningProbabilityOfEasterEggSkyRecipe" )}, // そらとぶたまご関連のレシピの抽選確率 - {0x359, new EventFlagPlayer(0 , 100 , 0857, "WinningProbabilityOfEasterEggFishRecipe" )}, // サカナのたまご関連のレシピの抽選確率 - {0x35A, new EventFlagPlayer(0 , 20 , 0858, "ShootDownEasterRecipeBalloon" )}, // イースター|今日、レシピのついたたまご型風船を撃ち落とした数 - {0x35B, new EventFlagPlayer(0 , 5 , 0859, "EasterRecipeAddLotNum" )}, // イースター|レシピ出現追加抽選実施回数 - {0x35C, new EventFlagPlayer(0 , 1 , 0860, "PynTalkBeforeFlag" )}, // ぴょんたろう|今までに会話したことある? - {0x35D, new EventFlagPlayer(0 , 1 , 0861, "PynTalkBackTodayFlag" )}, // ぴょんたろう|今日背後から話しかけたことある? - {0x35E, new EventFlagPlayer(0 , 1 , 0862, "PynTalkPreVisitDayFlag" )}, // ぴょんたろう|イースター前に会話した? - {0x35F, new EventFlagPlayer(0 , 1 , 0863, "PynTalkEasterDayFlag" )}, // ぴょんたろう|イースター当日に会話した? - {0x360, new EventFlagPlayer(0 , 1 , 0864, "PynCannotGetItemFlag" )}, // ぴょんたろう|受け取り損ねたアイテムがある? - {0x361, new EventFlagPlayer(0 , 1 , 0865, "PynExplainExchangeEggsFlag" )}, // ぴょんたろう|たまご交換の説明を聞いた? - {0x362, new EventFlagPlayer(0 , 1 , 0866, "PynExplainInventRecipeFlag" )}, // ぴょんたろう|プレイヤーがひらめいたレシピの説明を聞いた? - {0x363, new EventFlagPlayer(0 , 1 , 0867, "PynExplainNnpcRecipeFlag" )}, // ぴょんたろう|一般NPCからもらえるレシピのヒントを聞いた? - {0x364, new EventFlagPlayer(0 , 1 , 0868, "PynGetFirstRecipeEasterDayFlag" )}, // ぴょんたろう|イースター当日の初回会話でレシピを入手済み? - {0x365, new EventFlagPlayer(0 , 1 , 0869, "PynGetFinalMissionRecipeFlag" )}, // ぴょんたろう|イースターの最終お題レシピを入手済み? - {0x366, new EventFlagPlayer(0 , 1 , 0870, "PynCompleteDiyMissionFlag" )}, // ぴょんたろう|イースターのDIYミッションをクリア済み? - {0x367, new EventFlagPlayer(0 , 1 , 0871, "PynGetEggBasketFlag" )}, // ぴょんたろう|たまごのバスケットを入手済み? - {0x368, new EventFlagPlayer(0 , 1 , 0872, "PynExplainEasterDateFlag" )}, // ぴょんたろう|イースターの日付を聞いた? - {0x369, new EventFlagPlayer(0 , 1 , 0873, "SetMessageBottleEgg" )}, // イースター|今日タマゴのメッセージボトルを配置したか - {0x36A, new EventFlagPlayer(0 , 1 , 0874, "SetTreeEggLeaf" )}, // イースター|今日はっぱのタマゴの木を配置したか - {0x36B, new EventFlagPlayer(0 , 1 , 0875, "BuryEggGround" )}, // イースター|今日じめんのタマゴを埋めたか - {0x36C, new EventFlagPlayer(0 , 1 , 0876, "IsGetMessageBottleEgg" )}, // イースター|今日タマゴのメッセージボトルを入手したか - {0x36D, new EventFlagPlayer(0 , 2 , 0877, "HitMessageBottleEgg" )}, // イースター|漂着のタマゴが選ばれた回数 - {0x36E, new EventFlagPlayer(0 , 6 , 0878, "MissMessageBottleEgg" )}, // イースター|漂着のタマゴが選ばれなかった回数 - {0x36F, new EventFlagPlayer(0 , 2 , 0879, "EasterNnpcRecipeCount" )}, // イースター|一般NPCからもらったレシピの数 - {0x370, new EventFlagPlayer(0 , 10 , 0880, "LastEasterApproachVillagerIndex" )}, // イースター|最後にイースター用アプローチ会話をしたNPCの住人番号 - {0x371, new EventFlagPlayer(0 , 1 , 0881, "OpenDIYRecipeSeasonCategory" )}, // DIYレシピ・作業台|タブカテゴリ【季節】解禁 - {0x372, new EventFlagPlayer(0 , 9999, 0882, "LastPlayEasterYear" )}, // イースター|最後に遊んだイースターの年 - {0x373, new EventFlagPlayer(0 , 1 , 0883, "PynEvent_SendRecipeMail" )}, // イースター|受け取れなかったレシピを手紙で受け取った? - {0x374, new EventFlagPlayer(0 , 1 , 0884, "PynGetPreVisitRecipeFlag" )}, // イースター|準備期間にレシピを受け取った? - {0x376, new EventFlagPlayer(0 , 1 , 0886, "PynInventRecipeFlag" )}, // ぴょんたろう|イースターエッグ関連レシピをひらめいた? - {0x377, new EventFlagPlayer(0 , 1 , 0887, "SnowmanDIYMailFlag" )}, // ゆきだるま|DIYレシピの手紙送った? - {0x378, new EventFlagPlayer(0 , 64 , 0888, "AlwJuneBrideDayCount" )}, // リサ/ジューンブライド|今年クリアした回数 - {0x379, new EventFlagPlayer(0 , 1 , 0889, "EasterCannotGetNnpcRecipeFlag" )}, // イースター|一般NPCから受け取り損ねたレシピがある? - {0x37A, new EventFlagPlayer(0 , 1 , 0890, "AlwJuneBrideQuestStartFlag" )}, // リサ/ジューンブライド|クエスト開始フラグ - {0x37B, new EventFlagPlayer(0 , 1 , 0891, "AlwJuneBrideQuestClearFlag" )}, // リサ/ジューンブライド|今日クリアした? - {0x37C, new EventFlagPlayer(0 , 1 , 0892, "StampRallyRunningForPlayer" )}, // フータ/国際ミュージアム|スタンプラリーに参加中? - {0x37D, new EventFlagPlayer(0 , 1 , 0893, "OwlInsectStampRally1" )}, // フータ/国際ミュージアム|【ムシ】スタンプ1つ目を押した? - {0x37E, new EventFlagPlayer(0 , 1 , 0894, "OwlInsectStampRally2" )}, // フータ/国際ミュージアム|【ムシ】スタンプ2つ目を押した? - {0x37F, new EventFlagPlayer(0 , 1 , 0895, "OwlInsectStampRally3" )}, // フータ/国際ミュージアム|【ムシ】スタンプ3つ目を押した? - {0x380, new EventFlagPlayer(0 , 1 , 0896, "OwlFishStampRally1" )}, // フータ/国際ミュージアム|【サカナ】スタンプ1つ目を押した? - {0x381, new EventFlagPlayer(0 , 1 , 0897, "OwlFishStampRally2" )}, // フータ/国際ミュージアム|【サカナ】スタンプ2つ目を押した? - {0x382, new EventFlagPlayer(0 , 1 , 0898, "OwlFishStampRally3" )}, // フータ/国際ミュージアム|【サカナ】スタンプ3つ目を押した? - {0x383, new EventFlagPlayer(0 , 1 , 0899, "OwlFossilStampRally1" )}, // フータ/国際ミュージアム|【かせき】スタンプ1つ目を押した? - {0x384, new EventFlagPlayer(0 , 1 , 0900, "OwlFossilStampRally2" )}, // フータ/国際ミュージアム|【かせき】スタンプ2つ目を押した? - {0x385, new EventFlagPlayer(0 , 1 , 0901, "OwlFossilStampRally3" )}, // フータ/国際ミュージアム|【かせき】スタンプ3つ目を押した? - {0x386, new EventFlagPlayer(0 , 1 , 0902, "AlpJuneBrideExchangeFlag" )}, // カイゾー/ジューンブライド|今日交換した? - {0x387, new EventFlagPlayer(0 , 1 , 0903, "AlwJuneBrideRemakeOpenFlag" )}, // リサ/ジューンブライド|リメイクテーマ解禁済み? - {0x388, new EventFlagPlayer(0 , 9999, 0904, "MailSendFlag_VersionUp" )}, // 手紙|アップデートお礼手紙を送った - {0x389, new EventFlagPlayer(0 , 1 , 0905, "MailSendFlag_BundledEdition" )}, // 手紙|同梱版購入お礼手紙を送った - {0x38B, new EventFlagPlayer(0 , 1 , 0907, "GetMayDayTicket" )}, // メーデー|メーデーりょこうけんを入手した? - {0x38C, new EventFlagPlayer(0 , 1 , 0908, "WHEREAREN_VisitDone" )}, // HHD|ウェアラン諸島に行ったことがある - {0x38D, new EventFlagPlayer(0 , 1 , 0909, "PAnnouncePreEaster" )}, // 島内放送|イースター準備期間の放送を聞いた? - {0x390, new EventFlagPlayer(0 , 7 , 0912, "ShootDownEasterOverCountRecipeBalloon" )}, // イースター|たまご風船をレシピ排出数がない状態で撃ち落とした数をカウント - {0x391, new EventFlagPlayer(0 , 1 , 0913, "RcoEarthDayAnnouncement" )}, // アースデー|案内所たぬきちのアースデー告知を聞いた? - {0x392, new EventFlagPlayer(0 , 1 , 0914, "RcoEarthDayGetHedge" )}, // アースデー|アースデー期間にたぬきちから「いけがき」もらった? - {0x393, new EventFlagPlayer(0 , 1 , 0915, "SloTalkAboutHedge" )}, // レイジ|レイジから「いけがき」の話をされたことある? - {0x394, new EventFlagPlayer(0 , 3 , 0916, "SloBuyCount" )}, // レイジ|行商レイジから買い物した回数 - {0x397, new EventFlagPlayer(0 , 1 , 0919, "TalkRumorOVlgFavoriteToday" )}, // 今日RumorOP_Favorite(同じ島の住人P)を聞いたか? - {0x398, new EventFlagPlayer(0 , 1 , 0920, "EasterCompleteFlag" )}, // イースター|イベントを最後までクリアしたことがある? - {0x399, new EventFlagPlayer(0 , 1 , 0921, "PhoneCallPrintServiceDelayFlag" )}, // ポスター解禁入電が次回ゲーム開始時に先延ばしされたか? - {0x39A, new EventFlagPlayer(0 , 1 , 0922, "EarthdayDailyAllClear" )}, // アースデー用の5倍日課を両方クリアしたことがある - {0x39B, new EventFlagPlayer(0 , 9999, 0923, "GetCountEasterEggGround" )}, // イースター期間中のじめんのたまごの取得数 - {0x39C, new EventFlagPlayer(0 , 9999, 0924, "GetCountEasterEggRock" )}, // イースター期間中のいわのたまごの取得数 - {0x39D, new EventFlagPlayer(0 , 9999, 0925, "GetCountEasterEggLeaf" )}, // イースター期間中のはっぱのたまごの取得数 - {0x39E, new EventFlagPlayer(0 , 9999, 0926, "GetCountEasterEggForest" )}, // イースター期間中のもりのたまごの取得数 - {0x39F, new EventFlagPlayer(0 , 9999, 0927, "GetCountEasterEggSky" )}, // イースター期間中のそらとぶたまごの取得数 - {0x3A0, new EventFlagPlayer(0 , 9999, 0928, "GetCountEasterEggFish" )}, // イースター期間中のサカナのたまごの取得数 - {0x3A1, new EventFlagPlayer(0 , 1 , 0929, "DodHeardAboutMayDayTravelTicket" )}, // メーデー|モーリー|たぬきちから預かったメーデー旅行券の説明聞いたか? - {0x3A2, new EventFlagPlayer(0 , 1 , 0930, "UseMayDayTicket" )}, // メーデー|メーデー旅行券を使用した? - {0x3A6, new EventFlagPlayer(0 , 1 , 0934, "OwlShowPaintingMyself" )}, // フータ|自分が絵画クエストを達成した - {0x3A7, new EventFlagPlayer(0 , 1 , 0935, "Owl1stTalkMuseum2" )}, // フータ|博物館②完成後の挨拶した? - {0x3A8, new EventFlagPlayer(0 , 1 , 0936, "OwlPaintingQuestExplain" )}, // フータ|絵画クエストの説明を受けたか? - {0x3A9, new EventFlagPlayer(0 , 1 , 0937, "FutaReadyForMuseum2" )}, // フータ|博物館②建設条件達成の報告を聞いたか? - {0x3AA, new EventFlagPlayer(0 , 1 , 0938, "HeldCeremonyMuseum2" )}, // セレモニ|博物館②を開いた - {0x3AB, new EventFlagPlayer(0 , 2 , 0939, "EarthdayDailyClearNum" )}, // アースデー専用クエストを今日クリアした数 - {0x3AC, new EventFlagPlayer(0 , 1 , 0940, "OwlShowPaintingBeforeQuest" )}, // フータ|絵画クエスト前に絵画を見せたか? - {0x3AD, new EventFlagPlayer(0 , 1 , 0941, "OwlPaintingQuestDeclined" )}, // フータ|絵画クエストで寄贈を断ったことある - {0x3AE, new EventFlagPlayer(0 , 10 , 0942, "LastIslandRepApproachVillagerIndex" )}, // 最後に島評判アップアプローチ会話をしたNPCの住人番号 - {0x3B0, new EventFlagPlayer(0 , 1 , 0944, "ChangedPermanentNum" )}, // 疑似本体IDが合わないフラグ - {0x3B1, new EventFlagPlayer(0 , 1 , 0945, "ClearMayDayTour" )}, // メーデーツアーの謎解きをクリアした? - {0x3B2, new EventFlagPlayer(0 , 3 , 0946, "NnpcApproachNoIslandRepCount" )}, // アプローチ会話|評判UP応援会話を見ないまま経過したプレイ日数 - {0x3B3, new EventFlagPlayer(0 , 1 , 0947, "JuneBridePlacementDataClearFlag" )}, // ジューンブライド|配置データクリア - {0x3B4, new EventFlagPlayer(0 , 1 , 0948, "SloGetHedge" )}, // レイジ|レイジから「いけがき」をもらった? - {0x3B5, new EventFlagPlayer(0 , 1 , 0949, "XctGerReward" )}, // メーデー|みしらぬネコから報酬をもらった? - {0x3B6, new EventFlagPlayer(0 , 1 , 0950, "SpnJuneBrideClearTalkFrag" )}, // パニエル/ジューンブライド|今年クリア後の会話した? - {0x3B7, new EventFlagPlayer(0 , 1 , 0951, "AlwJuneBrideTalkBeforeFlag" )}, // リサ|面識ある? - {0x3B8, new EventFlagPlayer(0 , 1 , 0952, "AlpJuneBrideTalkBeforeFlag" )}, // カイゾー|面識ある? - {0x3B9, new EventFlagPlayer(0 , 1 , 0953, "SpnJuneBrideTalkEventFrag" )}, // パニエル/ジューンブライド|今年イベント期間中に会話した? - {0x3BA, new EventFlagPlayer(0 , 9999, 0954, "PynVisitYear" )}, // ぴょんたろうが来訪した年 - {0x3BB, new EventFlagPlayer(0 , 1 , 0955, "PynVisitToday" )}, // ぴょんたろうが今日来訪NPCとして来訪する - {0x3BC, new EventFlagPlayer(0 , 1 , 0956, "OwlStampPlayed" )}, // フータ/国際ミュージアム|今年スタンプラリーに参加した? - {0x3BF, new EventFlagPlayer(0 , 1 , 0959, "OwlStampPocketWasFull" )}, // フータ/国際ミュージアム|報酬受け取りでポケットいっぱいだった - {0x3C0, new EventFlagPlayer(0 , 1 , 0960, "OwlStampGotInsectReward" )}, // フータ/国際ミュージアム|その日、ムシ報酬を貰った - {0x3C1, new EventFlagPlayer(0 , 1 , 0961, "OwlStampGotFishReward" )}, // フータ/国際ミュージアム|その日、サカナ報酬を貰った - {0x3C2, new EventFlagPlayer(0 , 1 , 0962, "OwlStampGotFossilReward" )}, // フータ/国際ミュージアム|その日、かせき報酬を貰った - {0x3D5, new EventFlagPlayer(0 , 1 , 0981, "DocDeliveryPurchaseExplain" )}, // ロドリー|宅配・買取サービスの説明聞いた? - {0x3D6, new EventFlagPlayer(0 , 1 , 0982, "TalkRumorN2TodayAnyone" )}, // 今日誰かにRumorN2を聞いたか? - {0x3D7, new EventFlagPlayer(0 , 1 , 0983, "TownNewsHeardMuseum2OpenFlag" )}, // 村内放送|博物館建物②が建った告知を聞いた? - {0x3DC, new EventFlagPlayer(0 , 1 , 0988, "KinuyoMydesginMachineFlag" )}, // きぬよ|マイデザイン端末の説明聞いたことある? - {0x3DD, new EventFlagPlayer(0 , 1 , 0989, "OwlStampGotInsect" )}, // フータ/国際ミュージアム|その日、フータスタンプ(ムシ)を押した - {0x3DE, new EventFlagPlayer(0 , 1 , 0990, "OwlStampGotFish" )}, // フータ/国際ミュージアム|その日、フータスタンプ(サカナ)を押した - {0x3DF, new EventFlagPlayer(0 , 1 , 0991, "OwlStampGotFossil" )}, // フータ/国際ミュージアム|その日、フータスタンプ(かせき)を押した - {0x3E0, new EventFlagPlayer(0 , 1 , 0992, "CompleteEventMayDay" )}, // メーデーイベントが全て完了した - {0x3E1, new EventFlagPlayer(0 , 64 , 0993, "AlwJuneBrideDayAlreadyCount" )}, // リサ/ジューンブライド|今までに何日目までクリアしたか用カウント - {0x3E2, new EventFlagPlayer(0 , 1 , 0994, "PAnnounceEarthDay" )}, // 島内放送|アースデー初回ログイン時の放送を聞いた? - {0x3E3, new EventFlagPlayer(0 , 1 , 0995, "TipsChatFlag" )}, // チャット説明ダイアログを見たか? - {0x3E4, new EventFlagPlayer(0 , 1 , 0996, "RcoEarthDayAnnouncementPre" )}, // アースデー|案内所たぬきちのアースデー準備中告知を聞いた? - {0x3E5, new EventFlagPlayer(0 , 1 , 0997, "FoxPreVisitBuyArtFlag" )}, // つねきち|事前来訪中に美術品を買った? - {0x3E6, new EventFlagPlayer(0 , 1 , 0998, "FoxPreVisitWantSellFlag" )}, // つねきち|事前来訪で美術品を売り込み中? - {0x3E7, new EventFlagPlayer(0 , 1 , 0999, "SloTalkedToday" )}, // レイジ|今日会話した? - {0x3EB, new EventFlagPlayer(0 , 2 , 1003, "CurrentJuneBrideTheme" )}, // 現在のジューンブライドのテーマ - {0x3EC, new EventFlagPlayer(0 , 2 , 1004, "PreviousJuneBrideTheme" )}, // 前回のジューンブライドのテーマ - {0x3ED, new EventFlagPlayer(0 , 1 , 1005, "IsSelectedJuneBrideCuteThisYear" )}, // ジューンブライド|今年キュートが選ばれたか? - {0x3EE, new EventFlagPlayer(0 , 1 , 1006, "IsSelectedJuneBrideChicThisYear" )}, // ジューンブライド|今年シックが選ばれたか? - {0x3EF, new EventFlagPlayer(0 , 1 , 1007, "IsSelectedJuneBrideGardenThisYear" )}, // ジューンブライド|今年ガーデンが選ばれたか? - {0x3F2, new EventFlagPlayer(0 , 9999, 1010, "LastPlayJuneBrideYear" )}, // ジューンブライド|最後に遊んだジューンブライドの年 - {0x3F3, new EventFlagPlayer(0 , 1 , 1011, "FoxFirstTalkInShipFlag" )}, // つねきち|船内で会話したことある? - {0x3F4, new EventFlagPlayer(0 , 1 , 1012, "FoxInvitedShipFlag" )}, // つねきち|船へ誘導された? - {0x3F5, new EventFlagPlayer(0 , 1 , 1013, "NoticeAboutSmartPhoneCase" )}, // 作業台リメイク|スマホケースの説明ダイアログ見た - {0x3F6, new EventFlagPlayer(0 , 1 , 1014, "AlwJuneBridePleaseShootFlag" )}, // リサ/ジューンブライド|写真も撮ってと言われた - {0x3F7, new EventFlagPlayer(0 , 1 , 1015, "OwlPaintingQuestReminder" )}, // フータ|その日、美術品提出の催促を受けた - {0x3F8, new EventFlagPlayer(0 , 1 , 1016, "OwlShowDiveFishReport" )}, // フータ|海の幸発見の報告を受けた - {0x3F9, new EventFlagPlayer(0 , 1 , 1017, "DocUsePurchaseServiceFalg" )}, // ロドリー|買取サービス使った? - {0x3FA, new EventFlagPlayer(0 , 1 , 1018, "UsePurchaseBOXFalg" )}, // 今日、買取BOX使った?(入電のメッセージ分岐用) - {0x3FB, new EventFlagPlayer(0 , 1 , 1019, "FoxForcedTalkTodayFlag" )}, // つねきち|今日お店で入店時の強制会話した? - {0x3FC, new EventFlagPlayer(0 , 1 , 1020, "FoxForcedTalk2TodayFlag" )}, // つねきち|今日お店で退店時の強制会話した? - {0x3FE, new EventFlagPlayer(0 , 9999, 1022, "EDDIYFlowerWreathOrderYear" )}, // 花を摘んでリースをつくる活動受注年 - {0x3FF, new EventFlagPlayer(0 , 9999, 1023, "EDDIYCorollaOrderYear" )}, // 花を摘んで花冠をつくる活動受注年 - {0x400, new EventFlagPlayer(0 , 1 , 1024, "OwlStampGotRewardExplain" )}, // フータ/国際ミュージアム|スタンプラリー報酬は二重に貰えない説明を受けた - {0x401, new EventFlagPlayer(0 , 1 , 1025, "UseNavigationMayDayTour" )}, // メーデー|緊急脱出サービスを使用中? - {0x402, new EventFlagPlayer(0 , 1 , 1026, "FirstPlayAfterMuseumBuilt2Flag" )}, // 博物館2に拡張したあとのプレイ初日? - {0x404, new EventFlagPlayer(0 , 256 , 1028, "AlwJuneBrideTotalClearCount" )}, // リサ/ジューンブライド|今年クリアした回数(1日何回でも) - {0x405, new EventFlagPlayer(0 , 1 , 1029, "SloTalkedWeedFirst" )}, // レイジ|雑草初回会話したことある? - {0x406, new EventFlagPlayer(0 , 1 , 1030, "SpnJuneBrideGetFenceFrag" )}, // パニエル/ジューンブライド|今年柵もらった? - {0x407, new EventFlagPlayer(0 , 1 , 1031, "SpnJuneBrideNotGetFenceTodayFrag" )}, // パニエル/ジューンブライド|今日柵もらえなかった? - {0x408, new EventFlagPlayer(0 , 1 , 1032, "JuneBrideBGMHasUnlocked" )}, // ジューンブライド|今年BGMが解禁されているか? - {0x40A, new EventFlagPlayer(0 , 1 , 1034, "XctFirstTalk" )}, // みしらぬネコ/メーデー|面識ある? - {0x40B, new EventFlagPlayer(0 , 1 , 1035, "PAnnounceJuneBride" )}, // 島内放送|今年ジューンブライド初回ログイン時の放送を聞いた? - {0x40C, new EventFlagPlayer(0 , 1 , 1036, "StandByPhoneCallJuneBrideSpn" )}, // 電話デモ|今年パニエルからジューンブライド告知された? - {0x40D, new EventFlagPlayer(0 , 1 , 1037, "AlpJuneBrideGetStickFrag" )}, // カイゾー/ジューンブライド|今年ステッキもらった? - {0x40F, new EventFlagPlayer(0 , 10 , 1039, "LastApproachVillagerIndex" )}, // 最後にアプローチ会話をしたNPCの住人番号 - {0x410, new EventFlagPlayer(0 , 1 , 1040, "StandByPhoneCallJuneBride" )}, // 電話デモ|ジューンブライド告知電話するか? - {0x412, new EventFlagPlayer(0 , 1 , 1042, "OwlExplainDiveFishAfterComp" )}, // フータ|コンプ後に海の幸の追加説明を受けた - {0x414, new EventFlagPlayer(0 , 1 , 1044, "AlwJuneBridePartyTalkFlag" )}, // リサ/ジューンブライド|パーティの案内された - {0x415, new EventFlagPlayer(0 , 1 , 1045, "AlwJuneBrideLastDayTalkFlag" )}, // リサ/ジューンブライド|最終日の挨拶された - {0x416, new EventFlagPlayer(0 , 1 , 1046, "VisitFriendMileageGet" )}, // よその島へのおでかけマイルゲット - {0x417, new EventFlagPlayer(0 , 1 , 1047, "AlwJuneBrideBalloonFlag" )}, // リサ/ジューンブライド|バルーン出す状態? - {0x419, new EventFlagPlayer(0 , 1 , 1049, "GstRichItemFlag" )}, // ゆうたろう|高価な品もらった? - {0x41A, new EventFlagPlayer(1 , 1 , 1050, "MyDesignExchangeDiscloseAuthorID" )}, // マイデザイン交換端末|作者IDの公開 - {0x41B, new EventFlagPlayer(1 , 1 , 1051, "TapDiscloseDreamLandID" )}, // ゆめみ|夢番地の公開 - {0x41C, new EventFlagPlayer(0 , 1 , 1052, "PlayerPocketUIEnableInCommuneIsland" )}, // プレイヤー|コミューン島でのポケットUI解禁 - {0x41D, new EventFlagPlayer(0 , 5 , 1053, "GotoMysteryTour" )}, // モーリー|ミステリーツアー島に行った回数 - {0x41E, new EventFlagPlayer(0 , 1 , 1054, "EnableGotoRareMysteryTour" )}, // モーリー|ミステリーツアーのレア島に行っていいか? - {0x41F, new EventFlagPlayer(0 , 1 , 1055, "VisitMysteryTourID20" )}, // ID: 20のミステリーツアー島にその日行ったことがある - {0x420, new EventFlagPlayer(0 , 1 , 1056, "PAnnounceStampRally" )}, // 島内放送|今年国際ミュージアム初回ログイン時の放送を聞いた? - {0x421, new EventFlagPlayer(0 , 1 , 1057, "FoxPreVisitBuyArtMaxFlag" )}, // つねきち|事前来訪中に2個美術品を買った? - {0x424, new EventFlagPlayer(0 , 9999, 1060, "EDDIYFlowerWreathClearYear" )}, // 花を摘んでリースをつくる活動達成年 - {0x425, new EventFlagPlayer(0 , 9999, 1061, "EDDIYCorollaClearYear" )}, // 花を摘んで花冠をつくる活動達成年 - {0x426, new EventFlagPlayer(0 , 1 , 1062, "GulBQuestStartFlag" )}, // 海賊ジョニー|クエスト開始フラグ - {0x427, new EventFlagPlayer(0 , 1 , 1063, "GulBQuestFinishFlag" )}, // 海賊ジョニー|クエスト完了フラグ - {0x428, new EventFlagPlayer(0 , 1 , 1064, "GulBTalkBeforeFlag" )}, // 海賊ジョニー|今までに会話したことある? - {0x429, new EventFlagPlayer(0 , 1 , 1065, "GulBAnotherPlayerClearFlag" )}, // 海賊ジョニー|クエスト発生後に他のプレイヤーがクリアした? - {0x42A, new EventFlagPlayer(0 , 16 , 1066, "GulBPartsCount" )}, // 海賊ジョニー|渡したパーツの個数 - {0x42B, new EventFlagPlayer(0 , 1 , 1067, "GulBSitUpBeforeFlag" )}, // 海賊ジョニー|今までに起こしたことある? - {0x42C, new EventFlagPlayer(0 , 3 , 1068, "InducedNpcNum" )}, // お出かけ先で勧誘したNPCの数 - {0x42D, new EventFlagPlayer(0 , 1 , 1069, "TalkFreeMultiDayEventTodayFlag" )}, // 今日、期間型イベント用のFreeFを聞いたか? - {0x42E, new EventFlagPlayer(0 , -1 , 1070, "EarthDayBonus" )}, // アースデーの5倍クエストをクリアした日フラグ - {0x42F, new EventFlagPlayer(0 , 1 , 1071, "TalkVillagerClearToday" )}, // 日課あいさつ活動を今日クリア済み - {0x430, new EventFlagPlayer(0 , 1 , 1072, "EarthDayFirstQuestSystem" )}, // アースデーの5倍クエストをまだ出していない(システム用) - {0x431, new EventFlagPlayer(0 , 1 , 1073, "EarthDayFirstQuestTalk" )}, // アースデーの5倍クエストをまだ出していない(会話用) - {0x432, new EventFlagPlayer(0 , 1 , 1074, "SeoExchangeItemToday" )}, // ラコスケ|ホタテをその日渡した? - {0x433, new EventFlagPlayer(0 , 1 , 1075, "MailSendFlag_EarthDayNotice" )}, // 手紙|アースデー導入の手紙を送った? - {0x434, new EventFlagPlayer(0 , 1 , 1076, "PAnnounceMayDayTour" )}, // 島内放送|メーデー初回ログイン時の放送を聞いた? - {0x435, new EventFlagPlayer(0 , 1 , 1077, "DreamFirstExplain" )}, // ゆめみ|DLの初回説明読んだ? - {0x436, new EventFlagPlayer(0 , 1 , 1078, "TapDreamFirstTalk" )}, // ゆめみ|初回会話済ませた? - {0x437, new EventFlagPlayer(0 , 50 , 1079, "GulBHelpCount" )}, // 海賊ジョニー|助けた回数 - {0x438, new EventFlagPlayer(0 , 1 , 1080, "GulBGetQuestItem" )}, // 海賊ジョニー|クエストアイテムを入手した個数 - {0x439, new EventFlagPlayer(0 , 1 , 1081, "HasGottenMarinesuit" )}, // マリンスーツを入手したことがあるか? - {0x43A, new EventFlagPlayer(0 , 1 , 1082, "SeoFirstmeetingFlag" )}, // ラコスケにはじめて会った - {0x43D, new EventFlagPlayer(0 , 1 , 1085, "TalkRumorOActionTodayAnyone" )}, // 今日RumorOP_Action(同じ島の住人P)を聞いたか? - {0x43E, new EventFlagPlayer(0 , 1 , 1086, "SzaFireworksTalkTodayA" )}, // 花火大会しずえ|今日会話した?(5:00-19:00) - {0x43F, new EventFlagPlayer(0 , 1 , 1087, "SzaFireworksTalkTodayB" )}, // 花火大会しずえ|今日会話した?(19:00-24:00) - {0x440, new EventFlagPlayer(0 , 1 , 1088, "SzaFireworksRewardToday" )}, // 花火大会しずえ|今日「光るアクセサリー」もらった? - {0x443, new EventFlagPlayer(0 , 1 , 1091, "FireworksApproachEnd" )}, // 花火大会|専用アプローチ会話済 - {0x444, new EventFlagPlayer(0 , 11 , 1092, "FireworksApproachNpcIndex" )}, // 花火大会|専用アプローチ会話予定NPC住人番号 - {0x445, new EventFlagPlayer(0 , 1 , 1093, "FireworksApproachGetFirework" )}, // 花火大会|花火をもらった - {0x446, new EventFlagPlayer(0 , 1 , 1094, "TapDreamTalkToday" )}, // ゆめみ|今日ゆめみ室内を訪れた - {0x447, new EventFlagPlayer(0 , 1 , 1095, "TapULFirstExplain" )}, // ゆめみ|ULの初回説明読んだ? - {0x449, new EventFlagPlayer(0 , 1 , 1097, "TapDreamUploadToday" )}, // ゆめみ|今日夢をアップロードした - {0x44A, new EventFlagPlayer(0 , 1 , 1098, "TapDreamDeleteToday" )}, // ゆめみ|今日夢を削除した - {0x44B, new EventFlagPlayer(0 , 1 , 1099, "PknTalkBeforeFlag" )}, // パンプキング/ハロウィン|面識ある? - {0x44C, new EventFlagPlayer(0 , 1 , 1100, "PknTalkTodayFlag" )}, // パンプキング/ハロウィン|今日会話した? - {0x44D, new EventFlagPlayer(0 , 64 , 1101, "PknGiveCandyCount" )}, // パンプキング/ハロウィン|アメをあげた回数 - {0x44E, new EventFlagPlayer(0 , 1 , 1102, "PknGetCarriageFlag" )}, // パンプキング/ハロウィン|かぼちゃのばしゃもらった? - {0x44F, new EventFlagPlayer(0 , 1 , 1103, "PknGetBromideFlag" )}, // パンプキング/ハロウィン|ブロマイドもらった? - {0x450, new EventFlagPlayer(0 , 1 , 1104, "PknGetCarriageRecipeFlag" )}, // パンプキング/ハロウィン|かぼちゃのばしゃのレシピもらった? - {0x451, new EventFlagPlayer(0 , 1 , 1105, "OwlPaintingDiveFish" )}, // フータのうみのさちチュートリアル聞いた? - {0x452, new EventFlagPlayer(0 , 1 , 1106, "PAnnounceFireworksSza1" )}, // 島内放送|花火大会しずえ1回目の放送を聞いた? - {0x454, new EventFlagPlayer(0 , 1 , 1108, "RcmBoughtCandyTodayFlag" )}, // まめきち/ハロウィン|今日アメ買った? - {0x456, new EventFlagPlayer(0 , 1 , 1110, "WHEREAREN_Unlock_AccentWall" )}, // OneRoom|ライセンス(アクセントウォール)解禁 - {0x457, new EventFlagPlayer(0 , 1 , 1111, "FoxFirstTalkFireworksFlag" )}, // つねきち|花火大会で会話したことある? - {0x458, new EventFlagPlayer(0 , 1 , 1112, "CharacterCreationFlag" )}, // 夏パッチ以降でキャラメイク完了したか? - {0x459, new EventFlagPlayer(0 , 1 , 1113, "PublicAnnouncement_DiveFish" )}, // 泳ぎ解禁の島内放送聞いたか?手紙だす? - {0x45A, new EventFlagPlayer(0 , 1 , 1114, "DiveFish_GetLetter" )}, // 初回泳ぎ島内放送聞けず、手紙を受け取った - {0x45B, new EventFlagPlayer(0 , 1 , 1115, "DiveFishPublic_1day" )}, // 初回泳ぎ解禁島内放送を聞いた? - {0x45C, new EventFlagPlayer(0 , 1 , 1116, "DiveFishPublic_2day" )}, // 2日目の泳ぎ解禁島内放送を聞いた? - {0x45D, new EventFlagPlayer(0 , 1 , 1117, "RcmTalkAboutMarinesuitFlag" )}, // まめきち|マリンスーツの説明を聞いた - {0x45E, new EventFlagPlayer(0 , 1 , 1118, "Encylopedia_DiveFishMes" )}, // 夏パッチ後、図鑑開いてうみのさち追加案内を見た - {0x45F, new EventFlagPlayer(0 , 1 , 1119, "MyDesignExchangeExp_v1_4" )}, // マイデザイン交換| 夏パッチ2で追加された機能説明 - {0x460, new EventFlagPlayer(0 , 1 , 1120, "MyDesignExchangeExp_NormalUsage" )}, // マイデザイン交換| ノーマル用途追加の説明 - {0x461, new EventFlagPlayer(0 , 1 , 1121, "PlayerHouseBuiltToday" )}, // 今日自宅が完成した(今日テント→家になった) - {0x462, new EventFlagPlayer(0 , 1 , 1122, "ReceiveTapBedLetter" )}, // ゆめみからベッド付き手紙を受け取った - {0x463, new EventFlagPlayer(0 , 1 , 1123, "FoxTalkOnlyStandShopFlag" )}, // つねきち|屋台でしか会話したことがない? - {0x464, new EventFlagPlayer(0 , 1 , 1124, "NpcGetCandyTodayFlag" )}, // 一般NPC/ハロウィン|今日アメもらった? - {0x465, new EventFlagPlayer(0 , 1 , 1125, "DiveFish_FirstDonation" )}, // 海の幸を初寄贈した - {0x466, new EventFlagPlayer(0 , 1 , 1126, "TapSendThankyouLetter" )}, // ゆめみ|翌日、夢をアップしたお礼の手紙が届くか? - {0x467, new EventFlagPlayer(0 , 9999, 1127, "PickUpDIYGoldCount" )}, // ver1.4.0以降、拾われたことがない金鉱石を拾った回数 - {0x468, new EventFlagPlayer(0 , 1 , 1128, "FireworkCannotGetNnpcItemFlag" )}, // 花火大会|一般NPCから受け取り損ねたアイテムがある? - {0x46B, new EventFlagPlayer(0 , 7 , 1131, "SurpriseVisitCount" )}, // 突撃訪問発生までのカウント - {0x46C, new EventFlagPlayer(0 , 1 , 1132, "SurpriseVisitDone" )}, // 突撃訪問された事があるか - {0x46D, new EventFlagPlayer(0 , 1 , 1133, "GetHalloweenRag" )}, // 一般NPC/ハロウィン|ラグもらった? - {0x46E, new EventFlagPlayer(0 , 1 , 1134, "GetHalloweenWallPaper" )}, // 一般NPC/ハロウィン|かべがみもらった? - {0x46F, new EventFlagPlayer(0 , 1 , 1135, "GetHalloweenFloor" )}, // 一般NPC/ハロウィン|ゆかもらった? - {0x470, new EventFlagPlayer(0 , 1 , 1136, "GetHalloweenStickRecipe" )}, // パンプキング/ハロウィン|ステッキ(レシピ)もらった? - {0x471, new EventFlagPlayer(0 , 1 , 1137, "GetHalloweenGarland" )}, // 一般NPC/ハロウィン|ガーランドもらった? - {0x473, new EventFlagPlayer(0 , 1 , 1139, "GetHalloweenTableSetting" )}, // 一般NPC/ハロウィン|テーブルセッティングもらった? - {0x475, new EventFlagPlayer(0 , 1 , 1141, "GetHalloweenBag" )}, // 今年ハロウィンのはねをもらった - {0x476, new EventFlagPlayer(0 , 1 , 1142, "AddBodyColor" )}, // タヌポート|追加ボディカラー解禁 - {0x477, new EventFlagPlayer(0 , 1 , 1143, "AddEyeColor" )}, // タヌポート|追加アイカラー解禁 - {0x478, new EventFlagPlayer(0 , 1 , 1144, "AddCheekColor" )}, // タヌポート|追加チークカラー解禁 - {0x479, new EventFlagPlayer(0 , 1 , 1145, "SaveDataRestoringSettingNotice" )}, // セーブデータ復元|設定異常検知 - {0x47A, new EventFlagPlayer(0 , 1 , 1146, "TapTalkAboutMydesignShowcase" )}, // ゆめみ|マイデザインショーケースについて説明聞いた - {0x47B, new EventFlagPlayer(0 , 1 , 1147, "NpcHalloweenTrickFlag" )}, // ハロウィン|今日イタズラされた? - {0x47C, new EventFlagPlayer(0 , 1 , 1148, "TapFirstDreamIn" )}, // ゆめみ|夢の中に入ったことがある? - {0x47D, new EventFlagPlayer(0 , 1 , 1149, "TapFirstCheckMydesingShowcase" )}, // ゆめみ|夢の中のマイデザインショーケース端末にアクセスしたことがある? - {0x47F, new EventFlagPlayer(0 , 1 , 1151, "SpecialMakeChanged" )}, // プレイヤが特殊メイクに変更した - {0x480, new EventFlagPlayer(0 , 1 , 1152, "TalkMakeTodayAnyone" )}, // 今日誰かにメイク会話を聞いたか - {0x481, new EventFlagPlayer(0 , 1 , 1153, "RcmExplainCandyFlag" )}, // まめきち/ハロウィン|今年アメの説明聞いた? - {0x482, new EventFlagPlayer(0 , 1 , 1154, "RcmExplainPumpkinFlag" )}, // まめきち/ハロウィン|今日かぼちゃの苗の説明聞いた? - {0x483, new EventFlagPlayer(0 , 1 , 1155, "SzaFireworksSubmitMyDesignToday" )}, // 花火大会しずえ|今日マイデザイン花火を提出した? - {0x484, new EventFlagPlayer(0 , 1 , 1156, "PAnnounceHalloween" )}, // 島内放送|今年ハロウィン期間初回ログイン時の放送を聞いた? - {0x486, new EventFlagPlayer(0 , 1 , 1158, "ExplainPumpkinColorFlag" )}, // ハロウィン|今年かぼちゃの苗の説明聞いた? - {0x487, new EventFlagPlayer(0 , 1 , 1159, "SloExplainPumpkinSeedingFlag" )}, // レイジ/ハロウィン|今日かぼちゃの苗の特別価格の説明きいた? - {0x488, new EventFlagPlayer(0 , 1 , 1160, "CalcPastDays" )}, // 経過日数の計算をした - {0x489, new EventFlagPlayer(0 , 1 , 1161, "PlayerProducedByPlayerMoving" )}, // プレイヤーだけ引越し|プレイヤーだけ引越しによって作られたプレイヤーか? - {0x48A, new EventFlagPlayer(0 , 3000, 1162, "FireworksLastApproachYear" )}, // 花火大会|最後にアプローチ挙動をした年 - {0x48B, new EventFlagPlayer(0 , 1 , 1163, "RcoTalkAboutMovingBelongings" )}, // プレイヤーだけ引越し|たぬきちと所持品について話した - {0x48C, new EventFlagPlayer(0 , 1 , 1164, "RcmRctTalkAboutMovingBelongings" )}, // プレイヤーだけ引越し|まめきち、つぶきちと所持品について話した - {0x48D, new EventFlagPlayer(0 , 1 , 1165, "SloExplainAddVegetable" )}, // レイジ/ハロウィン|今日かぼちゃの苗販売の説明聞いた? - {0x48E, new EventFlagPlayer(0 , 1 , 1166, "PocketItemSendRecycleBoxByMoving" )}, // プレイヤーだけ引越し|ポケットの所持品がリサイクルBOXに送られた - {0x48F, new EventFlagPlayer(0 , 1 , 1167, "TentItemSendRecycleBoxByMoving" )}, // プレイヤーだけ引越し|テントの配置物がリサイクルBOXに送られた - {0x492, new EventFlagPlayer(0 , 1 , 1170, "PknTalkLastNoCandyFlag" )}, // パンプキング/ハロウィン|最後の会話時アメ持ってなかった? - {0x493, new EventFlagPlayer(0 , 1 , 1171, "AddHowtoBookMydesignPro2" )}, // マイデザインPROエディタ2解禁条件を満たしたか? - {0x494, new EventFlagPlayer(0 , 1 , 1172, "UnlockMydesignPro2" )}, // マイデザインPROエディタ2習得済みか? - {0x495, new EventFlagPlayer(0 , 1 , 1173, "ExplainMydesignPro2" )}, // マイデザインPROエディタ2習得後の説明を聞いたか? - {0x496, new EventFlagPlayer(0 , 1 , 1174, "RcoMachineExplainMydesignPro2" )}, // タヌポートでマイデザインPROエディタ2販売開始の案内聞いたか? - {0x499, new EventFlagPlayer(0 , 1 , 1177, "NotBuilt2PMyHomeAfterMoving" )}, // プレイヤーだけ引越し|(2P限定)引越し後、まだ家の場所を決めてない - {0x49A, new EventFlagPlayer(0 , 4 , 1178, "HarvestProgress" )}, // ハーベスト|完成した料理の数(プレイヤー単位) - {0x49B, new EventFlagPlayer(0 , 64 , 1179, "PknGiveLollipopCount" )}, // パンプキング/ハロウィン|ロリポップをあげた回数 - {0x49C, new EventFlagPlayer(0 , 1 , 1180, "TapSelWhereAreHere" )}, // ゆめみ|ここはどこ?を1度選んだらON - {0x49D, new EventFlagPlayer(0 , 1 , 1181, "PknTalkLastNotGetFlag" )}, // パンプキング/ハロウィン|最後の会話でアイテムもらえなかった? - {0x49E, new EventFlagPlayer(0 , 1 , 1182, "PknLastGiveCandyFlag" )}, // パンプキング/ハロウィン|前回渡したのはアメ? - {0x49F, new EventFlagPlayer(0 , 1 , 1183, "PknCompItemCandyFlag" )}, // パンプキング/ハロウィン|アメ報酬コンプした? - {0x4A0, new EventFlagPlayer(0 , 1 , 1184, "PknCompItemLollipopFlag" )}, // パンプキング/ハロウィン|ロリポップ報酬コンプした? - {0x4A1, new EventFlagPlayer(0 , 1 , 1185, "PknPumpkingLookChatFlag" )}, // パンプキング/ハロウィン|パンプキング装備の雑談した? - {0x4A2, new EventFlagPlayer(0 , 1 , 1186, "Mobile1stBoot_Camera_UnlockKeyGuideOff" )}, // スマホアプリ初起動|カメラアプリにキーガイドOFF追加 - {0x4A3, new EventFlagPlayer(0 , 1 , 1187, "GetHalloweenRobe" )}, // パンプキング/ハロウィン|ローブをもらった - {0x4A4, new EventFlagPlayer(0 , 1 , 1188, "GetHalloweenMask" )}, // パンプキング/ハロウィン|かぶりものをもらった - {0x4A5, new EventFlagPlayer(0 , 1 , 1189, "PknSendLetterFlag" )}, // パンプキング/ハロウィン|今年手紙送った? - {0x4A6, new EventFlagPlayer(0 , 1 , 1190, "PlayerMovingwithNoBelongings" )}, // プレイヤーだけ引越し|所持品(手荷物)なしで引越してきた - {0x4A7, new EventFlagPlayer(0 , 8 , 1191, "NpcGiveCandyCount" )}, // 一般NPC/ハロウィン|アメのお礼もらった回数 - {0x4A8, new EventFlagPlayer(0 , 1 , 1192, "GetHalloweenGarlandRecipe" )}, // 一般NPC/ハロウィン|ガーランドのレシピをもらった - {0x4A9, new EventFlagPlayer(0 , 1 , 1193, "GetHalloweenTableSettingRecipe" )}, // 一般NPC/ハロウィン|テーブルセッティングのレシピをもらった - {0x4AA, new EventFlagPlayer(0 , 1 , 1194, "NpcTalkLastNotGetFlag" )}, // 一般NPC/ハロウィン|イベント中、誰かと話した? - {0x4AB, new EventFlagPlayer(0 , 1 , 1195, "EnabledEmoticonIrregular" )}, // 漫符UI解禁済みかつ漫符入手会話が未発生 - {0x4AC, new EventFlagPlayer(0 , 1 , 1196, "CanGetMileTicketTrialForMoving" )}, // プレイヤーだけ引越し|引越しで来たプレイヤーに旅行券渡してよい? - {0x4AD, new EventFlagPlayer(0 , 1 , 1197, "PlayerMovingOrderHouseBuilt" )}, // たぬきち|家建築、増築申し込み当日にPだけ引越しした? - {0x4AE, new EventFlagPlayer(0 , 1 , 1198, "PlayerMovingOrderChangeHouseDesign" )}, // たぬきち|家外観変更申し込み当日にPだけ引越しした? - {0x4AF, new EventFlagPlayer(0 , 1 , 1199, "PlayerMovingOrderHouseMoveInIsland" )}, // たぬきち|自宅移設申し込み当日にPだけ引越しした? - {0x4B0, new EventFlagPlayer(0 , 1 , 1200, "PlayerMovingAfterHouseRemodel" )}, // たぬきち|家増築後説明の発生予約中にPだけ引越しした? - {0x4B1, new EventFlagPlayer(0 , 1 , 1201, "PlayerMovingAfterLoanFinish" )}, // たぬきち|ローン完済会話の発生予約中にPだけ引越しした? - {0x4B2, new EventFlagPlayer(0 , 1 , 1202, "TapUnlockFavorite" )}, // ゆめみ|「前に見た夢を見る」解禁 - {0x4B3, new EventFlagPlayer(0 , 9999, 1203, "LastPlayHalloweenYear" )}, // ハロウィン|最後に遊んだハロウィンの年 - {0x4B5, new EventFlagPlayer(0 , 1 , 1205, "PlayerMovingDefaultHouseHasBasement" )}, // プレイヤーだけ引越し|引越し時点で家に地下室がある - {0x4B6, new EventFlagPlayer(0 , 1 , 1206, "PlayerMovingEnable" )}, // プレイヤーだけ引越し|プレイヤーだけ引越しが可能か?(自宅完成済みか?) - {0x4B7, new EventFlagPlayer(0 , 1 , 1207, "RemakeWithRcoOfficeBeforeWS" )}, // プレイヤーだけ引越し|リメイクWS前に案内所でリメイクした - {0x4B8, new EventFlagPlayer(0 , 1 , 1208, "RemakeWithRcoTentBeforeWS" )}, // プレイヤーだけ引越し|リメイクWS前にたぬきちテントでリメイクした - {0x4B9, new EventFlagPlayer(0 , 1 , 1209, "IslandCreaterUnlockMoving" )}, // プレイヤーだけ引越し|引越しのタイミングで島クリエイター解禁した? - {0x4BA, new EventFlagPlayer(0 , 1 , 1210, "AnnounceHalloween" )}, // ハロウィンを島内放送で告知した(2回目放送用) - {0x4BB, new EventFlagPlayer(0 , 1 , 1211, "AnnounceHarvest" )}, // ハーベスト|当日島内放送で告知した(2回目放送用) - {0x4BE, new EventFlagPlayer(0 , 1 , 1214, "SloGetVegetableBasketDIY" )}, // レイジ|野菜の籠レシピもらった? - {0x4BF, new EventFlagPlayer(0 , 1 , 1215, "MilageSendLetterFlag" )}, // タヌポート/ハロウィン|新規肌・目の色の追加手紙送った? - {0x4C0, new EventFlagPlayer(0 , 1 , 1216, "NpcHalloweenGetMirrorFlag" )}, // ハロウィン|今日NPCからミラーもらった? - {0x4C1, new EventFlagPlayer(0 , 1 , 1217, "NpcHalloweenCandyHelpFlag" )}, // ハロウィン|今日NPCから救済用アメもらった? - {0x4C2, new EventFlagPlayer(0 , 1 , 1218, "PlayerMovingWithEmoticonUI" )}, // プレイヤーだけ引越し|引越しを漫符解禁状態でやったか? - {0x4C3, new EventFlagPlayer(0 , 1 , 1219, "AddHairStyle4" )}, // 『ホットなヘアアレンジ』解禁 - {0x4C7, new EventFlagPlayer(0 , 8 , 1223, "PknGetItem" )}, // パンプキング/ハロウィン|報酬アイテムは? - {0x4C9, new EventFlagPlayer(0 , 1 , 1225, "XctGetRewardThisIsland" )}, // メーデー|みしらぬネコから「今住んでる島で」報酬もらった? - {0x4CA, new EventFlagPlayer(0 , 1 , 1226, "HarvestHQDish1P" )}, // ハーベスト|Pが料理1クラムチャウダーの隠し食材納めた? - {0x4CB, new EventFlagPlayer(0 , 1 , 1227, "HarvestHQDish2P" )}, // ハーベスト|Pが料理2パンプキンパイの隠し食材納めた? - {0x4CC, new EventFlagPlayer(0 , 1 , 1228, "HarvestHQDish3P" )}, // ハーベスト|Pが料理3グラタンの隠し食材納めた? - {0x4CD, new EventFlagPlayer(0 , 1 , 1229, "HarvestHQDish4P" )}, // ハーベスト|Pが料理4サカナのムニエルの隠し食材納めた? - {0x4CE, new EventFlagPlayer(0 , 1 , 1230, "TukTalkFirst" )}, // ハーベスト|フランクリンとの面識あるか? - {0x4CF, new EventFlagPlayer(0 , 4 , 1231, "HarvestTalkAboutNextDishProgress" )}, // ハーベスト|次の料理の話を聞いたか? - {0x4D0, new EventFlagPlayer(0 , 1 , 1232, "TapUnlockLeaveTap" )}, // ゆめみ|「おまかせ」解禁 - {0x4D1, new EventFlagPlayer(0 , 8 , 1233, "HarvestKeepReward" )}, // ハーベスト|渡す報酬の種類情報 - {0x4D2, new EventFlagPlayer(0 , 1 , 1234, "RewindDays" )}, // 日付を巻き戻した - {0x4D3, new EventFlagPlayer(0 , 1 , 1235, "TukTalkBeforeEvent" )}, // ハーベスト|フランクリンとイベント開始前に会話した - {0x4D4, new EventFlagPlayer(0 , 1 , 1236, "TukTalkAfterEvent" )}, // ハーベスト|フランクリンとイベント終了後に会話した - {0x4D5, new EventFlagPlayer(0 , 1 , 1237, "AnnounceBeforeHarvest" )}, // ハーベスト|5日前~2日前に島内放送で告知した - {0x4D6, new EventFlagPlayer(0 , 1 , 1238, "PasswordIsOld" )}, // パスワードが古いのでPOPID使用不可 - {0x4D7, new EventFlagPlayer(0 , 3 , 1239, "FishExchangeLoseCount" )}, // ハーベスト|物々交換でハズレをもらった回数 - {0x4D8, new EventFlagPlayer(0 , 1 , 1240, "ReiTalkFirst" )}, // クリスマス|ジングルとの面識あるか? - {0x4D9, new EventFlagPlayer(0 , 1 , 1241, "ReiGetReward1" )}, // クリスマス|ジングルからくつしたのかざり受け取った? - {0x4DA, new EventFlagPlayer(0 , 1 , 1242, "ReiGetReward2" )}, // クリスマス|ジングルからプレゼントのやまレシピ受け取った? - {0x4DB, new EventFlagPlayer(0 , 1 , 1243, "ReiGetReward3" )}, // クリスマス|ジングルからクリスマスのソリ受け取った? - {0x4DC, new EventFlagPlayer(0 , 1 , 1244, "ReiStartQuest1" )}, // クリスマス|ジングルからラッピングDIYクエスト受注した? - {0x4DD, new EventFlagPlayer(0 , 1 , 1245, "ReiStartQuest2" )}, // クリスマス|ジングルからプレゼント配布クエスト受注した? - {0x4DF, new EventFlagPlayer(0 , 1 , 1247, "ReiFinishQuest1" )}, // クリスマス|ジングルのDIYクエスト完了した? - {0x4E0, new EventFlagPlayer(0 , 1 , 1248, "AnnouncePreChristmas" )}, // クリスマス|事前期間に島内放送で告知した? - {0x4E2, new EventFlagPlayer(0 , 1 , 1250, "WHEREAREN_NoticeAboutDustCloth" )}, // OneRoom|まごころ雑巾の初回ダイアログを見た? - {0x4E3, new EventFlagPlayer(0 , 10 , 1251, "SantaMissionNpcIndex1" )}, // クリスマス|サンタミッションでお返しをくれるNPC1 - {0x4E4, new EventFlagPlayer(0 , 10 , 1252, "SantaMissionNpcIndex2" )}, // クリスマス|サンタミッションでお返しをくれるNPC2 - {0x4E5, new EventFlagPlayer(0 , 10 , 1253, "SantaMissionNpcIndex3" )}, // クリスマス|サンタミッションでお返しをくれるNPC3 - {0x4E6, new EventFlagPlayer(0 , 1 , 1254, "ReceiveLeaveTapLetter" )}, // ゆめみ|おまかせ解禁の手紙を受け取った - {0x4E7, new EventFlagPlayer(0 , 1 , 1255, "RcmExplainToy" )}, // クリスマス|おもちゃ家具陳列の案内を受けた? - {0x4E8, new EventFlagPlayer(0 , 1 , 1256, "PckTalkTodayFlag" )}, // カーニバル/べルリーナ|今日すでに会話した? - {0x4E9, new EventFlagPlayer(0 , 9999, 1257, "ChristmasWreathGetYear" )}, // クリスマス|クリスマスリースをNPCから貰った年 - {0x4EA, new EventFlagPlayer(0 , 9 , 1258, "TukSecretRewardType" )}, // ハーベスト|フランクリンの隠し食材報酬抽選結果 - {0x4EC, new EventFlagPlayer(0 , 1 , 1260, "WHEREAREN_Unlock_ResortPlannerApp" )}, // OneRoom|リゾートプランナーアプリアンロック - {0x4ED, new EventFlagPlayer(0 , 1 , 1261, "WHEREAREN_Unlock_ResortStudyApp" )}, // OneRoom|リゾートスタディアプリアンロック - {0x4EE, new EventFlagPlayer(0 , 1 , 1262, "TapUpdatedDreamFirstTalk" )}, // ゆめみ|初回会話を1.6.0以降に行った? - {0x4EF, new EventFlagPlayer(0 , 1 , 1263, "SzaChristmasOrnament" )}, // クリスマス|しずえからオーナメント素材もらった? - {0x4F1, new EventFlagPlayer(0 , 1 , 1265, "CheckHarvestFtrInStore" )}, // ハーベスト|ハーベスト家具をお店でチェックしたことがあるか? - {0x4F2, new EventFlagPlayer(0 , 9999, 1266, "ChristmasPresentYear" )}, // クリスマス|自宅プレゼントをもらった年 - {0x4F3, new EventFlagPlayer(0 , 2 , 1267, "InputApproachBanCount" )}, // アプローチ|入力系アプローチ禁止カウント - {0x4F4, new EventFlagPlayer(0 , 1 , 1268, "PckLookChatFlag" )}, // カーニバル/べルリーナ|カーニバル装備の雑談した? - {0x4F5, new EventFlagPlayer(0 , 1 , 1269, "TukCancel1stRequest" )}, // ハーベスト|フランクリン1品目で「大変ですね」を選択した - {0x4F6, new EventFlagPlayer(0 , 1 , 1270, "ChristmasWrappingGiftFlag" )}, // クリスマス|プレゼント交換初回でラッピングもらった? - {0x4F8, new EventFlagPlayer(0 , 1 , 1272, "HarvestRefuseGiveHQFood1" )}, // ハーベスト|料理1の隠し食材を渡すのを拒んだ - {0x4F9, new EventFlagPlayer(0 , 1 , 1273, "HarvestRefuseGiveHQFood2" )}, // ハーベスト|料理2の隠し食材を渡すのを拒んだ - {0x4FA, new EventFlagPlayer(0 , 1 , 1274, "HarvestRefuseGiveHQFood3" )}, // ハーベスト|料理3の隠し食材を渡すのを拒んだ - {0x4FB, new EventFlagPlayer(0 , 1 , 1275, "HarvestRefuseGiveHQFood4" )}, // ハーベスト|料理4の隠し食材を渡すのを拒んだ - {0x4FC, new EventFlagPlayer(0 , 2 , 1276, "HarvestGetHint1" )}, // ハーベスト|料理1の隠し食材ヒント聞いた - {0x4FD, new EventFlagPlayer(0 , 2 , 1277, "HarvestGetHint2" )}, // ハーベスト|料理2の隠し食材ヒント聞いた - {0x4FE, new EventFlagPlayer(0 , 2 , 1278, "HarvestGetHint3" )}, // ハーベスト|料理3の隠し食材ヒント聞いた - {0x4FF, new EventFlagPlayer(0 , 2 , 1279, "HarvestGetHint4" )}, // ハーベスト|料理4の隠し食材ヒント聞いた - {0x500, new EventFlagPlayer(0 , 1 , 1280, "ChristmasWrappingPresentFlag" )}, // クリスマス|ラッピングを誰かくれようとしたか? - {0x501, new EventFlagPlayer(0 , 1 , 1281, "PckRecipeFlag" )}, // カーニバル/べルリーナ|にじいろのはねのレシピもらった? - {0x502, new EventFlagPlayer(0 , 1 , 1282, "RcoStorageExpansionReserved" )}, // たぬきち|収納の拡張を予約している - {0x503, new EventFlagPlayer(0 , 1 , 1283, "RcoStorageExpansionLevel" )}, // たぬきち|収納の拡張段階('20冬パッチ 1段階のみ) - {0x504, new EventFlagPlayer(0 , 1 , 1284, "PlayerMovingReservedStorageExpand" )}, // たぬきち|収納の拡張申し込み当日にPだけ引越しした? - {0x505, new EventFlagPlayer(0 , 1 , 1285, "MailSend_NoticeStorageExpansion" )}, // たぬきち|収納の拡張のお知らせ手紙の判定処理したか? - {0x506, new EventFlagPlayer(0 , 1 , 1286, "RcoStandbyNoticeStorageExpansion" )}, // たぬきち|収納の拡張について強制会話するか? - {0x507, new EventFlagPlayer(0 , 1 , 1287, "ChristmasWreathNoGetFlag" )}, // クリスマス|このNPCからリース受け取り損ねた - {0x508, new EventFlagPlayer(0 , 3 , 1288, "PckGetItem" )}, // カーニバル/べルリーナ|報酬アイテムは? - {0x509, new EventFlagPlayer(0 , 1 , 1289, "WHEREAREN_Unlock_CoordinateNpcHouse" )}, // OneRoom|ライセンス(NPC家コーディネート)解禁 - {0x50A, new EventFlagPlayer(0 , 1 , 1290, "GetCarnivalLight" )}, // カーニバル/べルリーナ|カーニバルなライトもらった? - {0x50B, new EventFlagPlayer(0 , 1 , 1291, "GetCarnivalFoodStand" )}, // カーニバル/べルリーナ|カーニバルな屋台もらった? - {0x50C, new EventFlagPlayer(0 , 1 , 1292, "GetCarnivalstage" )}, // カーニバル/べルリーナ|カーニバルなステージもらった? - {0x50D, new EventFlagPlayer(0 , 1 , 1293, "GetCarnivalConfettiMachine" )}, // カーニバル/べルリーナ|カーニバルなかみふぶきマシンもらった? - {0x50E, new EventFlagPlayer(0 , 1 , 1294, "GetCarnivalPercussion" )}, // カーニバル/べルリーナ|カーニバルなパーカッションもらった? - {0x50F, new EventFlagPlayer(0 , 1 , 1295, "GetCarnivalBalloonLight" )}, // カーニバル/べルリーナ|カーニバルバルーンライトもらった? - {0x510, new EventFlagPlayer(0 , 1 , 1296, "GetCarnivalUmbrellas" )}, // カーニバル/べルリーナ|カーニバルなパラソルもらった? - {0x511, new EventFlagPlayer(0 , 1 , 1297, "GetCarnivalFlag" )}, // カーニバル/べルリーナ|カーニバルなフラッグもらった? - {0x512, new EventFlagPlayer(0 , 1 , 1298, "GetCarnivalGarland" )}, // カーニバル/べルリーナ|カーニバルなガーランドもらった? - {0x513, new EventFlagPlayer(0 , 1 , 1299, "GetCarnivalFloat" )}, // カーニバル/べルリーナ|カーニバルなフロートもらった? - {0x515, new EventFlagPlayer(0 , 10 , 1301, "PckGiveFurnitureCount" )}, // カーニバル/べルリーナ|家具をもらった回数 - {0x516, new EventFlagPlayer(0 , 1 , 1302, "WHEREAREN_Unlock_ResortPlannerAppNetwork" )}, // OneRoom|リゾートプランナーアプリのツクッターアンロック - {0x517, new EventFlagPlayer(0 , 1 , 1303, "WHEREAREN_Unlock_ResortPlannerAppRevisit" )}, // OneRoom|リゾートプランナーアプリの再訪アンロック - {0x518, new EventFlagPlayer(0 , 1 , 1304, "SloExplainPumpkinColorFlag" )}, // レイジ|かぼちゃの苗説明聞いたことある? - {0x519, new EventFlagPlayer(0 , 1 , 1305, "SloExplainAddPumpkinFlag" )}, // レイジ|かぼちゃの苗販売開始の説明聞いた? - {0x51B, new EventFlagPlayer(0 , 1 , 1307, "TukSecretRewardType3rd" )}, // ハーベスト|フランクリンの隠し食材報酬抽選結果(3回目) - {0x51C, new EventFlagPlayer(0 , 1 , 1308, "PckTalkBeforeFlag" )}, // カーニバル/べルリーナ|面識ある? - {0x51D, new EventFlagPlayer(0 , 1 , 1309, "SendNNPCConversationPlayReport" )}, // 会話のフリのプレイレポートがその日送信されたか - {0x51E, new EventFlagPlayer(0 , 1 , 1310, "MainmenuMydesignShowcase" )}, // スマホUI|マイデザインショーケース解禁 - {0x51F, new EventFlagPlayer(0 , 8 , 1311, "ChristmasPrevPresentItemType" )}, // クリスマス|直前にNPCにもらったアイテムの種類 - {0x520, new EventFlagPlayer(0 , 1 , 1312, "ValentineLetterFlag" )}, // バレンタイン|手紙送った? - {0x522, new EventFlagPlayer(0 , 1 , 1314, "AnnounceChristmasEve" )}, // クリスマス|当日に島内放送で告知した?(2回目放送用) - {0x526, new EventFlagPlayer(0 , 511 , 1318, "GetCarnivalFurniture" )}, // カーニバル/ベルリーナ|どのカーニバル家具をもらったか? - {0x52C, new EventFlagPlayer(0 , 9999, 1324, "LastPlayValentineYear" )}, // バレンタイン|最後に遊んだバレンタインの年 - {0x52D, new EventFlagPlayer(0 , 1 , 1325, "PckRecipeTalkFlag" )}, // カーニバル/べルリーナ|にじいろのはねのレシピもらう会話した? - {0x52E, new EventFlagPlayer(0 , 1 , 1326, "Mobile1stBoot_MydesignShowcase" )}, // スマホアプリ初起動|マイデザインアプリにショーケース追加 - {0x52F, new EventFlagPlayer(0 , 1 , 1327, "MydesignExchangeTalkAboutMobile" )}, // マイデザイン交換| マイデザインショーケースアプリについて説明 - {0x530, new EventFlagPlayer(0 , 1 , 1328, "BuyReactionBook17" )}, // カーニバル用リアクション本を購入した - {0x531, new EventFlagPlayer(0 , 511 , 1329, "GetCarnivalFurnitureRed" )}, // カーニバル/ベルリーナ|どの赤色カーニバル家具をもらったか? - {0x532, new EventFlagPlayer(0 , 511 , 1330, "GetCarnivalFurnitureBlue" )}, // カーニバル/ベルリーナ|どの青色カーニバル家具をもらったか? - {0x533, new EventFlagPlayer(0 , 511 , 1331, "GetCarnivalFurnitureGreen" )}, // カーニバル/ベルリーナ|どの緑色カーニバル家具をもらったか? - {0x534, new EventFlagPlayer(0 , 511 , 1332, "GetCarnivalFurniturePurple" )}, // カーニバル/ベルリーナ|どの紫色カーニバル家具をもらったか? - {0x535, new EventFlagPlayer(0 , 511 , 1333, "GetCarnivalFurnitureRainbow" )}, // カーニバル/ベルリーナ|どの虹色カーニバル家具をもらったか? - {0x536, new EventFlagPlayer(0 , 1 , 1334, "PckColorLotteryFlag" )}, // カーニバル/ベルリーナ|色ごとにカーニバル家具の抽選をするか? - {0x537, new EventFlagPlayer(0 , 1 , 1335, "RcmChkReactionBook" )}, // カーニバル用リアクション本をチェックした - {0x538, new EventFlagPlayer(0 , 1 , 1336, "RcmChkCarnivalFtr" )}, // まめきち|カーニバル家具チェックした? - {0x539, new EventFlagPlayer(0 , 1 , 1337, "AnnounceCarnival" )}, // カーニバル|当日に島内放送で告知した?(2回目放送用) - {0x53A, new EventFlagPlayer(0 , 1 , 1338, "ShootDownShamrockRecipeBalloon" )}, // シャムロックデー|今日、シャムロックステッキのレシピ風船を撃ち落としたか - {0x53B, new EventFlagPlayer(0 , 1 , 1339, "MailSendFlag_ReceiveAnniversaryItem" )}, // 手紙|1周年手紙を送った - {0x53C, new EventFlagPlayer(0 , 1 , 1340, "AOC_EventFlag_002" )}, // AOC同期フラグ| 002 1.9.0NSO加入特典 - {0x53D, new EventFlagPlayer(0 , 1 , 1341, "UnlockSanrioCollaboPoster" )}, // サンリオNPCポスター解禁_キティ - {0x53E, new EventFlagPlayer(0 , 1 , 1342, "UnlockSanrioCollaboPoster2" )}, // サンリオNPCポスター解禁_プリン - {0x53F, new EventFlagPlayer(0 , 1 , 1343, "UnlockSanrioCollaboPoster3" )}, // サンリオNPCポスター解禁_キキララ - {0x540, new EventFlagPlayer(0 , 1 , 1344, "UnlockSanrioCollaboPoster4" )}, // サンリオNPCポスター解禁_シナモン - {0x541, new EventFlagPlayer(0 , 1 , 1345, "UnlockSanrioCollaboPoster5" )}, // サンリオNPCポスター解禁_マイメロ - {0x542, new EventFlagPlayer(0 , 1 , 1346, "UnlockSanrioCollaboPoster6" )}, // サンリオNPCポスター解禁_けろっぴ - {0x543, new EventFlagPlayer(0 , 1 , 1347, "AnnounceEaster" )}, // イースター(2021年)|当日に島内放送で告知した?(2回目放送用) - {0x544, new EventFlagPlayer(0 , 1 , 1348, "PhoneCallByRcoWherearen" )}, // 電話デモ|たぬきちからウェアラン入電受けたことがある? - {0x545, new EventFlagPlayer(0 , 1 , 1349, "RcoTalkWithOtg" )}, // たぬきち|タクミとの会話を聞いたことがある? - {0x547, new EventFlagPlayer(0 , 1 , 1351, "SloTalkCommuneBeforeFlag" )}, // レイジ|コミューンで会話したことある? - {0x548, new EventFlagPlayer(0 , 1 , 1352, "SloExplainVegetableSeedling" )}, // レイジ|野菜の苗の説明聞いたことある? - {0x549, new EventFlagPlayer(0 , 1 , 1353, "SloExplainPlumeriaSeedling" )}, // レイジ|プルメリアの苗の説明聞いたことある? - {0x54A, new EventFlagPlayer(0 , 1 , 1354, "SloExplainWeeding" )}, // レイジ|草むしりサービスの説明聞いたことある? - {0x54B, new EventFlagPlayer(0 , 1 , 1355, "AnnounceEasterReady" )}, // イースター(2021年)|準備期間に島内放送で告知した?(2回目放送用) - {0x54C, new EventFlagPlayer(0 , 1 , 1356, "AnnounceJuneBride" )}, // ジューンブライド(2021年)|当日に島内放送で告知した?(2回目放送用) - {0x54D, new EventFlagPlayer(0 , 1 , 1357, "StandByPhoneCallOtgVisit" )}, // OneRoom|電話デモ|タクミ訪問の入電するか? - {0x54E, new EventFlagPlayer(0 , 1 , 1358, "PynEvent_SendMailThisYear" )}, // イースター|今年手紙を受け取った? - {0x553, new EventFlagPlayer(0 , 1 , 1363, "UnlockWherearen" )}, // OneRoom|ウェアラン渡航解禁 - {0x555, new EventFlagPlayer(0 , 1 , 1365, "OwlArtStampRally1" )}, // フータ/国際ミュージアム|【美術品】スタンプ1つ目を押した? - {0x556, new EventFlagPlayer(0 , 1 , 1366, "OwlArtStampRally2" )}, // フータ/国際ミュージアム|【美術品】スタンプ2つ目を押した? - {0x557, new EventFlagPlayer(0 , 1 , 1367, "OwlArtStampRally3" )}, // フータ/国際ミュージアム|【美術品】スタンプ3つ目を押した? - {0x558, new EventFlagPlayer(0 , 1 , 1368, "OwlStampGotArtReward" )}, // フータ/国際ミュージアム|その日、美術品報酬を貰った - {0x559, new EventFlagPlayer(0 , 1 , 1369, "OwlStampGotArt" )}, // フータ/国際ミュージアム|その日、フータスタンプ(美術品)を押した - {0x55A, new EventFlagPlayer(0 , 1 , 1370, "OwlArtUnfinished" )}, // フータ/国際ミュージアム|初参加時、美術品部屋未完成 - {0x55C, new EventFlagPlayer(0 , 1 , 1372, "WHEREAREN_DisclosePlannerID" )}, // OneRoom|プランナーIDの公開 - {0x55D, new EventFlagPlayer(0 , 1 , 1373, "UnlockSanrioCollabo" )}, // サンリオコラボ解禁_キティ - {0x55E, new EventFlagPlayer(0 , 1 , 1374, "UnlockSanrioCollabo2" )}, // サンリオコラボ解禁_プリン - {0x55F, new EventFlagPlayer(0 , 1 , 1375, "UnlockSanrioCollabo3" )}, // サンリオコラボ解禁_キキララ - {0x560, new EventFlagPlayer(0 , 1 , 1376, "UnlockSanrioCollabo4" )}, // サンリオコラボ解禁_シナモン - {0x561, new EventFlagPlayer(0 , 1 , 1377, "UnlockSanrioCollabo5" )}, // サンリオコラボ解禁_マイメロ - {0x562, new EventFlagPlayer(0 , 1 , 1378, "UnlockSanrioCollabo6" )}, // サンリオコラボ解禁_けろっぴ - {0x565, new EventFlagPlayer(0 , 4 , 1381, "OwlClearCount" )}, // フータ/国際ミュージアム|クリアした部屋の個数 - {0x566, new EventFlagPlayer(0 , 1 , 1382, "WHEREAREN_Pickup_Disclose" )}, // OneRoom|現在、宣伝内容をピックアップに公開中か? - {0x567, new EventFlagPlayer(0 , 1 , 1383, "XctGetRewardSec" )}, // メーデー|みしらぬネコから2回目の報酬をもらった? - {0x568, new EventFlagPlayer(0 , 1 , 1384, "OwlStampPlayedThisYear" )}, // フータ/国際ミュージアム|今年サカナのスタンプラリーをクリアした? - {0x569, new EventFlagPlayer(0 , 1 , 1385, "OwlStampPlayedThisYear2" )}, // フータ/国際ミュージアム|今年ムシのスタンプラリーをクリアした? - {0x56A, new EventFlagPlayer(0 , 1 , 1386, "OwlStampPlayedThisYear3" )}, // フータ/国際ミュージアム|今年かせきのスタンプラリーをクリアした? - {0x56B, new EventFlagPlayer(0 , 1 , 1387, "OwlStampPlayedThisYear4" )}, // フータ/国際ミュージアム|今年美術品のスタンプラリーをクリアした? - {0x56C, new EventFlagPlayer(0 , 1 , 1388, "MuseumCafeEv_1_HeardExplanation" )}, // 博物館カフェ増築イベント|フータから依頼受けた? - {0x56D, new EventFlagPlayer(0 , 1 , 1389, "MuseumCafeEv_2_TalkedWithMasterAtIsland" )}, // 博物館カフェ増築イベント|離島でマスターと会話したことがある? - {0x56E, new EventFlagPlayer(0 , 1 , 1390, "MuseumCafeEv_3_ConfirmedVisitingTown" )}, // 博物館カフェ増築イベント|離島マスターに来訪の約束した? - {0x56F, new EventFlagPlayer(0 , 1 , 1391, "MuseumCafeEv_4_ReportedToOwl" )}, // 博物館カフェ増築イベント|フータにマスターのことを報告した? - {0x570, new EventFlagPlayer(0 , 1 , 1392, "Owl_HeardAboutCafeConstruction" )}, // フータ|カフェの工事のことを聞いた? - {0x571, new EventFlagPlayer(0 , 1 , 1393, "Owl_HeardAboutCafeOpen" )}, // フータ|カフェオープンのことを聞いた? - {0x572, new EventFlagPlayer(0 , 1 , 1394, "PgeThankToMainPC" )}, // マスター|カフェ開店後に島民代表が初会話した? - {0x573, new EventFlagPlayer(0 , 8 , 1395, "TodayFortune" )}, // ハッケミィ|今日の運勢 - {0x574, new EventFlagPlayer(0 , 8 , 1396, "ReserveFortune" )}, // ハッケミィ|発動前の運勢 - {0x575, new EventFlagPlayer(0 , 1 , 1397, "RadioGymnasticsFirstExplain" )}, // ラジオ体操|初回説明読んだ? - {0x576, new EventFlagPlayer(0 , 1 , 1398, "Bpt_1stTalk" )}, // ハッケミィ|占ったことがある? - {0x577, new EventFlagPlayer(0 , 1 , 1399, "Bpt_FinishFortune_Today" )}, // ハッケミィ|今日「今日の運勢」占い済? - {0x578, new EventFlagPlayer(0 , 1 , 1400, "Bpt_FinishCompatibilityToday" )}, // ハッケミィ|今日「相性占い」占い済? - {0x57A, new EventFlagPlayer(0 , 8 , 1402, "LastFortune" )}, // ハッケミィ|前回の運勢 - {0x57B, new EventFlagPlayer(0 , 1 , 1403, "SkkCommuneTalkBefore" )}, // シャンク|コミューンで以前話したことある? - {0x57C, new EventFlagPlayer(0 , 1 , 1404, "AlpJuneBrideNotGetLoveCrystalFrag" )}, // カイゾー/ジューンブライド|今日あいのけっしょうもらえなかった? - {0x57D, new EventFlagPlayer(0 , 1 , 1405, "AlwJuneBrideExchangeTalkFlag" )}, // リサ/ジューンブライド|今年交換回数制限の説明聞いた? - {0x57E, new EventFlagPlayer(0 , 9999, 1406, "LastPlayMuseumYear" )}, // 国際ミュージアム|最後に遊んだ国際ミュージアムの年 - {0x57F, new EventFlagPlayer(0 , -1 , 1407, "RadioGymnasticsCount" )}, // ラジオ体操|累計参加回数 - {0x580, new EventFlagPlayer(0 , 5 , 1408, "RadioGymnasticsGetReward" )}, // ラジオ体操|報酬何回もらった? - {0x581, new EventFlagPlayer(0 , 1 , 1409, "ExplainIslandRegulation" )}, // 条例|しずえから条例の説明受けた - {0x582, new EventFlagPlayer(0 , 1 , 1410, "MainmenuRecipe_v2" )}, // スマホUI|レシピ+解禁(v2.0.0料理レシピ) - {0x583, new EventFlagPlayer(0 , 1 , 1411, "Mobile1stBoot_DIYrecipe_v2" )}, // スマホアプリ初起動|DIYレシピ+(v2.0.0料理レシピ) - {0x584, new EventFlagPlayer(0 , 1 , 1412, "TapUnlockSearchByIslandName" )}, // ゆめみ|「島の名前で探す」解禁説明読んだ? - {0x585, new EventFlagPlayer(0 , 1 , 1413, "MuseumCafe_Telephone_Access1stTime" )}, // 喫茶ハトの巣|店内電話初回説明見たか? - {0x586, new EventFlagPlayer(0 , 1 , 1414, "AlpCommuneTalkBeforeFlag" )}, // カイゾー|コミューンで会話したことある? - {0x589, new EventFlagPlayer(0 , 1 , 1417, "FirstPlayAfterMuseumBuilt3Flag" )}, // 博物館3に拡張したあとのプレイ初日? - {0x58A, new EventFlagPlayer(0 , 1 , 1418, "ReserveCommuneExpansion" )}, // コミューン|拡張イベント予約 - {0x58C, new EventFlagPlayer(0 , 1 , 1420, "DoneCommuneSloOpenEvent" )}, // コミューン島レイジ開店イベント発生制御 - {0x58D, new EventFlagPlayer(0 , 1 , 1421, "DoneCommuneCmlOpenEvent" )}, // コミューン島ローラン開店イベント発生制御 - {0x58E, new EventFlagPlayer(0 , 1 , 1422, "DoneCommuneFoxOpenEvent" )}, // コミューン島つねきち開店イベント発生制御 - {0x58F, new EventFlagPlayer(0 , 1 , 1423, "DoneCommuneBptOpenEvent" )}, // コミューン島ハッケミィ開店イベント発生制御 - {0x590, new EventFlagPlayer(0 , 1 , 1424, "DoneCommuneSkkOpenEvent" )}, // コミューン島シャンク開店イベント発生制御 - {0x591, new EventFlagPlayer(0 , 1 , 1425, "DoneCommuneAlpOpenEvent" )}, // コミューン島リサカイゾー開店イベント発生制御 - {0x592, new EventFlagPlayer(0 , 1 , 1426, "PooTalkAboutHairArrange" )}, // カットリーヌ|初回ヘアアレンジの話を聞いた - {0x593, new EventFlagPlayer(0 , 1 , 1427, "PooRefuseHairArrange" )}, // カットリーヌ|ヘアアレンジを断った - {0x594, new EventFlagPlayer(0 , 1 , 1428, "PooTodayGetHairStyle" )}, // カットリーヌ|今日、ヘアアレンジをしてもらった - {0x595, new EventFlagPlayer(0 , 1 , 1429, "PooUndoHairStyelAfterArrange" )}, // カットリーヌ|ヘアアレンジ後、元に戻してもらった - {0x596, new EventFlagPlayer(0 , 1 , 1430, "PooGetNewHairStyle1" )}, // カットリーヌ|ヘアアレンジ解禁1(レイジ) - {0x597, new EventFlagPlayer(0 , 1 , 1431, "PooGetNewHairStyle2" )}, // カットリーヌ|ヘアアレンジ解禁2(ローラン) - {0x598, new EventFlagPlayer(0 , 1 , 1432, "PooGetNewHairStyle3" )}, // カットリーヌ|ヘアアレンジ解禁3(つねきち) - {0x599, new EventFlagPlayer(0 , 1 , 1433, "PooGetNewHairStyle4" )}, // カットリーヌ|ヘアアレンジ解禁4(ハッケミィ) - {0x59A, new EventFlagPlayer(0 , 1 , 1434, "PooGetNewHairStyle5" )}, // カットリーヌ|ヘアアレンジ解禁5(シャンク) - {0x59B, new EventFlagPlayer(0 , 1 , 1435, "PooGetNewHairStyle6" )}, // カットリーヌ|ヘアアレンジ解禁6(リサカイゾー) - {0x59C, new EventFlagPlayer(0 , 1 , 1436, "SpnTodayExplainedPhotoStudio" )}, // パニエル|撮影スタジオに今日初めて入った - {0x59D, new EventFlagPlayer(0 , 1 , 1437, "RcoCordinateNpcHouseSelEnable" )}, // たぬきち|NPC家コーデの選択肢が解禁 - {0x59E, new EventFlagPlayer(0 , 8 , 1438, "PgeItemGetCount" )}, // マスター|もらったアイテムの数 - {0x59F, new EventFlagPlayer(0 , 1 , 1439, "PgeTalkFirstFlag" )}, // マスター|面識ある? - {0x5A0, new EventFlagPlayer(0 , 1 , 1440, "AlwCommuneTalkBeforeFlag" )}, // リサ|コミューンで会話したことある? - {0x5A2, new EventFlagPlayer(0 , 1 , 1442, "CmlCommuneTalkBefore" )}, // ローラン|コミューンで会話したことある? - {0x5A4, new EventFlagPlayer(0 , 1 , 1444, "CmlCommuneBuyToday" )}, // ローラン|今日買い物した? - {0x5A5, new EventFlagPlayer(0 , 1 , 1445, "UnlockBuyRecipePlus" )}, // タヌポート|レシピ+の陳列開始 - {0x5A7, new EventFlagPlayer(0 , 1 , 1447, "Mobile1stBoot_MydesignPatternPlus" )}, // 汎用布地ページ追加後スマホアプリ初起動|マイデザイン - {0x5A8, new EventFlagPlayer(0 , 1 , 1448, "MainmenuMydesignPatternPlus" )}, // マイデザイン|汎用布地ページ追加 - {0x5A9, new EventFlagPlayer(0 , 1 , 1449, "Mobile1stBoot_Camera1stPersonView" )}, // 主観カメラ追加後スマホアプリ初起動|カメラ - {0x5AA, new EventFlagPlayer(0 , 1 , 1450, "MainmenuCamera1stPersonView" )}, // カメラ|主観カメラ解禁 - {0x5AC, new EventFlagPlayer(0 , 1 , 1452, "UnlockInterior_CeilingFurniture" )}, // インテリアモード|天井家具解禁 - {0x5AD, new EventFlagPlayer(0 , 1 , 1453, "FenceRemakeEnable" )}, // リメイク|柵リメイク解禁 - {0x5B0, new EventFlagPlayer(0 , 1 , 1456, "GetMayDayTicketFirst" )}, // メーデー|1.10.0未満でメーデーりょこうけんを入手したことがあるか? - {0x5B1, new EventFlagPlayer(0 , 1 , 1457, "TotakekeLive2_0Flag" )}, // とたけけ|2.0アプデ後に初めてライブ聴いた? - {0x5B2, new EventFlagPlayer(0 , 3 , 1458, "RcoStorageExpansion_v200_AddLevel" )}, // たぬきち|収納の拡張(v2.0.0)追加段階0~3 - {0x5B3, new EventFlagPlayer(0 , 1 , 1459, "MailSend_Notice_v200_AddStorage" )}, // たぬきち|収納の拡張(v2.0.0)段階追加お知らせの手紙判定したか? - {0x5B4, new EventFlagPlayer(0 , 1 , 1460, "RcoStandbyNotice_v200_AddStorage" )}, // たぬきち|収納の拡張(v2.0.0)段階追加のお知らせ強制会話するか? - {0x5B5, new EventFlagPlayer(0 , 1 , 1461, "RcoStandbyNotice_v200_AfterStorageExpansion")}, // たぬきち|収納の拡張(v2.0.0)収納拡張後の強制会話予約フラグ - {0x5B6, new EventFlagPlayer(0 , 1 , 1462, "PlayerMovingAfterStorageExpansion" )}, // たぬきち|収納拡張後の説明の発生予約中にPだけ引っ越しした? - {0x5B7, new EventFlagPlayer(0 , 1 , 1463, "UnlockBuyFenceRemake" )}, // タヌポート|柵リメイク解禁の陳列開始 - {0x5B8, new EventFlagPlayer(0 , 1 , 1464, "RcoHeardAboutMayDayTravelTicket" )}, // メーデー|たぬきち|メーデー旅行券の説明聞いたか? - {0x5B9, new EventFlagPlayer(0 , 1 , 1465, "XctGetRewardPast" )}, // メーデー|1.10.0未満でみしらぬネコから報酬をもらった? - {0x5BB, new EventFlagPlayer(0 , 1 , 1467, "SloExplainBuyVegetableSeedling" )}, // レイジ|野菜購入時に説明聞いたことある? - {0x5BC, new EventFlagPlayer(0 , 1 , 1468, "SloWeedingBeforeCommune" )}, // レイジ|コミューン誘致前に草むしりサービス解禁した? - {0x5BD, new EventFlagPlayer(0 , 1 , 1469, "FoxTalk2020FireworksFlag" )}, // つねきち|2020年の花火大会で会話したことない? - {0x5BE, new EventFlagPlayer(0 , 1 , 1470, "FoxTalkIceCandyTodayFlag" )}, // つねきち|アイスキャンディの説明した? - {0x5BF, new EventFlagPlayer(0 , 1 , 1471, "FoxTalkTapiocaTodayFlag" )}, // つねきち|タピオカドリンクの説明した? - {0x5C0, new EventFlagPlayer(0 , 1 , 1472, "KppTourExplain1st" )}, // かっぺい|かっぺいツアー初上陸で説明聞いた? - {0x5C1, new EventFlagPlayer(0 , 1 , 1473, "KppTakeTourTodayFlag" )}, // かっぺい|今日かっぺいツアー参加した? - {0x5C2, new EventFlagPlayer(0 , 1 , 1474, "KppFirstTalk" )}, // かっぺい|面識ある? - {0x5C3, new EventFlagPlayer(0 , 1 , 1475, "SpnTodayDonation" )}, // パニエル|今日募金したか? - {0x5C4, new EventFlagPlayer(0 , 1 , 1476, "SpnTodayThanksDonation" )}, // パニエル|今日募金を感謝されたか? - {0x5C5, new EventFlagPlayer(0 , 1 , 1477, "SpnTodayCompleteDonation" )}, // パニエル|今日募金達成したか? - {0x5C6, new EventFlagPlayer(0 , 1 , 1478, "AlwJuneBrideNoRemake1stFlag" )}, // リサ/ジューンブライド|今日1回目でリメイク解禁してなかった - {0x5C7, new EventFlagPlayer(0 , 1 , 1479, "RcoExplainStorageExpandCostIncrease" )}, // たぬきち|収納の拡張(v2.0.0)拡張工事の細かい説明聞いた - {0x5C8, new EventFlagPlayer(0 , 1 , 1480, "AnnounceHalloween2" )}, // 2021年ハロウィンを島内放送で告知した(2回目放送用) - {0x5C9, new EventFlagPlayer(0 , 1 , 1481, "HasLookMyHouseExplain_CeilingFtrAWall" )}, // 家の機能説明ダイアログ(v200天井家具、Aウォール)を見たか? - {0x5CA, new EventFlagPlayer(0 , 1 , 1482, "CompleteNoticeChangeHouseForm" )}, // たぬきち|v200家外観変更に「家の形」が増えたこと告知した? - {0x5CB, new EventFlagPlayer(0 , 1 , 1483, "SloTalkBeforeCommune" )}, // レイジ|コミューン誘致後に本島で会話した? - {0x5CC, new EventFlagPlayer(0 , 1 , 1484, "JoinedTodayRadioGymnastics" )}, // ラジオ体操|今日ラジオ体操に参加したか? - {0x5CD, new EventFlagPlayer(0 , 1 , 1485, "TalkSloCommuneOpenEvent" )}, // レイジ|コミューン開店イベントで話した - {0x5CE, new EventFlagPlayer(0 , 1 , 1486, "TalkCmlCommuneOpenEvent" )}, // ローラン|コミューン開店イベントで話した - {0x5CF, new EventFlagPlayer(0 , 1 , 1487, "TalkFoxCommuneOpenEvent" )}, // つねきち|コミューン開店イベントで話した - {0x5D0, new EventFlagPlayer(0 , 1 , 1488, "TalkBptCommuneOpenEvent" )}, // ハッケミィ|コミューン開店イベントで話した - {0x5D1, new EventFlagPlayer(0 , 1 , 1489, "TalkSkkCommuneOpenEvent" )}, // シャンク|コミューン開店イベントで話した - {0x5D2, new EventFlagPlayer(0 , 1 , 1490, "TalkAlpCommuneOpenEvent" )}, // リサカイゾー|コミューン開店イベントで話した - {0x5D3, new EventFlagPlayer(0 , 1 , 1491, "BptFirstTalk" )}, // ハッケミィ|面識ある? - {0x5D4, new EventFlagPlayer(0 , 1 , 1492, "SpnSendMailCommuneExpansion" )}, // パニエル|コミューン拡張の手紙出したか? - {0x5D5, new EventFlagPlayer(0 , 1023, 1493, "ChocolateVillagerIndex" )}, // 各インデックスの住民がチョコレート勧誘されているかどうか - {0x5D6, new EventFlagPlayer(0 , -1 , 1494, "LatestChocolateDate" )}, // 最新の勧誘をした日付 - {0x5D7, new EventFlagPlayer(0 , 1 , 1495, "PgeTalkCafeFlag" )}, // マスター|店で会話したことある? - {0x5D8, new EventFlagPlayer(0 , 1 , 1496, "AnnounceHarvest2" )}, // 2021年ハーベストを島内放送で告知した(2回目放送用) - {0x5D9, new EventFlagPlayer(0 , 1 , 1497, "MuseumCafeRandomVisitSpTalked_hgs" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(あさみ) - {0x5DA, new EventFlagPlayer(0 , 1 , 1498, "MuseumCafeRandomVisitSpTalked_hgh" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(きぬよ) - {0x5DB, new EventFlagPlayer(0 , 1 , 1499, "MuseumCafeRandomVisitSpTalked_doc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ロドリー) - {0x5DC, new EventFlagPlayer(0 , 1 , 1500, "MuseumCafeRandomVisitSpTalked_boc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ウリ) - {0x5DD, new EventFlagPlayer(0 , 1 , 1501, "MuseumCafeRandomVisitSpTalked_mol" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(リセットさん) - {0x5DE, new EventFlagPlayer(0 , 1 , 1502, "MuseumCafeRandomVisitSpTalked_mob" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ラケットさん) - {0x5DF, new EventFlagPlayer(0 , 1 , 1503, "MuseumCafeRandomVisitSpTalked_tkkA" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(とたけけ) - {0x5E0, new EventFlagPlayer(0 , 1 , 1504, "MuseumCafeRandomVisitSpTalked_skk" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(シャンク) - {0x5E1, new EventFlagPlayer(0 , 1 , 1505, "MuseumCafeRandomVisitSpTalked_cml" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ローラン) - {0x5E2, new EventFlagPlayer(0 , 1 , 1506, "MuseumCafeRandomVisitSpTalked_hgc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ことの) - {0x5E3, new EventFlagPlayer(0 , 1 , 1507, "MuseumCafeRandomVisitSpTalked_slo" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(レイジ) - {0x5E4, new EventFlagPlayer(0 , 1 , 1508, "MuseumCafeRandomVisitSpTalked_ows" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(フーコ) - {0x5E5, new EventFlagPlayer(0 , 1 , 1509, "MuseumCafeRandomVisitSpTalked_chy" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(レックス) - {0x5E6, new EventFlagPlayer(0 , 1 , 1510, "MuseumCafeRandomVisitSpTalked_bey" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ジャスティン) - {0x5E7, new EventFlagPlayer(0 , 5 , 1511, "MuseumCafeRandomVisitSpMeetCount_hgs" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(あさみ) - {0x5E8, new EventFlagPlayer(0 , 5 , 1512, "MuseumCafeRandomVisitSpMeetCount_hgh" )}, // 喫茶ハトの巣ランダム来訪特殊NPC店内で会った回数(きぬよ) - {0x5E9, new EventFlagPlayer(0 , 5 , 1513, "MuseumCafeRandomVisitSpMeetCount_doc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ロドリー) - {0x5EA, new EventFlagPlayer(0 , 5 , 1514, "MuseumCafeRandomVisitSpMeetCount_boc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ウリ) - {0x5EB, new EventFlagPlayer(0 , 5 , 1515, "MuseumCafeRandomVisitSpMeetCount_mol" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(リセットさん) - {0x5EC, new EventFlagPlayer(0 , 5 , 1516, "MuseumCafeRandomVisitSpMeetCount_mob" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ラケットさん) - {0x5ED, new EventFlagPlayer(0 , 5 , 1517, "MuseumCafeRandomVisitSpMeetCount_tkkA" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(とたけけ) - {0x5EE, new EventFlagPlayer(0 , 5 , 1518, "MuseumCafeRandomVisitSpMeetCount_skk" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(シャンク) - {0x5EF, new EventFlagPlayer(0 , 5 , 1519, "MuseumCafeRandomVisitSpMeetCount_cml" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ローラン) - {0x5F0, new EventFlagPlayer(0 , 5 , 1520, "MuseumCafeRandomVisitSpMeetCount_hgc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ことの) - {0x5F1, new EventFlagPlayer(0 , 5 , 1521, "MuseumCafeRandomVisitSpMeetCount_slo" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(レイジ) - {0x5F2, new EventFlagPlayer(0 , 5 , 1522, "MuseumCafeRandomVisitSpMeetCount_ows" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(フーコ) - {0x5F3, new EventFlagPlayer(0 , 5 , 1523, "MuseumCafeRandomVisitSpMeetCount_chy" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(レックス) - {0x5F4, new EventFlagPlayer(0 , 5 , 1524, "MuseumCafeRandomVisitSpMeetCount_bey" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ジャスティン) - {0x5F5, new EventFlagPlayer(0 , 1 , 1525, "DoneCommuneTtlOpenEvent" )}, // コミューン島コトブキ開店イベント発生制御 - {0x5F6, new EventFlagPlayer(0 , 1 , 1526, "DodSelectWherearen1st" )}, // モーリー|「お仕事に行く」の説明を聞いた - {0x5F7, new EventFlagPlayer(0 , 1 , 1527, "FortuneApproachTalked" )}, // 占い結果でのアプローチ会話発生済み - {0x5F8, new EventFlagPlayer(0 , 1 , 1528, "SawMuseumCafeTakeoutNpc" )}, // 喫茶ハトの巣|テイクアウトで来店した特殊NPCを見た - {0x5F9, new EventFlagPlayer(0 , 7 , 1529, "LastSawMuseumCafeTakeoutNpc" )}, // 喫茶ハトの巣|最後にテイクアウトで来店するのを見たNPC - {0x5FA, new EventFlagPlayer(0 , 1 , 1530, "KppTourDone_RareStarpiece" )}, // かっぺいツアー|レア島行った:星のかけら - {0x5FB, new EventFlagPlayer(0 , 1 , 1531, "KppTourDone_RareCherryBlossom" )}, // かっぺいツアー|レア島行った:桜の花びら - {0x5FC, new EventFlagPlayer(0 , 1 , 1532, "KppTourDone_RareSpringBamboo" )}, // かっぺいツアー|レア島行った:春のわかたけ - {0x5FD, new EventFlagPlayer(0 , 1 , 1533, "KppTourDone_RareSummerShell" )}, // かっぺいツアー|レア島行った:夏のかいがら - {0x5FE, new EventFlagPlayer(0 , 1 , 1534, "KppTourDone_RareMushroom" )}, // かっぺいツアー|レア島行った:キノコ - {0x5FF, new EventFlagPlayer(0 , 1 , 1535, "KppTourDone_RareMapleLeaf" )}, // かっぺいツアー|レア島行った:紅葉の葉っぱ - {0x600, new EventFlagPlayer(0 , 1 , 1536, "KppTourDone_RareSnowCrystal" )}, // かっぺいツアー|レア島行った:雪のけっしょう - {0x601, new EventFlagPlayer(0 , 1 , 1537, "MuseumCafe_Telephone_Calledxct" )}, // 喫茶ハトの巣|みしらぬネコ|amiiboでみしらぬネコを呼び出し会話したか? - {0x602, new EventFlagPlayer(0 , 1 , 1538, "MainmenuTips" )}, // スマホUI|徹底ライフサポート(Tips)解禁 - {0x603, new EventFlagPlayer(0 , 1 , 1539, "Mobile1stBoot_Tips" )}, // スマホアプリ初起動|徹底ライフサポート(Tips) - {0x604, new EventFlagPlayer(0 , 1 , 1540, "MydesignExchangeExp_v2_0" )}, // マイデザイン交換| v2.0.0で追加された機能説明 - {0x605, new EventFlagPlayer(0 , 1 , 1541, "TalkTtlCommuneOpenEvent" )}, // コトブキ|コミューン開店イベントで話した - {0x606, new EventFlagPlayer(0 , 1 , 1542, "FoxTalkFireworksFoodFlag" )}, // つねきち|花火大会で食べ物追加された会話聞いた? - {0x607, new EventFlagPlayer(0 , 1 , 1543, "AnnounceHalloween2Ready" )}, // 2021年ハロウィン|準備期間に島内放送で告知した?(2回目放送用) - {0x608, new EventFlagPlayer(0 , 1 , 1544, "PgeLikeTepidLasttimeFlag" )}, // マスター|前回ぬるい方が好きと答えた? - {0x60A, new EventFlagPlayer(0 , 3 , 1546, "PgeTepidCount" )}, // マスター|ぬるく入れるか聞くカウンタ - {0x60B, new EventFlagPlayer(0 , 1 , 1547, "SkkTalkFirstTimeCommune" )}, // シャンク|初会話がコミューン店の方だった - {0x60C, new EventFlagPlayer(0 , 1 , 1548, "TtlTodayTalkFlag" )}, // コトブキ|今日もう会話した? - {0x60D, new EventFlagPlayer(0 , 1 , 1549, "TtlBFirstTalkFlag" )}, // コトブキ|ドンどんぐりとして今年会話した? - {0x60F, new EventFlagPlayer(0 , 1 , 1551, "GetMayDayTicketBefore_v2_0" )}, // メーデー|2.0.0未満でメーデーりょこうけんを入手したことがあるか? - {0x610, new EventFlagPlayer(0 , 1 , 1552, "XctGetRewardEveryYear" )}, // メーデー|みしらぬネコから3回目以降の報酬をもらった? - {0x611, new EventFlagPlayer(0 , 1 , 1553, "FoxFirstTalkTodayFireworksFlag" )}, // つねきち|今日花火大会で会話した? - {0x612, new EventFlagPlayer(0 , 1 , 1554, "PlayerMovingWithPFlag555" )}, // パニエル|「撮影スタジオの説明」聞いた後に、P引越しした - {0x613, new EventFlagPlayer(0 , 1 , 1555, "PooTalkFirst" )}, // カットリーヌ|面識がある? - {0x614, new EventFlagPlayer(0 , 1 , 1556, "PooTalkToday" )}, // カットリーヌ|今日会話した? - {0x615, new EventFlagPlayer(0 , 1 , 1557, "PooTalkFirstToday" )}, // カットリーヌ|今日面識ができた? - {0x616, new EventFlagPlayer(0 , 1 , 1558, "PooGetNewHairStyle7" )}, // カットリーヌ|ヘアアレンジ解禁7(コトブキ) - {0x617, new EventFlagPlayer(0 , 1 , 1559, "WHEREAREN_TapFirstCheckMydesingShowcase" )}, // OneRoom|視察中にマイデザインショーケース端末にアクセスしたことがある? - {0x618, new EventFlagPlayer(0 , 1 , 1560, "PAAboutUnlockIslandRegulation" )}, // 島内放送|条例が解禁したこと聞いた - {0x619, new EventFlagPlayer(0 , 1 , 1561, "SelectedGotoCafe" )}, // 日課「喫茶店に行こうキャンペーン」を今日達成した - {0x61A, new EventFlagPlayer(0 , 2 , 1562, "SelectedDoRadioGymnastics" )}, // 日課「ラジオ体操をしよう」が出現カウンター - {0x61B, new EventFlagPlayer(0 , 1 , 1563, "TtlB_Acorn_Today" )}, // コトブキ|今日どんぐり貰った? - {0x61C, new EventFlagPlayer(0 , 1 , 1564, "HeldCeremonyMuseum3" )}, // セレモニ|博物館③を開いた - {0x61D, new EventFlagPlayer(0 , 1 , 1565, "StandByPhoneCallNpcNG" )}, // 電話デモ|NPCを呼び出せなかった入電するか? - {0x61E, new EventFlagPlayer(0 , 1 , 1566, "PgeTalkTakeOutFlag" )}, // マスター|テイクアウトの話聞いた? - {0x61F, new EventFlagPlayer(0 , 1 , 1567, "UnlockPlayerHair37" )}, // 髪型解禁:Hair37センターわけ - {0x620, new EventFlagPlayer(0 , 1 , 1568, "UnlockPlayerHair38" )}, // 髪型解禁:Hair38ウルフカット - {0x621, new EventFlagPlayer(0 , 1 , 1569, "UnlockPlayerHair39" )}, // 髪型解禁:Hair39オールバック - {0x622, new EventFlagPlayer(0 , 1 , 1570, "UnlockPlayerHair40" )}, // 髪型解禁:Hair40マッシュルーム - {0x623, new EventFlagPlayer(0 , 1 , 1571, "UnlockPlayerHair41" )}, // 髪型解禁:Hair41かっこいいMじ - {0x624, new EventFlagPlayer(0 , 1 , 1572, "UnlockPlayerHair42" )}, // 髪型解禁:Hair42そりこみぼうず - {0x625, new EventFlagPlayer(0 , 1 , 1573, "UnlockPlayerHair43" )}, // 髪型解禁:Hair43ハーフアップ - {0x626, new EventFlagPlayer(0 , 1 , 1574, "UnlockPlayerHair44" )}, // 髪型解禁:Hair44ふわひとつあみ - {0x627, new EventFlagPlayer(0 , 1 , 1575, "UnlockPlayerHair45" )}, // 髪型解禁:Hair45ふわひとつくくり - {0x628, new EventFlagPlayer(0 , 1 , 1576, "UnlockPlayerHair46" )}, // 髪型解禁:Hair46まとめがみ - {0x629, new EventFlagPlayer(0 , 1 , 1577, "UnlockPlayerHair47" )}, // 髪型解禁:Hair47みつあみツイン - {0x62A, new EventFlagPlayer(0 , 1 , 1578, "TtlChangeTtlB" )}, // コトブキをドンどんぐりに差し替え - {0x62B, new EventFlagPlayer(0 , 4095, 1579, "TkkFirstPlayNewSong" )}, // とたけけ|まだ演奏したことがない新曲かどうか - {0x62C, new EventFlagPlayer(0 , 8 , 1580, "XctCalledMessageBefore" )}, // メーデー|前の1537で出現したメッセージ番号 - {0x62D, new EventFlagPlayer(0 , 9999, 1581, "LastPlayFireWorksFestival" )}, // 花火大会|最後に遊んだ花火大会の年 - {0x62E, new EventFlagPlayer(0 , 1 , 1582, "SendAocPurchasingPrize" )}, // AOC|予約・購入特典を送付した - {0x62F, new EventFlagPlayer(0 , 1 , 1583, "FoxCommuneTalkBeforeFlag" )}, // つねきち|今日コミューンのつねきちからお店の説明聞いた? - {0x630, new EventFlagPlayer(0 , 1 , 1584, "FoxCommuneTalkLotteryTodayFlag" )}, // つねきち|今日コミューン開店イベントで話した - {0x631, new EventFlagPlayer(0 , 1 , 1585, "FoxCommuneTalkExplainFlag" )}, // つねきち|コミューンのつねきちからお店の説明聞いた? - {0x632, new EventFlagPlayer(0 , 1 , 1586, "FoxCommunePlayLotteryTodayFlag" )}, // つねきち|今日コミューンのつねきちのくじ引いた? - {0x634, new EventFlagPlayer(0 , 9999, 1588, "LastPlayMayDayYear" )}, // メーデー|最後に遊んだメーデーの年 - {0x635, new EventFlagPlayer(0 , 1 , 1589, "FoxCommuneTalkIceTodayFlag" )}, // つねきち|アイス系の説明した? - {0x636, new EventFlagPlayer(0 , 1 , 1590, "FoxCommuneTalkJuiceTodayFlag" )}, // つねきち|缶飲料の説明した? - {0x637, new EventFlagPlayer(0 , 1 , 1591, "FoxCommuneTalkTodayFlag" )}, // つねきち|今日コミューンのつねきちと会話した? - {0x639, new EventFlagPlayer(0 , 1 , 1593, "WHEREAREN_Unlock_RoomDimming" )}, // OneRoom|オリジナル調光アンロック - {0x63A, new EventFlagPlayer(0 , 1 , 1594, "OwlDonateDiveFishAtMuseumTent" )}, // フータ|テント状態のときに海の幸を見せた? - {0x63B, new EventFlagPlayer(0 , 1 , 1595, "FoxCommuneBuyArtTodayFlag" )}, // つねきち|今日コミューンで美術品買った? - {0x63C, new EventFlagPlayer(0 , 1 , 1596, "UnlockBuyFIXLadderRecipe" )}, // お店|はしごFIXキットのレシピ陳列開始 - {0x63D, new EventFlagPlayer(0 , 1 , 1597, "UnlockBuyInteriorModePro" )}, // タヌポート|もようがえPROライセンス陳列解禁 - {0x63E, new EventFlagPlayer(0 , 1 , 1598, "AlwCommuneTalkTodayFlag" )}, // リサ|今日コミューン島で会話した? - {0x63F, new EventFlagPlayer(0 , 1 , 1599, "UnlockBuyReactionCollection_v200" )}, // タヌポート|リアクション集v200陳列解禁 - {0x640, new EventFlagPlayer(0 , 1 , 1600, "UnlockBuyHairStyleCollection_v200" )}, // タヌポート|ヘアスタイル集v200陳列解禁 - {0x641, new EventFlagPlayer(0 , 1 , 1601, "RadioGymnasticsAchievementFinish" )}, // ラジオ体操の実績を今日カウントした - {0x642, new EventFlagPlayer(0 , 1 , 1602, "UnlockBuyTipsApp" )}, // タヌポート|徹底ライフサポートアプリ陳列解禁 - {0x643, new EventFlagPlayer(0 , 2 , 1603, "TreasureHuntJustMissed" )}, // 宝探し|ギリギリだったか - {0x644, new EventFlagPlayer(0 , 1 , 1604, "WHEREAREN_Use_AccentWall" )}, // アクセントウォールを使用したことがある - {0x645, new EventFlagPlayer(0 , 1 , 1605, "WHEREAREN_Unlock_DustCloth_01" )}, // OneRoom|まごころ雑巾アンロック01 - {0x646, new EventFlagPlayer(0 , 1 , 1606, "WHEREAREN_Unlock_DustCloth_02" )}, // OneRoom|まごころ雑巾アンロック02 - {0x648, new EventFlagPlayer(0 , 1 , 1608, "WHEREAREN_Unlock_EnvSound_01" )}, // OneRoom|環境音アンロック01 - {0x649, new EventFlagPlayer(0 , 1 , 1609, "WHEREAREN_Unlock_EnvSound_02" )}, // OneRoom|環境音アンロック02 - {0x64A, new EventFlagPlayer(0 , 1 , 1610, "WHEREAREN_Unlock_EnvSound_03" )}, // OneRoom|環境音アンロック03 - {0x64C, new EventFlagPlayer(0 , 1 , 1612, "WHEREAREN_Prev_Unlock_EnvSound_01" )}, // OneRoom|環境音アンロック01_事前フラグ - {0x64D, new EventFlagPlayer(0 , 1 , 1613, "WHEREAREN_Prev_Unlock_EnvSound_02" )}, // OneRoom|環境音アンロック02_事前フラグ - {0x64E, new EventFlagPlayer(0 , 1 , 1614, "WHEREAREN_Prev_Unlock_EnvSound_03" )}, // OneRoom|環境音アンロック03_事前フラグ - {0x650, new EventFlagPlayer(0 , 1 , 1616, "WHEREAREN_Unlock_RoomSizeModeUnlock" )}, // OneRoom|部屋サイズモードアンロック - {0x651, new EventFlagPlayer(0 , 1 , 1617, "Owl1stTalkMuseum3" )}, // フータ|博物館③(カフェ)完成後の挨拶した? - {0x652, new EventFlagPlayer(0 , 1 , 1618, "LectureAboutMarinesuitBuyIt" )}, // まめきち|マリンスーツを買ったときレクチャーをする? - {0x653, new EventFlagPlayer(0 , 1 , 1619, "TalkHHATodayAnyone" )}, // 今日誰かにHHAを聞いたか - {0x654, new EventFlagPlayer(0 , 1 , 1620, "UnlockBuyReactionCoolection_v160" )}, // タヌポート|リアクション集v160陳列解禁 - {0x655, new EventFlagPlayer(0 , 1 , 1621, "UnlockBuyHairStyleColection_v160" )}, // タヌポート|もっと!ヘアスタイル×6v160陳列解禁 - {0x656, new EventFlagPlayer(0 , 1 , 1622, "UnlockBuyAddBridgeSlope" )}, // タヌポート|インフラぞうせつライセンス陳列解禁 - {0x657, new EventFlagPlayer(0 , 1 , 1623, "MuseumPosterTalkAboutMakePoster" )}, // フータ/博物館コンプポスター|フータに「ポスター準備する話」を聞いたか? - {0x658, new EventFlagPlayer(0 , 1 , 1624, "MuseumPosterUnlockBuySel" )}, // フータ/博物館コンプポスター|自身が「ポスター買う」選択肢出すか? - {0x659, new EventFlagPlayer(0 , 1 , 1625, "MuseumPosterUnlockMyselfBug" )}, // フータ/博物館コンプポスター|自身がムシのポスター購入を解禁した? - {0x65A, new EventFlagPlayer(0 , 1 , 1626, "MuseumPosterUnlockMyselfFish" )}, // フータ/博物館コンプポスター|自身がサカナのポスター購入を解禁した? - {0x65B, new EventFlagPlayer(0 , 1 , 1627, "MuseumPosterUnlockMyselfFossil" )}, // フータ/博物館コンプポスター|自身が化石のポスター購入を解禁した? - {0x65C, new EventFlagPlayer(0 , 1 , 1628, "MuseumPosterUnlockMyselfPainting" )}, // フータ/博物館コンプポスター|自身が美術品のポスター購入を解禁した? - {0x65D, new EventFlagPlayer(0 , 1 , 1629, "MuseumPosterUnlockMySelfSea" )}, // フータ/博物館コンプポスター|自身が海の幸のポスター購入を解禁した? - {0x65E, new EventFlagPlayer(0 , 1 , 1630, "TtlTodayFirstTalkFlag" )}, // コトブキ|今日初会話した? - {0x65F, new EventFlagPlayer(0 , 256 , 1631, "BalloonShootCountSum" )}, // Tips|風船を撃ち落とした累計回数 - {0x660, new EventFlagPlayer(0 , 1 , 1632, "BocBuyNumCountSum" )}, // Tips|ウリからのカブ購入数X以上か?(X=15) - {0x664, new EventFlagPlayer(0 , 1 , 1636, "NoticeAboutInteriorModePlus_playerHouse" )}, // 自宅か撮影スタジオでインテリアモード開いてインテリアモード+の初回ダイアログを見た? - {0x665, new EventFlagPlayer(0 , 1 , 1637, "NoticeAboutInteriorModePlus_Dimming" )}, // インテリアモード+の調光追加の初回ダイアログを見た? - {0x666, new EventFlagPlayer(0 , 1 , 1638, "NoticeAboutInteriorModePlus_EnvironmentalSound1")}, // 環境音解禁の初回ダイアログを見た? - {0x667, new EventFlagPlayer(0 , 1 , 1639, "NoticeAboutInteriorModePlus_EnvironmentalSound2")}, // 環境音解禁の追加1ダイアログを見た? - {0x668, new EventFlagPlayer(0 , 1 , 1640, "NoticeAboutInteriorModePlus_EnvironmentalSound3")}, // 環境音解禁の追加2ダイアログを見た? - {0x669, new EventFlagPlayer(0 , 1 , 1641, "BuildAddtionalBridgeSlopeIntroduction" )}, // たぬきち|ライセンス所持状態で9本目の橋/坂建てようとしてる? - {0x66A, new EventFlagPlayer(0 , 1 , 1642, "NoticeAboutMagokoro_MainIsland" )}, // まごころ雑巾解禁後、本島側でスタジオ&家に入った初回ダイアログを見た? - {0x66B, new EventFlagPlayer(0 , 1 , 1643, "WHEREAREN_NoticeAboutDustCloth2" )}, // OneRoom|まごころ雑巾の追加用ダイアログを見た? - {0x66C, new EventFlagPlayer(0 , 1 , 1644, "GotToiletForTips" )}, // Tips|トイレ入手したか? - {0x66D, new EventFlagPlayer(0 , 1 , 1645, "GotBushForTips" )}, // Tips|低木入手したか? - {0x66E, new EventFlagPlayer(0 , 1 , 1646, "GetDresserForTips" )}, // Tips|ドレッサー入手したか? - {0x66F, new EventFlagPlayer(0 , 20 , 1647, "KppTourDidntHit_Rare" )}, // かっぺいツアー|連続ハズレカウンタ:レア島 - {0x670, new EventFlagPlayer(0 , 20 , 1648, "KppTourDidntHit_Haniwa" )}, // かっぺいツアー|連続ハズレカウンタ:はにわ島 - {0x671, new EventFlagPlayer(0 , 20 , 1649, "KppTourDidntHit_Vegetable" )}, // かっぺいツアー|連続ハズレカウンタ:やさい島 - {0x672, new EventFlagPlayer(0 , 20 , 1650, "KppTourDidntHit_DLC" )}, // かっぺいツアー|連続ハズレカウンタ:OneRoom島 - {0x673, new EventFlagPlayer(0 , 1 , 1651, "GotBonusMax" )}, // Tips|ログインボーナス上限X達したか? - {0x674, new EventFlagPlayer(0 , 512 , 1652, "GotBonusToday" )}, // Tips|今日のログインボーナスマイル? - {0x675, new EventFlagPlayer(0 , 1 , 1653, "PgeCoffeeEatInTodayFlag" )}, // マスター|今日イートインでコーヒー注文した? - {0x676, new EventFlagPlayer(0 , 1 , 1654, "RcmBlackFridayTodayFlag" )}, // まめきち|ブラックフライデーの入店時会話した? - {0x677, new EventFlagPlayer(0 , 256 , 1655, "DoneDIYCountNum" )}, // Tips|DIY家具or道具、または料理をX回したか? - {0x678, new EventFlagPlayer(0 , 1 , 1656, "RadioGymnasticsGotAllRewards" )}, // Tips|ラジオ体操の報酬プロテインまでもらった? - {0x679, new EventFlagPlayer(0 , 9999, 1657, "TtlBFirstTalkYear" )}, // コトブキ|ドンどんぐりと会話した年 - {0x67A, new EventFlagPlayer(0 , 1 , 1658, "LettersNumForTips" )}, // Tips|メッセージが100通以上残っている+未開封がある? - {0x67B, new EventFlagPlayer(0 , 3 , 1659, "WHEREAREN_GetInspectRewardsNum" )}, // OneRoom|見学した数についてナッティーからの話を聞いたかのフラグ - {0x67C, new EventFlagPlayer(0 , -1 , 1660, "JoinedPastRadioGymnasticsNum" )}, // Tips|前日以前に何回ラジオ体操に参加していないか - {0x67D, new EventFlagPlayer(0 , 1 , 1661, "WHEREAREN_NoticeAboutMemberPage" )}, // OneRoom|メンバーページを開いたときの説明ダイアログを見た? - {0x67E, new EventFlagPlayer(0 , 1 , 1662, "WHEREAREN_NoticeAboutMyPage" )}, // OneRoom|マイページを開いたときの説明ダイアログを見た? - {0x67F, new EventFlagPlayer(0 , 1 , 1663, "SpnExpandEventAfterJuneBride" )}, // パニエル|ジューンブライド初回から解禁イベントにハシゴ - {0x680, new EventFlagPlayer(0 , 1 , 1664, "RepayMileInteriorModePro" )}, // もようがえPROライセンスのマイルを返還する? - {0x681, new EventFlagPlayer(0 , 1 , 1665, "WHEREAREN_Mobile1stBoot_ResortPlannerApp" )}, // OneRoom|リゾプラappの初回起動かどうか? - {0x682, new EventFlagPlayer(0 , 1 , 1666, "MuseumCafe_Tel_CalledThisYearXct" )}, // 喫茶ハトの巣|みしらぬネコ|amiiboでみしらぬネコを今年呼び出し会話したか? - {0x683, new EventFlagPlayer(0 , 1 , 1667, "PooTalkAfterJuneBride" )}, // カットリーヌ|ジューンブライドクリア後の反応予約フラグ - {0x684, new EventFlagPlayer(0 , 1 , 1668, "KppTalkAboutVine" )}, // かっぺい|ツアーでツタの説明した? - {0x685, new EventFlagPlayer(0 , 1 , 1669, "IsOnPlayerMemoriesFireworksInMainfield" )}, // 思い出機能|花火が花火大会開催中にメインフィールドにいたがON? - {0x686, new EventFlagPlayer(0 , 1 , 1670, "IsOnPlayerMemoriesDivingFirst" )}, // 思い出機能|マリンスーツで初めて海に飛び込んだがON? - {0x687, new EventFlagPlayer(0 , 1 , 1671, "NoticeAboutInteriorModePlus_RoomSize" )}, // OneRoomでインテリアモード+の初回ダイアログを見た? - {0x688, new EventFlagPlayer(0 , 1 , 1672, "WHEREAREN_NoticeAboutResortPlannnerAppNet" )}, // OneRoom|マイページを開いたときの説明ダイアログを見た? - {0x689, new EventFlagPlayer(0 , 1 , 1673, "UnlockBuyATM" )}, // タヌポート|ATM陳列解禁 - {0x68A, new EventFlagPlayer(0 , 1 , 1674, "UnlockBuyStoreroom" )}, // タヌポート|ものおき&レシピ陳列解禁 - {0x68C, new EventFlagPlayer(0 , 1 , 1676, "NoticeAboutRoomSketch" )}, // ルームスケッチの初回ダイアログを見た? - {0x68D, new EventFlagPlayer(0 , 1 , 1677, "CommuneCompleteExpandEvent_Player" )}, // コミューン|自分がコミューン拡張(または初回イベント)みたか? - {0x68E, new EventFlagPlayer(0 , 1 , 1678, "PAnnounceAboutKppTourCompleted" )}, // 島内放送|かっぺいツアーに関する島内放送をしたか? - {0x68F, new EventFlagPlayer(0 , 1 , 1679, "MakePlayerAfterStartingKppTour" )}, // かっぺい|かっぺいツアー開始後に作られたプレイヤーか? - {0x690, new EventFlagPlayer(0 , 1 , 1680, "IsOnPlayerMemoriesSeasonPetal" )}, // 思い出機能|桜の花びらをその日初めて取得したがON? - {0x691, new EventFlagPlayer(0 , 1 , 1681, "IsOnPlayerMemoriesSeasonCrystal" )}, // 思い出機能|雪の結晶をその日初めて取得したがON? - {0x692, new EventFlagPlayer(0 , 1 , 1682, "IsOnPlayerMemoriesSeasonLeaf" )}, // 思い出機能|紅葉をその日初めて取得したがON? - {0x693, new EventFlagPlayer(0 , 1 , 1683, "IsOnPlayerMemoriesSeasonBamboo" )}, // 思い出機能|はるのわかたけをその日初めて取得したがON? - {0x694, new EventFlagPlayer(0 , 1 , 1684, "IsOnPlayerMemoriesSeasonShell" )}, // 思い出機能|夏のかいがらをその日初めて取得したがON? - {0x695, new EventFlagPlayer(0 , 1 , 1685, "IsOnPlayerMemoriesSeasonAcorn" )}, // 思い出機能|どんぐりをその日初めて取得したがON? - {0x696, new EventFlagPlayer(0 , 1 , 1686, "IsOnPlayerMemoriesSeasonPinecone" )}, // 思い出機能|まつぼっくりをその日初めて取得したがON? - {0x697, new EventFlagPlayer(0 , 1 , 1687, "WHERWAREN_NoticeAbout_ResortPlanner" )}, // OneRoom|ツクッターの初回ダイアログを見終わったか? - {0x698, new EventFlagPlayer(0 , 1 , 1688, "WHEREAREN_PlayingContentsToday" )}, // OneRoom|今日OneRoomを遊んだか - {0x699, new EventFlagPlayer(0 , 1 , 1689, "WHEREAREN_PlayedContentsBefore" )}, // OneRoom|前回OneRoomを遊んだか - {0x69A, new EventFlagPlayer(0 , 1 , 1690, "MuseumPosterTodayflagbug" )}, // フータ/博物館コンプポスター|ムシのポスターもらった? - {0x69B, new EventFlagPlayer(0 , 1 , 1691, "MuseumPosterTodayflagfish" )}, // フータ/博物館コンプポスター|サカナのポスターもらった? - {0x69C, new EventFlagPlayer(0 , 1 , 1692, "MuseumPosterTodayflagfossil" )}, // フータ/博物館コンプポスター|かせきのポスターもらった? - {0x69D, new EventFlagPlayer(0 , 1 , 1693, "MuseumPosterTodayflagpainting" )}, // フータ/博物館コンプポスター|美術品のポスターもらった? - {0x69E, new EventFlagPlayer(0 , 1 , 1694, "MuseumPosterTodayflagsea" )}, // フータ/博物館コンプポスター|海の幸のポスターもらった? - {0x69F, new EventFlagPlayer(0 , 1 , 1695, "WHEREAREN_RcoHeardRemakeWS" )}, // たぬきち|飛行場でリメイク体験会の話を聞いた - {0x6A0, new EventFlagPlayer(0 , 1 , 1696, "IsOnPlayerMemoriesMushSplendid" )}, // 思い出機能|りっぱなキノコをその日初めて取得したがON? - {0x6A1, new EventFlagPlayer(0 , 1 , 1697, "IsOnPlayerMemoriesMushRound" )}, // 思い出機能|まるいキノコをその日初めて取得したがON? - {0x6A2, new EventFlagPlayer(0 , 1 , 1698, "IsOnPlayerMemoriesMushSlender" )}, // 思い出機能|ほそいキノコをその日初めて取得したがON? - {0x6A3, new EventFlagPlayer(0 , 1 , 1699, "IsOnPlayerMemoriesMushFlat" )}, // 思い出機能|ひらたいキノコをその日初めて取得したがON? - {0x6A4, new EventFlagPlayer(0 , 1 , 1700, "IsOnPlayerMemoriesMushRare" )}, // 思い出機能|めずらしいキノコをその日初めて取得したがON? - {0x6A5, new EventFlagPlayer(0 , 1 , 1701, "RejectedTips" )}, // 徹底ライフサポート(Tips)受け取り拒否設定がON? - {0x6A6, new EventFlagPlayer(0 , 1 , 1702, "UnlockBuyRcoOnePieceAerobics" )}, // ラジオ体操|レオタードをタヌポートにも陳列 - {0x6A7, new EventFlagPlayer(0 , 1 , 1703, "UnlockBuyRcoYogaMat" )}, // ラジオ体操|ヨガマットをタヌポートにも陳列 - {0x6AA, new EventFlagPlayer(0 , 1 , 1706, "DodSelectWherearenFromBeginning" )}, // モーリー|「お仕事に行く」の説明を他の件と一緒に聞いた - {0x6AB, new EventFlagPlayer(0 , 1 , 1707, "EquipDustClothWithGateOpen" )}, // まごころ雑巾|開門中にまごころ雑巾を装備のダイアログを見た? - {0x6AD, new EventFlagPlayer(0 , 1 , 1709, "WHEREAREN_NoticeAboutFirstPublication_ResortPlanner")}, // OneRoom|マイページにて「施工事例から選んでね」ダイアログを一度表示したかどうか? - {0x6AE, new EventFlagPlayer(0 , 1 , 1710, "TalkAboutNpcHouseCoordeHint" )}, // たぬきち|NPC家コーデ内装初回説明したか? - {0x6AF, new EventFlagPlayer(0 , 10 , 1711, "NpcHouseCoordinateTodayCount" )}, // たぬきち|NPC家コーデの当日内回数チェックカウンタ - {0x6B0, new EventFlagPlayer(0 , 1 , 1712, "PublicAnnouncement_MarinsuitHint" )}, // 島内放送|マリンスーツのヒントを聞いたか? - {0x6B1, new EventFlagPlayer(0 , 1 , 1713, "WHEREAREN_NoticeAboutSNSShare" )}, // OneRoom|ツクッター初回掲載後のSN共有の説明を見た? - {0x6B2, new EventFlagPlayer(0 , 10 , 1714, "PlanPalmSeedOnSand" )}, // Tips|やしのみを砂浜に植えた回数 - {0x6B3, new EventFlagPlayer(0 , 10 , 1715, "PlanBambooshoot" )}, // Tips|たけのこを植えた回数 - {0x6B4, new EventFlagPlayer(0 , 1 , 1716, "PlayerDoneEating" )}, // Tips|料理を1回以上「食べる」をした - {0x6B5, new EventFlagPlayer(0 , 10 , 1717, "OpenUIMenuLoadTipsCount" )}, // Tips|徹底ライフサポートUIを開いた回数 - {0x6B6, new EventFlagPlayer(0 , 1 , 1718, "PlayerUsedChangeStick" )}, // Tips|変身ステッキを使ったことがあるか - {0x6B7, new EventFlagPlayer(0 , 1 , 1719, "ScanAmiiboInCafe" )}, // Tips|喫茶店でAmiibo読み込みを行った - {0x6B8, new EventFlagPlayer(0 , 1 , 1720, "ScanAmiiboInPhotoStudio" )}, // Tips|撮影スタジオでAmiibo読み込みを行った - {0x6B9, new EventFlagPlayer(0 , 1 , 1721, "RequestedAlpRemake" )}, // Tips|カイゾーにリメイクを依頼した - {0x6BA, new EventFlagPlayer(0 , 1 , 1722, "RequestedAlpUniqueRemake" )}, // Tips|カイゾーにカイゾーにしかできないリメイクを依頼した - {0x6BB, new EventFlagPlayer(0 , 1 , 1723, "AlreadyCheckedFirstTips1" )}, // 初回用固定Tips1を見た - {0x6BC, new EventFlagPlayer(0 , 1 , 1724, "AlreadyCheckedFirstTips2" )}, // 初回用固定Tips2を見た - {0x6BD, new EventFlagPlayer(0 , 1 , 1725, "AlreadyCheckedOneRoomFirstTips1" )}, // OneRoom権利獲得後初回固定Tips1を見た - {0x6BE, new EventFlagPlayer(0 , 1 , 1726, "SloFirstTalkCommune" )}, // レイジ|コミューン島で初対面会話した? - {0x6BF, new EventFlagPlayer(0 , 5 , 1727, "SalmonCookingRecipeCount" )}, // DIY|レシピ1つ覚えた後、サケを釣り上げた回数をカウント - {0x6C0, new EventFlagPlayer(0 , 1 , 1728, "StandByCallByRcoNpcHouseCoodinate" )}, // 電話デモ|たぬきちNPC家エディット導入入電するか? - {0x6C1, new EventFlagPlayer(0 , 1 , 1729, "RcoCoordinateUnlockWithPhoneCall" )}, // たぬきち|NPC家エディット解禁電話聞いたか? - {0x6C2, new EventFlagPlayer(0 , 3 , 1730, "SloVegetableCount" )}, // レイジ|野菜の苗を買い物した回数 - {0x6C3, new EventFlagPlayer(0 , 1 , 1731, "SloBuyVegetableToday" )}, // レイジ|今日野菜の買い物したか - {0x6C4, new EventFlagPlayer(0 , 1 , 1732, "SloBuyToday" )}, // レイジ|今日レイジから買い物したか? - {0x6C6, new EventFlagPlayer(0 , 1 , 1734, "WHEREAREN_IsSnsShareCanceled" )}, // OneRoom|デイリー表示される掲載後のSNSShareをキャンセルしたか? - {0x6C8, new EventFlagPlayer(0 , 1 , 1736, "OtgTipsUnlockGardenEdit" )}, // Tips|2件目庭(季節変更、時間帯変更、庭エディット解禁) - {0x6C9, new EventFlagPlayer(0 , 1 , 1737, "OtgTipsComplete1stOrder" )}, // Tips|1件目完了(オーディオ家具解禁) - {0x6CA, new EventFlagPlayer(0 , 1 , 1738, "RcoBuildMovingPurchase_v200" )}, // たぬきち|v2.0.0で何らかの移設費用支払った? - {0x6CB, new EventFlagPlayer(0 , 1 , 1739, "SendLetterBuildMovingPricedown" )}, // たぬきち|移設費用値下げの手紙送った? - {0x6CC, new EventFlagPlayer(0 , 1 , 1740, "ReturnMyHomeMoving8000PMoving" )}, // たぬきち|Pだけ引越しで返金されたマイホーム移設費用は8000ベル? - {0x6CD, new EventFlagPlayer(0 , 1 , 1741, "OtgTipsUnlockWorkingTable" )}, // Tips|6件目完了(2FDIY作業台解禁) - {0x6CE, new EventFlagPlayer(0 , 1 , 1742, "WHEREAREN_UnlockMessageBottleAfter" )}, // Tips|ウェアラン諸島でメッセージボトル解禁されてから1成長処理経過 - {0x6CF, new EventFlagPlayer(0 , 1 , 1743, "OtgTipsCompleteSchoolBuild" )}, // Tips|学校完成(キャストUI、施設リフォーム解禁) - {0x6D0, new EventFlagPlayer(0 , 1 , 1744, "OtgTipsCompleteSloSchoolEvent" )}, // Tips|レイジの授業完了(交配花の一部解禁) - {0x6D1, new EventFlagPlayer(0 , 1 , 1745, "RcoOfficeBuiltLetter" )}, // 案内所完成の案内手紙投函された - {0x6D2, new EventFlagPlayer(0 , 1 , 1746, "WatchedRcoAnnouceAfter200ver" )}, // 2.0.0以降verでたぬきち島内放送を見た - {0x6D3, new EventFlagPlayer(0 , 1 , 1747, "OtgTipsComplete2ndFacilityBuild" )}, // Tips|カフェ/レストラン少なくともどちらかが完成 - {0x6D4, new EventFlagPlayer(0 , 1 , 1748, "OtgTipsUnlockDIYFtrCatalog" )}, // Tips|DIYしたことある家具のカタログ解禁 - {0x6D5, new EventFlagPlayer(0 , 1 , 1749, "ScanAmiiboInTanuport" )}, // Tips|タヌポートでAmiibo読み込みを行った - {0x6D6, new EventFlagPlayer(0 , 1 , 1750, "OtgTipsUnlockHouseShare" )}, // Tips|シェアハウス解禁 - {0x6D7, new EventFlagPlayer(0 , 1 , 1751, "OtgTipsCompleteCafeBuild" )}, // Tips|カフェ完成 - {0x6D8, new EventFlagPlayer(0 , 1 , 1752, "OtgTipsCompleteRestaulantBuild" )}, // Tips|レストラン完成 - {0x6D9, new EventFlagPlayer(0 , 1 , 1753, "OtgTipsCompleteHospitalBuild" )}, // Tips|病院完成 - {0x6DA, new EventFlagPlayer(0 , 1 , 1754, "OtgTipsCompleteBoutiqueBuild" )}, // Tips|アパレルショップ完成 - {0x6DB, new EventFlagPlayer(0 , 1 , 1755, "OtgTipsCompleteHospitalDonation" )}, // Tips|病院の募金が完了した - {0x6DC, new EventFlagPlayer(0 , 1 , 1756, "OtgTipsBuildEitherCafeRestaulant" )}, // Tips|カフェ/レストランどちらかが未完成 - {0x6DD, new EventFlagPlayer(0 , 1 , 1757, "WHEREAREN_SeqAvailableAmiiboDone" )}, // Tips|amiibo読取機解禁イベントを見た? - {0x6DE, new EventFlagPlayer(0 , 2 , 1758, "BocFirstMail" )}, // ウリ|商店が建ったときの手紙を出したか? - {0x6DF, new EventFlagPlayer(0 , 1 , 1759, "OtgTipsExplainManCatalog" )}, // Tips|ナッティーカタログ解禁説明聞いた? - {0x6E0, new EventFlagPlayer(0 , 1 , 1760, "OtgTipsUnlockATM" )}, // Tips|事務所ATM解禁した? - {0x6E1, new EventFlagPlayer(0 , 1 , 1761, "CommuneATMChkToday" )}, // コミューン|今日ATMをチェックした? - {0x6E2, new EventFlagPlayer(0 , 1 , 1762, "SpnCommuneATMNoticeDone" )}, // パニエル|ATMについて喋った? - {0x6E3, new EventFlagPlayer(0 , 1 , 1763, "RcoTalkAboutNpcHouseEditOfficeBuild" )}, // たぬきち|Pだけ引越し後案内所完成したら、NPC家コーデの解禁告知するか? - {0x6E4, new EventFlagPlayer(0 , 1 , 1764, "RcoPMovingUnlockNpcEditWithPhoneCall" )}, // たぬきち|入電は聞いたがNPC家コーデを解禁せずにPだけ引越しした - {0x6E5, new EventFlagPlayer(0 , 1 , 1765, "WHERWAREN_NoticeAbout_ResortPlannerRevisit" )}, // OneRoom|訪問機能の説明ダイアログを見た? - {0x6E6, new EventFlagPlayer(0 , 1 , 1766, "PublicAnnoucement_EvNotice_Carnival" )}, // 島内放送|カーニバルの予告を聞いたか? - {0x6E7, new EventFlagPlayer(0 , 1 , 1767, "WHEREAREN_OtgVisitThisIsland" )}, // 今住んでる島でOneRoomの解禁イベントを見た - {0x6E8, new EventFlagPlayer(0 , 1 , 1768, "DocUnlockSpnOtgDirectRoute" )}, // ロドリー|直行便解禁会話見た? - {0x6E9, new EventFlagPlayer(0 , 1 , 1769, "UnlockCatalogPokiBag" )}, // カタログ|ポキ袋をスタジオやOneRoomのカタログで解禁 - {0x6EA, new EventFlagPlayer(0 , 1 , 1770, "PAnnounceFishingEvNotice_Jan" )}, // 島内放送|釣り大会の予告を聞いたか(1月) - {0x6EB, new EventFlagPlayer(0 , 1 , 1771, "PAnnounceFishingEvNotice_Apr" )}, // 島内放送|釣り大会の予告を聞いたか(4月) - {0x6EC, new EventFlagPlayer(0 , 1 , 1772, "PAnnounceFishingEvNotice_Jul" )}, // 島内放送|釣り大会の予告を聞いたか(7月) - {0x6ED, new EventFlagPlayer(0 , 1 , 1773, "PAnnounceFishingEvNotice_Oct" )}, // 島内放送|釣り大会の予告を聞いたか(10月) - {0x6EE, new EventFlagPlayer(0 , 1 , 1774, "PAnnounceInsectEvNotice_1" )}, // 島内放送|ムシとり大会の予告を聞いたか① - {0x6EF, new EventFlagPlayer(0 , 1 , 1775, "PAnnounceInsectEvNotice_2" )}, // 島内放送|ムシとり大会の予告を聞いたか② - {0x6F0, new EventFlagPlayer(0 , 1 , 1776, "PAnnounceInsectEvNotice_3" )}, // 島内放送|ムシとり大会の予告を聞いたか③ - {0x6F1, new EventFlagPlayer(0 , 1 , 1777, "PAnnounceInsectEvNotice_4" )}, // 島内放送|ムシとり大会の予告を聞いたか④ - {0x6F2, new EventFlagPlayer(0 , 1 , 1778, "PAnnounceFireWorksEvNotice" )}, // 島内放送|花火大会の予告を聞いたか - {0x6F3, new EventFlagPlayer(0 , 1 , 1779, "PAnnounceCountdownEvNotice" )}, // 島内放送|大晦日の予告を聞いたか - {0x6F4, new EventFlagPlayer(0 , 1 , 1780, "StandByPhoneCallMayDayTour" )}, // 電話デモ|メーデー告知の入電するか? - {0x6F7, new EventFlagPlayer(0 , 1 , 1783, "DrinkCoffeeToday" )}, // 喫茶ハトの巣|今日コーヒーを飲んだか(実績用) - {0x6F8, new EventFlagPlayer(0 , 1 , 1784, "RcoTipsPurchaseBoxUsed" )}, // Tips|買取BOX使ったことある? - {0x6F9, new EventFlagPlayer(0 , 1 , 1785, "SloExplainbush" )}, // レイジ|低木について個別に説明するか? - {0x6FA, new EventFlagPlayer(0 , 1 , 1786, "SloRecommendbush" )}, // レイジ|コミューン島今週のおすすめの低木を伝えたか - {0x6FB, new EventFlagPlayer(0 , 2 , 1787, "PMovingTmpDustCloth" )}, // プレイヤーだけ引越し|まごころ雑巾をP引越し時に一時的に使えなくするためのtmpフラグ - {0x6FC, new EventFlagPlayer(0 , 1 , 1788, "RcoTipsRcoMachineLoginBonus" )}, // Tips|タヌポートログボのTips出す? - }; - - private const string Unknown = "???"; - - public static string GetName(ushort index, short count, IReadOnlyDictionary str) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - { - string name = val.Name; - if (str.TryGetValue(name, out var translated)) - name = translated; - return $"{index:00} - {name} = {count}"; - } - return $"{index:00} - {Unknown} = {count}"; - } - - public static string GetName(ushort index, short count) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - return $"{index:00} - {val.Name} = {count}"; - return $"{index:00} - {Unknown} = {count}"; - } + Name = name; + Index = index; + DefaultValue = init; + MaxValue = max; } -} + + public static readonly IReadOnlyDictionary List = new Dictionary + { + {0x002, new EventFlagPlayer(0 , 9 , 0002, "PrologueNpcHintCount" )}, // NPCの序盤ヒントをいくつまで聞いたか + {0x003, new EventFlagPlayer(0 , 31 , 0003, "TotakekeLiveCount" )}, // とたけけライブを聴いた回数 + {0x008, new EventFlagPlayer(0 , 1 , 0008, "JohnnyQuestStartFlag" )}, // ジョニークエスト開始フラグ(海賊ジョニーは別フラグ) + {0x009, new EventFlagPlayer(0 , 1 , 0009, "JohnnyQuestFinishFlag" )}, // ジョニークエスト完了フラグ(海賊ジョニーは別フラグ) + {0x00A, new EventFlagPlayer(0 , 8 , 0010, "JonnyTalkCount" )}, // 寝ているジョニーに話しかけた回数(海賊ジョニー共用) + {0x00B, new EventFlagPlayer(0 , 1 , 0011, "HasPlayedTreasureHunt" )}, // 宝探しクエストをした事がある + {0x00D, new EventFlagPlayer(0 , 1 , 0013, "ShizueCmnExplanationTowntune" )}, // しずえ|メロ説明聞いたか? + {0x00E, new EventFlagPlayer(0 , 1 , 0014, "ShizueCmnExplanationTownflag" )}, // しずえ|村の旗説明聞いたか? + {0x00F, new EventFlagPlayer(0 , 1 , 0015, "ShizueCmnExplanationComplaint" )}, // しずえ|『村民のこと』の説明聞いたか? + {0x011, new EventFlagPlayer(0 , 1 , 0017, "FutaTalkedWhenAsleep" )}, // フータ|寝てる時に話かけたことがある? + {0x012, new EventFlagPlayer(0 , 1 , 0018, "FutaExplanationDonationComp" )}, // フータ|博物館コンプの報告を受けたか? + {0x013, new EventFlagPlayer(0 , 1 , 0019, "FutaTalkedInMuseumToday" )}, // フータ|博物館内で今日会話した? + {0x014, new EventFlagPlayer(0 , 1 , 0020, "FutaHeardCommentary" )}, // フータ|コレってなに?で解説聞いた? + {0x015, new EventFlagPlayer(0 , 1 , 0021, "FutaReadyForMuseum" )}, // フータ|博物館建設条件達成の報告聞いた? + {0x016, new EventFlagPlayer(0 , 1 , 0022, "FutaReadyForMuseumToday" )}, // フータ|今日博物館の条件達成した当日か? + {0x017, new EventFlagPlayer(0 , 1 , 0023, "KaburibaTalkTodayFlag" )}, // ウリ|今日すでに会話した? + {0x018, new EventFlagPlayer(0 , 1 , 0024, "KaburibaTalkBeforeFlag" )}, // ウリ|今までに会話したことある? + {0x019, new EventFlagPlayer(0 , 1 , 0025, "KaburibaBuyKabuTodayFlag" )}, // ウリ|今日カブ買った? + {0x01A, new EventFlagPlayer(0 , 1 , 0026, "KinuyoTalkBoforeFlag" )}, // きぬよ|今までに会話したことある? + {0x01B, new EventFlagPlayer(0 , 1 , 0027, "KinuyoTalkTodayFlag" )}, // きぬよ|今日すでに会話した?(来訪用) + {0x01D, new EventFlagPlayer(0 , 1 , 0029, "SkkTalkBeforeFlag" )}, // シャンク|今までに会話したことある? + {0x01F, new EventFlagPlayer(0 , 1 , 0031, "ReijiTalkBeforeFlag" )}, // レイジ|今までに会話したことある?(面識ある?) + {0x021, new EventFlagPlayer(0 , 1 , 0033, "RollanTalkTodayFlag" )}, // ローラン|今日すでに会話した? + {0x022, new EventFlagPlayer(0 , 3 , 0034, "RollanBuyLargeCount" )}, // ローラン|今日ラグ大を買った枚数 + {0x023, new EventFlagPlayer(0 , 3 , 0035, "RollanBuyMediumCount" )}, // ローラン|今日ラグ中を買った枚数 + {0x024, new EventFlagPlayer(0 , 3 , 0036, "RollanBuySmallCount" )}, // ローラン|今日ラグ小を買った枚数 + {0x025, new EventFlagPlayer(0 , 1 , 0037, "RcmTalkBeforeFlag" )}, // まめきち|店内で会話したことある? + {0x026, new EventFlagPlayer(0 , 1 , 0038, "RcmTookReqMarket" )}, // まめきち|商店設置場所決め依頼された + {0x027, new EventFlagPlayer(0 , 1 , 0039, "RcmDeclinedMarketReq" )}, // まめきち|商店設置場所決め依頼を断ったことある + {0x028, new EventFlagPlayer(0 , 1 , 0040, "DoneCharacterCreation" )}, // キャラメイク完了 + {0x029, new EventFlagPlayer(0 , 1 , 0041, "RcmNoTurnipSellToday" )}, // まめきち|カブ買取不可の説明今日受けた? + {0x02C, new EventFlagPlayer(0 , 1 , 0044, "ValidatePlayerSaveFlag" )}, // プレイヤーセーブデータが有効化された + {0x02D, new EventFlagPlayer(0 , 1 , 0045, "MakeVillagePlayerFlag" )}, // 村民代表か? + {0x02E, new EventFlagPlayer(0 , 1 , 0046, "PrologueDone1stTalkAtPlaza" )}, // 1P序盤|広場での最初の会話終わった? + {0x02F, new EventFlagPlayer(0 , 1 , 0047, "HighAndLowPlayed" )}, // ミニゲームのハイ&ローをプレイした事がある + {0x030, new EventFlagPlayer(0 , 1 , 0048, "HappyHomeMission1" )}, // HHA/ハッピーホームでミッション1をクリヤーした + {0x033, new EventFlagPlayer(0 , 1 , 0051, "OccurrenceCoinStone" )}, // コイン岩を発生させたか + {0x034, new EventFlagPlayer(0 , 1 , 0052, "HappyHomeMission2" )}, // HHA/ハッピーホームでミッション2をクリヤーした + {0x035, new EventFlagPlayer(0 , 1 , 0053, "SeoRejectFlag" )}, // ラコスケ|ホタテ渡すの断った? + {0x036, new EventFlagPlayer(0 , 1 , 0054, "HappyHomeMission3" )}, // HHA/ハッピーホームでミッション3をクリヤーした + {0x03B, new EventFlagPlayer(0 , 999 , 0059, "CatchFishFesCount" )}, // つり大会|保持している大会ポイント + {0x03C, new EventFlagPlayer(0 , 999 , 0060, "CatchInsectFesCount" )}, // ムシとり大会|保持している大会ポイント + {0x03D, new EventFlagPlayer(0 , 1 , 0061, "PlayerPocketUIEnable" )}, // プレイヤー|ポケットUI解禁 + {0x03E, new EventFlagPlayer(0 , 1 , 0062, "PlayerMainUImenuEnable" )}, // プレイヤー|メイン(スマホ)UI解禁 + {0x03F, new EventFlagPlayer(0 , 1 , 0063, "Prologue4AfterBuiltPcTent" )}, // たぬきち|自宅テント設営後に話した? + {0x040, new EventFlagPlayer(0 , 1 , 0064, "RcoHearedWhatShouldIAsk" )}, // たぬきち|『何聞けばいい?』を聞いた + {0x042, new EventFlagPlayer(0 , 1 , 0066, "Prologue4OwlNoMuseum" )}, // フータ|博物館設営前に話した? + {0x043, new EventFlagPlayer(0 , 1 , 0067, "Prologue4OwlGetTent" )}, // フータ|テントを受け取ったか? + {0x044, new EventFlagPlayer(0 , 1 , 0068, "Prologue4OwlBuiltMuseum" )}, // フータ|のテント設営後に話した? + {0x045, new EventFlagPlayer(0 , 1 , 0069, "Prologue4RcmNoShop" )}, // まめきち|商店設営前に話した? + {0x046, new EventFlagPlayer(0 , 1 , 0070, "Prologue4RcmGetTent" )}, // まめきち|お店の工事看板を受け取ったか? + {0x047, new EventFlagPlayer(0 , 1 , 0071, "Prologue4RcmBuiltShop" )}, // まめきち|お店の工事看板設営後に話した? + {0x048, new EventFlagPlayer(0 , 1 , 0072, "Prologue4HaNoTent" )}, // 初期HA|テント設営前に話した? + {0x049, new EventFlagPlayer(0 , 1 , 0073, "Prologue4HaGetTent" )}, // 初期HA|テントを受け取ったか? + {0x04A, new EventFlagPlayer(0 , 1 , 0074, "Prologue4HaBuiltTent" )}, // 初期HA|テント設営後に話した? + {0x04B, new EventFlagPlayer(0 , 1 , 0075, "Prologue4AnNoTent" )}, // 初期AN|テント設営前に話した? + {0x04C, new EventFlagPlayer(0 , 1 , 0076, "Prologue4AnGetTent" )}, // 初期AN|テントを受け取ったか? + {0x04D, new EventFlagPlayer(0 , 1 , 0077, "Prologue4AnBuiltTent" )}, // 初期AN|テント設営後に話した? + {0x04E, new EventFlagPlayer(0 , 1 , 0078, "BirthdayNGavePresentFlag" )}, // NPC誕生日|ホストにプレゼントを渡した? + {0x04F, new EventFlagPlayer(0 , 1 , 0079, "BirthdayPCandleFlag" )}, // プレイヤー誕生日|ローソク吹き消した? + {0x050, new EventFlagPlayer(0 , 1 , 0080, "BirthdayPNotPresentFlag" )}, // プレイヤー誕生日|プレゼントもらえなかった? + {0x052, new EventFlagPlayer(0 , 1 , 0082, "SickQuestFirst" )}, // 病気クエストをクリアしたことがあるか? + {0x053, new EventFlagPlayer(0 , 1 , 0083, "TotakekeTalkBeforeFlag" )}, // とたけけ|今までに会話したことある? + {0x054, new EventFlagPlayer(0 , 1 , 0084, "JohnnyTalkBeforeFlag" )}, // ジョニー|今までに会話したことある?(海賊ジョニーは別フラグ) + {0x055, new EventFlagPlayer(0 , 1 , 0085, "KotonoTalkBeforeFlag" )}, // ことの|今までに会話したことある? + {0x056, new EventFlagPlayer(0 , 1 , 0086, "RollanTalkBeforeFlag" )}, // ローラン|今までに会話したことある? + {0x058, new EventFlagPlayer(0 , 1 , 0088, "TunekichiTalkBefore" )}, // つねきち|今までに会話したことある? + {0x059, new EventFlagPlayer(0 , 128 , 0089, "KotonoQuestCount" )}, // ことの|ことのとの親密度 + {0x05A, new EventFlagPlayer(0 , 1 , 0090, "KotonoQuestStartFlag" )}, // ことの|クエスト開始 + {0x05B, new EventFlagPlayer(0 , 1 , 0091, "KotonoQuestClearFlag" )}, // ことの|クエスト完了 + {0x05C, new EventFlagPlayer(0 , 1 , 0092, "KotonoQuestRefuseFlag" )}, // ことの|クエスト断った? + {0x05D, new EventFlagPlayer(0 , 1 , 0093, "MainmenuEncyclopedia" )}, // スマホUI|図鑑解禁 + {0x05E, new EventFlagPlayer(0 , 1 , 0094, "MainmenuMap" )}, // スマホUI|マップ解禁 + {0x05F, new EventFlagPlayer(0 , 1 , 0095, "MainmenuMydesign" )}, // スマホUI|マイデザイン解禁 + {0x060, new EventFlagPlayer(0 , 1 , 0096, "MainmenuBank" )}, // スマホUI|モバイルバンク解禁 + {0x061, new EventFlagPlayer(0 , 1 , 0097, "RcmTalked1P1stday" )}, // まめきち|1Pが初日にテントで会話した? + {0x062, new EventFlagPlayer(0 , 1 , 0098, "HappyHomeMission4" )}, // HHA/ハッピーホームでミッション4をクリヤーした + {0x063, new EventFlagPlayer(0 , 1 , 0099, "RcoHeardDetailDIYtrial" )}, // たぬきち|DIY体験の材料の説明聞いた? + {0x064, new EventFlagPlayer(0 , 1 , 0100, "SzaTaled1stTime" )}, // しずえ|役場内で会話したことがあるか? + {0x065, new EventFlagPlayer(0 , 1 , 0101, "HappyHomeMission5" )}, // HHA/ハッピーホームでミッション5をクリヤーした + {0x066, new EventFlagPlayer(0 , 1 , 0102, "HappyHomeMission6" )}, // HHA/ハッピーホームでミッション6をクリヤーした + {0x06B, new EventFlagPlayer(0 , 1 , 0107, "OdekakeTutorial" )}, // 空港|モーリー|おでかけ初回説明済? + {0x06C, new EventFlagPlayer(0 , 1 , 0108, "OdekakeTutorialKeyword" )}, // 空港|モーリー|おでかけあいことばマッチメイク初回説明済? + {0x06E, new EventFlagPlayer(0 , 1 , 0110, "RcoGotWorkingwear" )}, // たぬきち|アルバイトの服もらった? + {0x06F, new EventFlagPlayer(0 , 1 , 0111, "RcoHeardWorkExplain1" )}, // たぬきち|1つ目の仕事内容聞いた? + {0x070, new EventFlagPlayer(0 , 1 , 0112, "RcoHeardWorkExplain2" )}, // たぬきち|2つ目の仕事内容聞いた? + {0x071, new EventFlagPlayer(0 , 1 , 0113, "RcoFinishMakingAxe" )}, // たぬきち|チュートリアル斧作り終えた? + {0x072, new EventFlagPlayer(0 , 1 , 0114, "OdekakeFirstTalk" )}, // 空港|モーリー|おでかけ初めて話しかけた? + {0x073, new EventFlagPlayer(0 , 1 , 0115, "OdekakeFirstOpenGate" )}, // 空港|モーリー|おでかけ始めて改札を開けた説明済? + {0x07E, new EventFlagPlayer(0 , 1 , 0126, "SzaGotDiyRecipe001" )}, // しずえ|しずえDIYレシピ1もらった? + {0x07F, new EventFlagPlayer(0 , 1 , 0127, "OwlGotDiyRecipe001" )}, // フータ|フータDIYレシピ1もらった? + {0x080, new EventFlagPlayer(0 , 1 , 0128, "TownNewsHeard1st" )}, // 村内放送|村内放送を聞いた事がある? + {0x083, new EventFlagPlayer(0 , 1 , 0131, "GyroidPlazaTalk1st" )}, // 募金ハニワくん|広場募金ハニワくんと話した? + {0x084, new EventFlagPlayer(0 , 1 , 0132, "PlayerLoanRepaying" )}, // ローン返済中? + {0x085, new EventFlagPlayer(0 , 1 , 0133, "PlayerLoanFinish1st" )}, // ローン完済した? + {0x086, new EventFlagPlayer(0 , 1 , 0134, "RcoHeardRemodel1" )}, // 増築提案受けた? + {0x087, new EventFlagPlayer(0 , 1 , 0135, "UsedCoinStone" )}, // コイン岩を使ったか + {0x088, new EventFlagPlayer(0 , 1 , 0136, "OwlFinished1stTalk" )}, // フータ|初対面挨拶したか? + {0x089, new EventFlagPlayer(0 , 1 , 0137, "OwlTalkDuringConst1" )}, // フータ|テント→博物館工事中に会話したか? + {0x08A, new EventFlagPlayer(0 , 1 , 0138, "OwlDonationDone" )}, // フータ|博物館(テント)で寄贈したことある? + {0x08B, new EventFlagPlayer(0 , 1 , 0139, "Owl1stTalkMuseum1" )}, // フータ|博物館①完成後の挨拶した? + {0x08C, new EventFlagPlayer(0 , 1 , 0140, "EnableEmoticonUI" )}, // 漫符UI解禁 + {0x08D, new EventFlagPlayer(0 , 1 , 0141, "RcoDoneDIYmyself" )}, // たぬきち|たぬきちテント内で自分でDIYしたことがある? + {0x08E, new EventFlagPlayer(0 , 1 , 0142, "RcoOrderedHouseBuilt" )}, // たぬきち|家建築申し込み当日? + {0x08F, new EventFlagPlayer(0 , 1 , 0143, "RcmHeardAboutRenual" )}, // まめきち|改装告知聞いた? + {0x090, new EventFlagPlayer(0 , 1 , 0144, "RcmHeardAboutNewOpen1" )}, // まめきち|新装開店の案内聞いた?(商店・小) + {0x091, new EventFlagPlayer(0 , 1 , 0145, "RcmHeardAboutNewOpen2" )}, // まめきち|新装開店の案内聞いた?(商店・大) + {0x096, new EventFlagPlayer(0 , 1 , 0150, "ChmTalkRuleFirst" )}, // [大会]レックス|初回ルール説明聞いたか? + {0x097, new EventFlagPlayer(0 , 1 , 0151, "ChmQuestFinish" )}, // [大会]レックス|結果発表あるか? + {0x099, new EventFlagPlayer(0 , 1 , 0153, "ChmTalkPoint_BeforeEv" )}, // [大会]レックス|受付前、ポイント交換のお誘い聞いた? + {0x09A, new EventFlagPlayer(0 , 1 , 0154, "ChmTalkFirst_EvQuestFinish" )}, // [大会]レックス|今日大会クエストしたか? + {0x09B, new EventFlagPlayer(0 , 1 , 0155, "ChmTalkFirst_AfterEv" )}, // [大会]レックス|受付終了後、初回会話聞いた? + {0x09C, new EventFlagPlayer(0 , 1 , 0156, "RcoGotDonationRewardFlower" )}, // たぬきち|虫魚提供報酬の花をもらった当日? + {0x09F, new EventFlagPlayer(0 , 1 , 0159, "TownNewsHeardTownHallOpenFlag" )}, // 村内放送|案内所が建った告知(しずえ引継ぎ)を聞いた? + {0x0A0, new EventFlagPlayer(0 , 1 , 0160, "TownNewsHeardShopOpen1Flag" )}, // 村内放送|商店の新装開店告知を聞いた?(商店・小) + {0x0A1, new EventFlagPlayer(0 , 1 , 0161, "TownNewsHeardShopOpen2Flag" )}, // 村内放送|商店の新装開店告知を聞いた?(商店・大) + {0x0A3, new EventFlagPlayer(0 , 1 , 0163, "TownNewsHeardMuseumOpenFlag" )}, // 村内放送|博物館建物が建った告知を聞いた? + {0x0A5, new EventFlagPlayer(0 , 1 , 0165, "TownNewsHeardMuseumCafeOpenFlag" )}, // 村内放送|ミュージアムカフェのオープン告知を聞いた? + {0x0A6, new EventFlagPlayer(0 , 1 , 0166, "MarvelAtCockroarchToday" )}, // ゴキブリに驚いた + {0x0A7, new EventFlagPlayer(0 , 1 , 0167, "GstTalkBefore" )}, // ゆうたろう|今までに会話したことある? + {0x0A8, new EventFlagPlayer(0 , 1 , 0168, "GstQuestStartFlag" )}, // ゆうたろう|クエスト発生中? + {0x0A9, new EventFlagPlayer(0 , 1 , 0169, "GstQuestClearFlag" )}, // ゆうたろう|今日クエストクリアした? + {0x0AA, new EventFlagPlayer(0 , 1 , 0170, "GstQuestBreakFlag" )}, // ゆうたろう|一度クエスト発生させてゲーム終了した? + {0x0AB, new EventFlagPlayer(0 , 1 , 0171, "MainmenuRecipe" )}, // スマホUI|レシピ解禁 + {0x0AC, new EventFlagPlayer(0 , 1 , 0172, "PurchaseBoxUseTodayFlag" )}, // 時間外買取BOX|今日すでに利用した? + {0x0B1, new EventFlagPlayer(0 , 1 , 0177, "TownNewsHeardEventOpen" )}, // 村内放送|イベント開始時の村内放送を聞いたことがある? + {0x0B2, new EventFlagPlayer(0 , 1 , 0178, "PostHasNewMessage" )}, // ポスト|新着メッセージカードがある? + {0x0B4, new EventFlagPlayer(0 , 1 , 0180, "EnablePcTownDecoration" )}, // フィールド家具配置解禁 + {0x0B5, new EventFlagPlayer(1 , 1 , 0181, "KaburibaConditionFlag" )}, // ウリ|プレイヤーが住む前から来訪していた? + {0x0B6, new EventFlagPlayer(0 , 1 , 0182, "SzaHeardSonkatsuExplain" )}, // しずえ|村活のことの説明聞いた? + {0x0B7, new EventFlagPlayer(0 , 1 , 0183, "SzaHeardMuraokoshiExplain" )}, // しずえ|村おこしのことの説明聞いた? + {0x0B8, new EventFlagPlayer(0 , 1 , 0184, "SzaHeardAboutHousingKit" )}, // たぬきち|土地確保解禁の説明聞いた? + {0x0BA, new EventFlagPlayer(0 , 1 , 0186, "SeoFirstFlag" )}, // ラコスケ|ホタテを渡したことある? + {0x0BF, new EventFlagPlayer(0 , 1 , 0191, "FoxTalkTodayFlag" )}, // つねきち|今日本島に来訪したつねきちと会話した? + {0x0C0, new EventFlagPlayer(0 , 1 , 0192, "FoxBuyTodayFlag" )}, // つねきち|今日いなりマーケットで買い物した? + {0x0C1, new EventFlagPlayer(0 , 1 , 0193, "FoxBuyArtTodayFlag" )}, // つねきち|今日いなりマーケットで美術品買った? + {0x0C2, new EventFlagPlayer(0 , 1 , 0194, "TownNewsHeardEventSpaceOpenFlag" )}, // 村内放送|村内放送でイベント広場が完成した告知を聞いた? + {0x0C3, new EventFlagPlayer(0 , 1 , 0195, "PcDidNotKnowKK" )}, // プレイヤー|序盤にとたけけ知らないと答えた + {0x0C4, new EventFlagPlayer(0 , 1 , 0196, "RcoAfterHouseRemodel" )}, // たぬきち|家増築後の説明発生する? + {0x0C6, new EventFlagPlayer(0 , 1 , 0198, "HeardAboutBuildingTownOffice" )}, // しずえ|役場建設開始の説明聞いた? + {0x0C7, new EventFlagPlayer(0 , 1 , 0199, "PgeTalkTodayFlag" )}, // マスター|今日すでに会話した? + {0x0C8, new EventFlagPlayer(0 , 1 , 0200, "PgeItemGetFirstFlag" )}, // マスター|今日アイテムもらった? + {0x0C9, new EventFlagPlayer(0 , 50 , 0201, "PgeRegularCount" )}, // マスター|常連度 + {0x0CA, new EventFlagPlayer(0 , 1 , 0202, "PgeTalkValentineFlag" )}, // マスター|今日バレンタインでコーヒー飲んだ? + {0x0CB, new EventFlagPlayer(0 , 1 , 0203, "PgeTalkBirthdayFlag" )}, // マスター|今日誕生日などイベント系の会話した? + {0x0CD, new EventFlagPlayer(0 , 1 , 0205, "RcoFenceShoppingExplain" )}, // たぬきち|柵購入の説明を受けたことがある? + {0x0CE, new EventFlagPlayer(0 , 1 , 0206, "Ttl1stmet" )}, // コトブキ|初対面会話済か? + {0x0CF, new EventFlagPlayer(1 , 5 , 0207, "PcTownmakeLv" )}, // プレイヤーの村づくりライセンスレベル + {0x0D0, new EventFlagPlayer(0 , 1 , 0208, "PcUpgradeTownmakeToday" )}, // 今日上級村づくりライセンスを入手したか? + {0x0D1, new EventFlagPlayer(0 , 1 , 0209, "PcHousingLoanFinish" )}, // 住宅ローン完全終了 + {0x0D2, new EventFlagPlayer(0 , 1 , 0210, "PgeCoffeeTodayFlag" )}, // マスター|今日コーヒーかホットチョコレート注文した? + {0x0D3, new EventFlagPlayer(0 , 1 , 0211, "RcoGetTvForCongratsHouse" )}, // たぬきち|新築祝いもらった? + {0x0D4, new EventFlagPlayer(0 , 1 , 0212, "RcoItemFullForTv" )}, // たぬきち|新築祝いもらう時アイテムいっぱいだった + {0x0D7, new EventFlagPlayer(0 , 1 , 0215, "PlayerEnableEating" )}, // プレイヤー|『食べる』解禁 + {0x0D8, new EventFlagPlayer(0 , 1 , 0216, "PlayerStungByBee" )}, // プレイヤー|ハチにさされたか? + {0x0D9, new EventFlagPlayer(0 , 1 , 0217, "GetEmoticonTodayFlag" )}, // 今日すでに漫符を入手した? + {0x0DA, new EventFlagPlayer(0 , 1 , 0218, "BevTalkRuleFirst" )}, // [大会]ジャスティン|初回ルール説明聞いたか? + {0x0DB, new EventFlagPlayer(0 , 1 , 0219, "BevQuestFinish" )}, // [大会]ジャスティン|結果発表あるか? + {0x0DD, new EventFlagPlayer(0 , 1 , 0221, "BevTalkPoint_BeforeEv" )}, // [大会]ジャスティン|受付前ポイント交換のお誘い聞いた? + {0x0DE, new EventFlagPlayer(0 , 1 , 0222, "BevTalkFirst_EvQuestFinish" )}, // [大会]ジャスティン|今日クエストしたか? + {0x0DF, new EventFlagPlayer(0 , 1 , 0223, "BevTalkFirst_AfterEv" )}, // [大会]ジャスティン|受付終了後、初回会話聞いた? + {0x0E9, new EventFlagPlayer(0 , 1 , 0233, "TutorialFinishAndPast1day" )}, // 序盤シーケンス終了後1日以上経過 + {0x0EA, new EventFlagPlayer(0 , 1 , 0234, "HasGottenToolChangeStick" )}, // 変身ステッキを入手したことがあるか? + {0x0EB, new EventFlagPlayer(0 , 1 , 0235, "GetBirthdayTable" )}, // 今年バースデーテーブルを貰った + {0x0EC, new EventFlagPlayer(0 , 1 , 0236, "GetBirthdayCandle" )}, // 今年バースデーキャンドルを貰った + {0x0ED, new EventFlagPlayer(0 , 1 , 0237, "GetBirthdayHat" )}, // 今年バースデーハットを貰った + {0x0EE, new EventFlagPlayer(0 , 1 , 0238, "GetBirthdayBoard" )}, // 今年バースデーボードを貰った + {0x0EF, new EventFlagPlayer(0 , 1 , 0239, "GetBirthdaySunglasses" )}, // 今年バースデーサングラスを貰った + {0x0F6, new EventFlagPlayer(0 , 1 , 0246, "MainUiClockEnable" )}, // SYS|時計表示ON + {0x0F7, new EventFlagPlayer(0 , 1 , 0247, "PrologueAfterBuiltTentTalk" )}, // 序盤|テント設営後の広場会話終わった + {0x0F8, new EventFlagPlayer(0 , 1 , 0248, "PrologueForCampfire1" )}, // 序盤|キャンプ材料集めの話聞いた(1) + {0x0F9, new EventFlagPlayer(0 , 1 , 0249, "PlayerPickupEnable" )}, // SYS|プレイヤー|拾う(Y)解禁 + {0x0FA, new EventFlagPlayer(0 , 1 , 0250, "HaveTownFruit4CampFire" )}, // 序盤|特産果物揃った状態でたぬきちに話しかけた + {0x0FB, new EventFlagPlayer(0 , 1 , 0251, "PrologueForCampfire2" )}, // 序盤|キャンプ材料集めの話聞いた(2) + {0x0FC, new EventFlagPlayer(0 , 1 , 0252, "SzaTalkBeforeCountdown" )}, // しずえ|年越し前に話した? + {0x0FD, new EventFlagPlayer(0 , 1 , 0253, "SzaTalkAfterCountdown" )}, // しずえ|年越し後に話した? + {0x0FE, new EventFlagPlayer(0 , 1 , 0254, "SzaGotNewYearHat" )}, // しずえ|スティックライトもらった? + {0x0FF, new EventFlagPlayer(0 , 1 , 0255, "SzaGotCracker" )}, // たぬきち|クラッカーもらった? + {0x100, new EventFlagPlayer(0 , 1 , 0256, "PrologueStartedCampfire" )}, // プロローグ|キャンプファイヤー開始 + {0x101, new EventFlagPlayer(0 , 1 , 0257, "AllowPcTentEntering" )}, // 〔序盤〕プレイヤー自宅テント入場解禁 + {0x102, new EventFlagPlayer(0 , 1 , 0258, "TkkTalkToday" )}, // とたけけ|今日すでに会話した? + {0x103, new EventFlagPlayer(0 , 1 , 0259, "TkkLiveToday" )}, // とたけけ|今日ライブを聴いた? + {0x104, new EventFlagPlayer(0 , 1 , 0260, "PcMaingameStart" )}, // プロローグ終了~本番ゲーム開始~ + {0x105, new EventFlagPlayer(0 , 1 , 0261, "TkkGetMusicToday" )}, // とたけけ|今日ミュージックをもらった? + {0x106, new EventFlagPlayer(0 , 100 , 0262, "MoveNpcTradeSkipCount" )}, // 引越交換処理スキップカウント + {0x107, new EventFlagPlayer(0 , 1 , 0263, "RcoTalked1stAfterPrologue" )}, // たぬきち|序盤終了後初会話した? + {0x108, new EventFlagPlayer(0 , 1 , 0264, "RcmTalked1stAfterPrologue" )}, // まめきち|序盤終了後初会話した? + {0x109, new EventFlagPlayer(0 , 1 , 0265, "RcoTentAdviceCanceled" )}, // たぬきち|テントのアドバイスキャンセルしたことある + {0x10A, new EventFlagPlayer(0 , 1 , 0266, "RcoHeardAboutMyhome" )}, // たぬきち|『お家のこと』初めて聞いた? + {0x10B, new EventFlagPlayer(0 , 1 , 0267, "PlayerFirstShootDownBalloon" )}, // 風船を初めて撃ち落とした? + {0x10C, new EventFlagPlayer(0 , 1 , 0268, "PrologueFinishTkkDream" )}, // 序盤|とたけけの夢終了 + {0x10D, new EventFlagPlayer(0 , 1 , 0269, "RcoPaid1stCharge" )}, // たぬきち|移住費用支払い完了 + {0x10E, new EventFlagPlayer(0 , 1 , 0270, "RcoTentEnableDIYtrial" )}, // たぬきち|DIY体験選択肢解禁 + {0x10F, new EventFlagPlayer(0 , 1 , 0271, "RcoDIYtrialOngoing" )}, // たぬきち|DIY体験中 + {0x110, new EventFlagPlayer(0 , 1 , 0272, "RcoDIYtrialGetMaterial" )}, // たぬきち|DIY体験中に材料揃った状態でたぬきちに話しかけた + {0x111, new EventFlagPlayer(0 , 1 , 0273, "RcoTentDonation" )}, // たぬきち|たぬきちに虫魚預けたことある + {0x112, new EventFlagPlayer(0 , 1 , 0274, "RcoTentDonatinDeclined" )}, // たぬきち|たぬきちに虫魚預けるのを断ったことある + {0x113, new EventFlagPlayer(0 , 1 , 0275, "EnableBuildMuseumTent" )}, // 博物館テント設置条件満たした + {0x114, new EventFlagPlayer(0 , 1 , 0276, "RcoTookRequestMuseum" )}, // たぬきち|博物館テント設置場所決め依頼された + {0x115, new EventFlagPlayer(0 , 1 , 0277, "DecidedMuseumTentPlace" )}, // 博物館テント設営場所確定した + {0x116, new EventFlagPlayer(0 , 1 , 0278, "RcoDeclinedMuseumReq" )}, // たぬきち|博物館設置場所決め依頼を断ったことある + {0x11C, new EventFlagPlayer(0 , 1 , 0284, "RcmDeclinedQuestReq" )}, // まめきち|商店建築の材料集め依頼を断ったことがある + {0x11D, new EventFlagPlayer(0 , 1 , 0285, "RcmTookQuestReq" )}, // まめきち|商店建築の材料集め依頼された + {0x11E, new EventFlagPlayer(0 , 1 , 0286, "JohnnyAnotherPlayerClearFlag" )}, // ジョニー|クエスト発生後に他のプレイヤーがクリアした?(海賊ジョニーは別フラグ) + {0x124, new EventFlagPlayer(0 , 1 , 0292, "NnpcFinishHintTalk" )}, // NPCの序盤ヒント会話を聞き終えた + {0x12A, new EventFlagPlayer(0 , 11 , 0298, "HgsCloseness" )}, // あさみ|あさみとの親密度 + {0x12B, new EventFlagPlayer(0 , 1 , 0299, "HgsTalkTodayFlag" )}, // あさみ|今日すでに会話した? + {0x12C, new EventFlagPlayer(0 , 3 , 0300, "NnpcApproachNoEmoticonCount" )}, // アプローチ会話|漫符入手会話を見ないまま経過したプレイ日数 + {0x12D, new EventFlagPlayer(0 , 1 , 0301, "HgsAllowAddFriendship" )}, // あさみ|親密度加算許可 + {0x12F, new EventFlagPlayer(0 , 1 , 0303, "MainmenuCall" )}, // スマホUI|住人呼び出し解禁 + {0x130, new EventFlagPlayer(0 , 1 , 0304, "EmergencyEscapeExplain" )}, // 緊急脱出|説明聞いた + {0x132, new EventFlagPlayer(0 , 1 , 0306, "HHAGradeMailFlag" )}, // HHA|評価の手紙送付ON? + {0x133, new EventFlagPlayer(0 , 1 , 0307, "EnableSmatDeviceNortification" )}, // スマホUI|通知機能有効化 + {0x134, new EventFlagPlayer(0 , 1 , 0308, "CatchFishFes_Bonus" )}, // つり大会|到達ボーナスある? + {0x135, new EventFlagPlayer(0 , 1 , 0309, "CatchFishFes_CooperativeBonus" )}, // つり大会|通信ボーナスある? + {0x136, new EventFlagPlayer(0 , 1 , 0310, "CatchInsectFes_Bonus" )}, // ムシとり大会|到達ボーナスある? + {0x137, new EventFlagPlayer(0 , 1 , 0311, "CatchInsectFes_CooperativeBonus" )}, // ムシとり大会|通信ボーナスある? + {0x138, new EventFlagPlayer(0 , 1 , 0312, "LookNpcHouseVisitNpc" )}, // 他のNPCの家に訪問中のNPCを見た + {0x139, new EventFlagPlayer(0 , 1 , 0313, "MainmenuFriendList" )}, // スマホUI|フレンドリスト解禁 + {0x13A, new EventFlagPlayer(1 , 1 , 0314, "FriendListMainSwitch" )}, // フレンドリストUI|メインスイッチ + {0x13B, new EventFlagPlayer(0 , 1 , 0315, "SnowmanGotDay1Flag" )}, // ゆきだるま|今日すでに1日目の報酬もらった? + {0x13C, new EventFlagPlayer(0 , 1 , 0316, "SnowmanGotDay2Flag" )}, // ゆきだるま|今日すでに2日目の報酬もらった? + {0x13D, new EventFlagPlayer(0 , 1 , 0317, "SnowmanGotDay3Flag" )}, // ゆきだるま|今日すでに3日目の報酬もらった? + {0x13E, new EventFlagPlayer(0 , 1 , 0318, "SnowmanGotDay4Flag" )}, // ゆきだるま|今日すでに4日目の報酬もらった? + {0x13F, new EventFlagPlayer(0 , 1 , 0319, "MainmenuOnlineShopping" )}, // スマホUI|カタログショッピング解禁 + {0x140, new EventFlagPlayer(0 , 1 , 0320, "MainmenuRndDailyQuest" )}, // スマホUI|マイレージ+解禁 + {0x141, new EventFlagPlayer(0 , 1 , 0321, "MainmenuAchievement" )}, // スマホUI|実績(たぬきマイル)解禁 + {0x143, new EventFlagPlayer(0 , 1 , 0323, "SnowmanBuildFlag" )}, // ゆきだるま|作ったことある? + {0x144, new EventFlagPlayer(0 , 1 , 0324, "SnowmanFirstBuildTodayFlag" )}, // ゆきだるま|今日初めてゆきだるまを作った? + {0x146, new EventFlagPlayer(0 , 1 , 0326, "ObjRcoMachineCheck1st" )}, // OBJ|たぬポートにアクセスしたことがある? + {0x148, new EventFlagPlayer(0 , 100 , 0328, "ReservedNpcGroupActivityMorning" )}, // 朝の時間帯にNPCの集団行動が予約されているか + {0x149, new EventFlagPlayer(0 , 100 , 0329, "ReservedNpcGroupActivityNoon" )}, // 昼の時間帯にNPCの集団行動が予約されているか + {0x14A, new EventFlagPlayer(0 , 100 , 0330, "ReservedNpcGroupActivityEvening" )}, // 夕方の時間帯にNPCの集団行動が予約されているか + {0x14B, new EventFlagPlayer(0 , 100 , 0331, "ReservedNpcGroupActivityNignt" )}, // 夜の時間帯にNPCの集団行動が予約されているか + {0x14D, new EventFlagPlayer(0 , 1 , 0333, "RcoMoveHouseReserved" )}, // たぬきち|プレイヤ家の引越しを予約しているか + {0x14E, new EventFlagPlayer(0 , 1 , 0334, "RcoChangeHouseDesignReserved" )}, // たぬきち|家外観変更の予約をしているか + {0x14F, new EventFlagPlayer(0 , 1 , 0335, "RcoMoveNpcHouseFacilityReserved" )}, // たぬきち|NPC家か施設の移設を予約しているか + {0x151, new EventFlagPlayer(0 , 1 , 0337, "PlayerSonkatsuQuestEnable" )}, // SYS|マイレージ+のカウント処理解禁 + {0x152, new EventFlagPlayer(0 , 1 , 0338, "RcoMoveShopReserved" )}, // たぬきち|お店の移設を予約している + {0x153, new EventFlagPlayer(0 , 1 , 0339, "RcoMoveMuseumReserved" )}, // たぬきち|博物館の移設を予約している + {0x154, new EventFlagPlayer(0 , 1 , 0340, "RcoMoveTailorReserved" )}, // たぬきち|仕立て屋の移設を予約している + {0x155, new EventFlagPlayer(0 , 1 , 0341, "ChyDaily_TalkFirst" )}, // レックス|面識ある?(大会、来訪共通) + {0x157, new EventFlagPlayer(0 , 1 , 0343, "BeyDaily_TalkFirst" )}, // ジャスティン|面識ある?(大会、来訪共通) + {0x158, new EventFlagPlayer(0 , 1 , 0344, "BeyDaily_QuestClear" )}, // ジャスティン|来訪クエスト達成会話聞いた? + {0x159, new EventFlagPlayer(0 , 1 , 0345, "AccessLostPropertyBox1st" )}, // 落とし物BOX|アクセスしたことがあるか? + {0x15A, new EventFlagPlayer(0 , 1 , 0346, "Mobile1stBoot_Camera" )}, // スマホアプリ初起動|カメラ + {0x15B, new EventFlagPlayer(0 , 1 , 0347, "Mobile1stBoot_MilageProgram" )}, // スマホアプリ初起動|たぬきマイレージ + {0x15C, new EventFlagPlayer(0 , 1 , 0348, "Mobile1stBoot_MilagePlus" )}, // スマホアプリ初起動|マイレージプラス + {0x15D, new EventFlagPlayer(0 , 1 , 0349, "Mobile1stBoot_Encyclopedia" )}, // スマホアプリ初起動|いきもの図鑑 + {0x15E, new EventFlagPlayer(0 , 1 , 0350, "Mobile1stBoot_DIYrecipe" )}, // スマホアプリ初起動|DIYレシピ + {0x15F, new EventFlagPlayer(0 , 1 , 0351, "Mobile1stBoot_OnlineShopping" )}, // スマホアプリ初起動|たぬきショッピング + {0x161, new EventFlagPlayer(0 , 1 , 0353, "Mobile1stBoot_Mydesign" )}, // スマホアプリ初起動|マイデザイン + {0x162, new EventFlagPlayer(0 , 1 , 0354, "Mobile1stBoot_SharePlay" )}, // スマホアプリ初起動|住人呼び出し + {0x163, new EventFlagPlayer(0 , 1 , 0355, "Mobile1stBoot_BestFriend" )}, // スマホアプリ初起動|ベストフレンド + {0x164, new EventFlagPlayer(0 , 1 , 0356, "Mobile1stBoot_Passport" )}, // スマホアプリ初起動|パスポート + {0x165, new EventFlagPlayer(0 , 1 , 0357, "Mobile1stBoot_Map" )}, // スマホアプリ初起動|マップ + {0x167, new EventFlagPlayer(0 , 1 , 0359, "Mobile1stBoot_SOS" )}, // スマホアプリ初起動|SOS + {0x168, new EventFlagPlayer(0 , 1 , 0360, "RctTalkBeforeFalg" )}, // つぶきち|オートセーブ解禁以降、会話したことあるか? + {0x169, new EventFlagPlayer(0 , 255 , 0361, "AmountHeardPublicAnnouncement" )}, // 島内放送を聞いた回数 + {0x16A, new EventFlagPlayer(0 , 1 , 0362, "SzaTalkAboutOfficeService" )}, // しずえ|案内所で工事ライセンスの説明聞いた? + {0x16B, new EventFlagPlayer(0 , 1 , 0363, "SzaFlowerQuestClear" )}, // しずえ|花を渡すおつかいをクリアした? + {0x16C, new EventFlagPlayer(0 , 1 , 0364, "RcoTalkAboutBuildBridge" )}, // xたぬきち|橋建設について説明受けた + {0x16D, new EventFlagPlayer(0 , 1 , 0365, "RcoTalkAboutBuildSlope" )}, // xたぬきち|坂建設について説明受けた + {0x16E, new EventFlagPlayer(0 , 1 , 0366, "RcoTalkAboutDeleteBridgeSlope" )}, // たぬきち|橋坂撤去について説明受けた + {0x16F, new EventFlagPlayer(0 , 1 , 0367, "RcoBuildBridgeReserved" )}, // xたぬきち|今日、橋建設を予約済み + {0x170, new EventFlagPlayer(0 , 1 , 0368, "RcoBuildSlopeReserved" )}, // xたぬきち|今日、坂建設を予約済み + {0x171, new EventFlagPlayer(0 , 1 , 0369, "RcoDeleteBridgeSlopeReserved" )}, // xたぬきち|今日、橋撤去を予約済み + {0x172, new EventFlagPlayer(0 , 1 , 0370, "RcoDeleteSlopeReserved" )}, // xたぬきち|今日、坂撤去を予約済み + {0x173, new EventFlagPlayer(0 , 1 , 0371, "OwlShowFossilMyself" )}, // フータ|化石発見の報告を受けた + {0x174, new EventFlagPlayer(0 , 1 , 0372, "RcmShowHardWood" )}, // まめきち|かたいもくざいを見せた + {0x175, new EventFlagPlayer(0 , 1 , 0373, "RcoTalkAfterMuseumTent" )}, // たぬきち|博物館テント設置場所決め後会話発動させる? + {0x176, new EventFlagPlayer(0 , 1 , 0374, "PlayerGotHardWood" )}, // プレイヤー|かたいもくざいを拾ったことがある + {0x177, new EventFlagPlayer(0 , 1 , 0375, "RcmSellCampingStuffReaction" )}, // まめきち|序盤に支給品を売却しようとした反応発生 + {0x178, new EventFlagPlayer(0 , 1 , 0376, "OBJRcoMachineChkPlusEnable" )}, // OBJ|たぬポートにプラス会員になった後話しかけた + {0x179, new EventFlagPlayer(0 , 8 , 0377, "SysCountOpenedToolManual" )}, // 道具の説明の解禁数カウント + {0x17A, new EventFlagPlayer(0 , 1 , 0378, "RcoHeardThanksForBuiltOwlTent" )}, // たぬきち|ヒントでフータテント設営お礼聞いた + {0x17C, new EventFlagPlayer(0 , 1 , 0380, "AnnouncementOwlMovedIn" )}, // 島内放送|フータ移住開始のアナウンス聞いた? + {0x17D, new EventFlagPlayer(0 , 1 , 0381, "RcmTalkAboutCupboard" )}, // まめきち|戸棚を調べて説明を受けた + {0x17E, new EventFlagPlayer(0 , 2 , 0382, "RcoDonateStatus" )}, // ×たぬきち|テント内フロー分岐用 0:DIY~ 1:生き物~ 2:(なし) + {0x17F, new EventFlagPlayer(0 , 1 , 0383, "RcoGotLoginBonusToday" )}, // タヌポート|今日ログインボーナス獲得済? + {0x180, new EventFlagPlayer(0 , 7 , 0384, "RcoMachineDailyLoginDays" )}, // タヌポート|連続ログインカウント + {0x181, new EventFlagPlayer(0 , 1 , 0385, "RcoMachineDailyLoginCheck" )}, // タヌポート|連続ログインチェック + {0x182, new EventFlagPlayer(0 , 1 , 0386, "RcoMachineEnableExchange" )}, // タヌポート|マイル交換開始の説明聞いた? + {0x183, new EventFlagPlayer(0 , 16 , 0387, "JohnnyPartsCount" )}, // ジョニー|渡したパーツの個数(海賊ジョニーは別フラグ) + {0x184, new EventFlagPlayer(0 , 9 , 0388, "BeyDaily_QuestCount" )}, // ジャスティン|指定サイズの魚を釣り上げた回数 + {0x185, new EventFlagPlayer(0 , 1 , 0389, "TalkRumorPActionTodayAnyone" )}, // 今日RumorP_Action(現在プレイヤー)を聞いたか? + {0x186, new EventFlagPlayer(0 , 1 , 0390, "TalkRumorPFavoriteTodayAnyone" )}, // 今日誰かにRumorP_Favoriteを聞いたか? + {0x188, new EventFlagPlayer(0 , 1 , 0392, "IsToolShortcutManualOpen" )}, // 道具ショートカット説明解禁済か? + {0x189, new EventFlagPlayer(0 , 1 , 0393, "RcoMachineExplainAboutPlaneTicket" )}, // タヌポート|マイル航空券の説明聞いた? + {0x18A, new EventFlagPlayer(0 , 1 , 0394, "DodExplainAboutMysteryTour" )}, // モーリー|ミステリーツアーの説明聞いた? + {0x18E, new EventFlagPlayer(0 , 1 , 0398, "IsGetMessageBottle" )}, // プレイヤ|今日メッセージボトルを拾った + {0x18F, new EventFlagPlayer(0 , 1 , 0399, "DodFirstTalkAfterPlusEnable" )}, // モーリー|初会話したのはマイレージ+解禁後? + {0x190, new EventFlagPlayer(0 , 1 , 0400, "ImmQHousingKitGetFirst" )}, // たぬきち|ハウジングキット初めてもらった + {0x191, new EventFlagPlayer(0 , 1 , 0401, "ImmQFirstExplain" )}, // たぬきち|移住クエストの最初の説明聞いた + {0x192, new EventFlagPlayer(0 , 1 , 0402, "ImmQRunningForPlayer" )}, // たぬきち|自身が移住クエスト実施中か + {0x193, new EventFlagPlayer(0 , 1 , 0403, "DodUseFirstFreeTour" )}, // モーリー|ミステリーツアーの初回無料権使った? + {0x194, new EventFlagPlayer(0 , 1 , 0404, "AppUrgentEscapeUseToday" )}, // 緊急脱出|本日利用した + {0x195, new EventFlagPlayer(0 , 1 , 0405, "AppUrgentEscapeNoPayment" )}, // 緊急脱出|前回、マイル支払ってない + {0x196, new EventFlagPlayer(0 , 1 , 0406, "ImmQSetHousingAbyMySelf" )}, // たぬきち|移住クエスト自分でハウジングA置いた + {0x197, new EventFlagPlayer(0 , 1 , 0407, "ImmQSetHousingBbyMySelf" )}, // たぬきち|移住クエスト自分でハウジングB置いた + {0x198, new EventFlagPlayer(0 , 1 , 0408, "ImmQSetHousingCbyMySelf" )}, // たぬきち|移住クエスト自分でハウジングC置いた + {0x199, new EventFlagPlayer(0 , 1 , 0409, "ImmQSetOutdoorAbyMySelf" )}, // たぬきち|移住クエスト自分で外置き家具A置いた + {0x19A, new EventFlagPlayer(0 , 1 , 0410, "ImmQSetOutdoorBbyMySelf" )}, // たぬきち|移住クエスト自分で外置き家具B置いた + {0x19B, new EventFlagPlayer(0 , 1 , 0411, "ImmQSetOutdoorCbyMySelf" )}, // たぬきち|移住クエスト自分で外置き家具C置いた + {0x19C, new EventFlagPlayer(0 , 1 , 0412, "RcoHeardNoticeOfficeBuild" )}, // たぬきち|案内所建物建築予告聞いた + {0x19F, new EventFlagPlayer(0 , 1 , 0415, "RcoTalkBeforeCountdown" )}, // たぬきち|年越し前に話した? + {0x1A0, new EventFlagPlayer(0 , 1 , 0416, "RcoTalkAfterCountdown" )}, // たぬきち|年越し後に話した? + {0x1A1, new EventFlagPlayer(0 , 1 , 0417, "ChyDaily_TalkFirstDay" )}, // レックス|今回の来訪中に話したか? + {0x1A2, new EventFlagPlayer(0 , 1 , 0418, "ChyDaily_SellCount" )}, // レックス|買取総数(今回計算含む)/未使用 + {0x1A3, new EventFlagPlayer(0 , 1 , 0419, "ChyDaily_SellFirst" )}, // レックス|今日買取した? + {0x1A6, new EventFlagPlayer(0 , 1 , 0422, "NetIsRegistHomeLand" )}, // 通信|独自サーバに島登録したか? + {0x1A7, new EventFlagPlayer(0 , 1 , 0423, "FriendListNotifyUpdate" )}, // フレンドリスト|更新要求通知 + {0x1A8, new EventFlagPlayer(0 , 1 , 0424, "FriendListNotifyLook" )}, // スマホUI|ベストフレンドリストアイコン用更新通知 + {0x1A9, new EventFlagPlayer(0 , 100 , 0425, "CatchFishContinueCount" )}, // つり|逃げられずに釣り上げた回数 + {0x1AA, new EventFlagPlayer(0 , 1 , 0426, "FriendMailSendEnable" )}, // メッセージカード|フレンドへの送信解禁 + {0x1AC, new EventFlagPlayer(0 , 1 , 0428, "BeyDaily_TalkFirstDay" )}, // ジャスティン|今回の来訪中に話した? + {0x1AE, new EventFlagPlayer(0 , 20 , 0430, "PrayStarToday" )}, // 今日祈った回数 + {0x1AF, new EventFlagPlayer(0 , 40 , 0431, "StarPieceGrowCount" )}, // 星素材発生カウンタ + {0x1B0, new EventFlagPlayer(0 , 1 , 0432, "BeyDaily_QuestStart" )}, // ジャスティン|クエスト申し込みした? + {0x1B1, new EventFlagPlayer(0 , 1 , 0433, "KinuyoChkMydesginFlag" )}, // きぬよ|仕立て屋のマイデザインチェックしたことある? + {0x1B3, new EventFlagPlayer(0 , 1 , 0435, "HgsGotCloth" )}, // あさみ|汎用布地もらったことある? + {0x1B4, new EventFlagPlayer(0 , 100 , 0436, "RcmDeliver_00" )}, // まめきち|商店建設クエストでかたいもくざいを渡した数 + {0x1B6, new EventFlagPlayer(0 , 1 , 0438, "HasTalkedAllVillagerToday" )}, // 今日全ての住民NPCと話したか? + {0x1B7, new EventFlagPlayer(0 , 1 , 0439, "AmiiboPhoneTalkFirst" )}, // amiiboフォン+と話したことがあるか? + {0x1B8, new EventFlagPlayer(0 , 1 , 0440, "PrintServiceExplain" )}, // タヌポートでポスター販売開始の案内聞いたか? + {0x1B9, new EventFlagPlayer(0 , 3 , 0441, "SendPuromaidoCount" )}, // 今日プリントしたブロマイドの数 + {0x1BA, new EventFlagPlayer(0 , 1 , 0442, "KinuyoTalkInTailorFlag" )}, // きぬよ|仕立て屋で会話したことある? + {0x1BB, new EventFlagPlayer(0 , 1 , 0443, "KinuyoForcesTalkTodayFlag" )}, // きぬよ|今日仕立て屋で入店時の強制会話した? + {0x1BC, new EventFlagPlayer(0 , 1 , 0444, "KinuyoForcedTalk2TodayFlag" )}, // きぬよ|今日仕立て屋で退店時の強制会話した? + {0x1BD, new EventFlagPlayer(0 , 999 , 0445, "ChyEvent_TotalPoint" )}, // [大会]レックス|ムシとり大会累計ポイント + {0x1BE, new EventFlagPlayer(0 , 999 , 0446, "BeyEvent_TotalPoint" )}, // [大会]ジャスティン|つり大会累計ポイント + {0x1BF, new EventFlagPlayer(0 , 1 , 0447, "ChyEvent_GetTrophyGold" )}, // [大会]レックス|トロフィ金もらったか? + {0x1C0, new EventFlagPlayer(0 , 1 , 0448, "ChyEvent_GetTrophySilver" )}, // [大会]レックス|トロフィ銀もらったか? + {0x1C1, new EventFlagPlayer(0 , 1 , 0449, "ChyEvent_GetTrophyCopper" )}, // [大会]レックス|トロフィ銅もらったか? + {0x1C2, new EventFlagPlayer(0 , 1 , 0450, "BeyEvent_GetTrophyGold" )}, // [大会]ジャスティン|トロフィ金もらったか? + {0x1C3, new EventFlagPlayer(0 , 1 , 0451, "BeyEvent_GetTrophySilver" )}, // [大会]ジャスティン|トロフィ銀もらったか? + {0x1C4, new EventFlagPlayer(0 , 1 , 0452, "BeyEvent_GetTrophyCopper" )}, // [大会]ジャスティン|トロフィ銅もらったか? + {0x1C5, new EventFlagPlayer(0 , 1 , 0453, "PurchaseBoxUseOnceFlag" )}, // 時間外買取BOX|自分の島で調べたことがある? + {0x1C6, new EventFlagPlayer(0 , 1 , 0454, "BeyDaily_ReqObj" )}, // ジャスティン|サカナOBJ申込した? + {0x1C7, new EventFlagPlayer(0 , 1 , 0455, "ChyDaily_ReqObj" )}, // レックス|ムシOBJ申込した? + {0x1C8, new EventFlagPlayer(0 , 1 , 0456, "BeyDaily_ExplainReqObj_First" )}, // ジャスティン|サカナOBJ初回説明聞いた? + {0x1C9, new EventFlagPlayer(0 , 1 , 0457, "ChyDaily_ExplainReqObj_First" )}, // レックス|ムシOBJ初回説明聞いた? + {0x1CB, new EventFlagPlayer(0 , 1 , 0459, "KinuyoTailorBuildFlag" )}, // きぬよ|仕立て屋の場所決めたプレイヤー? + {0x1CC, new EventFlagPlayer(0 , 1 , 0460, "BirthdayPToldlPartySharePlay" )}, // プレイヤー誕生日|NPCから誕生会の案内聞いた? + {0x1CD, new EventFlagPlayer(0 , 1 , 0461, "TalkSnpcTodayAnyone" )}, // 今日誰かにSnpcを聞いたか? + {0x1CE, new EventFlagPlayer(0 , 1 , 0462, "RcmForcedTalkTodayFlag" )}, // まめきち|今日お店で入店時の強制会話した? + {0x1CF, new EventFlagPlayer(0 , 1 , 0463, "RcmForcedTalk2TodayFlag" )}, // まめきち|今日お店で退店時の強制会話した? + {0x1D0, new EventFlagPlayer(0 , 1 , 0464, "KinuyoMetShopFlag" )}, // きぬよ|商店で会った? + {0x1D1, new EventFlagPlayer(0 , 1 , 0465, "ImmQGetHousingFullItem" )}, // たぬきち|ハウジングキットもらうとき、持ち物いっぱいだった + {0x1D2, new EventFlagPlayer(0 , 1 , 0466, "TownNewsReserve" )}, // 村内放送|村内放送予約フラグ + {0x1D3, new EventFlagPlayer(0 , 1 , 0467, "BeyDaily_ExolainQ_First" )}, // ジャスティン|初回クエスト説明聞いた? + {0x1D4, new EventFlagPlayer(0 , 1 , 0468, "ImmQHeardClearInfoA" )}, // たぬきち|移住クエストAをクリアした旨を聞いたことがある + {0x1D5, new EventFlagPlayer(0 , 1 , 0469, "ImmQHeardClearInfoB" )}, // たぬきち|移住クエストBをクリアした旨を聞いたことがある + {0x1D6, new EventFlagPlayer(0 , 1 , 0470, "ImmQHeardClearInfoC" )}, // たぬきち|移住クエストCをクリアした旨を聞いたことがある + {0x1D7, new EventFlagPlayer(0 , 1 , 0471, "ImmQHeardNoticeRemoveFtr" )}, // たぬきち|聞いていない移住クエストクリアの告知がある? + {0x1D8, new EventFlagPlayer(0 , 1 , 0472, "RcoImmQClear1QuestToday" )}, // たぬきち|今日、移住クエストの1工程を既にクリアしてる + {0x1D9, new EventFlagPlayer(0 , 1 , 0473, "ImmQTalkRcoHaveBridgeKit" )}, // たぬきち|まるたのはしキット持った状態で会話した + {0x1DA, new EventFlagPlayer(0 , 1 , 0474, "ImmQTalkRcoBridgeKitSet" )}, // たぬきち|まるたのはしキットを設置したお礼会話発動させる? + {0x1DB, new EventFlagPlayer(0 , 1 , 0475, "ImmQSetBridgeKitMySelf" )}, // たぬきち|まるたのはしキットを自分自身が設置した + {0x1DC, new EventFlagPlayer(0 , 1 , 0476, "ImmQTalkRcoBridgeComplete" )}, // たぬきち|まるたのはしが完成してから会話した + {0x1DD, new EventFlagPlayer(0 , 1 , 0477, "ImmQTalkAboutPrize" )}, // たぬきち|移住クエスト報酬会話した + {0x1DE, new EventFlagPlayer(0 , 1 , 0478, "ImmQGetQuestPrize" )}, // たぬきち|移住クエストの報酬もらった + {0x1DF, new EventFlagPlayer(0 , 1 , 0479, "ChyDaily_AnnounceEvent" )}, // レックス|ムシとり大会予告聞いた? + {0x1E0, new EventFlagPlayer(0 , 1 , 0480, "BeyDaily_AnnounceEvent" )}, // ジャスティン|つり大会予告聞いた? + {0x1E1, new EventFlagPlayer(0 , 1 , 0481, "CampInvite" )}, // キャンプ場に誘った + {0x1E2, new EventFlagPlayer(0 , 1 , 0482, "CampFirstTalk" )}, // キャンパーNPCとの初回会話を済ませた + {0x1E3, new EventFlagPlayer(0 , 1 , 0483, "CampQuestAccept" )}, // キャンプ家具クエストを受注した + {0x1E4, new EventFlagPlayer(0 , 1 , 0484, "CampQuestRecipiFailed" )}, // キャンプ家具クエストのレシピを受け取れなかった + {0x1E5, new EventFlagPlayer(0 , 1 , 0485, "CampQuestRejected" )}, // キャンプ家具クエストを断った + {0x1E6, new EventFlagPlayer(0 , 1 , 0486, "CampGameGetRare" )}, // キャンプゲームでレア枠アイテムを入手した + {0x1E8, new EventFlagPlayer(0 , 1 , 0488, "Camp_InduceFailFlag" )}, // キャンプ|勧誘失敗フラグ + {0x1EA, new EventFlagPlayer(0 , 1 , 0490, "Camp_InduceFailSameNpcLiving" )}, // キャンプ|勧誘失敗理由|同名NPCが村に住んでいる + {0x1EB, new EventFlagPlayer(0 , 1 , 0491, "Camp_InduceFailSameNpcMoveIn" )}, // キャンプ|勧誘失敗理由|同名NPCが転入確定状態 + {0x1EC, new EventFlagPlayer(0 , 1 , 0492, "Camp_InduceFailVillagerMax" )}, // キャンプ|勧誘失敗理由|住人数が既に上限 + {0x1ED, new EventFlagPlayer(0 , 1 , 0493, "Camp_InduceFailSellPlaceNothing" )}, // キャンプ|勧誘失敗理由|売り土地が無い + {0x1EE, new EventFlagPlayer(0 , 1 , 0494, "CalendarEventAchievementFinish" )}, // カレンダーイベントの実績を今日カウントした + {0x1EF, new EventFlagPlayer(0 , 1 , 0495, "RollanGotWallpaperFlag" )}, // ローラン|今日かべがみひきかえた? + {0x1F0, new EventFlagPlayer(0 , 1 , 0496, "RollanGotCarpetFlag" )}, // ローラン|今日ゆかひきかえた? + {0x1F7, new EventFlagPlayer(0 , 1 , 0503, "ImmQTakeFruit" )}, // たぬきち|移住クエストで今日果物もらった + {0x1F8, new EventFlagPlayer(0 , 1 , 0504, "ImmQTakeRemakeKit" )}, // xたぬきち|移住クエストで今日リメイクキットもらった + {0x1F9, new EventFlagPlayer(0 , 1 , 0505, "ImmQBridgeMadeinRcoTent" )}, // たぬきち|はしキットをたぬきちテントで作った + {0x1FA, new EventFlagPlayer(0 , 1 , 0506, "IslandDevQuestShowCampKit" )}, // たぬきち|キャンプ場よていちキットをたぬきちに見せた + {0x1FB, new EventFlagPlayer(0 , 1 , 0507, "IslandDevQuestCampMadeRcotent" )}, // たぬきち|キャンプ場よていちキットを案内所で作った + {0x1FC, new EventFlagPlayer(0 , 1 , 0508, "IslandDevQuestTalkAfterCampSet" )}, // たぬきち|キャンプ場よていちキットをセットしてから会話した + {0x1FD, new EventFlagPlayer(0 , 1 , 0509, "IslandDevQuestCampSetMySelf" )}, // たぬきち|キャンプ場よていちキットを自身で設置した + {0x1FF, new EventFlagPlayer(0 , 1 , 0511, "IslandDevQuestGetRecipeCampKit" )}, // たぬきち|キャンプ場よていちキットのレシピを受け取った + {0x200, new EventFlagPlayer(0 , 1 , 0512, "IslandDevQuestOrderFirstCamperMyself" )}, // たぬきち|1人目のキャンプ客から移住の相談を自身が受けた + {0x201, new EventFlagPlayer(0 , 1 , 0513, "MainmenuConstructLicense" )}, // スマホUI|造成ライセンスアプリ解禁 + {0x202, new EventFlagPlayer(0 , 1 , 0514, "FirstPlayAfterOfficeBuiltFlag" )}, // 案内所の建物が完成したあとのプレイ初日? + {0x203, new EventFlagPlayer(0 , 1 , 0515, "FirstPlayAfterShopBuiltFlag" )}, // 商店が完成したあとのプレイ初日? + {0x204, new EventFlagPlayer(0 , 1 , 0516, "FirstPlayAfterShopBuilt2Flag" )}, // 商店を拡張したあとのプレイ初日? + {0x205, new EventFlagPlayer(0 , 1 , 0517, "FirstPlayAfterMuseumTentFlag" )}, // フータのテントが完成したあとのプレイ初日? + {0x206, new EventFlagPlayer(0 , 1 , 0518, "FirstPlayAfterMuseumBuiltFlag" )}, // 博物館が完成したあとのプレイ初日? + {0x207, new EventFlagPlayer(0 , 1 , 0519, "FirstPlayAfterTailorBuiltFlag" )}, // 仕立て屋が完成したあとのプレイ初日? + {0x208, new EventFlagPlayer(0 , 1 , 0520, "SzaHeardTodayIslandEvaluation" )}, // しずえ|今日の島の評価を聞いた + {0x209, new EventFlagPlayer(0 , 1 , 0521, "IslandEvaluationUnlockMyself" )}, // しずえ|自分自身が島の評価を解禁した + {0x20A, new EventFlagPlayer(0 , 1 , 0522, "SzaHeardAboutIslandEvaluation" )}, // しずえ|島の評価に関する説明を聞いた + {0x20B, new EventFlagPlayer(0 , 1 , 0523, "ConstructionWorkToday" )}, // 工事ライセンス|説明を見た + {0x20C, new EventFlagPlayer(0 , 1 , 0524, "PlayToday" )}, // 今日プレイした + {0x20D, new EventFlagPlayer(0 , 1 , 0525, "TalkFreeIPresentTodayAnyone" )}, // 今日誰かにFreeI_Presentを聞いたか? + {0x20E, new EventFlagPlayer(0 , 1 , 0526, "IslandDevQuestTalkAfterBuildCamp" )}, // たぬきち|キャンプ場が完成してから会話した + {0x20F, new EventFlagPlayer(0 , 1 , 0527, "IslandDevQuestTalkAboutFirstCamper" )}, // たぬきち|1人目のキャンプ客に会いに行く依頼を自身が受けた + {0x210, new EventFlagPlayer(0 , 1 , 0528, "GetHousingKitForFirstCamper" )}, // たぬきち|1人目のキャンプ客用のハウジングキット受け取った + {0x211, new EventFlagPlayer(0 , 1 , 0529, "ItemFullHousingKitForFirstCamper" )}, // たぬきち|1人目のキャンプ客用のキット、持ち物いっぱいで受取失敗した + {0x212, new EventFlagPlayer(0 , 1 , 0530, "SetHousingKitForFirstCamper" )}, // たぬきち|1人目のキャンプ客用のハウジングキットを、自らセットした + {0x214, new EventFlagPlayer(0 , 6 , 0532, "ChyDaily_InsectSellNum" )}, // レックス|今回の来訪中に買取した数 + {0x216, new EventFlagPlayer(0 , 1 , 0534, "SharePlayGuideDone" )}, // おすそわけプレイの解説ダイアログを見た + {0x217, new EventFlagPlayer(0 , 1 , 0535, "CommuneIslandAvailable" )}, // パニエル|コミューン島に招待された + {0x218, new EventFlagPlayer(0 , 1 , 0536, "VisitedCommune" )}, // コミューン島に上陸したことがある + {0x21A, new EventFlagPlayer(0 , 1 , 0538, "ChyEvent_TalkTrophyGold" )}, // [大会]レックス|金トロフィ会話した? + {0x21B, new EventFlagPlayer(0 , 1 , 0539, "ChyEvent_TalkTrophySilver" )}, // [大会]レックス|銀トロフィ会話した? + {0x21C, new EventFlagPlayer(0 , 1 , 0540, "ChyEvent_TalkTrophyCopper" )}, // [大会]レックス|銅トロフィ会話した? + {0x21D, new EventFlagPlayer(0 , 1 , 0541, "BeyEvent_TalkTrophyGold" )}, // [大会]ジャスティン|金トロフィ会話した? + {0x21E, new EventFlagPlayer(0 , 1 , 0542, "BeyEvent_TalkTrophySilver" )}, // [大会]ジャスティン|銀トロフィ会話した? + {0x21F, new EventFlagPlayer(0 , 1 , 0543, "BeyEvent_TalkTrophyCopper" )}, // [大会]ジャスティン|銅トロフィ会話した? + {0x220, new EventFlagPlayer(0 , 1 , 0544, "SpnFirstTalkedAtCommuneIsland" )}, // パニエル|コミューン島で初回会話した? + {0x222, new EventFlagPlayer(0 , 1 , 0546, "AppUrgentEscapeCallToday" )}, // 緊急脱出|本日電話した + {0x223, new EventFlagPlayer(0 , 1 , 0547, "KotonoGotSampleFlag" )}, // ことの|サンプルもらった? + {0x224, new EventFlagPlayer(0 , 1 , 0548, "KotonoGotTicketFlag" )}, // ことの|ひきかえけんもらったことある? + {0x225, new EventFlagPlayer(0 , 1 , 0549, "OwsFirstTalk" )}, // フーコ|面識ある? + {0x226, new EventFlagPlayer(0 , 1 , 0550, "OwsTalkedToday" )}, // フーコ|今日会話した? + {0x22A, new EventFlagPlayer(0 , 1 , 0554, "OwsPresentFirstRecipe" )}, // フーコ|最初のレシピもらった? + {0x22B, new EventFlagPlayer(0 , 1 , 0555, "SpnPhotoStudioGuideDone" )}, // パニエル|撮影スタジオの説明を聞いた + {0x22C, new EventFlagPlayer(0 , 1 , 0556, "GetBirthdayCake" )}, // 今年バースデーケーキをもらった + {0x22D, new EventFlagPlayer(0 , 1 , 0557, "GetBirthdayFloorParty" )}, // 今年パーティのゆかをもらった + {0x22E, new EventFlagPlayer(0 , 1 , 0558, "GetBirthdayWallParty" )}, // 今年パーティのかべがみをもらった + {0x22F, new EventFlagPlayer(0 , 1 , 0559, "AddHairStyle1" )}, // 『ポップなヘアアレンジ』解禁 + {0x230, new EventFlagPlayer(0 , 1 , 0560, "AddHairStyle2" )}, // 『クールなヘアアレンジ』解禁 + {0x231, new EventFlagPlayer(0 , 1 , 0561, "AddHairStyle3" )}, // 寝ぐせ解禁 + {0x232, new EventFlagPlayer(0 , 1 , 0562, "TanuportAmiiboBromideUnlock" )}, // タヌポート|amiibo ブロマイド機能を解禁 + {0x233, new EventFlagPlayer(0 , 1 , 0563, "AddHairColor" )}, // タヌポート|追加ヘアカラー解禁 + {0x234, new EventFlagPlayer(0 , 1 , 0564, "EnableDiyRemake" )}, // DIY作業台|リメイク解禁 + {0x235, new EventFlagPlayer(0 , 1 , 0565, "GetLicenseGrdStone" )}, // 工事ライセンス|道路工事:石だたみ解禁 + {0x236, new EventFlagPlayer(0 , 1 , 0566, "GetLicenseGrdBrick" )}, // 工事ライセンス|道路工事:レンガの道解禁 + {0x237, new EventFlagPlayer(0 , 1 , 0567, "GetLicenseGrdDarkSoil" )}, // 工事ライセンス|道路工事:畑の道解禁 + {0x238, new EventFlagPlayer(0 , 1 , 0568, "GetLicenseGrdStonePattern" )}, // 工事ライセンス|道路工事:おうぎの石だたみ解禁 + {0x239, new EventFlagPlayer(0 , 1 , 0569, "GetLicenseGrdSand" )}, // 工事ライセンス|道路工事:すなの道解禁 + {0x23A, new EventFlagPlayer(0 , 1 , 0570, "GetLicenseGrdTile" )}, // 工事ライセンス|道路工事:テラコッタタイル解禁 + {0x23B, new EventFlagPlayer(0 , 1 , 0571, "GetLicenseGrdWood" )}, // 工事ライセンス|道路工事:くみ木の道解禁 + {0x23C, new EventFlagPlayer(0 , 1 , 0572, "GetLicenseRiver" )}, // 工事ライセンス|河川工事解禁 + {0x23D, new EventFlagPlayer(0 , 1 , 0573, "GetLicenseCliff" )}, // 工事ライセンス|崖工事解禁 + {0x23E, new EventFlagPlayer(0 , 1 , 0574, "EquipLicenseHelmet" )}, // 工事ライセンス|装備状態 + {0x240, new EventFlagPlayer(0 , 1 , 0576, "OwsPresentTodayRecipe" )}, // フーコ|今日レシピ(または素材)もらった? + {0x241, new EventFlagPlayer(0 , 1 , 0577, "OwsPresentThisZodiacRecipe" )}, // フーコ|今月の星座レシピもらった + {0x242, new EventFlagPlayer(1 , 12 , 0578, "OwsThisZodiac" )}, // フーコ|最後に遊んだ日の星座 + {0x243, new EventFlagPlayer(0 , 1 , 0579, "NewYearPlayReportSend" )}, // カウントダウンのプレイレポートを送った + {0x244, new EventFlagPlayer(0 , 1 , 0580, "RctOutsideHintToday" )}, // 今日、屋外ヒントつぶきちと会話した + {0x245, new EventFlagPlayer(0 , 1 , 0581, "DecideShopArea" )}, // お店の建設場所を決定した + {0x246, new EventFlagPlayer(0 , 1 , 0582, "HeardEatingHintAtShop" )}, // お店で「食べる」ヒント聞いた + {0x248, new EventFlagPlayer(0 , 1 , 0584, "KinuyoExplainFittingRoomFlag" )}, // きぬよ|試着室の説明聞いたことある? + {0x249, new EventFlagPlayer(0 , 1 , 0585, "HasLookMyHouseExplain" )}, // 家の機能説明ダイアログを見たことがある? + {0x24A, new EventFlagPlayer(0 , 1 , 0586, "TownNewsHeardRemakeTrialFlag" )}, // 村内放送|リメイク体験開催のお知らせを聞いた? + {0x24B, new EventFlagPlayer(0 , 1 , 0587, "RcoEnableRemakeTrial" )}, // たぬきち|リメイク体験選択肢解禁 + {0x24C, new EventFlagPlayer(0 , 1 , 0588, "RcoRemakeTrialOngoing" )}, // たぬきち|リメイク体験中 + {0x24D, new EventFlagPlayer(0 , 1 , 0589, "RcoRemakeTrialGetFurniture" )}, // たぬきち|リメイク体験中に必要な家具を持った状態でたぬきちに話しかけた + {0x24F, new EventFlagPlayer(0 , 1 , 0591, "RcoTalkAboutRemakeTrial" )}, // たぬきち|リメイク体験会のお誘い会話発動させるか? + {0x250, new EventFlagPlayer(0 , 1 , 0592, "RcoStayMyHouseImmQClear" )}, // たぬきち|移住クエストクリアで自宅前にくるか? + {0x251, new EventFlagPlayer(0 , 5 , 0593, "1stPresentHatType" )}, // (1P)初期HAからもらった帽子タイプは? + {0x253, new EventFlagPlayer(0 , 1 , 0595, "DodHeardAboutMileTravelTicket" )}, // モーリー|たぬきちから預かったマイル旅行券の説明聞いたか? + {0x255, new EventFlagPlayer(0 , 1 , 0597, "DocMysterytourExplain1st" )}, // ロドリー|ミステリーツアー初上陸で説明聞いた? + {0x256, new EventFlagPlayer(0 , 3 , 0598, "CampGameClear" )}, // キャンプゲームクリア回数 + {0x257, new EventFlagPlayer(0 , 1 , 0599, "RctTnx4CollectingMaterials" )}, // つぶきち|資材集め協力のお礼を聞いた? + {0x258, new EventFlagPlayer(0 , 1 , 0600, "RctTnx4CollectingMaterials2" )}, // つぶきち|資材集め終了のお礼を聞いた? + {0x259, new EventFlagPlayer(0 , 1 , 0601, "RctTnx4ConfirmingStorePlace" )}, // つぶきち|店の場所決め終了のお礼を聞いた? + {0x25A, new EventFlagPlayer(0 , 1 , 0602, "RcoFinishAdvice" )}, // たぬきち|アドバイス終了? + {0x25B, new EventFlagPlayer(5 , 5 , 0603, "RumorPFavoriteProgressDays" )}, // RumorP_Favoriteを聞いてからの経過日数 + {0x25C, new EventFlagPlayer(0 , 1 , 0604, "PAnnounceExplainCeremony" )}, // 島内放送|セレモニーの説明入った? + {0x25D, new EventFlagPlayer(0 , 1 , 0605, "PAnnounceTailorBuilt" )}, // 島内放送|仕立て屋オープンの話聞いた? + {0x25E, new EventFlagPlayer(0 , 1 , 0606, "RctHintCongratsMyhome" )}, // つぶきち|マイホームのお祝いを聞いた? + {0x25F, new EventFlagPlayer(0 , 1 , 0607, "PAnnounceCampsite" )}, // 島内放送|キャンプ場オープンの話聞いた? + {0x260, new EventFlagPlayer(0 , 1 , 0608, "PAnnounceHeardOfficeRenual" )}, // 島内放送|案内所改装の話聞いた? + {0x261, new EventFlagPlayer(0 , 1 , 0609, "RcoFirstTalkNewOffice" )}, // たぬきち|案内所建物初会話聞いた? + {0x262, new EventFlagPlayer(0 , 1 , 0610, "ItemRingEnable" )}, // アイテムリング解禁 + {0x263, new EventFlagPlayer(0 , 1 , 0611, "RcoTalkAboutOfficeWork" )}, // たぬきち|案内所での業務内容聞いた? + {0x264, new EventFlagPlayer(0 , 1 , 0612, "TwinTurnipExplanation" )}, // まめつぶからカブ価と高額買取品の説明聞いた? + {0x265, new EventFlagPlayer(0 , 1 , 0613, "HeldCeremonyMarket1" )}, // セレモニ|商店(小)を開いた + {0x266, new EventFlagPlayer(0 , 1 , 0614, "HeldCeremonyMarket2" )}, // セレモニ|商店(大)を開いた + {0x267, new EventFlagPlayer(0 , 1 , 0615, "HerdCeremonyOffice" )}, // セレモニ|案内所を開いた + {0x268, new EventFlagPlayer(0 , 1 , 0616, "HeldCeremonyMuseum" )}, // セレモニ|博物館を開いた + {0x269, new EventFlagPlayer(0 , 1 , 0617, "HeldCeremonyTailor" )}, // セレモニ|仕立て屋を開いた + {0x26A, new EventFlagPlayer(0 , 1 , 0618, "HeldCeremonyCampSite" )}, // セレモニ|キャンプ場を開いた + {0x26B, new EventFlagPlayer(0 , 1 , 0619, "HeldCeremonyBridge" )}, // セレモニ|橋を開いた + {0x26C, new EventFlagPlayer(0 , 1 , 0620, "HeldCeremonySlope" )}, // セレモニ|坂を開いた + {0x26D, new EventFlagPlayer(0 , 1 , 0621, "HghPeddlerPurchaceToday" )}, // きぬよ行商|今回の来訪で商品購入した + {0x26E, new EventFlagPlayer(0 , 1 , 0622, "RollanBuyWallpaperCount" )}, // ローラン|今日フシギなかべがみを買った? + {0x26F, new EventFlagPlayer(0 , 1 , 0623, "RollanBuyCarpetCount" )}, // ローラン|今日フシギなゆかを買った? + {0x270, new EventFlagPlayer(0 , 1 , 0624, "RcoTalkAboutMoveBuilding" )}, // たぬきち|建物移設の説明した + {0x271, new EventFlagPlayer(0 , 1 , 0625, "UseMigrantHousingKit1st" )}, // 移住クエ用ハウジングキットを初めて使用しようとした + {0x272, new EventFlagPlayer(0 , 1 , 0626, "RcoHeardLadderExplain" )}, // たぬきち|電話ではしごの説明を聞いた + {0x273, new EventFlagPlayer(0 , 1 , 0627, "RcoReciveMigrantEvPhone1st" )}, // たぬきち|移住クエ予定地設置後初めての電話かかってきた + {0x274, new EventFlagPlayer(0 , 1 , 0628, "SzaTalkAboutIncresePopulation" )}, // しずえ|島の評判:人口8人突破報告を聞いた + {0x275, new EventFlagPlayer(0 , 1 , 0629, "RcoMoveCampSiteReserved" )}, // たぬきち|キャンプ場の移設を予約している + {0x276, new EventFlagPlayer(0 , 1 , 0630, "SkkPurchaseToday" )}, // シャンク|今回の来訪で商品購入した + {0x277, new EventFlagPlayer(0 , 1 , 0631, "SkkTalkTodayFlag" )}, // シャンク|今日会話した? + {0x278, new EventFlagPlayer(0 , 1 , 0632, "TkkFirstLiveJoined" )}, // とたけけ|初ライブに自身が参加した? + {0x279, new EventFlagPlayer(0 , 1 , 0633, "FirstPlayAfterPlayerMake" )}, // このプレイヤを作った初日? + {0x27A, new EventFlagPlayer(0 , 1 , 0634, "RcoMigrantProgressTalk1st" )}, // たぬきち|移住クエ経過強制会話を聞いたことがある? + {0x27B, new EventFlagPlayer(0 , 1 , 0635, "DodTodayFlightMileGet" )}, // モーリー|今日のおでかけマイルもらった + {0x27C, new EventFlagPlayer(0 , 1 , 0636, "PAnnouceHeardRemakeWsNewsToday" )}, // 島内放送|今日リメイクワークショップの案内聞いた + {0x27D, new EventFlagPlayer(0 , 1 , 0637, "HghGetTailorHousingKit" )}, // きぬよ|自分が仕立て屋予定地キット受け取った + {0x27E, new EventFlagPlayer(0 , 1 , 0638, "SzaTalkAboutIncreseHousingKit" )}, // しずえ|島の評判:ハウジングキット含め8軒突破報告を聞いた + {0x27F, new EventFlagPlayer(0 , 1 , 0639, "HghHeardRequestHousingKit" )}, // きぬよ|仕立て屋の場所探しの依頼を聞いた + {0x280, new EventFlagPlayer(0 , 1 , 0640, "HghEndRequestHousingKit" )}, // きぬよ|仕立て屋の場所探しの話が完結した + {0x281, new EventFlagPlayer(0 , 1 , 0641, "OfficeSzaIntroduction" )}, // 案内所|強制会話で直接しずえの紹介受けた + {0x282, new EventFlagPlayer(0 , 1 , 0642, "PAnnouceHeardKkProject" )}, // 島内放送|とたけけプロジェクトの予告発生した? + {0x283, new EventFlagPlayer(0 , 1 , 0643, "RcoHeardAboutKkProject1st" )}, // たぬきち|けけプロジェクトの存在を聞いた? + {0x284, new EventFlagPlayer(0 , 1 , 0644, "GetLicenseGrdMydesign" )}, // 工事ライセンス|道路工事:マイデザイン地面貼り工事解禁 + {0x285, new EventFlagPlayer(0 , 1 , 0645, "RcoHeardAbout1stCamperToday" )}, // たぬきち|初キャンパーの話と勧誘依頼を今日聞いた? + {0x286, new EventFlagPlayer(0 , 1 , 0646, "RcoHeardAboutEvaluationStart" )}, // たぬきち|評価開始前の会話を聞いた? + {0x287, new EventFlagPlayer(0 , 1 , 0647, "RcoHeardAboutEvalutationDetail" )}, // たぬきち|評価の詳細を聞いた? + {0x288, new EventFlagPlayer(0 , 1 , 0648, "RcoAwaitingExplanation" )}, // たぬきち|お願い聞いてねと頼まれてる状態? + {0x289, new EventFlagPlayer(0 , 1 , 0649, "SzaHeardAboutEvaluationDetail" )}, // しずえ|村の評判の詳細説明を聞いた? + {0x28A, new EventFlagPlayer(0 , 1 , 0650, "PopDiyGoldFromStoneToday" )}, // 今日、岩から金鉱石を出した? + {0x28B, new EventFlagPlayer(0 , 1 , 0651, "BeyEvent_TalkFirst" )}, // [大会]ジャスティン|つり大会の日に会話したか? + {0x28C, new EventFlagPlayer(0 , 10 , 0652, "AppUrgentEscapeMobCounter" )}, // 緊急脱出|ラケットさん出現カウンター + {0x28D, new EventFlagPlayer(0 , 1 , 0653, "AppUrgentEscapeTodayShiftMob" )}, // 緊急脱出|今日の当番はラケットさん + {0x28E, new EventFlagPlayer(0 , 1 , 0654, "GotMedicineRecipe" )}, // (NPCから)おくすりのレシピをもらった + {0x28F, new EventFlagPlayer(0 , 1 , 0655, "MessageCardPayment" )}, // メッセージカードの代金を支払っているか + {0x290, new EventFlagPlayer(0 , 1 , 0656, "PlayerHalfAsleepDemoFlag" )}, // 寝ぼけデモフラグ + {0x291, new EventFlagPlayer(0 , 1 , 0657, "ChyEvent_TalkFirst" )}, // [大会]レックス|ムシとり大会の日に会話をしたか? + {0x292, new EventFlagPlayer(0 , 1 , 0658, "RcoWallFtrRemoveHouseRemodel" )}, // たぬきち|家増築時に壁掛け家具の撤去が発生した? + {0x293, new EventFlagPlayer(0 , 1 , 0659, "LegacyMyDesignDLEnable" )}, // Blanco|3DSマイデザインのダウンロード解禁 + {0x294, new EventFlagPlayer(0 , 1 , 0660, "Got2ndLoach" )}, // 2匹目のドジョウ + {0x295, new EventFlagPlayer(0 , 1 , 0661, "PlayReportDaily" )}, // デイリープレイレポート + {0x296, new EventFlagPlayer(0 , 1 , 0662, "UseCloset" )}, // クロゼット機能を利用したことがある + {0x297, new EventFlagPlayer(0 , 1 , 0663, "RemakeWs_TalkWhenItemFull" )}, // リメイク体験会で持ち物いっぱいを指摘された + {0x299, new EventFlagPlayer(0 , 1 , 0665, "ImmQCompleteDemo" )}, // 移住クエスト|クリア時の単独デモを見たか? + {0x29A, new EventFlagPlayer(0 , 1 , 0666, "DodSelectCommune1st" )}, // モーリー|コミューン島に行くを選んだことがある + {0x29B, new EventFlagPlayer(0 , 1 , 0667, "SpnTalkAtHomelandToday" )}, // パニエル|自分の島で会話して招待された当日か? + {0x29C, new EventFlagPlayer(0 , 1 , 0668, "SpnTalkAtCommuneToday" )}, // パニエル|今日コミューン島で会話したか? + {0x29D, new EventFlagPlayer(0 , 1 , 0669, "UpgradePocket30" )}, // 持ち物欄が30に拡張された + {0x29E, new EventFlagPlayer(0 , 1 , 0670, "UpgradePocket40" )}, // 持ち物欄が40に拡張された + {0x29F, new EventFlagPlayer(0 , 20 , 0671, "IllegalReportCount" )}, // 通報回数 + {0x2A0, new EventFlagPlayer(0 , 1 , 0672, "SellPocket40" )}, // 持ち物欄を40にするアイテムを陳列するか? + {0x2A1, new EventFlagPlayer(0 , 1 , 0673, "BeyDaily_GetDemo_Clear" )}, // 来訪クエスト達成時ゲットデモを見たか? + {0x2A2, new EventFlagPlayer(0 , 1 , 0674, "OpenDIYRecipeEtcCategory" )}, // DIYレシピ・作業台|タブカテゴリ【その他】解禁 + {0x2A3, new EventFlagPlayer(0 , 1 , 0675, "RcoBuildBridgeSlopeMyself" )}, // たぬきち|今、橋/坂建設を申し込んでいるのが自分? + {0x2A4, new EventFlagPlayer(0 , 1 , 0676, "RcoRemoveBridgeSlopeMyself" )}, // たぬきち|今、橋/坂撤去を申し込んでいるのが自分? + {0x2A5, new EventFlagPlayer(0 , 1 , 0677, "RcoTalkAboutBuildBridgeSlope" )}, // たぬきち|橋/坂建築について説明受けた + {0x2A6, new EventFlagPlayer(0 , 1 , 0678, "RcoTalkAboutHaniwa" )}, // たぬきち|募金集めのハニワについて説明受けた + {0x2A7, new EventFlagPlayer(0 , 1 , 0679, "PAnnounceHintRnd" )}, // 村内放送|ヒント発生制御用フラグ + {0x2A8, new EventFlagPlayer(0 , 1 , 0680, "PickUpFirst" )}, // Yボタン「ひろう」が可能な状態だが、ものを拾ったことがない + {0x2A9, new EventFlagPlayer(0 , 1 , 0681, "StandByGameStartPhoneCall" )}, // 電話デモ|ゲーム開始時入電するか? + {0x2AA, new EventFlagPlayer(0 , 1 , 0682, "StandByPhoneCallPrintService" )}, // 電話デモ|プリントサービス入電するか? + {0x2AB, new EventFlagPlayer(0 , 1 , 0683, "StandByPhoneCallSharePlay" )}, // 電話デモ|おすそわけ解禁入電するか? + {0x2AC, new EventFlagPlayer(0 , 1 , 0684, "StandByPhoneCallPurchaseBox" )}, // 電話デモ|買取BOX入金電話するか? + {0x2AD, new EventFlagPlayer(0 , 3 , 0685, "HeardAboutFreeDKeywordA" )}, // 肩書会話|今日同じ島のPの肩書会話を聞いた? + {0x2AE, new EventFlagPlayer(0 , 3 , 0686, "HeardAboutFreeDKeywordB" )}, // 肩書会話|今日他の島のPの肩書会話を聞いた? + {0x2AF, new EventFlagPlayer(0 , 3 , 0687, "HeardAboutFreeDKeywordC" )}, // 肩書会話|今日訪問先のPの肩書会話を聞いた? + {0x2B0, new EventFlagPlayer(0 , 1 , 0688, "RcoMoveSomeBuiding" )}, // たぬきち|なにかの建物の移設を依頼しているか? + {0x2B1, new EventFlagPlayer(0 , 1 , 0689, "BuiltMyHome" )}, // マイホームが建った + {0x2B2, new EventFlagPlayer(0 , 1 , 0690, "RcoMoveHousingSetSomeBuild" )}, // たぬきち|移設用のハウジングキット設置した + {0x2B4, new EventFlagPlayer(0 , 1 , 0692, "SzaIslandEvaluation5star1st" )}, // しずえ|島の評価で初めて5つ星とった + {0x2B5, new EventFlagPlayer(0 , 1 , 0693, "JohnnySitUpBeforeFlag" )}, // ジョニー|今までに起こしたことある?(海賊ジョニーは別フラグ) + {0x2B6, new EventFlagPlayer(0 , 1 , 0694, "CampFirstTalk_FirstVisitor" )}, // キャンパーNPCとの初回会話を済ませた(初回キャンパー用) + {0x2B7, new EventFlagPlayer(0 , 1 , 0695, "BocAllowAddBuyCount" )}, // ウリ|カブ購入回数加算許可 + {0x2B8, new EventFlagPlayer(0 , 10 , 0696, "BocBuyCount" )}, // ウリ|カブ購入回数 + {0x2B9, new EventFlagPlayer(0 , 300 , 0697, "BocBuyNumCount" )}, // ウリ|カブ購入個数 + {0x2BD, new EventFlagPlayer(0 , 10 , 0701, "EmoticonLastLearnVillagerIndex" )}, // 最後に漫符を教わったNPCの住人番号 + {0x2BE, new EventFlagPlayer(0 , 1 , 0702, "MainmenuUnlockMydesingPro" )}, // スマホUI|PROデザイン解禁 + {0x2BF, new EventFlagPlayer(0 , 255 , 0703, "HeardCurrentPlayerActivityInfo" )}, // 今回の行動に関する噂話を聞いたプレイヤーの情報 + {0x2C0, new EventFlagPlayer(0 , 255 , 0704, "HeardPreviousPlayerActivityInfo" )}, // 前回の行動に関する噂話を聞いたプレイヤーの情報 + {0x2C1, new EventFlagPlayer(0 , 9999, 0705, "DodPresentCounter" )}, // 飛行場|ノベルティ用搭乗回数 + {0x2C2, new EventFlagPlayer(0 , 3 , 0706, "DodPresentCounterToday" )}, // 飛行場|今日の搭乗回数カウンタ + {0x2C3, new EventFlagPlayer(0 , 1 , 0707, "DodSingleFlightToday" )}, // 飛行場|今日ツアー島、パニー島に行ったか? + {0x2C4, new EventFlagPlayer(0 , 20 , 0708, "DodPresentSendCounter" )}, // 飛行場|ノベルティ入手カウンタ + {0x2C5, new EventFlagPlayer(-1, -1 , 0709, "BDayMsgSenderSNpcUniqueID0" )}, // バースデーメッセージを送ったSNpcのユニークID + {0x2C6, new EventFlagPlayer(-1, -1 , 0710, "BDayMsgSenderSNpcUniqueID1" )}, // バースデーメッセージを送ったSNpcのユニークID + {0x2C7, new EventFlagPlayer(-1, -1 , 0711, "BDayMsgSenderNNpcUniqueID0" )}, // バースデーメッセージを送ったNNpcのユニークID + {0x2C8, new EventFlagPlayer(-1, -1 , 0712, "BDayMsgSenderNNpcUniqueID1" )}, // バースデーメッセージを送ったNNpcのユニークID + {0x2C9, new EventFlagPlayer(0 , -1 , 0713, "BDayMsgRandomSead" )}, // バースデーメッセージの内容を決定する乱数のシード値 + {0x2CA, new EventFlagPlayer(0 , 1 , 0714, "UnlockMyDesignProCategory" )}, // スマホUI|PROデザインのタブカテゴリ解禁 + {0x2D5, new EventFlagPlayer(0 , 30 , 0725, "BalloonShootCountToday" )}, // 今日風船をいくつ撃ったか? + {0x2D6, new EventFlagPlayer(0 , 1 , 0726, "ContributedBuildBridgeorSlope" )}, // セレモニ|橋か坂の建設に貢献した + {0x2D7, new EventFlagPlayer(0 , 1 , 0727, "ContributedTodaysCeremonyBridgeorSlope" )}, // セレモニ|今日の橋か坂のセレモニーに貢献した + {0x2D8, new EventFlagPlayer(0 , 1 , 0728, "Mobile1stBootAfterUnlockPro_Mydesign" )}, // プロ編集解禁後スマホアプリ初起動|マイデザイン + {0x2D9, new EventFlagPlayer(0 , 1 , 0729, "TkkBirthdayMessageFlag" )}, // とたけけ|バースデーメッセージ送った? + {0x2DA, new EventFlagPlayer(0 , 1 , 0730, "TalkFirstCamperAfterSetHousing" )}, // たぬきち|1人目のキャンプ客とハウジングキットセット後会話した + {0x2DB, new EventFlagPlayer(0 , 1 , 0731, "TalkFirstCamperAfterRequestSetHousing" )}, // たぬきち|1人目のキャンプ客とハウジングキット設置依頼後会話した + {0x2DC, new EventFlagPlayer(0 , 1 , 0732, "NnpcAppE_Rep_OccuredToday" )}, // NNPC_ApproachE_IslandReputationが今日発生した + {0x2DD, new EventFlagPlayer(0 , 10 , 0733, "SzaPAAccidentCounter" )}, // 村内放送|しずえがハッとするイベント発生カウンタ + {0x2DF, new EventFlagPlayer(0 , 1 , 0735, "SzaIslandEvaluationTalkAbout1Star" )}, // しずえ|島の環境:ゆうたろうからの感想を見たことがある + {0x2E0, new EventFlagPlayer(0 , 1 , 0736, "SzaIslandEvaluationHeardToday" )}, // しずえ|島の環境を今日聞いた + {0x2E4, new EventFlagPlayer(0 , 1 , 0740, "DailyQuestFivePointDay" )}, // 日課の5倍ポイントデーか? + {0x2E5, new EventFlagPlayer(0 , 1 , 0741, "DailyQuestFirstFivePoint" )}, // 日課の初回5倍ポイント使用済みか? + {0x2E6, new EventFlagPlayer(0 , 3 , 0742, "DailyQuestFivePointMiss" )}, // 日課ポイント5倍デーはずれ回数 + {0x2E7, new EventFlagPlayer(0 , -1 , 0743, "DailyQuestFivePointQuest" )}, // 日課ポイント5倍対象ユニークID + {0x2E8, new EventFlagPlayer(0 , 1 , 0744, "DailyQuestFirstFivePointToday" )}, // 今日日課の初回5倍ポイントが選ばれているか? + {0x2E9, new EventFlagPlayer(0 , 1 , 0745, "DailyQuestFivePointSelect" )}, // 日課ポイント5倍デー抽選済みフラグ + {0x2EA, new EventFlagPlayer(0 , 1 , 0746, "AppE_WelcomoMigrants_Occured" )}, // AppE_WelcomeMigrantsが発生した + {0x2EB, new EventFlagPlayer(0 , 999 , 0747, "BeyEvent_ResultGetFish" )}, // [大会]つり大会|(結果発表用)捕まえたサカナ数 + {0x2EC, new EventFlagPlayer(0 , 999 , 0748, "ChyEvent_ResultGetInsect" )}, // [大会]ムシとり大会|(結果発表用)捕まえたムシ数 + {0x2ED, new EventFlagPlayer(0 , 1 , 0749, "KotonoKateTalkFlag" )}, // ことの|ケイトの説明聞いたことある? + {0x2EE, new EventFlagPlayer(0 , 999 , 0750, "BeyEvent_ResultGetPoint" )}, // [大会]つり大会|(結果発表用)獲得したポイント + {0x2EF, new EventFlagPlayer(0 , 999 , 0751, "ChyEvent_ResultGetPoint" )}, // [大会]ムシとり大会|(結果発表用)獲得したポイント + {0x2F0, new EventFlagPlayer(0 , 1 , 0752, "PhoneCallByRcm" )}, // 電話デモ|まめきちの入電受けたことある + {0x2F1, new EventFlagPlayer(0 , 1 , 0753, "PhoneCallByRct" )}, // 電話デモ|つぶきちの入電受けたことある + {0x2F2, new EventFlagPlayer(0 , 1 , 0754, "ThisPCcreatedbeforeOfficeUpgrading" )}, // 案内所がテントのうちに作成されたプレイヤーか? + {0x2F3, new EventFlagPlayer(0 , 1 , 0755, "RcoMachineAmiiboCamperUnlock" )}, // タヌポート|amiiboキャンパー勧誘機能解禁 + {0x2F4, new EventFlagPlayer(0 , 1 , 0756, "ObjRcoMachineHeardExplanation" )}, // タヌポート|たぬきちの最初の説明を聞いた? + {0x2F5, new EventFlagPlayer(0 , 1 , 0757, "OwlHeardInsectExplanation" )}, // フータ|寄贈経由でムシの解説を聞いたことがある? + {0x2F6, new EventFlagPlayer(0 , 1 , 0758, "OwlEverDonatedInsect" )}, // フータ|自分がムシを寄贈したことがある + {0x2F7, new EventFlagPlayer(0 , 1 , 0759, "2P_CreatedAfterOwlMoving" )}, // フータのテント完成以降に作られたプレイヤー + {0x2F8, new EventFlagPlayer(0 , 1 , 0760, "OwlGotDiyRecipe" )}, // フータからテントでDIYレシピもらったか? + {0x2F9, new EventFlagPlayer(0 , 1 , 0761, "RcoTalkAboutMoveMyHome" )}, // たぬきち|自宅の移設の解禁情報を聞いた? + {0x2FA, new EventFlagPlayer(0 , 1 , 0762, "RcoPAnnounceMuseumSP" )}, // 島内放送|フータ移住アナウンスで寄贈完了のことを聞いた? + {0x2FB, new EventFlagPlayer(0 , 1 , 0763, "PAnnounceHeardMarketUpgradeInfo" )}, // 島内放送|商店小→大の改装決定のアナウンスを聞いた?(たぬきち) + {0x2FC, new EventFlagPlayer(0 , 1 , 0764, "PAnnounceHeardMarketUpgradeInfoSza" )}, // 島内放送|商店小→大の改装決定のアナウンスを聞いた?(しずえ) + {0x2FD, new EventFlagPlayer(0 , 1 , 0765, "NoticeAboutLicenseRiver" )}, // 工事ライセンス|河川工事解禁して初起動した? + {0x2FE, new EventFlagPlayer(0 , 1 , 0766, "NoticeAboutLicenseCliff" )}, // 工事ライセンス|崖工事解禁して初起動した? + {0x2FF, new EventFlagPlayer(0 , 1 , 0767, "OdekakeFirstInternet" )}, // 空港|モーリー|おでかけ初めてインターネットの島を選択 + {0x300, new EventFlagPlayer(0 , 1 , 0768, "UploadProfileGrowupDaily" )}, // 成長処理でプロフィールアップロードを行ったか? + {0x301, new EventFlagPlayer(0 , 30 , 0769, "GoldenBalloonCount" )}, // 金の風船発生条件カウンタ + {0x302, new EventFlagPlayer(0 , 200 , 0770, "GoldenAxeLearningCount" )}, // 金のオノレシピひらめきカウンタ + {0x303, new EventFlagPlayer(0 , 3 , 0771, "LastUseLicense" )}, // 工事ライセンス|最後に使ったライセンスをできるだけ記憶する + {0x304, new EventFlagPlayer(0 , 1 , 0772, "GoldenRodRecipeSent" )}, // 金のつりざおレシピ投函済か? + {0x305, new EventFlagPlayer(0 , 1 , 0773, "GoldenNetRecipeSent" )}, // 金のあみレシピ投函済か? + {0x306, new EventFlagPlayer(0 , 1 , 0774, "CompleteFish" )}, // サカナコンプリート済か? + {0x307, new EventFlagPlayer(0 , 1 , 0775, "CompleteInsects" )}, // ムシコンプリート済か? + {0x308, new EventFlagPlayer(0 , 1 , 0776, "Experienced3starEvaluation" )}, // 3つ星以下の島の評価を聞いたことがある + {0x309, new EventFlagPlayer(0 , 20 , 0777, "CountGotTrash" )}, // ゴミを釣り上げて入手した回数カウント + {0x30A, new EventFlagPlayer(0 , 10 , 0778, "CountGotTrash_Can" )}, // あきかんを釣り上げて入手した回数カウント + {0x30B, new EventFlagPlayer(0 , 10 , 0779, "CountGotTrash_Tire" )}, // タイヤを釣り上げて入手した回数カウント + {0x30C, new EventFlagPlayer(0 , 50 , 0780, "JohnnyHelpCount" )}, // ジョニー|助けた回数(海賊ジョニーは別フラグ) + {0x30D, new EventFlagPlayer(0 , 1 , 0781, "CatchtFesBox_Valid" )}, // ムシサカナBOXの中身をキープ + {0x30E, new EventFlagPlayer(0 , 1 , 0782, "TreasurePlayerWin" )}, // 宝探しプレイヤー勝利 + {0x30F, new EventFlagPlayer(0 , 1 , 0783, "PAnnounce_SummerShell" )}, // 島内放送|季節素材告知_夏_なつのかいがら + {0x310, new EventFlagPlayer(0 , 1 , 0784, "PAnnounce_AutumnNuts" )}, // 島内放送|季節素材告知_秋_木の実 + {0x311, new EventFlagPlayer(0 , 1 , 0785, "UploadPlayerProfileIllegal" )}, // アップロードしたプレイヤープロフィールがNG扱いに + {0x312, new EventFlagPlayer(0 , 1 , 0786, "PAnnounce_AutumnMushroom" )}, // 島内放送|季節素材告知_秋_キノコ + {0x313, new EventFlagPlayer(0 , 1 , 0787, "PAnnounce_WinterSnowFlake" )}, // 島内放送|季節素材告知_冬_雪の結晶 + {0x314, new EventFlagPlayer(0 , 1 , 0788, "PAnnounce_WinterSnowball" )}, // 島内放送|季節素材告知_冬_雪だるま + {0x315, new EventFlagPlayer(0 , 1 , 0789, "PAnnounce_WinterOrnament" )}, // 島内放送|季節素材告知_冬_オーナメント + {0x316, new EventFlagPlayer(0 , 1 , 0790, "NotStartImmQByDIYDisable" )}, // 移住クエスト|DIY未修得で移住クエストを始められない + {0x317, new EventFlagPlayer(0 , 1 , 0791, "PAnnounce_AutumnRedLeaf" )}, // 島内放送|季節素材告知_秋_もみじ + {0x318, new EventFlagPlayer(0 , 1 , 0792, "PAnnounce_SpringSakura" )}, // 島内放送|季節素材告知_春_桜の花びら + {0x319, new EventFlagPlayer(0 , 1 , 0793, "PAnnounce_SpringBamboo" )}, // 島内放送|季節素材告知_春_春の若竹 + {0x31A, new EventFlagPlayer(0 , 1 , 0794, "RcoHeardInviteRemakeWS" )}, // たぬきち|リメイク体験会のお誘い会話聞いた + {0x31C, new EventFlagPlayer(0 , 1 , 0796, "KinuyoPROdesginFlag" )}, // きぬよ|PROデザインの説明聞いたことある? + {0x31D, new EventFlagPlayer(0 , 1 , 0797, "NoticeAboutMydesingOnWorkBench" )}, // 作業台|マイデザインリメイク選んで説明ダイアログ見た + {0x31E, new EventFlagPlayer(0 , -1 , 0798, "LatestMysteryTourUniqueID" )}, // 最後に選出したミステリーツアーのユニークID + {0x31F, new EventFlagPlayer(0 , 1 , 0799, "OwlMultiDonateExplain" )}, // フータ|複数鑑定&コレって何説明聞いた? + {0x320, new EventFlagPlayer(0 , 1 , 0800, "StandByPhoneCallIslandCreater" )}, // 電話デモ|島クリエイタの解禁入電するか? + {0x321, new EventFlagPlayer(0 , -1 , 0801, "PastDaysFromLastPlay" )}, // 最後にプレイした日から今日の成長処理までの経過日数 + {0x322, new EventFlagPlayer(0 , 1 , 0802, "UncollectedTreasure" )}, // 宝未回収で終了 + {0x323, new EventFlagPlayer(0 , 1 , 0803, "VisitMysteryTourID11" )}, // ID: 11のミステリーツアー島にその日行ったことがある + {0x324, new EventFlagPlayer(0 , 1 , 0804, "VisitMysteryTourID12" )}, // ID: 12のミステリーツアー島にその日行ったことがある + {0x325, new EventFlagPlayer(0 , 1 , 0805, "VisitMysteryTourID13" )}, // ID: 13のミステリーツアー島にその日行ったことがある + {0x326, new EventFlagPlayer(0 , 1 , 0806, "VisitMysteryTourID14" )}, // ID: 14のミステリーツアー島にその日行ったことがある + {0x327, new EventFlagPlayer(0 , 1 , 0807, "VisitMysteryTourID16" )}, // ID: 16のミステリーツアー島にその日行ったことがある + {0x328, new EventFlagPlayer(0 , 1 , 0808, "VisitMysteryTourID17" )}, // ID: 17のミステリーツアー島にその日行ったことがある + {0x329, new EventFlagPlayer(0 , 1 , 0809, "VisitMysteryTourID19" )}, // ID: 19のミステリーツアー島にその日行ったことがある + {0x32A, new EventFlagPlayer(0 , 1 , 0810, "VisitMysteryTourID21" )}, // ID: 21のミステリーツアー島にその日行ったことがある + {0x32B, new EventFlagPlayer(0 , 1 , 0811, "VisitMysteryTourID24" )}, // ID: 24のミステリーツアー島にその日行ったことがある + {0x32C, new EventFlagPlayer(0 , 1 , 0812, "FriendMailGuideRetentionPeriod" )}, // メッセージカード|サーバ保持期間に関する説明を見たか? + {0x32D, new EventFlagPlayer(0 , 1 , 0813, "StandByRcoVisitMyHomeAfterTkkFirstLive" )}, // たぬきち|とたけけライブ後の自宅訪問するか? + {0x32E, new EventFlagPlayer(0 , 1 , 0814, "SpnTalkBeforeGotHouseToday" )}, // パニエル|家ないプレイヤー(ホスト)が島で今日会話した + {0x32F, new EventFlagPlayer(0 , 1 , 0815, "TodayGrowUp" )}, // 今日成長処理済みか + {0x330, new EventFlagPlayer(0 , 32 , 0816, "KotonoQuestClearCount" )}, // ことの|クリアした回数 + {0x331, new EventFlagPlayer(0 , 1 , 0817, "PhotoStudioUseCantCallAmiibo" )}, // 撮影スタジオ|呼べないamiiboを使った + {0x332, new EventFlagPlayer(0 , 1 , 0818, "ChyDaily_ObjEntry1" )}, // レックス(来訪)|OBJ申込(1回目)した + {0x333, new EventFlagPlayer(0 , 1 , 0819, "ChyDaily_ObjEntry2" )}, // レックス(来訪)|OBJ申込(2回目)した + {0x334, new EventFlagPlayer(0 , 1 , 0820, "ChyDaily_ObjEntry3" )}, // レックス(来訪)|OBJ申込(3回目)した + {0x335, new EventFlagPlayer(0 , 1 , 0821, "BeyDaily_ObjEntry1" )}, // ジャスティン(来訪)|OBJ申込(1回目)した + {0x336, new EventFlagPlayer(0 , 1 , 0822, "BeyDaily_ObjEntry2" )}, // ジャスティン(来訪)|OBJ申込(2回目)した + {0x337, new EventFlagPlayer(0 , 1 , 0823, "BeyDaily_ObjEntry3" )}, // ジャスティン(来訪)|OBJ申込(3回目)した + {0x338, new EventFlagPlayer(0 , 1 , 0824, "BeyDaily_TalkAlways1" )}, // ジャスティン(来訪)|OBJ申込後雑談①聞いた + {0x339, new EventFlagPlayer(0 , 1 , 0825, "BeyDaily_TalkAlways2" )}, // ジャスティン(来訪)|OBJ申込後雑談②聞いた + {0x33A, new EventFlagPlayer(0 , 1 , 0826, "BeyDaily_TalkAlways3" )}, // ジャスティン(来訪)|OBJ申込後雑談③聞いた + {0x33B, new EventFlagPlayer(0 , 1 , 0827, "CampQuestRecipeGet" )}, // キャンプ家具クエストでレシピを貰った + {0x33C, new EventFlagPlayer(0 , 1 , 0828, "Mobile1stBoot_IslandCreater" )}, // スマホアプリ初起動|島クリエイター + {0x33D, new EventFlagPlayer(0 , 1 , 0829, "Closet_Explain_ChangeStick" )}, // タンスで変身ステッキの説明を聞いた + {0x33E, new EventFlagPlayer(0 , 1 , 0830, "TkkFirstLiveToday" )}, // とたけけ|今日初めてライブを聴いた? + {0x33F, new EventFlagPlayer(0 , 1 , 0831, "1stBootIslandCreaterCleanService" )}, // 島クリエイター|お片付けサービスの説明聞いた + {0x340, new EventFlagPlayer(0 , 1 , 0832, "MarketBuiltMyVillage" )}, // 自分の村のお店が開店した + {0x341, new EventFlagPlayer(0 , 1 , 0833, "Mobile1stBootUnlockCantEditMydesign" )}, // 編集不可デザイン保存後スマホアプリ初起動|マイデザイン + {0x342, new EventFlagPlayer(0 , 1 , 0834, "DodHeardAboutIslandCreator" )}, // モーリー|島クリエイター強制解除されたことある? + {0x343, new EventFlagPlayer(0 , 5 , 0835, "SzaBeforeIslandEvaluation" )}, // しずえ|前回聞いた島の評判(1~5) + {0x344, new EventFlagPlayer(0 , 1 , 0836, "PAnnouceProcessDoneToday" )}, // 村内放送のProcess処理を今日行ったか? + {0x345, new EventFlagPlayer(0 , 1 , 0837, "ImprovePlayerProfile" )}, // NG扱いとなったプレイヤープロフィールが修正されたか? + {0x346, new EventFlagPlayer(0 , 1 , 0838, "EnableInviteMoveoutNPC" )}, // よその島の引っ越し状態のNPCを勧誘可能か? + {0x348, new EventFlagPlayer(0 , 1 , 0840, "TodayMainGrowUp" )}, // 今日メインプレイヤーとして成長処理済みか + {0x349, new EventFlagPlayer(0 , 1 , 0841, "SzaTalkAtOfficeToday" )}, // しずえ|案内所で今日話しかけたか? + {0x34A, new EventFlagPlayer(0 , 1 , 0842, "MainmenuChatLog" )}, // スマホUI|チャットログ解禁 + {0x34B, new EventFlagPlayer(0 , 1 , 0843, "Mobile1stBoot_ChatLog" )}, // スマホアプリ初起動|チャットログ + {0x34C, new EventFlagPlayer(0 , 1 , 0844, "Activate_WebService" )}, // Blanco解禁 + {0x34D, new EventFlagPlayer(0 , 1 , 0845, "MyDesignExchangeFirstAccess" )}, // マイデザイン交換端末|初回アクセス + {0x34E, new EventFlagPlayer(0 , 1 , 0846, "MyDesignExchangeUploadOnce" )}, // マイデザイン交換端末|一度でも投稿したか? + {0x34F, new EventFlagPlayer(0 , 1 , 0847, "OhirakiRollbackTutorial" )}, // 通信|緊急おひらきによるロールバックの説明をしたか? + {0x350, new EventFlagPlayer(0 , 1 , 0848, "SzaTalkFirstNotOffice" )}, // しずえ|案内所以外で初めて会話した + {0x351, new EventFlagPlayer(0 , 1 , 0849, "Talk1stCamperMultiplay" )}, // キャンプ場|通信中に最初のキャンパーと会話したか? + {0x352, new EventFlagPlayer(0 , 20 , 0850, "EasterTodayRecipeRandomGenerateNum" )}, // イースター|今日のランダム出現レシピ数 + {0x353, new EventFlagPlayer(0 , 1 , 0851, "ObjRcoMachineHeardFenceRecipe" )}, // タヌポート|たぬきちに柵レシピ解禁の話聞いた?(2P専用) + {0x354, new EventFlagPlayer(0 , 100 , 0852, "WinningProbabilityOfEasterEggGroundRecipe" )}, // じめんのたまご関連のレシピの抽選確率 + {0x355, new EventFlagPlayer(0 , 100 , 0853, "WinningProbabilityOfEasterEggRockRecipe" )}, // いわのたまご関連のレシピの抽選確率 + {0x356, new EventFlagPlayer(0 , 100 , 0854, "WinningProbabilityOfEasterEggLeafRecipe" )}, // はっぱのたまご関連のレシピの抽選確率 + {0x357, new EventFlagPlayer(0 , 100 , 0855, "WinningProbabilityOfEasterEggForestRecipe" )}, // もりのたまご関連のレシピの抽選確率 + {0x358, new EventFlagPlayer(0 , 100 , 0856, "WinningProbabilityOfEasterEggSkyRecipe" )}, // そらとぶたまご関連のレシピの抽選確率 + {0x359, new EventFlagPlayer(0 , 100 , 0857, "WinningProbabilityOfEasterEggFishRecipe" )}, // サカナのたまご関連のレシピの抽選確率 + {0x35A, new EventFlagPlayer(0 , 20 , 0858, "ShootDownEasterRecipeBalloon" )}, // イースター|今日、レシピのついたたまご型風船を撃ち落とした数 + {0x35B, new EventFlagPlayer(0 , 5 , 0859, "EasterRecipeAddLotNum" )}, // イースター|レシピ出現追加抽選実施回数 + {0x35C, new EventFlagPlayer(0 , 1 , 0860, "PynTalkBeforeFlag" )}, // ぴょんたろう|今までに会話したことある? + {0x35D, new EventFlagPlayer(0 , 1 , 0861, "PynTalkBackTodayFlag" )}, // ぴょんたろう|今日背後から話しかけたことある? + {0x35E, new EventFlagPlayer(0 , 1 , 0862, "PynTalkPreVisitDayFlag" )}, // ぴょんたろう|イースター前に会話した? + {0x35F, new EventFlagPlayer(0 , 1 , 0863, "PynTalkEasterDayFlag" )}, // ぴょんたろう|イースター当日に会話した? + {0x360, new EventFlagPlayer(0 , 1 , 0864, "PynCannotGetItemFlag" )}, // ぴょんたろう|受け取り損ねたアイテムがある? + {0x361, new EventFlagPlayer(0 , 1 , 0865, "PynExplainExchangeEggsFlag" )}, // ぴょんたろう|たまご交換の説明を聞いた? + {0x362, new EventFlagPlayer(0 , 1 , 0866, "PynExplainInventRecipeFlag" )}, // ぴょんたろう|プレイヤーがひらめいたレシピの説明を聞いた? + {0x363, new EventFlagPlayer(0 , 1 , 0867, "PynExplainNnpcRecipeFlag" )}, // ぴょんたろう|一般NPCからもらえるレシピのヒントを聞いた? + {0x364, new EventFlagPlayer(0 , 1 , 0868, "PynGetFirstRecipeEasterDayFlag" )}, // ぴょんたろう|イースター当日の初回会話でレシピを入手済み? + {0x365, new EventFlagPlayer(0 , 1 , 0869, "PynGetFinalMissionRecipeFlag" )}, // ぴょんたろう|イースターの最終お題レシピを入手済み? + {0x366, new EventFlagPlayer(0 , 1 , 0870, "PynCompleteDiyMissionFlag" )}, // ぴょんたろう|イースターのDIYミッションをクリア済み? + {0x367, new EventFlagPlayer(0 , 1 , 0871, "PynGetEggBasketFlag" )}, // ぴょんたろう|たまごのバスケットを入手済み? + {0x368, new EventFlagPlayer(0 , 1 , 0872, "PynExplainEasterDateFlag" )}, // ぴょんたろう|イースターの日付を聞いた? + {0x369, new EventFlagPlayer(0 , 1 , 0873, "SetMessageBottleEgg" )}, // イースター|今日タマゴのメッセージボトルを配置したか + {0x36A, new EventFlagPlayer(0 , 1 , 0874, "SetTreeEggLeaf" )}, // イースター|今日はっぱのタマゴの木を配置したか + {0x36B, new EventFlagPlayer(0 , 1 , 0875, "BuryEggGround" )}, // イースター|今日じめんのタマゴを埋めたか + {0x36C, new EventFlagPlayer(0 , 1 , 0876, "IsGetMessageBottleEgg" )}, // イースター|今日タマゴのメッセージボトルを入手したか + {0x36D, new EventFlagPlayer(0 , 2 , 0877, "HitMessageBottleEgg" )}, // イースター|漂着のタマゴが選ばれた回数 + {0x36E, new EventFlagPlayer(0 , 6 , 0878, "MissMessageBottleEgg" )}, // イースター|漂着のタマゴが選ばれなかった回数 + {0x36F, new EventFlagPlayer(0 , 2 , 0879, "EasterNnpcRecipeCount" )}, // イースター|一般NPCからもらったレシピの数 + {0x370, new EventFlagPlayer(0 , 10 , 0880, "LastEasterApproachVillagerIndex" )}, // イースター|最後にイースター用アプローチ会話をしたNPCの住人番号 + {0x371, new EventFlagPlayer(0 , 1 , 0881, "OpenDIYRecipeSeasonCategory" )}, // DIYレシピ・作業台|タブカテゴリ【季節】解禁 + {0x372, new EventFlagPlayer(0 , 9999, 0882, "LastPlayEasterYear" )}, // イースター|最後に遊んだイースターの年 + {0x373, new EventFlagPlayer(0 , 1 , 0883, "PynEvent_SendRecipeMail" )}, // イースター|受け取れなかったレシピを手紙で受け取った? + {0x374, new EventFlagPlayer(0 , 1 , 0884, "PynGetPreVisitRecipeFlag" )}, // イースター|準備期間にレシピを受け取った? + {0x376, new EventFlagPlayer(0 , 1 , 0886, "PynInventRecipeFlag" )}, // ぴょんたろう|イースターエッグ関連レシピをひらめいた? + {0x377, new EventFlagPlayer(0 , 1 , 0887, "SnowmanDIYMailFlag" )}, // ゆきだるま|DIYレシピの手紙送った? + {0x378, new EventFlagPlayer(0 , 64 , 0888, "AlwJuneBrideDayCount" )}, // リサ/ジューンブライド|今年クリアした回数 + {0x379, new EventFlagPlayer(0 , 1 , 0889, "EasterCannotGetNnpcRecipeFlag" )}, // イースター|一般NPCから受け取り損ねたレシピがある? + {0x37A, new EventFlagPlayer(0 , 1 , 0890, "AlwJuneBrideQuestStartFlag" )}, // リサ/ジューンブライド|クエスト開始フラグ + {0x37B, new EventFlagPlayer(0 , 1 , 0891, "AlwJuneBrideQuestClearFlag" )}, // リサ/ジューンブライド|今日クリアした? + {0x37C, new EventFlagPlayer(0 , 1 , 0892, "StampRallyRunningForPlayer" )}, // フータ/国際ミュージアム|スタンプラリーに参加中? + {0x37D, new EventFlagPlayer(0 , 1 , 0893, "OwlInsectStampRally1" )}, // フータ/国際ミュージアム|【ムシ】スタンプ1つ目を押した? + {0x37E, new EventFlagPlayer(0 , 1 , 0894, "OwlInsectStampRally2" )}, // フータ/国際ミュージアム|【ムシ】スタンプ2つ目を押した? + {0x37F, new EventFlagPlayer(0 , 1 , 0895, "OwlInsectStampRally3" )}, // フータ/国際ミュージアム|【ムシ】スタンプ3つ目を押した? + {0x380, new EventFlagPlayer(0 , 1 , 0896, "OwlFishStampRally1" )}, // フータ/国際ミュージアム|【サカナ】スタンプ1つ目を押した? + {0x381, new EventFlagPlayer(0 , 1 , 0897, "OwlFishStampRally2" )}, // フータ/国際ミュージアム|【サカナ】スタンプ2つ目を押した? + {0x382, new EventFlagPlayer(0 , 1 , 0898, "OwlFishStampRally3" )}, // フータ/国際ミュージアム|【サカナ】スタンプ3つ目を押した? + {0x383, new EventFlagPlayer(0 , 1 , 0899, "OwlFossilStampRally1" )}, // フータ/国際ミュージアム|【かせき】スタンプ1つ目を押した? + {0x384, new EventFlagPlayer(0 , 1 , 0900, "OwlFossilStampRally2" )}, // フータ/国際ミュージアム|【かせき】スタンプ2つ目を押した? + {0x385, new EventFlagPlayer(0 , 1 , 0901, "OwlFossilStampRally3" )}, // フータ/国際ミュージアム|【かせき】スタンプ3つ目を押した? + {0x386, new EventFlagPlayer(0 , 1 , 0902, "AlpJuneBrideExchangeFlag" )}, // カイゾー/ジューンブライド|今日交換した? + {0x387, new EventFlagPlayer(0 , 1 , 0903, "AlwJuneBrideRemakeOpenFlag" )}, // リサ/ジューンブライド|リメイクテーマ解禁済み? + {0x388, new EventFlagPlayer(0 , 9999, 0904, "MailSendFlag_VersionUp" )}, // 手紙|アップデートお礼手紙を送った + {0x389, new EventFlagPlayer(0 , 1 , 0905, "MailSendFlag_BundledEdition" )}, // 手紙|同梱版購入お礼手紙を送った + {0x38B, new EventFlagPlayer(0 , 1 , 0907, "GetMayDayTicket" )}, // メーデー|メーデーりょこうけんを入手した? + {0x38C, new EventFlagPlayer(0 , 1 , 0908, "WHEREAREN_VisitDone" )}, // HHD|ウェアラン諸島に行ったことがある + {0x38D, new EventFlagPlayer(0 , 1 , 0909, "PAnnouncePreEaster" )}, // 島内放送|イースター準備期間の放送を聞いた? + {0x390, new EventFlagPlayer(0 , 7 , 0912, "ShootDownEasterOverCountRecipeBalloon" )}, // イースター|たまご風船をレシピ排出数がない状態で撃ち落とした数をカウント + {0x391, new EventFlagPlayer(0 , 1 , 0913, "RcoEarthDayAnnouncement" )}, // アースデー|案内所たぬきちのアースデー告知を聞いた? + {0x392, new EventFlagPlayer(0 , 1 , 0914, "RcoEarthDayGetHedge" )}, // アースデー|アースデー期間にたぬきちから「いけがき」もらった? + {0x393, new EventFlagPlayer(0 , 1 , 0915, "SloTalkAboutHedge" )}, // レイジ|レイジから「いけがき」の話をされたことある? + {0x394, new EventFlagPlayer(0 , 3 , 0916, "SloBuyCount" )}, // レイジ|行商レイジから買い物した回数 + {0x397, new EventFlagPlayer(0 , 1 , 0919, "TalkRumorOVlgFavoriteToday" )}, // 今日RumorOP_Favorite(同じ島の住人P)を聞いたか? + {0x398, new EventFlagPlayer(0 , 1 , 0920, "EasterCompleteFlag" )}, // イースター|イベントを最後までクリアしたことがある? + {0x399, new EventFlagPlayer(0 , 1 , 0921, "PhoneCallPrintServiceDelayFlag" )}, // ポスター解禁入電が次回ゲーム開始時に先延ばしされたか? + {0x39A, new EventFlagPlayer(0 , 1 , 0922, "EarthdayDailyAllClear" )}, // アースデー用の5倍日課を両方クリアしたことがある + {0x39B, new EventFlagPlayer(0 , 9999, 0923, "GetCountEasterEggGround" )}, // イースター期間中のじめんのたまごの取得数 + {0x39C, new EventFlagPlayer(0 , 9999, 0924, "GetCountEasterEggRock" )}, // イースター期間中のいわのたまごの取得数 + {0x39D, new EventFlagPlayer(0 , 9999, 0925, "GetCountEasterEggLeaf" )}, // イースター期間中のはっぱのたまごの取得数 + {0x39E, new EventFlagPlayer(0 , 9999, 0926, "GetCountEasterEggForest" )}, // イースター期間中のもりのたまごの取得数 + {0x39F, new EventFlagPlayer(0 , 9999, 0927, "GetCountEasterEggSky" )}, // イースター期間中のそらとぶたまごの取得数 + {0x3A0, new EventFlagPlayer(0 , 9999, 0928, "GetCountEasterEggFish" )}, // イースター期間中のサカナのたまごの取得数 + {0x3A1, new EventFlagPlayer(0 , 1 , 0929, "DodHeardAboutMayDayTravelTicket" )}, // メーデー|モーリー|たぬきちから預かったメーデー旅行券の説明聞いたか? + {0x3A2, new EventFlagPlayer(0 , 1 , 0930, "UseMayDayTicket" )}, // メーデー|メーデー旅行券を使用した? + {0x3A6, new EventFlagPlayer(0 , 1 , 0934, "OwlShowPaintingMyself" )}, // フータ|自分が絵画クエストを達成した + {0x3A7, new EventFlagPlayer(0 , 1 , 0935, "Owl1stTalkMuseum2" )}, // フータ|博物館②完成後の挨拶した? + {0x3A8, new EventFlagPlayer(0 , 1 , 0936, "OwlPaintingQuestExplain" )}, // フータ|絵画クエストの説明を受けたか? + {0x3A9, new EventFlagPlayer(0 , 1 , 0937, "FutaReadyForMuseum2" )}, // フータ|博物館②建設条件達成の報告を聞いたか? + {0x3AA, new EventFlagPlayer(0 , 1 , 0938, "HeldCeremonyMuseum2" )}, // セレモニ|博物館②を開いた + {0x3AB, new EventFlagPlayer(0 , 2 , 0939, "EarthdayDailyClearNum" )}, // アースデー専用クエストを今日クリアした数 + {0x3AC, new EventFlagPlayer(0 , 1 , 0940, "OwlShowPaintingBeforeQuest" )}, // フータ|絵画クエスト前に絵画を見せたか? + {0x3AD, new EventFlagPlayer(0 , 1 , 0941, "OwlPaintingQuestDeclined" )}, // フータ|絵画クエストで寄贈を断ったことある + {0x3AE, new EventFlagPlayer(0 , 10 , 0942, "LastIslandRepApproachVillagerIndex" )}, // 最後に島評判アップアプローチ会話をしたNPCの住人番号 + {0x3B0, new EventFlagPlayer(0 , 1 , 0944, "ChangedPermanentNum" )}, // 疑似本体IDが合わないフラグ + {0x3B1, new EventFlagPlayer(0 , 1 , 0945, "ClearMayDayTour" )}, // メーデーツアーの謎解きをクリアした? + {0x3B2, new EventFlagPlayer(0 , 3 , 0946, "NnpcApproachNoIslandRepCount" )}, // アプローチ会話|評判UP応援会話を見ないまま経過したプレイ日数 + {0x3B3, new EventFlagPlayer(0 , 1 , 0947, "JuneBridePlacementDataClearFlag" )}, // ジューンブライド|配置データクリア + {0x3B4, new EventFlagPlayer(0 , 1 , 0948, "SloGetHedge" )}, // レイジ|レイジから「いけがき」をもらった? + {0x3B5, new EventFlagPlayer(0 , 1 , 0949, "XctGerReward" )}, // メーデー|みしらぬネコから報酬をもらった? + {0x3B6, new EventFlagPlayer(0 , 1 , 0950, "SpnJuneBrideClearTalkFrag" )}, // パニエル/ジューンブライド|今年クリア後の会話した? + {0x3B7, new EventFlagPlayer(0 , 1 , 0951, "AlwJuneBrideTalkBeforeFlag" )}, // リサ|面識ある? + {0x3B8, new EventFlagPlayer(0 , 1 , 0952, "AlpJuneBrideTalkBeforeFlag" )}, // カイゾー|面識ある? + {0x3B9, new EventFlagPlayer(0 , 1 , 0953, "SpnJuneBrideTalkEventFrag" )}, // パニエル/ジューンブライド|今年イベント期間中に会話した? + {0x3BA, new EventFlagPlayer(0 , 9999, 0954, "PynVisitYear" )}, // ぴょんたろうが来訪した年 + {0x3BB, new EventFlagPlayer(0 , 1 , 0955, "PynVisitToday" )}, // ぴょんたろうが今日来訪NPCとして来訪する + {0x3BC, new EventFlagPlayer(0 , 1 , 0956, "OwlStampPlayed" )}, // フータ/国際ミュージアム|今年スタンプラリーに参加した? + {0x3BF, new EventFlagPlayer(0 , 1 , 0959, "OwlStampPocketWasFull" )}, // フータ/国際ミュージアム|報酬受け取りでポケットいっぱいだった + {0x3C0, new EventFlagPlayer(0 , 1 , 0960, "OwlStampGotInsectReward" )}, // フータ/国際ミュージアム|その日、ムシ報酬を貰った + {0x3C1, new EventFlagPlayer(0 , 1 , 0961, "OwlStampGotFishReward" )}, // フータ/国際ミュージアム|その日、サカナ報酬を貰った + {0x3C2, new EventFlagPlayer(0 , 1 , 0962, "OwlStampGotFossilReward" )}, // フータ/国際ミュージアム|その日、かせき報酬を貰った + {0x3D5, new EventFlagPlayer(0 , 1 , 0981, "DocDeliveryPurchaseExplain" )}, // ロドリー|宅配・買取サービスの説明聞いた? + {0x3D6, new EventFlagPlayer(0 , 1 , 0982, "TalkRumorN2TodayAnyone" )}, // 今日誰かにRumorN2を聞いたか? + {0x3D7, new EventFlagPlayer(0 , 1 , 0983, "TownNewsHeardMuseum2OpenFlag" )}, // 村内放送|博物館建物②が建った告知を聞いた? + {0x3DC, new EventFlagPlayer(0 , 1 , 0988, "KinuyoMydesginMachineFlag" )}, // きぬよ|マイデザイン端末の説明聞いたことある? + {0x3DD, new EventFlagPlayer(0 , 1 , 0989, "OwlStampGotInsect" )}, // フータ/国際ミュージアム|その日、フータスタンプ(ムシ)を押した + {0x3DE, new EventFlagPlayer(0 , 1 , 0990, "OwlStampGotFish" )}, // フータ/国際ミュージアム|その日、フータスタンプ(サカナ)を押した + {0x3DF, new EventFlagPlayer(0 , 1 , 0991, "OwlStampGotFossil" )}, // フータ/国際ミュージアム|その日、フータスタンプ(かせき)を押した + {0x3E0, new EventFlagPlayer(0 , 1 , 0992, "CompleteEventMayDay" )}, // メーデーイベントが全て完了した + {0x3E1, new EventFlagPlayer(0 , 64 , 0993, "AlwJuneBrideDayAlreadyCount" )}, // リサ/ジューンブライド|今までに何日目までクリアしたか用カウント + {0x3E2, new EventFlagPlayer(0 , 1 , 0994, "PAnnounceEarthDay" )}, // 島内放送|アースデー初回ログイン時の放送を聞いた? + {0x3E3, new EventFlagPlayer(0 , 1 , 0995, "TipsChatFlag" )}, // チャット説明ダイアログを見たか? + {0x3E4, new EventFlagPlayer(0 , 1 , 0996, "RcoEarthDayAnnouncementPre" )}, // アースデー|案内所たぬきちのアースデー準備中告知を聞いた? + {0x3E5, new EventFlagPlayer(0 , 1 , 0997, "FoxPreVisitBuyArtFlag" )}, // つねきち|事前来訪中に美術品を買った? + {0x3E6, new EventFlagPlayer(0 , 1 , 0998, "FoxPreVisitWantSellFlag" )}, // つねきち|事前来訪で美術品を売り込み中? + {0x3E7, new EventFlagPlayer(0 , 1 , 0999, "SloTalkedToday" )}, // レイジ|今日会話した? + {0x3EB, new EventFlagPlayer(0 , 2 , 1003, "CurrentJuneBrideTheme" )}, // 現在のジューンブライドのテーマ + {0x3EC, new EventFlagPlayer(0 , 2 , 1004, "PreviousJuneBrideTheme" )}, // 前回のジューンブライドのテーマ + {0x3ED, new EventFlagPlayer(0 , 1 , 1005, "IsSelectedJuneBrideCuteThisYear" )}, // ジューンブライド|今年キュートが選ばれたか? + {0x3EE, new EventFlagPlayer(0 , 1 , 1006, "IsSelectedJuneBrideChicThisYear" )}, // ジューンブライド|今年シックが選ばれたか? + {0x3EF, new EventFlagPlayer(0 , 1 , 1007, "IsSelectedJuneBrideGardenThisYear" )}, // ジューンブライド|今年ガーデンが選ばれたか? + {0x3F2, new EventFlagPlayer(0 , 9999, 1010, "LastPlayJuneBrideYear" )}, // ジューンブライド|最後に遊んだジューンブライドの年 + {0x3F3, new EventFlagPlayer(0 , 1 , 1011, "FoxFirstTalkInShipFlag" )}, // つねきち|船内で会話したことある? + {0x3F4, new EventFlagPlayer(0 , 1 , 1012, "FoxInvitedShipFlag" )}, // つねきち|船へ誘導された? + {0x3F5, new EventFlagPlayer(0 , 1 , 1013, "NoticeAboutSmartPhoneCase" )}, // 作業台リメイク|スマホケースの説明ダイアログ見た + {0x3F6, new EventFlagPlayer(0 , 1 , 1014, "AlwJuneBridePleaseShootFlag" )}, // リサ/ジューンブライド|写真も撮ってと言われた + {0x3F7, new EventFlagPlayer(0 , 1 , 1015, "OwlPaintingQuestReminder" )}, // フータ|その日、美術品提出の催促を受けた + {0x3F8, new EventFlagPlayer(0 , 1 , 1016, "OwlShowDiveFishReport" )}, // フータ|海の幸発見の報告を受けた + {0x3F9, new EventFlagPlayer(0 , 1 , 1017, "DocUsePurchaseServiceFalg" )}, // ロドリー|買取サービス使った? + {0x3FA, new EventFlagPlayer(0 , 1 , 1018, "UsePurchaseBOXFalg" )}, // 今日、買取BOX使った?(入電のメッセージ分岐用) + {0x3FB, new EventFlagPlayer(0 , 1 , 1019, "FoxForcedTalkTodayFlag" )}, // つねきち|今日お店で入店時の強制会話した? + {0x3FC, new EventFlagPlayer(0 , 1 , 1020, "FoxForcedTalk2TodayFlag" )}, // つねきち|今日お店で退店時の強制会話した? + {0x3FE, new EventFlagPlayer(0 , 9999, 1022, "EDDIYFlowerWreathOrderYear" )}, // 花を摘んでリースをつくる活動受注年 + {0x3FF, new EventFlagPlayer(0 , 9999, 1023, "EDDIYCorollaOrderYear" )}, // 花を摘んで花冠をつくる活動受注年 + {0x400, new EventFlagPlayer(0 , 1 , 1024, "OwlStampGotRewardExplain" )}, // フータ/国際ミュージアム|スタンプラリー報酬は二重に貰えない説明を受けた + {0x401, new EventFlagPlayer(0 , 1 , 1025, "UseNavigationMayDayTour" )}, // メーデー|緊急脱出サービスを使用中? + {0x402, new EventFlagPlayer(0 , 1 , 1026, "FirstPlayAfterMuseumBuilt2Flag" )}, // 博物館2に拡張したあとのプレイ初日? + {0x404, new EventFlagPlayer(0 , 256 , 1028, "AlwJuneBrideTotalClearCount" )}, // リサ/ジューンブライド|今年クリアした回数(1日何回でも) + {0x405, new EventFlagPlayer(0 , 1 , 1029, "SloTalkedWeedFirst" )}, // レイジ|雑草初回会話したことある? + {0x406, new EventFlagPlayer(0 , 1 , 1030, "SpnJuneBrideGetFenceFrag" )}, // パニエル/ジューンブライド|今年柵もらった? + {0x407, new EventFlagPlayer(0 , 1 , 1031, "SpnJuneBrideNotGetFenceTodayFrag" )}, // パニエル/ジューンブライド|今日柵もらえなかった? + {0x408, new EventFlagPlayer(0 , 1 , 1032, "JuneBrideBGMHasUnlocked" )}, // ジューンブライド|今年BGMが解禁されているか? + {0x40A, new EventFlagPlayer(0 , 1 , 1034, "XctFirstTalk" )}, // みしらぬネコ/メーデー|面識ある? + {0x40B, new EventFlagPlayer(0 , 1 , 1035, "PAnnounceJuneBride" )}, // 島内放送|今年ジューンブライド初回ログイン時の放送を聞いた? + {0x40C, new EventFlagPlayer(0 , 1 , 1036, "StandByPhoneCallJuneBrideSpn" )}, // 電話デモ|今年パニエルからジューンブライド告知された? + {0x40D, new EventFlagPlayer(0 , 1 , 1037, "AlpJuneBrideGetStickFrag" )}, // カイゾー/ジューンブライド|今年ステッキもらった? + {0x40F, new EventFlagPlayer(0 , 10 , 1039, "LastApproachVillagerIndex" )}, // 最後にアプローチ会話をしたNPCの住人番号 + {0x410, new EventFlagPlayer(0 , 1 , 1040, "StandByPhoneCallJuneBride" )}, // 電話デモ|ジューンブライド告知電話するか? + {0x412, new EventFlagPlayer(0 , 1 , 1042, "OwlExplainDiveFishAfterComp" )}, // フータ|コンプ後に海の幸の追加説明を受けた + {0x414, new EventFlagPlayer(0 , 1 , 1044, "AlwJuneBridePartyTalkFlag" )}, // リサ/ジューンブライド|パーティの案内された + {0x415, new EventFlagPlayer(0 , 1 , 1045, "AlwJuneBrideLastDayTalkFlag" )}, // リサ/ジューンブライド|最終日の挨拶された + {0x416, new EventFlagPlayer(0 , 1 , 1046, "VisitFriendMileageGet" )}, // よその島へのおでかけマイルゲット + {0x417, new EventFlagPlayer(0 , 1 , 1047, "AlwJuneBrideBalloonFlag" )}, // リサ/ジューンブライド|バルーン出す状態? + {0x419, new EventFlagPlayer(0 , 1 , 1049, "GstRichItemFlag" )}, // ゆうたろう|高価な品もらった? + {0x41A, new EventFlagPlayer(1 , 1 , 1050, "MyDesignExchangeDiscloseAuthorID" )}, // マイデザイン交換端末|作者IDの公開 + {0x41B, new EventFlagPlayer(1 , 1 , 1051, "TapDiscloseDreamLandID" )}, // ゆめみ|夢番地の公開 + {0x41C, new EventFlagPlayer(0 , 1 , 1052, "PlayerPocketUIEnableInCommuneIsland" )}, // プレイヤー|コミューン島でのポケットUI解禁 + {0x41D, new EventFlagPlayer(0 , 5 , 1053, "GotoMysteryTour" )}, // モーリー|ミステリーツアー島に行った回数 + {0x41E, new EventFlagPlayer(0 , 1 , 1054, "EnableGotoRareMysteryTour" )}, // モーリー|ミステリーツアーのレア島に行っていいか? + {0x41F, new EventFlagPlayer(0 , 1 , 1055, "VisitMysteryTourID20" )}, // ID: 20のミステリーツアー島にその日行ったことがある + {0x420, new EventFlagPlayer(0 , 1 , 1056, "PAnnounceStampRally" )}, // 島内放送|今年国際ミュージアム初回ログイン時の放送を聞いた? + {0x421, new EventFlagPlayer(0 , 1 , 1057, "FoxPreVisitBuyArtMaxFlag" )}, // つねきち|事前来訪中に2個美術品を買った? + {0x424, new EventFlagPlayer(0 , 9999, 1060, "EDDIYFlowerWreathClearYear" )}, // 花を摘んでリースをつくる活動達成年 + {0x425, new EventFlagPlayer(0 , 9999, 1061, "EDDIYCorollaClearYear" )}, // 花を摘んで花冠をつくる活動達成年 + {0x426, new EventFlagPlayer(0 , 1 , 1062, "GulBQuestStartFlag" )}, // 海賊ジョニー|クエスト開始フラグ + {0x427, new EventFlagPlayer(0 , 1 , 1063, "GulBQuestFinishFlag" )}, // 海賊ジョニー|クエスト完了フラグ + {0x428, new EventFlagPlayer(0 , 1 , 1064, "GulBTalkBeforeFlag" )}, // 海賊ジョニー|今までに会話したことある? + {0x429, new EventFlagPlayer(0 , 1 , 1065, "GulBAnotherPlayerClearFlag" )}, // 海賊ジョニー|クエスト発生後に他のプレイヤーがクリアした? + {0x42A, new EventFlagPlayer(0 , 16 , 1066, "GulBPartsCount" )}, // 海賊ジョニー|渡したパーツの個数 + {0x42B, new EventFlagPlayer(0 , 1 , 1067, "GulBSitUpBeforeFlag" )}, // 海賊ジョニー|今までに起こしたことある? + {0x42C, new EventFlagPlayer(0 , 3 , 1068, "InducedNpcNum" )}, // お出かけ先で勧誘したNPCの数 + {0x42D, new EventFlagPlayer(0 , 1 , 1069, "TalkFreeMultiDayEventTodayFlag" )}, // 今日、期間型イベント用のFreeFを聞いたか? + {0x42E, new EventFlagPlayer(0 , -1 , 1070, "EarthDayBonus" )}, // アースデーの5倍クエストをクリアした日フラグ + {0x42F, new EventFlagPlayer(0 , 1 , 1071, "TalkVillagerClearToday" )}, // 日課あいさつ活動を今日クリア済み + {0x430, new EventFlagPlayer(0 , 1 , 1072, "EarthDayFirstQuestSystem" )}, // アースデーの5倍クエストをまだ出していない(システム用) + {0x431, new EventFlagPlayer(0 , 1 , 1073, "EarthDayFirstQuestTalk" )}, // アースデーの5倍クエストをまだ出していない(会話用) + {0x432, new EventFlagPlayer(0 , 1 , 1074, "SeoExchangeItemToday" )}, // ラコスケ|ホタテをその日渡した? + {0x433, new EventFlagPlayer(0 , 1 , 1075, "MailSendFlag_EarthDayNotice" )}, // 手紙|アースデー導入の手紙を送った? + {0x434, new EventFlagPlayer(0 , 1 , 1076, "PAnnounceMayDayTour" )}, // 島内放送|メーデー初回ログイン時の放送を聞いた? + {0x435, new EventFlagPlayer(0 , 1 , 1077, "DreamFirstExplain" )}, // ゆめみ|DLの初回説明読んだ? + {0x436, new EventFlagPlayer(0 , 1 , 1078, "TapDreamFirstTalk" )}, // ゆめみ|初回会話済ませた? + {0x437, new EventFlagPlayer(0 , 50 , 1079, "GulBHelpCount" )}, // 海賊ジョニー|助けた回数 + {0x438, new EventFlagPlayer(0 , 1 , 1080, "GulBGetQuestItem" )}, // 海賊ジョニー|クエストアイテムを入手した個数 + {0x439, new EventFlagPlayer(0 , 1 , 1081, "HasGottenMarinesuit" )}, // マリンスーツを入手したことがあるか? + {0x43A, new EventFlagPlayer(0 , 1 , 1082, "SeoFirstmeetingFlag" )}, // ラコスケにはじめて会った + {0x43D, new EventFlagPlayer(0 , 1 , 1085, "TalkRumorOActionTodayAnyone" )}, // 今日RumorOP_Action(同じ島の住人P)を聞いたか? + {0x43E, new EventFlagPlayer(0 , 1 , 1086, "SzaFireworksTalkTodayA" )}, // 花火大会しずえ|今日会話した?(5:00-19:00) + {0x43F, new EventFlagPlayer(0 , 1 , 1087, "SzaFireworksTalkTodayB" )}, // 花火大会しずえ|今日会話した?(19:00-24:00) + {0x440, new EventFlagPlayer(0 , 1 , 1088, "SzaFireworksRewardToday" )}, // 花火大会しずえ|今日「光るアクセサリー」もらった? + {0x443, new EventFlagPlayer(0 , 1 , 1091, "FireworksApproachEnd" )}, // 花火大会|専用アプローチ会話済 + {0x444, new EventFlagPlayer(0 , 11 , 1092, "FireworksApproachNpcIndex" )}, // 花火大会|専用アプローチ会話予定NPC住人番号 + {0x445, new EventFlagPlayer(0 , 1 , 1093, "FireworksApproachGetFirework" )}, // 花火大会|花火をもらった + {0x446, new EventFlagPlayer(0 , 1 , 1094, "TapDreamTalkToday" )}, // ゆめみ|今日ゆめみ室内を訪れた + {0x447, new EventFlagPlayer(0 , 1 , 1095, "TapULFirstExplain" )}, // ゆめみ|ULの初回説明読んだ? + {0x449, new EventFlagPlayer(0 , 1 , 1097, "TapDreamUploadToday" )}, // ゆめみ|今日夢をアップロードした + {0x44A, new EventFlagPlayer(0 , 1 , 1098, "TapDreamDeleteToday" )}, // ゆめみ|今日夢を削除した + {0x44B, new EventFlagPlayer(0 , 1 , 1099, "PknTalkBeforeFlag" )}, // パンプキング/ハロウィン|面識ある? + {0x44C, new EventFlagPlayer(0 , 1 , 1100, "PknTalkTodayFlag" )}, // パンプキング/ハロウィン|今日会話した? + {0x44D, new EventFlagPlayer(0 , 64 , 1101, "PknGiveCandyCount" )}, // パンプキング/ハロウィン|アメをあげた回数 + {0x44E, new EventFlagPlayer(0 , 1 , 1102, "PknGetCarriageFlag" )}, // パンプキング/ハロウィン|かぼちゃのばしゃもらった? + {0x44F, new EventFlagPlayer(0 , 1 , 1103, "PknGetBromideFlag" )}, // パンプキング/ハロウィン|ブロマイドもらった? + {0x450, new EventFlagPlayer(0 , 1 , 1104, "PknGetCarriageRecipeFlag" )}, // パンプキング/ハロウィン|かぼちゃのばしゃのレシピもらった? + {0x451, new EventFlagPlayer(0 , 1 , 1105, "OwlPaintingDiveFish" )}, // フータのうみのさちチュートリアル聞いた? + {0x452, new EventFlagPlayer(0 , 1 , 1106, "PAnnounceFireworksSza1" )}, // 島内放送|花火大会しずえ1回目の放送を聞いた? + {0x454, new EventFlagPlayer(0 , 1 , 1108, "RcmBoughtCandyTodayFlag" )}, // まめきち/ハロウィン|今日アメ買った? + {0x456, new EventFlagPlayer(0 , 1 , 1110, "WHEREAREN_Unlock_AccentWall" )}, // OneRoom|ライセンス(アクセントウォール)解禁 + {0x457, new EventFlagPlayer(0 , 1 , 1111, "FoxFirstTalkFireworksFlag" )}, // つねきち|花火大会で会話したことある? + {0x458, new EventFlagPlayer(0 , 1 , 1112, "CharacterCreationFlag" )}, // 夏パッチ以降でキャラメイク完了したか? + {0x459, new EventFlagPlayer(0 , 1 , 1113, "PublicAnnouncement_DiveFish" )}, // 泳ぎ解禁の島内放送聞いたか?手紙だす? + {0x45A, new EventFlagPlayer(0 , 1 , 1114, "DiveFish_GetLetter" )}, // 初回泳ぎ島内放送聞けず、手紙を受け取った + {0x45B, new EventFlagPlayer(0 , 1 , 1115, "DiveFishPublic_1day" )}, // 初回泳ぎ解禁島内放送を聞いた? + {0x45C, new EventFlagPlayer(0 , 1 , 1116, "DiveFishPublic_2day" )}, // 2日目の泳ぎ解禁島内放送を聞いた? + {0x45D, new EventFlagPlayer(0 , 1 , 1117, "RcmTalkAboutMarinesuitFlag" )}, // まめきち|マリンスーツの説明を聞いた + {0x45E, new EventFlagPlayer(0 , 1 , 1118, "Encylopedia_DiveFishMes" )}, // 夏パッチ後、図鑑開いてうみのさち追加案内を見た + {0x45F, new EventFlagPlayer(0 , 1 , 1119, "MyDesignExchangeExp_v1_4" )}, // マイデザイン交換| 夏パッチ2で追加された機能説明 + {0x460, new EventFlagPlayer(0 , 1 , 1120, "MyDesignExchangeExp_NormalUsage" )}, // マイデザイン交換| ノーマル用途追加の説明 + {0x461, new EventFlagPlayer(0 , 1 , 1121, "PlayerHouseBuiltToday" )}, // 今日自宅が完成した(今日テント→家になった) + {0x462, new EventFlagPlayer(0 , 1 , 1122, "ReceiveTapBedLetter" )}, // ゆめみからベッド付き手紙を受け取った + {0x463, new EventFlagPlayer(0 , 1 , 1123, "FoxTalkOnlyStandShopFlag" )}, // つねきち|屋台でしか会話したことがない? + {0x464, new EventFlagPlayer(0 , 1 , 1124, "NpcGetCandyTodayFlag" )}, // 一般NPC/ハロウィン|今日アメもらった? + {0x465, new EventFlagPlayer(0 , 1 , 1125, "DiveFish_FirstDonation" )}, // 海の幸を初寄贈した + {0x466, new EventFlagPlayer(0 , 1 , 1126, "TapSendThankyouLetter" )}, // ゆめみ|翌日、夢をアップしたお礼の手紙が届くか? + {0x467, new EventFlagPlayer(0 , 9999, 1127, "PickUpDIYGoldCount" )}, // ver1.4.0以降、拾われたことがない金鉱石を拾った回数 + {0x468, new EventFlagPlayer(0 , 1 , 1128, "FireworkCannotGetNnpcItemFlag" )}, // 花火大会|一般NPCから受け取り損ねたアイテムがある? + {0x46B, new EventFlagPlayer(0 , 7 , 1131, "SurpriseVisitCount" )}, // 突撃訪問発生までのカウント + {0x46C, new EventFlagPlayer(0 , 1 , 1132, "SurpriseVisitDone" )}, // 突撃訪問された事があるか + {0x46D, new EventFlagPlayer(0 , 1 , 1133, "GetHalloweenRag" )}, // 一般NPC/ハロウィン|ラグもらった? + {0x46E, new EventFlagPlayer(0 , 1 , 1134, "GetHalloweenWallPaper" )}, // 一般NPC/ハロウィン|かべがみもらった? + {0x46F, new EventFlagPlayer(0 , 1 , 1135, "GetHalloweenFloor" )}, // 一般NPC/ハロウィン|ゆかもらった? + {0x470, new EventFlagPlayer(0 , 1 , 1136, "GetHalloweenStickRecipe" )}, // パンプキング/ハロウィン|ステッキ(レシピ)もらった? + {0x471, new EventFlagPlayer(0 , 1 , 1137, "GetHalloweenGarland" )}, // 一般NPC/ハロウィン|ガーランドもらった? + {0x473, new EventFlagPlayer(0 , 1 , 1139, "GetHalloweenTableSetting" )}, // 一般NPC/ハロウィン|テーブルセッティングもらった? + {0x475, new EventFlagPlayer(0 , 1 , 1141, "GetHalloweenBag" )}, // 今年ハロウィンのはねをもらった + {0x476, new EventFlagPlayer(0 , 1 , 1142, "AddBodyColor" )}, // タヌポート|追加ボディカラー解禁 + {0x477, new EventFlagPlayer(0 , 1 , 1143, "AddEyeColor" )}, // タヌポート|追加アイカラー解禁 + {0x478, new EventFlagPlayer(0 , 1 , 1144, "AddCheekColor" )}, // タヌポート|追加チークカラー解禁 + {0x479, new EventFlagPlayer(0 , 1 , 1145, "SaveDataRestoringSettingNotice" )}, // セーブデータ復元|設定異常検知 + {0x47A, new EventFlagPlayer(0 , 1 , 1146, "TapTalkAboutMydesignShowcase" )}, // ゆめみ|マイデザインショーケースについて説明聞いた + {0x47B, new EventFlagPlayer(0 , 1 , 1147, "NpcHalloweenTrickFlag" )}, // ハロウィン|今日イタズラされた? + {0x47C, new EventFlagPlayer(0 , 1 , 1148, "TapFirstDreamIn" )}, // ゆめみ|夢の中に入ったことがある? + {0x47D, new EventFlagPlayer(0 , 1 , 1149, "TapFirstCheckMydesingShowcase" )}, // ゆめみ|夢の中のマイデザインショーケース端末にアクセスしたことがある? + {0x47F, new EventFlagPlayer(0 , 1 , 1151, "SpecialMakeChanged" )}, // プレイヤが特殊メイクに変更した + {0x480, new EventFlagPlayer(0 , 1 , 1152, "TalkMakeTodayAnyone" )}, // 今日誰かにメイク会話を聞いたか + {0x481, new EventFlagPlayer(0 , 1 , 1153, "RcmExplainCandyFlag" )}, // まめきち/ハロウィン|今年アメの説明聞いた? + {0x482, new EventFlagPlayer(0 , 1 , 1154, "RcmExplainPumpkinFlag" )}, // まめきち/ハロウィン|今日かぼちゃの苗の説明聞いた? + {0x483, new EventFlagPlayer(0 , 1 , 1155, "SzaFireworksSubmitMyDesignToday" )}, // 花火大会しずえ|今日マイデザイン花火を提出した? + {0x484, new EventFlagPlayer(0 , 1 , 1156, "PAnnounceHalloween" )}, // 島内放送|今年ハロウィン期間初回ログイン時の放送を聞いた? + {0x486, new EventFlagPlayer(0 , 1 , 1158, "ExplainPumpkinColorFlag" )}, // ハロウィン|今年かぼちゃの苗の説明聞いた? + {0x487, new EventFlagPlayer(0 , 1 , 1159, "SloExplainPumpkinSeedingFlag" )}, // レイジ/ハロウィン|今日かぼちゃの苗の特別価格の説明きいた? + {0x488, new EventFlagPlayer(0 , 1 , 1160, "CalcPastDays" )}, // 経過日数の計算をした + {0x489, new EventFlagPlayer(0 , 1 , 1161, "PlayerProducedByPlayerMoving" )}, // プレイヤーだけ引越し|プレイヤーだけ引越しによって作られたプレイヤーか? + {0x48A, new EventFlagPlayer(0 , 3000, 1162, "FireworksLastApproachYear" )}, // 花火大会|最後にアプローチ挙動をした年 + {0x48B, new EventFlagPlayer(0 , 1 , 1163, "RcoTalkAboutMovingBelongings" )}, // プレイヤーだけ引越し|たぬきちと所持品について話した + {0x48C, new EventFlagPlayer(0 , 1 , 1164, "RcmRctTalkAboutMovingBelongings" )}, // プレイヤーだけ引越し|まめきち、つぶきちと所持品について話した + {0x48D, new EventFlagPlayer(0 , 1 , 1165, "SloExplainAddVegetable" )}, // レイジ/ハロウィン|今日かぼちゃの苗販売の説明聞いた? + {0x48E, new EventFlagPlayer(0 , 1 , 1166, "PocketItemSendRecycleBoxByMoving" )}, // プレイヤーだけ引越し|ポケットの所持品がリサイクルBOXに送られた + {0x48F, new EventFlagPlayer(0 , 1 , 1167, "TentItemSendRecycleBoxByMoving" )}, // プレイヤーだけ引越し|テントの配置物がリサイクルBOXに送られた + {0x492, new EventFlagPlayer(0 , 1 , 1170, "PknTalkLastNoCandyFlag" )}, // パンプキング/ハロウィン|最後の会話時アメ持ってなかった? + {0x493, new EventFlagPlayer(0 , 1 , 1171, "AddHowtoBookMydesignPro2" )}, // マイデザインPROエディタ2解禁条件を満たしたか? + {0x494, new EventFlagPlayer(0 , 1 , 1172, "UnlockMydesignPro2" )}, // マイデザインPROエディタ2習得済みか? + {0x495, new EventFlagPlayer(0 , 1 , 1173, "ExplainMydesignPro2" )}, // マイデザインPROエディタ2習得後の説明を聞いたか? + {0x496, new EventFlagPlayer(0 , 1 , 1174, "RcoMachineExplainMydesignPro2" )}, // タヌポートでマイデザインPROエディタ2販売開始の案内聞いたか? + {0x499, new EventFlagPlayer(0 , 1 , 1177, "NotBuilt2PMyHomeAfterMoving" )}, // プレイヤーだけ引越し|(2P限定)引越し後、まだ家の場所を決めてない + {0x49A, new EventFlagPlayer(0 , 4 , 1178, "HarvestProgress" )}, // ハーベスト|完成した料理の数(プレイヤー単位) + {0x49B, new EventFlagPlayer(0 , 64 , 1179, "PknGiveLollipopCount" )}, // パンプキング/ハロウィン|ロリポップをあげた回数 + {0x49C, new EventFlagPlayer(0 , 1 , 1180, "TapSelWhereAreHere" )}, // ゆめみ|ここはどこ?を1度選んだらON + {0x49D, new EventFlagPlayer(0 , 1 , 1181, "PknTalkLastNotGetFlag" )}, // パンプキング/ハロウィン|最後の会話でアイテムもらえなかった? + {0x49E, new EventFlagPlayer(0 , 1 , 1182, "PknLastGiveCandyFlag" )}, // パンプキング/ハロウィン|前回渡したのはアメ? + {0x49F, new EventFlagPlayer(0 , 1 , 1183, "PknCompItemCandyFlag" )}, // パンプキング/ハロウィン|アメ報酬コンプした? + {0x4A0, new EventFlagPlayer(0 , 1 , 1184, "PknCompItemLollipopFlag" )}, // パンプキング/ハロウィン|ロリポップ報酬コンプした? + {0x4A1, new EventFlagPlayer(0 , 1 , 1185, "PknPumpkingLookChatFlag" )}, // パンプキング/ハロウィン|パンプキング装備の雑談した? + {0x4A2, new EventFlagPlayer(0 , 1 , 1186, "Mobile1stBoot_Camera_UnlockKeyGuideOff" )}, // スマホアプリ初起動|カメラアプリにキーガイドOFF追加 + {0x4A3, new EventFlagPlayer(0 , 1 , 1187, "GetHalloweenRobe" )}, // パンプキング/ハロウィン|ローブをもらった + {0x4A4, new EventFlagPlayer(0 , 1 , 1188, "GetHalloweenMask" )}, // パンプキング/ハロウィン|かぶりものをもらった + {0x4A5, new EventFlagPlayer(0 , 1 , 1189, "PknSendLetterFlag" )}, // パンプキング/ハロウィン|今年手紙送った? + {0x4A6, new EventFlagPlayer(0 , 1 , 1190, "PlayerMovingwithNoBelongings" )}, // プレイヤーだけ引越し|所持品(手荷物)なしで引越してきた + {0x4A7, new EventFlagPlayer(0 , 8 , 1191, "NpcGiveCandyCount" )}, // 一般NPC/ハロウィン|アメのお礼もらった回数 + {0x4A8, new EventFlagPlayer(0 , 1 , 1192, "GetHalloweenGarlandRecipe" )}, // 一般NPC/ハロウィン|ガーランドのレシピをもらった + {0x4A9, new EventFlagPlayer(0 , 1 , 1193, "GetHalloweenTableSettingRecipe" )}, // 一般NPC/ハロウィン|テーブルセッティングのレシピをもらった + {0x4AA, new EventFlagPlayer(0 , 1 , 1194, "NpcTalkLastNotGetFlag" )}, // 一般NPC/ハロウィン|イベント中、誰かと話した? + {0x4AB, new EventFlagPlayer(0 , 1 , 1195, "EnabledEmoticonIrregular" )}, // 漫符UI解禁済みかつ漫符入手会話が未発生 + {0x4AC, new EventFlagPlayer(0 , 1 , 1196, "CanGetMileTicketTrialForMoving" )}, // プレイヤーだけ引越し|引越しで来たプレイヤーに旅行券渡してよい? + {0x4AD, new EventFlagPlayer(0 , 1 , 1197, "PlayerMovingOrderHouseBuilt" )}, // たぬきち|家建築、増築申し込み当日にPだけ引越しした? + {0x4AE, new EventFlagPlayer(0 , 1 , 1198, "PlayerMovingOrderChangeHouseDesign" )}, // たぬきち|家外観変更申し込み当日にPだけ引越しした? + {0x4AF, new EventFlagPlayer(0 , 1 , 1199, "PlayerMovingOrderHouseMoveInIsland" )}, // たぬきち|自宅移設申し込み当日にPだけ引越しした? + {0x4B0, new EventFlagPlayer(0 , 1 , 1200, "PlayerMovingAfterHouseRemodel" )}, // たぬきち|家増築後説明の発生予約中にPだけ引越しした? + {0x4B1, new EventFlagPlayer(0 , 1 , 1201, "PlayerMovingAfterLoanFinish" )}, // たぬきち|ローン完済会話の発生予約中にPだけ引越しした? + {0x4B2, new EventFlagPlayer(0 , 1 , 1202, "TapUnlockFavorite" )}, // ゆめみ|「前に見た夢を見る」解禁 + {0x4B3, new EventFlagPlayer(0 , 9999, 1203, "LastPlayHalloweenYear" )}, // ハロウィン|最後に遊んだハロウィンの年 + {0x4B5, new EventFlagPlayer(0 , 1 , 1205, "PlayerMovingDefaultHouseHasBasement" )}, // プレイヤーだけ引越し|引越し時点で家に地下室がある + {0x4B6, new EventFlagPlayer(0 , 1 , 1206, "PlayerMovingEnable" )}, // プレイヤーだけ引越し|プレイヤーだけ引越しが可能か?(自宅完成済みか?) + {0x4B7, new EventFlagPlayer(0 , 1 , 1207, "RemakeWithRcoOfficeBeforeWS" )}, // プレイヤーだけ引越し|リメイクWS前に案内所でリメイクした + {0x4B8, new EventFlagPlayer(0 , 1 , 1208, "RemakeWithRcoTentBeforeWS" )}, // プレイヤーだけ引越し|リメイクWS前にたぬきちテントでリメイクした + {0x4B9, new EventFlagPlayer(0 , 1 , 1209, "IslandCreaterUnlockMoving" )}, // プレイヤーだけ引越し|引越しのタイミングで島クリエイター解禁した? + {0x4BA, new EventFlagPlayer(0 , 1 , 1210, "AnnounceHalloween" )}, // ハロウィンを島内放送で告知した(2回目放送用) + {0x4BB, new EventFlagPlayer(0 , 1 , 1211, "AnnounceHarvest" )}, // ハーベスト|当日島内放送で告知した(2回目放送用) + {0x4BE, new EventFlagPlayer(0 , 1 , 1214, "SloGetVegetableBasketDIY" )}, // レイジ|野菜の籠レシピもらった? + {0x4BF, new EventFlagPlayer(0 , 1 , 1215, "MilageSendLetterFlag" )}, // タヌポート/ハロウィン|新規肌・目の色の追加手紙送った? + {0x4C0, new EventFlagPlayer(0 , 1 , 1216, "NpcHalloweenGetMirrorFlag" )}, // ハロウィン|今日NPCからミラーもらった? + {0x4C1, new EventFlagPlayer(0 , 1 , 1217, "NpcHalloweenCandyHelpFlag" )}, // ハロウィン|今日NPCから救済用アメもらった? + {0x4C2, new EventFlagPlayer(0 , 1 , 1218, "PlayerMovingWithEmoticonUI" )}, // プレイヤーだけ引越し|引越しを漫符解禁状態でやったか? + {0x4C3, new EventFlagPlayer(0 , 1 , 1219, "AddHairStyle4" )}, // 『ホットなヘアアレンジ』解禁 + {0x4C7, new EventFlagPlayer(0 , 8 , 1223, "PknGetItem" )}, // パンプキング/ハロウィン|報酬アイテムは? + {0x4C9, new EventFlagPlayer(0 , 1 , 1225, "XctGetRewardThisIsland" )}, // メーデー|みしらぬネコから「今住んでる島で」報酬もらった? + {0x4CA, new EventFlagPlayer(0 , 1 , 1226, "HarvestHQDish1P" )}, // ハーベスト|Pが料理1クラムチャウダーの隠し食材納めた? + {0x4CB, new EventFlagPlayer(0 , 1 , 1227, "HarvestHQDish2P" )}, // ハーベスト|Pが料理2パンプキンパイの隠し食材納めた? + {0x4CC, new EventFlagPlayer(0 , 1 , 1228, "HarvestHQDish3P" )}, // ハーベスト|Pが料理3グラタンの隠し食材納めた? + {0x4CD, new EventFlagPlayer(0 , 1 , 1229, "HarvestHQDish4P" )}, // ハーベスト|Pが料理4サカナのムニエルの隠し食材納めた? + {0x4CE, new EventFlagPlayer(0 , 1 , 1230, "TukTalkFirst" )}, // ハーベスト|フランクリンとの面識あるか? + {0x4CF, new EventFlagPlayer(0 , 4 , 1231, "HarvestTalkAboutNextDishProgress" )}, // ハーベスト|次の料理の話を聞いたか? + {0x4D0, new EventFlagPlayer(0 , 1 , 1232, "TapUnlockLeaveTap" )}, // ゆめみ|「おまかせ」解禁 + {0x4D1, new EventFlagPlayer(0 , 8 , 1233, "HarvestKeepReward" )}, // ハーベスト|渡す報酬の種類情報 + {0x4D2, new EventFlagPlayer(0 , 1 , 1234, "RewindDays" )}, // 日付を巻き戻した + {0x4D3, new EventFlagPlayer(0 , 1 , 1235, "TukTalkBeforeEvent" )}, // ハーベスト|フランクリンとイベント開始前に会話した + {0x4D4, new EventFlagPlayer(0 , 1 , 1236, "TukTalkAfterEvent" )}, // ハーベスト|フランクリンとイベント終了後に会話した + {0x4D5, new EventFlagPlayer(0 , 1 , 1237, "AnnounceBeforeHarvest" )}, // ハーベスト|5日前~2日前に島内放送で告知した + {0x4D6, new EventFlagPlayer(0 , 1 , 1238, "PasswordIsOld" )}, // パスワードが古いのでPOPID使用不可 + {0x4D7, new EventFlagPlayer(0 , 3 , 1239, "FishExchangeLoseCount" )}, // ハーベスト|物々交換でハズレをもらった回数 + {0x4D8, new EventFlagPlayer(0 , 1 , 1240, "ReiTalkFirst" )}, // クリスマス|ジングルとの面識あるか? + {0x4D9, new EventFlagPlayer(0 , 1 , 1241, "ReiGetReward1" )}, // クリスマス|ジングルからくつしたのかざり受け取った? + {0x4DA, new EventFlagPlayer(0 , 1 , 1242, "ReiGetReward2" )}, // クリスマス|ジングルからプレゼントのやまレシピ受け取った? + {0x4DB, new EventFlagPlayer(0 , 1 , 1243, "ReiGetReward3" )}, // クリスマス|ジングルからクリスマスのソリ受け取った? + {0x4DC, new EventFlagPlayer(0 , 1 , 1244, "ReiStartQuest1" )}, // クリスマス|ジングルからラッピングDIYクエスト受注した? + {0x4DD, new EventFlagPlayer(0 , 1 , 1245, "ReiStartQuest2" )}, // クリスマス|ジングルからプレゼント配布クエスト受注した? + {0x4DF, new EventFlagPlayer(0 , 1 , 1247, "ReiFinishQuest1" )}, // クリスマス|ジングルのDIYクエスト完了した? + {0x4E0, new EventFlagPlayer(0 , 1 , 1248, "AnnouncePreChristmas" )}, // クリスマス|事前期間に島内放送で告知した? + {0x4E2, new EventFlagPlayer(0 , 1 , 1250, "WHEREAREN_NoticeAboutDustCloth" )}, // OneRoom|まごころ雑巾の初回ダイアログを見た? + {0x4E3, new EventFlagPlayer(0 , 10 , 1251, "SantaMissionNpcIndex1" )}, // クリスマス|サンタミッションでお返しをくれるNPC1 + {0x4E4, new EventFlagPlayer(0 , 10 , 1252, "SantaMissionNpcIndex2" )}, // クリスマス|サンタミッションでお返しをくれるNPC2 + {0x4E5, new EventFlagPlayer(0 , 10 , 1253, "SantaMissionNpcIndex3" )}, // クリスマス|サンタミッションでお返しをくれるNPC3 + {0x4E6, new EventFlagPlayer(0 , 1 , 1254, "ReceiveLeaveTapLetter" )}, // ゆめみ|おまかせ解禁の手紙を受け取った + {0x4E7, new EventFlagPlayer(0 , 1 , 1255, "RcmExplainToy" )}, // クリスマス|おもちゃ家具陳列の案内を受けた? + {0x4E8, new EventFlagPlayer(0 , 1 , 1256, "PckTalkTodayFlag" )}, // カーニバル/べルリーナ|今日すでに会話した? + {0x4E9, new EventFlagPlayer(0 , 9999, 1257, "ChristmasWreathGetYear" )}, // クリスマス|クリスマスリースをNPCから貰った年 + {0x4EA, new EventFlagPlayer(0 , 9 , 1258, "TukSecretRewardType" )}, // ハーベスト|フランクリンの隠し食材報酬抽選結果 + {0x4EC, new EventFlagPlayer(0 , 1 , 1260, "WHEREAREN_Unlock_ResortPlannerApp" )}, // OneRoom|リゾートプランナーアプリアンロック + {0x4ED, new EventFlagPlayer(0 , 1 , 1261, "WHEREAREN_Unlock_ResortStudyApp" )}, // OneRoom|リゾートスタディアプリアンロック + {0x4EE, new EventFlagPlayer(0 , 1 , 1262, "TapUpdatedDreamFirstTalk" )}, // ゆめみ|初回会話を1.6.0以降に行った? + {0x4EF, new EventFlagPlayer(0 , 1 , 1263, "SzaChristmasOrnament" )}, // クリスマス|しずえからオーナメント素材もらった? + {0x4F1, new EventFlagPlayer(0 , 1 , 1265, "CheckHarvestFtrInStore" )}, // ハーベスト|ハーベスト家具をお店でチェックしたことがあるか? + {0x4F2, new EventFlagPlayer(0 , 9999, 1266, "ChristmasPresentYear" )}, // クリスマス|自宅プレゼントをもらった年 + {0x4F3, new EventFlagPlayer(0 , 2 , 1267, "InputApproachBanCount" )}, // アプローチ|入力系アプローチ禁止カウント + {0x4F4, new EventFlagPlayer(0 , 1 , 1268, "PckLookChatFlag" )}, // カーニバル/べルリーナ|カーニバル装備の雑談した? + {0x4F5, new EventFlagPlayer(0 , 1 , 1269, "TukCancel1stRequest" )}, // ハーベスト|フランクリン1品目で「大変ですね」を選択した + {0x4F6, new EventFlagPlayer(0 , 1 , 1270, "ChristmasWrappingGiftFlag" )}, // クリスマス|プレゼント交換初回でラッピングもらった? + {0x4F8, new EventFlagPlayer(0 , 1 , 1272, "HarvestRefuseGiveHQFood1" )}, // ハーベスト|料理1の隠し食材を渡すのを拒んだ + {0x4F9, new EventFlagPlayer(0 , 1 , 1273, "HarvestRefuseGiveHQFood2" )}, // ハーベスト|料理2の隠し食材を渡すのを拒んだ + {0x4FA, new EventFlagPlayer(0 , 1 , 1274, "HarvestRefuseGiveHQFood3" )}, // ハーベスト|料理3の隠し食材を渡すのを拒んだ + {0x4FB, new EventFlagPlayer(0 , 1 , 1275, "HarvestRefuseGiveHQFood4" )}, // ハーベスト|料理4の隠し食材を渡すのを拒んだ + {0x4FC, new EventFlagPlayer(0 , 2 , 1276, "HarvestGetHint1" )}, // ハーベスト|料理1の隠し食材ヒント聞いた + {0x4FD, new EventFlagPlayer(0 , 2 , 1277, "HarvestGetHint2" )}, // ハーベスト|料理2の隠し食材ヒント聞いた + {0x4FE, new EventFlagPlayer(0 , 2 , 1278, "HarvestGetHint3" )}, // ハーベスト|料理3の隠し食材ヒント聞いた + {0x4FF, new EventFlagPlayer(0 , 2 , 1279, "HarvestGetHint4" )}, // ハーベスト|料理4の隠し食材ヒント聞いた + {0x500, new EventFlagPlayer(0 , 1 , 1280, "ChristmasWrappingPresentFlag" )}, // クリスマス|ラッピングを誰かくれようとしたか? + {0x501, new EventFlagPlayer(0 , 1 , 1281, "PckRecipeFlag" )}, // カーニバル/べルリーナ|にじいろのはねのレシピもらった? + {0x502, new EventFlagPlayer(0 , 1 , 1282, "RcoStorageExpansionReserved" )}, // たぬきち|収納の拡張を予約している + {0x503, new EventFlagPlayer(0 , 1 , 1283, "RcoStorageExpansionLevel" )}, // たぬきち|収納の拡張段階('20冬パッチ 1段階のみ) + {0x504, new EventFlagPlayer(0 , 1 , 1284, "PlayerMovingReservedStorageExpand" )}, // たぬきち|収納の拡張申し込み当日にPだけ引越しした? + {0x505, new EventFlagPlayer(0 , 1 , 1285, "MailSend_NoticeStorageExpansion" )}, // たぬきち|収納の拡張のお知らせ手紙の判定処理したか? + {0x506, new EventFlagPlayer(0 , 1 , 1286, "RcoStandbyNoticeStorageExpansion" )}, // たぬきち|収納の拡張について強制会話するか? + {0x507, new EventFlagPlayer(0 , 1 , 1287, "ChristmasWreathNoGetFlag" )}, // クリスマス|このNPCからリース受け取り損ねた + {0x508, new EventFlagPlayer(0 , 3 , 1288, "PckGetItem" )}, // カーニバル/べルリーナ|報酬アイテムは? + {0x509, new EventFlagPlayer(0 , 1 , 1289, "WHEREAREN_Unlock_CoordinateNpcHouse" )}, // OneRoom|ライセンス(NPC家コーディネート)解禁 + {0x50A, new EventFlagPlayer(0 , 1 , 1290, "GetCarnivalLight" )}, // カーニバル/べルリーナ|カーニバルなライトもらった? + {0x50B, new EventFlagPlayer(0 , 1 , 1291, "GetCarnivalFoodStand" )}, // カーニバル/べルリーナ|カーニバルな屋台もらった? + {0x50C, new EventFlagPlayer(0 , 1 , 1292, "GetCarnivalstage" )}, // カーニバル/べルリーナ|カーニバルなステージもらった? + {0x50D, new EventFlagPlayer(0 , 1 , 1293, "GetCarnivalConfettiMachine" )}, // カーニバル/べルリーナ|カーニバルなかみふぶきマシンもらった? + {0x50E, new EventFlagPlayer(0 , 1 , 1294, "GetCarnivalPercussion" )}, // カーニバル/べルリーナ|カーニバルなパーカッションもらった? + {0x50F, new EventFlagPlayer(0 , 1 , 1295, "GetCarnivalBalloonLight" )}, // カーニバル/べルリーナ|カーニバルバルーンライトもらった? + {0x510, new EventFlagPlayer(0 , 1 , 1296, "GetCarnivalUmbrellas" )}, // カーニバル/べルリーナ|カーニバルなパラソルもらった? + {0x511, new EventFlagPlayer(0 , 1 , 1297, "GetCarnivalFlag" )}, // カーニバル/べルリーナ|カーニバルなフラッグもらった? + {0x512, new EventFlagPlayer(0 , 1 , 1298, "GetCarnivalGarland" )}, // カーニバル/べルリーナ|カーニバルなガーランドもらった? + {0x513, new EventFlagPlayer(0 , 1 , 1299, "GetCarnivalFloat" )}, // カーニバル/べルリーナ|カーニバルなフロートもらった? + {0x515, new EventFlagPlayer(0 , 10 , 1301, "PckGiveFurnitureCount" )}, // カーニバル/べルリーナ|家具をもらった回数 + {0x516, new EventFlagPlayer(0 , 1 , 1302, "WHEREAREN_Unlock_ResortPlannerAppNetwork" )}, // OneRoom|リゾートプランナーアプリのツクッターアンロック + {0x517, new EventFlagPlayer(0 , 1 , 1303, "WHEREAREN_Unlock_ResortPlannerAppRevisit" )}, // OneRoom|リゾートプランナーアプリの再訪アンロック + {0x518, new EventFlagPlayer(0 , 1 , 1304, "SloExplainPumpkinColorFlag" )}, // レイジ|かぼちゃの苗説明聞いたことある? + {0x519, new EventFlagPlayer(0 , 1 , 1305, "SloExplainAddPumpkinFlag" )}, // レイジ|かぼちゃの苗販売開始の説明聞いた? + {0x51B, new EventFlagPlayer(0 , 1 , 1307, "TukSecretRewardType3rd" )}, // ハーベスト|フランクリンの隠し食材報酬抽選結果(3回目) + {0x51C, new EventFlagPlayer(0 , 1 , 1308, "PckTalkBeforeFlag" )}, // カーニバル/べルリーナ|面識ある? + {0x51D, new EventFlagPlayer(0 , 1 , 1309, "SendNNPCConversationPlayReport" )}, // 会話のフリのプレイレポートがその日送信されたか + {0x51E, new EventFlagPlayer(0 , 1 , 1310, "MainmenuMydesignShowcase" )}, // スマホUI|マイデザインショーケース解禁 + {0x51F, new EventFlagPlayer(0 , 8 , 1311, "ChristmasPrevPresentItemType" )}, // クリスマス|直前にNPCにもらったアイテムの種類 + {0x520, new EventFlagPlayer(0 , 1 , 1312, "ValentineLetterFlag" )}, // バレンタイン|手紙送った? + {0x522, new EventFlagPlayer(0 , 1 , 1314, "AnnounceChristmasEve" )}, // クリスマス|当日に島内放送で告知した?(2回目放送用) + {0x526, new EventFlagPlayer(0 , 511 , 1318, "GetCarnivalFurniture" )}, // カーニバル/ベルリーナ|どのカーニバル家具をもらったか? + {0x52C, new EventFlagPlayer(0 , 9999, 1324, "LastPlayValentineYear" )}, // バレンタイン|最後に遊んだバレンタインの年 + {0x52D, new EventFlagPlayer(0 , 1 , 1325, "PckRecipeTalkFlag" )}, // カーニバル/べルリーナ|にじいろのはねのレシピもらう会話した? + {0x52E, new EventFlagPlayer(0 , 1 , 1326, "Mobile1stBoot_MydesignShowcase" )}, // スマホアプリ初起動|マイデザインアプリにショーケース追加 + {0x52F, new EventFlagPlayer(0 , 1 , 1327, "MydesignExchangeTalkAboutMobile" )}, // マイデザイン交換| マイデザインショーケースアプリについて説明 + {0x530, new EventFlagPlayer(0 , 1 , 1328, "BuyReactionBook17" )}, // カーニバル用リアクション本を購入した + {0x531, new EventFlagPlayer(0 , 511 , 1329, "GetCarnivalFurnitureRed" )}, // カーニバル/ベルリーナ|どの赤色カーニバル家具をもらったか? + {0x532, new EventFlagPlayer(0 , 511 , 1330, "GetCarnivalFurnitureBlue" )}, // カーニバル/ベルリーナ|どの青色カーニバル家具をもらったか? + {0x533, new EventFlagPlayer(0 , 511 , 1331, "GetCarnivalFurnitureGreen" )}, // カーニバル/ベルリーナ|どの緑色カーニバル家具をもらったか? + {0x534, new EventFlagPlayer(0 , 511 , 1332, "GetCarnivalFurniturePurple" )}, // カーニバル/ベルリーナ|どの紫色カーニバル家具をもらったか? + {0x535, new EventFlagPlayer(0 , 511 , 1333, "GetCarnivalFurnitureRainbow" )}, // カーニバル/ベルリーナ|どの虹色カーニバル家具をもらったか? + {0x536, new EventFlagPlayer(0 , 1 , 1334, "PckColorLotteryFlag" )}, // カーニバル/ベルリーナ|色ごとにカーニバル家具の抽選をするか? + {0x537, new EventFlagPlayer(0 , 1 , 1335, "RcmChkReactionBook" )}, // カーニバル用リアクション本をチェックした + {0x538, new EventFlagPlayer(0 , 1 , 1336, "RcmChkCarnivalFtr" )}, // まめきち|カーニバル家具チェックした? + {0x539, new EventFlagPlayer(0 , 1 , 1337, "AnnounceCarnival" )}, // カーニバル|当日に島内放送で告知した?(2回目放送用) + {0x53A, new EventFlagPlayer(0 , 1 , 1338, "ShootDownShamrockRecipeBalloon" )}, // シャムロックデー|今日、シャムロックステッキのレシピ風船を撃ち落としたか + {0x53B, new EventFlagPlayer(0 , 1 , 1339, "MailSendFlag_ReceiveAnniversaryItem" )}, // 手紙|1周年手紙を送った + {0x53C, new EventFlagPlayer(0 , 1 , 1340, "AOC_EventFlag_002" )}, // AOC同期フラグ| 002 1.9.0NSO加入特典 + {0x53D, new EventFlagPlayer(0 , 1 , 1341, "UnlockSanrioCollaboPoster" )}, // サンリオNPCポスター解禁_キティ + {0x53E, new EventFlagPlayer(0 , 1 , 1342, "UnlockSanrioCollaboPoster2" )}, // サンリオNPCポスター解禁_プリン + {0x53F, new EventFlagPlayer(0 , 1 , 1343, "UnlockSanrioCollaboPoster3" )}, // サンリオNPCポスター解禁_キキララ + {0x540, new EventFlagPlayer(0 , 1 , 1344, "UnlockSanrioCollaboPoster4" )}, // サンリオNPCポスター解禁_シナモン + {0x541, new EventFlagPlayer(0 , 1 , 1345, "UnlockSanrioCollaboPoster5" )}, // サンリオNPCポスター解禁_マイメロ + {0x542, new EventFlagPlayer(0 , 1 , 1346, "UnlockSanrioCollaboPoster6" )}, // サンリオNPCポスター解禁_けろっぴ + {0x543, new EventFlagPlayer(0 , 1 , 1347, "AnnounceEaster" )}, // イースター(2021年)|当日に島内放送で告知した?(2回目放送用) + {0x544, new EventFlagPlayer(0 , 1 , 1348, "PhoneCallByRcoWherearen" )}, // 電話デモ|たぬきちからウェアラン入電受けたことがある? + {0x545, new EventFlagPlayer(0 , 1 , 1349, "RcoTalkWithOtg" )}, // たぬきち|タクミとの会話を聞いたことがある? + {0x547, new EventFlagPlayer(0 , 1 , 1351, "SloTalkCommuneBeforeFlag" )}, // レイジ|コミューンで会話したことある? + {0x548, new EventFlagPlayer(0 , 1 , 1352, "SloExplainVegetableSeedling" )}, // レイジ|野菜の苗の説明聞いたことある? + {0x549, new EventFlagPlayer(0 , 1 , 1353, "SloExplainPlumeriaSeedling" )}, // レイジ|プルメリアの苗の説明聞いたことある? + {0x54A, new EventFlagPlayer(0 , 1 , 1354, "SloExplainWeeding" )}, // レイジ|草むしりサービスの説明聞いたことある? + {0x54B, new EventFlagPlayer(0 , 1 , 1355, "AnnounceEasterReady" )}, // イースター(2021年)|準備期間に島内放送で告知した?(2回目放送用) + {0x54C, new EventFlagPlayer(0 , 1 , 1356, "AnnounceJuneBride" )}, // ジューンブライド(2021年)|当日に島内放送で告知した?(2回目放送用) + {0x54D, new EventFlagPlayer(0 , 1 , 1357, "StandByPhoneCallOtgVisit" )}, // OneRoom|電話デモ|タクミ訪問の入電するか? + {0x54E, new EventFlagPlayer(0 , 1 , 1358, "PynEvent_SendMailThisYear" )}, // イースター|今年手紙を受け取った? + {0x553, new EventFlagPlayer(0 , 1 , 1363, "UnlockWherearen" )}, // OneRoom|ウェアラン渡航解禁 + {0x555, new EventFlagPlayer(0 , 1 , 1365, "OwlArtStampRally1" )}, // フータ/国際ミュージアム|【美術品】スタンプ1つ目を押した? + {0x556, new EventFlagPlayer(0 , 1 , 1366, "OwlArtStampRally2" )}, // フータ/国際ミュージアム|【美術品】スタンプ2つ目を押した? + {0x557, new EventFlagPlayer(0 , 1 , 1367, "OwlArtStampRally3" )}, // フータ/国際ミュージアム|【美術品】スタンプ3つ目を押した? + {0x558, new EventFlagPlayer(0 , 1 , 1368, "OwlStampGotArtReward" )}, // フータ/国際ミュージアム|その日、美術品報酬を貰った + {0x559, new EventFlagPlayer(0 , 1 , 1369, "OwlStampGotArt" )}, // フータ/国際ミュージアム|その日、フータスタンプ(美術品)を押した + {0x55A, new EventFlagPlayer(0 , 1 , 1370, "OwlArtUnfinished" )}, // フータ/国際ミュージアム|初参加時、美術品部屋未完成 + {0x55C, new EventFlagPlayer(0 , 1 , 1372, "WHEREAREN_DisclosePlannerID" )}, // OneRoom|プランナーIDの公開 + {0x55D, new EventFlagPlayer(0 , 1 , 1373, "UnlockSanrioCollabo" )}, // サンリオコラボ解禁_キティ + {0x55E, new EventFlagPlayer(0 , 1 , 1374, "UnlockSanrioCollabo2" )}, // サンリオコラボ解禁_プリン + {0x55F, new EventFlagPlayer(0 , 1 , 1375, "UnlockSanrioCollabo3" )}, // サンリオコラボ解禁_キキララ + {0x560, new EventFlagPlayer(0 , 1 , 1376, "UnlockSanrioCollabo4" )}, // サンリオコラボ解禁_シナモン + {0x561, new EventFlagPlayer(0 , 1 , 1377, "UnlockSanrioCollabo5" )}, // サンリオコラボ解禁_マイメロ + {0x562, new EventFlagPlayer(0 , 1 , 1378, "UnlockSanrioCollabo6" )}, // サンリオコラボ解禁_けろっぴ + {0x565, new EventFlagPlayer(0 , 4 , 1381, "OwlClearCount" )}, // フータ/国際ミュージアム|クリアした部屋の個数 + {0x566, new EventFlagPlayer(0 , 1 , 1382, "WHEREAREN_Pickup_Disclose" )}, // OneRoom|現在、宣伝内容をピックアップに公開中か? + {0x567, new EventFlagPlayer(0 , 1 , 1383, "XctGetRewardSec" )}, // メーデー|みしらぬネコから2回目の報酬をもらった? + {0x568, new EventFlagPlayer(0 , 1 , 1384, "OwlStampPlayedThisYear" )}, // フータ/国際ミュージアム|今年サカナのスタンプラリーをクリアした? + {0x569, new EventFlagPlayer(0 , 1 , 1385, "OwlStampPlayedThisYear2" )}, // フータ/国際ミュージアム|今年ムシのスタンプラリーをクリアした? + {0x56A, new EventFlagPlayer(0 , 1 , 1386, "OwlStampPlayedThisYear3" )}, // フータ/国際ミュージアム|今年かせきのスタンプラリーをクリアした? + {0x56B, new EventFlagPlayer(0 , 1 , 1387, "OwlStampPlayedThisYear4" )}, // フータ/国際ミュージアム|今年美術品のスタンプラリーをクリアした? + {0x56C, new EventFlagPlayer(0 , 1 , 1388, "MuseumCafeEv_1_HeardExplanation" )}, // 博物館カフェ増築イベント|フータから依頼受けた? + {0x56D, new EventFlagPlayer(0 , 1 , 1389, "MuseumCafeEv_2_TalkedWithMasterAtIsland" )}, // 博物館カフェ増築イベント|離島でマスターと会話したことがある? + {0x56E, new EventFlagPlayer(0 , 1 , 1390, "MuseumCafeEv_3_ConfirmedVisitingTown" )}, // 博物館カフェ増築イベント|離島マスターに来訪の約束した? + {0x56F, new EventFlagPlayer(0 , 1 , 1391, "MuseumCafeEv_4_ReportedToOwl" )}, // 博物館カフェ増築イベント|フータにマスターのことを報告した? + {0x570, new EventFlagPlayer(0 , 1 , 1392, "Owl_HeardAboutCafeConstruction" )}, // フータ|カフェの工事のことを聞いた? + {0x571, new EventFlagPlayer(0 , 1 , 1393, "Owl_HeardAboutCafeOpen" )}, // フータ|カフェオープンのことを聞いた? + {0x572, new EventFlagPlayer(0 , 1 , 1394, "PgeThankToMainPC" )}, // マスター|カフェ開店後に島民代表が初会話した? + {0x573, new EventFlagPlayer(0 , 8 , 1395, "TodayFortune" )}, // ハッケミィ|今日の運勢 + {0x574, new EventFlagPlayer(0 , 8 , 1396, "ReserveFortune" )}, // ハッケミィ|発動前の運勢 + {0x575, new EventFlagPlayer(0 , 1 , 1397, "RadioGymnasticsFirstExplain" )}, // ラジオ体操|初回説明読んだ? + {0x576, new EventFlagPlayer(0 , 1 , 1398, "Bpt_1stTalk" )}, // ハッケミィ|占ったことがある? + {0x577, new EventFlagPlayer(0 , 1 , 1399, "Bpt_FinishFortune_Today" )}, // ハッケミィ|今日「今日の運勢」占い済? + {0x578, new EventFlagPlayer(0 , 1 , 1400, "Bpt_FinishCompatibilityToday" )}, // ハッケミィ|今日「相性占い」占い済? + {0x57A, new EventFlagPlayer(0 , 8 , 1402, "LastFortune" )}, // ハッケミィ|前回の運勢 + {0x57B, new EventFlagPlayer(0 , 1 , 1403, "SkkCommuneTalkBefore" )}, // シャンク|コミューンで以前話したことある? + {0x57C, new EventFlagPlayer(0 , 1 , 1404, "AlpJuneBrideNotGetLoveCrystalFrag" )}, // カイゾー/ジューンブライド|今日あいのけっしょうもらえなかった? + {0x57D, new EventFlagPlayer(0 , 1 , 1405, "AlwJuneBrideExchangeTalkFlag" )}, // リサ/ジューンブライド|今年交換回数制限の説明聞いた? + {0x57E, new EventFlagPlayer(0 , 9999, 1406, "LastPlayMuseumYear" )}, // 国際ミュージアム|最後に遊んだ国際ミュージアムの年 + {0x57F, new EventFlagPlayer(0 , -1 , 1407, "RadioGymnasticsCount" )}, // ラジオ体操|累計参加回数 + {0x580, new EventFlagPlayer(0 , 5 , 1408, "RadioGymnasticsGetReward" )}, // ラジオ体操|報酬何回もらった? + {0x581, new EventFlagPlayer(0 , 1 , 1409, "ExplainIslandRegulation" )}, // 条例|しずえから条例の説明受けた + {0x582, new EventFlagPlayer(0 , 1 , 1410, "MainmenuRecipe_v2" )}, // スマホUI|レシピ+解禁(v2.0.0料理レシピ) + {0x583, new EventFlagPlayer(0 , 1 , 1411, "Mobile1stBoot_DIYrecipe_v2" )}, // スマホアプリ初起動|DIYレシピ+(v2.0.0料理レシピ) + {0x584, new EventFlagPlayer(0 , 1 , 1412, "TapUnlockSearchByIslandName" )}, // ゆめみ|「島の名前で探す」解禁説明読んだ? + {0x585, new EventFlagPlayer(0 , 1 , 1413, "MuseumCafe_Telephone_Access1stTime" )}, // 喫茶ハトの巣|店内電話初回説明見たか? + {0x586, new EventFlagPlayer(0 , 1 , 1414, "AlpCommuneTalkBeforeFlag" )}, // カイゾー|コミューンで会話したことある? + {0x589, new EventFlagPlayer(0 , 1 , 1417, "FirstPlayAfterMuseumBuilt3Flag" )}, // 博物館3に拡張したあとのプレイ初日? + {0x58A, new EventFlagPlayer(0 , 1 , 1418, "ReserveCommuneExpansion" )}, // コミューン|拡張イベント予約 + {0x58C, new EventFlagPlayer(0 , 1 , 1420, "DoneCommuneSloOpenEvent" )}, // コミューン島レイジ開店イベント発生制御 + {0x58D, new EventFlagPlayer(0 , 1 , 1421, "DoneCommuneCmlOpenEvent" )}, // コミューン島ローラン開店イベント発生制御 + {0x58E, new EventFlagPlayer(0 , 1 , 1422, "DoneCommuneFoxOpenEvent" )}, // コミューン島つねきち開店イベント発生制御 + {0x58F, new EventFlagPlayer(0 , 1 , 1423, "DoneCommuneBptOpenEvent" )}, // コミューン島ハッケミィ開店イベント発生制御 + {0x590, new EventFlagPlayer(0 , 1 , 1424, "DoneCommuneSkkOpenEvent" )}, // コミューン島シャンク開店イベント発生制御 + {0x591, new EventFlagPlayer(0 , 1 , 1425, "DoneCommuneAlpOpenEvent" )}, // コミューン島リサカイゾー開店イベント発生制御 + {0x592, new EventFlagPlayer(0 , 1 , 1426, "PooTalkAboutHairArrange" )}, // カットリーヌ|初回ヘアアレンジの話を聞いた + {0x593, new EventFlagPlayer(0 , 1 , 1427, "PooRefuseHairArrange" )}, // カットリーヌ|ヘアアレンジを断った + {0x594, new EventFlagPlayer(0 , 1 , 1428, "PooTodayGetHairStyle" )}, // カットリーヌ|今日、ヘアアレンジをしてもらった + {0x595, new EventFlagPlayer(0 , 1 , 1429, "PooUndoHairStyelAfterArrange" )}, // カットリーヌ|ヘアアレンジ後、元に戻してもらった + {0x596, new EventFlagPlayer(0 , 1 , 1430, "PooGetNewHairStyle1" )}, // カットリーヌ|ヘアアレンジ解禁1(レイジ) + {0x597, new EventFlagPlayer(0 , 1 , 1431, "PooGetNewHairStyle2" )}, // カットリーヌ|ヘアアレンジ解禁2(ローラン) + {0x598, new EventFlagPlayer(0 , 1 , 1432, "PooGetNewHairStyle3" )}, // カットリーヌ|ヘアアレンジ解禁3(つねきち) + {0x599, new EventFlagPlayer(0 , 1 , 1433, "PooGetNewHairStyle4" )}, // カットリーヌ|ヘアアレンジ解禁4(ハッケミィ) + {0x59A, new EventFlagPlayer(0 , 1 , 1434, "PooGetNewHairStyle5" )}, // カットリーヌ|ヘアアレンジ解禁5(シャンク) + {0x59B, new EventFlagPlayer(0 , 1 , 1435, "PooGetNewHairStyle6" )}, // カットリーヌ|ヘアアレンジ解禁6(リサカイゾー) + {0x59C, new EventFlagPlayer(0 , 1 , 1436, "SpnTodayExplainedPhotoStudio" )}, // パニエル|撮影スタジオに今日初めて入った + {0x59D, new EventFlagPlayer(0 , 1 , 1437, "RcoCordinateNpcHouseSelEnable" )}, // たぬきち|NPC家コーデの選択肢が解禁 + {0x59E, new EventFlagPlayer(0 , 8 , 1438, "PgeItemGetCount" )}, // マスター|もらったアイテムの数 + {0x59F, new EventFlagPlayer(0 , 1 , 1439, "PgeTalkFirstFlag" )}, // マスター|面識ある? + {0x5A0, new EventFlagPlayer(0 , 1 , 1440, "AlwCommuneTalkBeforeFlag" )}, // リサ|コミューンで会話したことある? + {0x5A2, new EventFlagPlayer(0 , 1 , 1442, "CmlCommuneTalkBefore" )}, // ローラン|コミューンで会話したことある? + {0x5A4, new EventFlagPlayer(0 , 1 , 1444, "CmlCommuneBuyToday" )}, // ローラン|今日買い物した? + {0x5A5, new EventFlagPlayer(0 , 1 , 1445, "UnlockBuyRecipePlus" )}, // タヌポート|レシピ+の陳列開始 + {0x5A7, new EventFlagPlayer(0 , 1 , 1447, "Mobile1stBoot_MydesignPatternPlus" )}, // 汎用布地ページ追加後スマホアプリ初起動|マイデザイン + {0x5A8, new EventFlagPlayer(0 , 1 , 1448, "MainmenuMydesignPatternPlus" )}, // マイデザイン|汎用布地ページ追加 + {0x5A9, new EventFlagPlayer(0 , 1 , 1449, "Mobile1stBoot_Camera1stPersonView" )}, // 主観カメラ追加後スマホアプリ初起動|カメラ + {0x5AA, new EventFlagPlayer(0 , 1 , 1450, "MainmenuCamera1stPersonView" )}, // カメラ|主観カメラ解禁 + {0x5AC, new EventFlagPlayer(0 , 1 , 1452, "UnlockInterior_CeilingFurniture" )}, // インテリアモード|天井家具解禁 + {0x5AD, new EventFlagPlayer(0 , 1 , 1453, "FenceRemakeEnable" )}, // リメイク|柵リメイク解禁 + {0x5B0, new EventFlagPlayer(0 , 1 , 1456, "GetMayDayTicketFirst" )}, // メーデー|1.10.0未満でメーデーりょこうけんを入手したことがあるか? + {0x5B1, new EventFlagPlayer(0 , 1 , 1457, "TotakekeLive2_0Flag" )}, // とたけけ|2.0アプデ後に初めてライブ聴いた? + {0x5B2, new EventFlagPlayer(0 , 3 , 1458, "RcoStorageExpansion_v200_AddLevel" )}, // たぬきち|収納の拡張(v2.0.0)追加段階0~3 + {0x5B3, new EventFlagPlayer(0 , 1 , 1459, "MailSend_Notice_v200_AddStorage" )}, // たぬきち|収納の拡張(v2.0.0)段階追加お知らせの手紙判定したか? + {0x5B4, new EventFlagPlayer(0 , 1 , 1460, "RcoStandbyNotice_v200_AddStorage" )}, // たぬきち|収納の拡張(v2.0.0)段階追加のお知らせ強制会話するか? + {0x5B5, new EventFlagPlayer(0 , 1 , 1461, "RcoStandbyNotice_v200_AfterStorageExpansion")}, // たぬきち|収納の拡張(v2.0.0)収納拡張後の強制会話予約フラグ + {0x5B6, new EventFlagPlayer(0 , 1 , 1462, "PlayerMovingAfterStorageExpansion" )}, // たぬきち|収納拡張後の説明の発生予約中にPだけ引っ越しした? + {0x5B7, new EventFlagPlayer(0 , 1 , 1463, "UnlockBuyFenceRemake" )}, // タヌポート|柵リメイク解禁の陳列開始 + {0x5B8, new EventFlagPlayer(0 , 1 , 1464, "RcoHeardAboutMayDayTravelTicket" )}, // メーデー|たぬきち|メーデー旅行券の説明聞いたか? + {0x5B9, new EventFlagPlayer(0 , 1 , 1465, "XctGetRewardPast" )}, // メーデー|1.10.0未満でみしらぬネコから報酬をもらった? + {0x5BB, new EventFlagPlayer(0 , 1 , 1467, "SloExplainBuyVegetableSeedling" )}, // レイジ|野菜購入時に説明聞いたことある? + {0x5BC, new EventFlagPlayer(0 , 1 , 1468, "SloWeedingBeforeCommune" )}, // レイジ|コミューン誘致前に草むしりサービス解禁した? + {0x5BD, new EventFlagPlayer(0 , 1 , 1469, "FoxTalk2020FireworksFlag" )}, // つねきち|2020年の花火大会で会話したことない? + {0x5BE, new EventFlagPlayer(0 , 1 , 1470, "FoxTalkIceCandyTodayFlag" )}, // つねきち|アイスキャンディの説明した? + {0x5BF, new EventFlagPlayer(0 , 1 , 1471, "FoxTalkTapiocaTodayFlag" )}, // つねきち|タピオカドリンクの説明した? + {0x5C0, new EventFlagPlayer(0 , 1 , 1472, "KppTourExplain1st" )}, // かっぺい|かっぺいツアー初上陸で説明聞いた? + {0x5C1, new EventFlagPlayer(0 , 1 , 1473, "KppTakeTourTodayFlag" )}, // かっぺい|今日かっぺいツアー参加した? + {0x5C2, new EventFlagPlayer(0 , 1 , 1474, "KppFirstTalk" )}, // かっぺい|面識ある? + {0x5C3, new EventFlagPlayer(0 , 1 , 1475, "SpnTodayDonation" )}, // パニエル|今日募金したか? + {0x5C4, new EventFlagPlayer(0 , 1 , 1476, "SpnTodayThanksDonation" )}, // パニエル|今日募金を感謝されたか? + {0x5C5, new EventFlagPlayer(0 , 1 , 1477, "SpnTodayCompleteDonation" )}, // パニエル|今日募金達成したか? + {0x5C6, new EventFlagPlayer(0 , 1 , 1478, "AlwJuneBrideNoRemake1stFlag" )}, // リサ/ジューンブライド|今日1回目でリメイク解禁してなかった + {0x5C7, new EventFlagPlayer(0 , 1 , 1479, "RcoExplainStorageExpandCostIncrease" )}, // たぬきち|収納の拡張(v2.0.0)拡張工事の細かい説明聞いた + {0x5C8, new EventFlagPlayer(0 , 1 , 1480, "AnnounceHalloween2" )}, // 2021年ハロウィンを島内放送で告知した(2回目放送用) + {0x5C9, new EventFlagPlayer(0 , 1 , 1481, "HasLookMyHouseExplain_CeilingFtrAWall" )}, // 家の機能説明ダイアログ(v200天井家具、Aウォール)を見たか? + {0x5CA, new EventFlagPlayer(0 , 1 , 1482, "CompleteNoticeChangeHouseForm" )}, // たぬきち|v200家外観変更に「家の形」が増えたこと告知した? + {0x5CB, new EventFlagPlayer(0 , 1 , 1483, "SloTalkBeforeCommune" )}, // レイジ|コミューン誘致後に本島で会話した? + {0x5CC, new EventFlagPlayer(0 , 1 , 1484, "JoinedTodayRadioGymnastics" )}, // ラジオ体操|今日ラジオ体操に参加したか? + {0x5CD, new EventFlagPlayer(0 , 1 , 1485, "TalkSloCommuneOpenEvent" )}, // レイジ|コミューン開店イベントで話した + {0x5CE, new EventFlagPlayer(0 , 1 , 1486, "TalkCmlCommuneOpenEvent" )}, // ローラン|コミューン開店イベントで話した + {0x5CF, new EventFlagPlayer(0 , 1 , 1487, "TalkFoxCommuneOpenEvent" )}, // つねきち|コミューン開店イベントで話した + {0x5D0, new EventFlagPlayer(0 , 1 , 1488, "TalkBptCommuneOpenEvent" )}, // ハッケミィ|コミューン開店イベントで話した + {0x5D1, new EventFlagPlayer(0 , 1 , 1489, "TalkSkkCommuneOpenEvent" )}, // シャンク|コミューン開店イベントで話した + {0x5D2, new EventFlagPlayer(0 , 1 , 1490, "TalkAlpCommuneOpenEvent" )}, // リサカイゾー|コミューン開店イベントで話した + {0x5D3, new EventFlagPlayer(0 , 1 , 1491, "BptFirstTalk" )}, // ハッケミィ|面識ある? + {0x5D4, new EventFlagPlayer(0 , 1 , 1492, "SpnSendMailCommuneExpansion" )}, // パニエル|コミューン拡張の手紙出したか? + {0x5D5, new EventFlagPlayer(0 , 1023, 1493, "ChocolateVillagerIndex" )}, // 各インデックスの住民がチョコレート勧誘されているかどうか + {0x5D6, new EventFlagPlayer(0 , -1 , 1494, "LatestChocolateDate" )}, // 最新の勧誘をした日付 + {0x5D7, new EventFlagPlayer(0 , 1 , 1495, "PgeTalkCafeFlag" )}, // マスター|店で会話したことある? + {0x5D8, new EventFlagPlayer(0 , 1 , 1496, "AnnounceHarvest2" )}, // 2021年ハーベストを島内放送で告知した(2回目放送用) + {0x5D9, new EventFlagPlayer(0 , 1 , 1497, "MuseumCafeRandomVisitSpTalked_hgs" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(あさみ) + {0x5DA, new EventFlagPlayer(0 , 1 , 1498, "MuseumCafeRandomVisitSpTalked_hgh" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(きぬよ) + {0x5DB, new EventFlagPlayer(0 , 1 , 1499, "MuseumCafeRandomVisitSpTalked_doc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ロドリー) + {0x5DC, new EventFlagPlayer(0 , 1 , 1500, "MuseumCafeRandomVisitSpTalked_boc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ウリ) + {0x5DD, new EventFlagPlayer(0 , 1 , 1501, "MuseumCafeRandomVisitSpTalked_mol" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(リセットさん) + {0x5DE, new EventFlagPlayer(0 , 1 , 1502, "MuseumCafeRandomVisitSpTalked_mob" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ラケットさん) + {0x5DF, new EventFlagPlayer(0 , 1 , 1503, "MuseumCafeRandomVisitSpTalked_tkkA" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(とたけけ) + {0x5E0, new EventFlagPlayer(0 , 1 , 1504, "MuseumCafeRandomVisitSpTalked_skk" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(シャンク) + {0x5E1, new EventFlagPlayer(0 , 1 , 1505, "MuseumCafeRandomVisitSpTalked_cml" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ローラン) + {0x5E2, new EventFlagPlayer(0 , 1 , 1506, "MuseumCafeRandomVisitSpTalked_hgc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ことの) + {0x5E3, new EventFlagPlayer(0 , 1 , 1507, "MuseumCafeRandomVisitSpTalked_slo" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(レイジ) + {0x5E4, new EventFlagPlayer(0 , 1 , 1508, "MuseumCafeRandomVisitSpTalked_ows" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(フーコ) + {0x5E5, new EventFlagPlayer(0 , 1 , 1509, "MuseumCafeRandomVisitSpTalked_chy" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(レックス) + {0x5E6, new EventFlagPlayer(0 , 1 , 1510, "MuseumCafeRandomVisitSpTalked_bey" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC今日店内で会話したか(ジャスティン) + {0x5E7, new EventFlagPlayer(0 , 5 , 1511, "MuseumCafeRandomVisitSpMeetCount_hgs" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(あさみ) + {0x5E8, new EventFlagPlayer(0 , 5 , 1512, "MuseumCafeRandomVisitSpMeetCount_hgh" )}, // 喫茶ハトの巣ランダム来訪特殊NPC店内で会った回数(きぬよ) + {0x5E9, new EventFlagPlayer(0 , 5 , 1513, "MuseumCafeRandomVisitSpMeetCount_doc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ロドリー) + {0x5EA, new EventFlagPlayer(0 , 5 , 1514, "MuseumCafeRandomVisitSpMeetCount_boc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ウリ) + {0x5EB, new EventFlagPlayer(0 , 5 , 1515, "MuseumCafeRandomVisitSpMeetCount_mol" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(リセットさん) + {0x5EC, new EventFlagPlayer(0 , 5 , 1516, "MuseumCafeRandomVisitSpMeetCount_mob" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ラケットさん) + {0x5ED, new EventFlagPlayer(0 , 5 , 1517, "MuseumCafeRandomVisitSpMeetCount_tkkA" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(とたけけ) + {0x5EE, new EventFlagPlayer(0 , 5 , 1518, "MuseumCafeRandomVisitSpMeetCount_skk" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(シャンク) + {0x5EF, new EventFlagPlayer(0 , 5 , 1519, "MuseumCafeRandomVisitSpMeetCount_cml" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ローラン) + {0x5F0, new EventFlagPlayer(0 , 5 , 1520, "MuseumCafeRandomVisitSpMeetCount_hgc" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ことの) + {0x5F1, new EventFlagPlayer(0 , 5 , 1521, "MuseumCafeRandomVisitSpMeetCount_slo" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(レイジ) + {0x5F2, new EventFlagPlayer(0 , 5 , 1522, "MuseumCafeRandomVisitSpMeetCount_ows" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(フーコ) + {0x5F3, new EventFlagPlayer(0 , 5 , 1523, "MuseumCafeRandomVisitSpMeetCount_chy" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(レックス) + {0x5F4, new EventFlagPlayer(0 , 5 , 1524, "MuseumCafeRandomVisitSpMeetCount_bey" )}, // 喫茶ハトの巣|ランダム来訪特殊NPC店内で会った回数(ジャスティン) + {0x5F5, new EventFlagPlayer(0 , 1 , 1525, "DoneCommuneTtlOpenEvent" )}, // コミューン島コトブキ開店イベント発生制御 + {0x5F6, new EventFlagPlayer(0 , 1 , 1526, "DodSelectWherearen1st" )}, // モーリー|「お仕事に行く」の説明を聞いた + {0x5F7, new EventFlagPlayer(0 , 1 , 1527, "FortuneApproachTalked" )}, // 占い結果でのアプローチ会話発生済み + {0x5F8, new EventFlagPlayer(0 , 1 , 1528, "SawMuseumCafeTakeoutNpc" )}, // 喫茶ハトの巣|テイクアウトで来店した特殊NPCを見た + {0x5F9, new EventFlagPlayer(0 , 7 , 1529, "LastSawMuseumCafeTakeoutNpc" )}, // 喫茶ハトの巣|最後にテイクアウトで来店するのを見たNPC + {0x5FA, new EventFlagPlayer(0 , 1 , 1530, "KppTourDone_RareStarpiece" )}, // かっぺいツアー|レア島行った:星のかけら + {0x5FB, new EventFlagPlayer(0 , 1 , 1531, "KppTourDone_RareCherryBlossom" )}, // かっぺいツアー|レア島行った:桜の花びら + {0x5FC, new EventFlagPlayer(0 , 1 , 1532, "KppTourDone_RareSpringBamboo" )}, // かっぺいツアー|レア島行った:春のわかたけ + {0x5FD, new EventFlagPlayer(0 , 1 , 1533, "KppTourDone_RareSummerShell" )}, // かっぺいツアー|レア島行った:夏のかいがら + {0x5FE, new EventFlagPlayer(0 , 1 , 1534, "KppTourDone_RareMushroom" )}, // かっぺいツアー|レア島行った:キノコ + {0x5FF, new EventFlagPlayer(0 , 1 , 1535, "KppTourDone_RareMapleLeaf" )}, // かっぺいツアー|レア島行った:紅葉の葉っぱ + {0x600, new EventFlagPlayer(0 , 1 , 1536, "KppTourDone_RareSnowCrystal" )}, // かっぺいツアー|レア島行った:雪のけっしょう + {0x601, new EventFlagPlayer(0 , 1 , 1537, "MuseumCafe_Telephone_Calledxct" )}, // 喫茶ハトの巣|みしらぬネコ|amiiboでみしらぬネコを呼び出し会話したか? + {0x602, new EventFlagPlayer(0 , 1 , 1538, "MainmenuTips" )}, // スマホUI|徹底ライフサポート(Tips)解禁 + {0x603, new EventFlagPlayer(0 , 1 , 1539, "Mobile1stBoot_Tips" )}, // スマホアプリ初起動|徹底ライフサポート(Tips) + {0x604, new EventFlagPlayer(0 , 1 , 1540, "MydesignExchangeExp_v2_0" )}, // マイデザイン交換| v2.0.0で追加された機能説明 + {0x605, new EventFlagPlayer(0 , 1 , 1541, "TalkTtlCommuneOpenEvent" )}, // コトブキ|コミューン開店イベントで話した + {0x606, new EventFlagPlayer(0 , 1 , 1542, "FoxTalkFireworksFoodFlag" )}, // つねきち|花火大会で食べ物追加された会話聞いた? + {0x607, new EventFlagPlayer(0 , 1 , 1543, "AnnounceHalloween2Ready" )}, // 2021年ハロウィン|準備期間に島内放送で告知した?(2回目放送用) + {0x608, new EventFlagPlayer(0 , 1 , 1544, "PgeLikeTepidLasttimeFlag" )}, // マスター|前回ぬるい方が好きと答えた? + {0x60A, new EventFlagPlayer(0 , 3 , 1546, "PgeTepidCount" )}, // マスター|ぬるく入れるか聞くカウンタ + {0x60B, new EventFlagPlayer(0 , 1 , 1547, "SkkTalkFirstTimeCommune" )}, // シャンク|初会話がコミューン店の方だった + {0x60C, new EventFlagPlayer(0 , 1 , 1548, "TtlTodayTalkFlag" )}, // コトブキ|今日もう会話した? + {0x60D, new EventFlagPlayer(0 , 1 , 1549, "TtlBFirstTalkFlag" )}, // コトブキ|ドンどんぐりとして今年会話した? + {0x60F, new EventFlagPlayer(0 , 1 , 1551, "GetMayDayTicketBefore_v2_0" )}, // メーデー|2.0.0未満でメーデーりょこうけんを入手したことがあるか? + {0x610, new EventFlagPlayer(0 , 1 , 1552, "XctGetRewardEveryYear" )}, // メーデー|みしらぬネコから3回目以降の報酬をもらった? + {0x611, new EventFlagPlayer(0 , 1 , 1553, "FoxFirstTalkTodayFireworksFlag" )}, // つねきち|今日花火大会で会話した? + {0x612, new EventFlagPlayer(0 , 1 , 1554, "PlayerMovingWithPFlag555" )}, // パニエル|「撮影スタジオの説明」聞いた後に、P引越しした + {0x613, new EventFlagPlayer(0 , 1 , 1555, "PooTalkFirst" )}, // カットリーヌ|面識がある? + {0x614, new EventFlagPlayer(0 , 1 , 1556, "PooTalkToday" )}, // カットリーヌ|今日会話した? + {0x615, new EventFlagPlayer(0 , 1 , 1557, "PooTalkFirstToday" )}, // カットリーヌ|今日面識ができた? + {0x616, new EventFlagPlayer(0 , 1 , 1558, "PooGetNewHairStyle7" )}, // カットリーヌ|ヘアアレンジ解禁7(コトブキ) + {0x617, new EventFlagPlayer(0 , 1 , 1559, "WHEREAREN_TapFirstCheckMydesingShowcase" )}, // OneRoom|視察中にマイデザインショーケース端末にアクセスしたことがある? + {0x618, new EventFlagPlayer(0 , 1 , 1560, "PAAboutUnlockIslandRegulation" )}, // 島内放送|条例が解禁したこと聞いた + {0x619, new EventFlagPlayer(0 , 1 , 1561, "SelectedGotoCafe" )}, // 日課「喫茶店に行こうキャンペーン」を今日達成した + {0x61A, new EventFlagPlayer(0 , 2 , 1562, "SelectedDoRadioGymnastics" )}, // 日課「ラジオ体操をしよう」が出現カウンター + {0x61B, new EventFlagPlayer(0 , 1 , 1563, "TtlB_Acorn_Today" )}, // コトブキ|今日どんぐり貰った? + {0x61C, new EventFlagPlayer(0 , 1 , 1564, "HeldCeremonyMuseum3" )}, // セレモニ|博物館③を開いた + {0x61D, new EventFlagPlayer(0 , 1 , 1565, "StandByPhoneCallNpcNG" )}, // 電話デモ|NPCを呼び出せなかった入電するか? + {0x61E, new EventFlagPlayer(0 , 1 , 1566, "PgeTalkTakeOutFlag" )}, // マスター|テイクアウトの話聞いた? + {0x61F, new EventFlagPlayer(0 , 1 , 1567, "UnlockPlayerHair37" )}, // 髪型解禁:Hair37センターわけ + {0x620, new EventFlagPlayer(0 , 1 , 1568, "UnlockPlayerHair38" )}, // 髪型解禁:Hair38ウルフカット + {0x621, new EventFlagPlayer(0 , 1 , 1569, "UnlockPlayerHair39" )}, // 髪型解禁:Hair39オールバック + {0x622, new EventFlagPlayer(0 , 1 , 1570, "UnlockPlayerHair40" )}, // 髪型解禁:Hair40マッシュルーム + {0x623, new EventFlagPlayer(0 , 1 , 1571, "UnlockPlayerHair41" )}, // 髪型解禁:Hair41かっこいいMじ + {0x624, new EventFlagPlayer(0 , 1 , 1572, "UnlockPlayerHair42" )}, // 髪型解禁:Hair42そりこみぼうず + {0x625, new EventFlagPlayer(0 , 1 , 1573, "UnlockPlayerHair43" )}, // 髪型解禁:Hair43ハーフアップ + {0x626, new EventFlagPlayer(0 , 1 , 1574, "UnlockPlayerHair44" )}, // 髪型解禁:Hair44ふわひとつあみ + {0x627, new EventFlagPlayer(0 , 1 , 1575, "UnlockPlayerHair45" )}, // 髪型解禁:Hair45ふわひとつくくり + {0x628, new EventFlagPlayer(0 , 1 , 1576, "UnlockPlayerHair46" )}, // 髪型解禁:Hair46まとめがみ + {0x629, new EventFlagPlayer(0 , 1 , 1577, "UnlockPlayerHair47" )}, // 髪型解禁:Hair47みつあみツイン + {0x62A, new EventFlagPlayer(0 , 1 , 1578, "TtlChangeTtlB" )}, // コトブキをドンどんぐりに差し替え + {0x62B, new EventFlagPlayer(0 , 4095, 1579, "TkkFirstPlayNewSong" )}, // とたけけ|まだ演奏したことがない新曲かどうか + {0x62C, new EventFlagPlayer(0 , 8 , 1580, "XctCalledMessageBefore" )}, // メーデー|前の1537で出現したメッセージ番号 + {0x62D, new EventFlagPlayer(0 , 9999, 1581, "LastPlayFireWorksFestival" )}, // 花火大会|最後に遊んだ花火大会の年 + {0x62E, new EventFlagPlayer(0 , 1 , 1582, "SendAocPurchasingPrize" )}, // AOC|予約・購入特典を送付した + {0x62F, new EventFlagPlayer(0 , 1 , 1583, "FoxCommuneTalkBeforeFlag" )}, // つねきち|今日コミューンのつねきちからお店の説明聞いた? + {0x630, new EventFlagPlayer(0 , 1 , 1584, "FoxCommuneTalkLotteryTodayFlag" )}, // つねきち|今日コミューン開店イベントで話した + {0x631, new EventFlagPlayer(0 , 1 , 1585, "FoxCommuneTalkExplainFlag" )}, // つねきち|コミューンのつねきちからお店の説明聞いた? + {0x632, new EventFlagPlayer(0 , 1 , 1586, "FoxCommunePlayLotteryTodayFlag" )}, // つねきち|今日コミューンのつねきちのくじ引いた? + {0x634, new EventFlagPlayer(0 , 9999, 1588, "LastPlayMayDayYear" )}, // メーデー|最後に遊んだメーデーの年 + {0x635, new EventFlagPlayer(0 , 1 , 1589, "FoxCommuneTalkIceTodayFlag" )}, // つねきち|アイス系の説明した? + {0x636, new EventFlagPlayer(0 , 1 , 1590, "FoxCommuneTalkJuiceTodayFlag" )}, // つねきち|缶飲料の説明した? + {0x637, new EventFlagPlayer(0 , 1 , 1591, "FoxCommuneTalkTodayFlag" )}, // つねきち|今日コミューンのつねきちと会話した? + {0x639, new EventFlagPlayer(0 , 1 , 1593, "WHEREAREN_Unlock_RoomDimming" )}, // OneRoom|オリジナル調光アンロック + {0x63A, new EventFlagPlayer(0 , 1 , 1594, "OwlDonateDiveFishAtMuseumTent" )}, // フータ|テント状態のときに海の幸を見せた? + {0x63B, new EventFlagPlayer(0 , 1 , 1595, "FoxCommuneBuyArtTodayFlag" )}, // つねきち|今日コミューンで美術品買った? + {0x63C, new EventFlagPlayer(0 , 1 , 1596, "UnlockBuyFIXLadderRecipe" )}, // お店|はしごFIXキットのレシピ陳列開始 + {0x63D, new EventFlagPlayer(0 , 1 , 1597, "UnlockBuyInteriorModePro" )}, // タヌポート|もようがえPROライセンス陳列解禁 + {0x63E, new EventFlagPlayer(0 , 1 , 1598, "AlwCommuneTalkTodayFlag" )}, // リサ|今日コミューン島で会話した? + {0x63F, new EventFlagPlayer(0 , 1 , 1599, "UnlockBuyReactionCollection_v200" )}, // タヌポート|リアクション集v200陳列解禁 + {0x640, new EventFlagPlayer(0 , 1 , 1600, "UnlockBuyHairStyleCollection_v200" )}, // タヌポート|ヘアスタイル集v200陳列解禁 + {0x641, new EventFlagPlayer(0 , 1 , 1601, "RadioGymnasticsAchievementFinish" )}, // ラジオ体操の実績を今日カウントした + {0x642, new EventFlagPlayer(0 , 1 , 1602, "UnlockBuyTipsApp" )}, // タヌポート|徹底ライフサポートアプリ陳列解禁 + {0x643, new EventFlagPlayer(0 , 2 , 1603, "TreasureHuntJustMissed" )}, // 宝探し|ギリギリだったか + {0x644, new EventFlagPlayer(0 , 1 , 1604, "WHEREAREN_Use_AccentWall" )}, // アクセントウォールを使用したことがある + {0x645, new EventFlagPlayer(0 , 1 , 1605, "WHEREAREN_Unlock_DustCloth_01" )}, // OneRoom|まごころ雑巾アンロック01 + {0x646, new EventFlagPlayer(0 , 1 , 1606, "WHEREAREN_Unlock_DustCloth_02" )}, // OneRoom|まごころ雑巾アンロック02 + {0x648, new EventFlagPlayer(0 , 1 , 1608, "WHEREAREN_Unlock_EnvSound_01" )}, // OneRoom|環境音アンロック01 + {0x649, new EventFlagPlayer(0 , 1 , 1609, "WHEREAREN_Unlock_EnvSound_02" )}, // OneRoom|環境音アンロック02 + {0x64A, new EventFlagPlayer(0 , 1 , 1610, "WHEREAREN_Unlock_EnvSound_03" )}, // OneRoom|環境音アンロック03 + {0x64C, new EventFlagPlayer(0 , 1 , 1612, "WHEREAREN_Prev_Unlock_EnvSound_01" )}, // OneRoom|環境音アンロック01_事前フラグ + {0x64D, new EventFlagPlayer(0 , 1 , 1613, "WHEREAREN_Prev_Unlock_EnvSound_02" )}, // OneRoom|環境音アンロック02_事前フラグ + {0x64E, new EventFlagPlayer(0 , 1 , 1614, "WHEREAREN_Prev_Unlock_EnvSound_03" )}, // OneRoom|環境音アンロック03_事前フラグ + {0x650, new EventFlagPlayer(0 , 1 , 1616, "WHEREAREN_Unlock_RoomSizeModeUnlock" )}, // OneRoom|部屋サイズモードアンロック + {0x651, new EventFlagPlayer(0 , 1 , 1617, "Owl1stTalkMuseum3" )}, // フータ|博物館③(カフェ)完成後の挨拶した? + {0x652, new EventFlagPlayer(0 , 1 , 1618, "LectureAboutMarinesuitBuyIt" )}, // まめきち|マリンスーツを買ったときレクチャーをする? + {0x653, new EventFlagPlayer(0 , 1 , 1619, "TalkHHATodayAnyone" )}, // 今日誰かにHHAを聞いたか + {0x654, new EventFlagPlayer(0 , 1 , 1620, "UnlockBuyReactionCoolection_v160" )}, // タヌポート|リアクション集v160陳列解禁 + {0x655, new EventFlagPlayer(0 , 1 , 1621, "UnlockBuyHairStyleColection_v160" )}, // タヌポート|もっと!ヘアスタイル×6v160陳列解禁 + {0x656, new EventFlagPlayer(0 , 1 , 1622, "UnlockBuyAddBridgeSlope" )}, // タヌポート|インフラぞうせつライセンス陳列解禁 + {0x657, new EventFlagPlayer(0 , 1 , 1623, "MuseumPosterTalkAboutMakePoster" )}, // フータ/博物館コンプポスター|フータに「ポスター準備する話」を聞いたか? + {0x658, new EventFlagPlayer(0 , 1 , 1624, "MuseumPosterUnlockBuySel" )}, // フータ/博物館コンプポスター|自身が「ポスター買う」選択肢出すか? + {0x659, new EventFlagPlayer(0 , 1 , 1625, "MuseumPosterUnlockMyselfBug" )}, // フータ/博物館コンプポスター|自身がムシのポスター購入を解禁した? + {0x65A, new EventFlagPlayer(0 , 1 , 1626, "MuseumPosterUnlockMyselfFish" )}, // フータ/博物館コンプポスター|自身がサカナのポスター購入を解禁した? + {0x65B, new EventFlagPlayer(0 , 1 , 1627, "MuseumPosterUnlockMyselfFossil" )}, // フータ/博物館コンプポスター|自身が化石のポスター購入を解禁した? + {0x65C, new EventFlagPlayer(0 , 1 , 1628, "MuseumPosterUnlockMyselfPainting" )}, // フータ/博物館コンプポスター|自身が美術品のポスター購入を解禁した? + {0x65D, new EventFlagPlayer(0 , 1 , 1629, "MuseumPosterUnlockMySelfSea" )}, // フータ/博物館コンプポスター|自身が海の幸のポスター購入を解禁した? + {0x65E, new EventFlagPlayer(0 , 1 , 1630, "TtlTodayFirstTalkFlag" )}, // コトブキ|今日初会話した? + {0x65F, new EventFlagPlayer(0 , 256 , 1631, "BalloonShootCountSum" )}, // Tips|風船を撃ち落とした累計回数 + {0x660, new EventFlagPlayer(0 , 1 , 1632, "BocBuyNumCountSum" )}, // Tips|ウリからのカブ購入数X以上か?(X=15) + {0x664, new EventFlagPlayer(0 , 1 , 1636, "NoticeAboutInteriorModePlus_playerHouse" )}, // 自宅か撮影スタジオでインテリアモード開いてインテリアモード+の初回ダイアログを見た? + {0x665, new EventFlagPlayer(0 , 1 , 1637, "NoticeAboutInteriorModePlus_Dimming" )}, // インテリアモード+の調光追加の初回ダイアログを見た? + {0x666, new EventFlagPlayer(0 , 1 , 1638, "NoticeAboutInteriorModePlus_EnvironmentalSound1")}, // 環境音解禁の初回ダイアログを見た? + {0x667, new EventFlagPlayer(0 , 1 , 1639, "NoticeAboutInteriorModePlus_EnvironmentalSound2")}, // 環境音解禁の追加1ダイアログを見た? + {0x668, new EventFlagPlayer(0 , 1 , 1640, "NoticeAboutInteriorModePlus_EnvironmentalSound3")}, // 環境音解禁の追加2ダイアログを見た? + {0x669, new EventFlagPlayer(0 , 1 , 1641, "BuildAddtionalBridgeSlopeIntroduction" )}, // たぬきち|ライセンス所持状態で9本目の橋/坂建てようとしてる? + {0x66A, new EventFlagPlayer(0 , 1 , 1642, "NoticeAboutMagokoro_MainIsland" )}, // まごころ雑巾解禁後、本島側でスタジオ&家に入った初回ダイアログを見た? + {0x66B, new EventFlagPlayer(0 , 1 , 1643, "WHEREAREN_NoticeAboutDustCloth2" )}, // OneRoom|まごころ雑巾の追加用ダイアログを見た? + {0x66C, new EventFlagPlayer(0 , 1 , 1644, "GotToiletForTips" )}, // Tips|トイレ入手したか? + {0x66D, new EventFlagPlayer(0 , 1 , 1645, "GotBushForTips" )}, // Tips|低木入手したか? + {0x66E, new EventFlagPlayer(0 , 1 , 1646, "GetDresserForTips" )}, // Tips|ドレッサー入手したか? + {0x66F, new EventFlagPlayer(0 , 20 , 1647, "KppTourDidntHit_Rare" )}, // かっぺいツアー|連続ハズレカウンタ:レア島 + {0x670, new EventFlagPlayer(0 , 20 , 1648, "KppTourDidntHit_Haniwa" )}, // かっぺいツアー|連続ハズレカウンタ:はにわ島 + {0x671, new EventFlagPlayer(0 , 20 , 1649, "KppTourDidntHit_Vegetable" )}, // かっぺいツアー|連続ハズレカウンタ:やさい島 + {0x672, new EventFlagPlayer(0 , 20 , 1650, "KppTourDidntHit_DLC" )}, // かっぺいツアー|連続ハズレカウンタ:OneRoom島 + {0x673, new EventFlagPlayer(0 , 1 , 1651, "GotBonusMax" )}, // Tips|ログインボーナス上限X達したか? + {0x674, new EventFlagPlayer(0 , 512 , 1652, "GotBonusToday" )}, // Tips|今日のログインボーナスマイル? + {0x675, new EventFlagPlayer(0 , 1 , 1653, "PgeCoffeeEatInTodayFlag" )}, // マスター|今日イートインでコーヒー注文した? + {0x676, new EventFlagPlayer(0 , 1 , 1654, "RcmBlackFridayTodayFlag" )}, // まめきち|ブラックフライデーの入店時会話した? + {0x677, new EventFlagPlayer(0 , 256 , 1655, "DoneDIYCountNum" )}, // Tips|DIY家具or道具、または料理をX回したか? + {0x678, new EventFlagPlayer(0 , 1 , 1656, "RadioGymnasticsGotAllRewards" )}, // Tips|ラジオ体操の報酬プロテインまでもらった? + {0x679, new EventFlagPlayer(0 , 9999, 1657, "TtlBFirstTalkYear" )}, // コトブキ|ドンどんぐりと会話した年 + {0x67A, new EventFlagPlayer(0 , 1 , 1658, "LettersNumForTips" )}, // Tips|メッセージが100通以上残っている+未開封がある? + {0x67B, new EventFlagPlayer(0 , 3 , 1659, "WHEREAREN_GetInspectRewardsNum" )}, // OneRoom|見学した数についてナッティーからの話を聞いたかのフラグ + {0x67C, new EventFlagPlayer(0 , -1 , 1660, "JoinedPastRadioGymnasticsNum" )}, // Tips|前日以前に何回ラジオ体操に参加していないか + {0x67D, new EventFlagPlayer(0 , 1 , 1661, "WHEREAREN_NoticeAboutMemberPage" )}, // OneRoom|メンバーページを開いたときの説明ダイアログを見た? + {0x67E, new EventFlagPlayer(0 , 1 , 1662, "WHEREAREN_NoticeAboutMyPage" )}, // OneRoom|マイページを開いたときの説明ダイアログを見た? + {0x67F, new EventFlagPlayer(0 , 1 , 1663, "SpnExpandEventAfterJuneBride" )}, // パニエル|ジューンブライド初回から解禁イベントにハシゴ + {0x680, new EventFlagPlayer(0 , 1 , 1664, "RepayMileInteriorModePro" )}, // もようがえPROライセンスのマイルを返還する? + {0x681, new EventFlagPlayer(0 , 1 , 1665, "WHEREAREN_Mobile1stBoot_ResortPlannerApp" )}, // OneRoom|リゾプラappの初回起動かどうか? + {0x682, new EventFlagPlayer(0 , 1 , 1666, "MuseumCafe_Tel_CalledThisYearXct" )}, // 喫茶ハトの巣|みしらぬネコ|amiiboでみしらぬネコを今年呼び出し会話したか? + {0x683, new EventFlagPlayer(0 , 1 , 1667, "PooTalkAfterJuneBride" )}, // カットリーヌ|ジューンブライドクリア後の反応予約フラグ + {0x684, new EventFlagPlayer(0 , 1 , 1668, "KppTalkAboutVine" )}, // かっぺい|ツアーでツタの説明した? + {0x685, new EventFlagPlayer(0 , 1 , 1669, "IsOnPlayerMemoriesFireworksInMainfield" )}, // 思い出機能|花火が花火大会開催中にメインフィールドにいたがON? + {0x686, new EventFlagPlayer(0 , 1 , 1670, "IsOnPlayerMemoriesDivingFirst" )}, // 思い出機能|マリンスーツで初めて海に飛び込んだがON? + {0x687, new EventFlagPlayer(0 , 1 , 1671, "NoticeAboutInteriorModePlus_RoomSize" )}, // OneRoomでインテリアモード+の初回ダイアログを見た? + {0x688, new EventFlagPlayer(0 , 1 , 1672, "WHEREAREN_NoticeAboutResortPlannnerAppNet" )}, // OneRoom|マイページを開いたときの説明ダイアログを見た? + {0x689, new EventFlagPlayer(0 , 1 , 1673, "UnlockBuyATM" )}, // タヌポート|ATM陳列解禁 + {0x68A, new EventFlagPlayer(0 , 1 , 1674, "UnlockBuyStoreroom" )}, // タヌポート|ものおき&レシピ陳列解禁 + {0x68C, new EventFlagPlayer(0 , 1 , 1676, "NoticeAboutRoomSketch" )}, // ルームスケッチの初回ダイアログを見た? + {0x68D, new EventFlagPlayer(0 , 1 , 1677, "CommuneCompleteExpandEvent_Player" )}, // コミューン|自分がコミューン拡張(または初回イベント)みたか? + {0x68E, new EventFlagPlayer(0 , 1 , 1678, "PAnnounceAboutKppTourCompleted" )}, // 島内放送|かっぺいツアーに関する島内放送をしたか? + {0x68F, new EventFlagPlayer(0 , 1 , 1679, "MakePlayerAfterStartingKppTour" )}, // かっぺい|かっぺいツアー開始後に作られたプレイヤーか? + {0x690, new EventFlagPlayer(0 , 1 , 1680, "IsOnPlayerMemoriesSeasonPetal" )}, // 思い出機能|桜の花びらをその日初めて取得したがON? + {0x691, new EventFlagPlayer(0 , 1 , 1681, "IsOnPlayerMemoriesSeasonCrystal" )}, // 思い出機能|雪の結晶をその日初めて取得したがON? + {0x692, new EventFlagPlayer(0 , 1 , 1682, "IsOnPlayerMemoriesSeasonLeaf" )}, // 思い出機能|紅葉をその日初めて取得したがON? + {0x693, new EventFlagPlayer(0 , 1 , 1683, "IsOnPlayerMemoriesSeasonBamboo" )}, // 思い出機能|はるのわかたけをその日初めて取得したがON? + {0x694, new EventFlagPlayer(0 , 1 , 1684, "IsOnPlayerMemoriesSeasonShell" )}, // 思い出機能|夏のかいがらをその日初めて取得したがON? + {0x695, new EventFlagPlayer(0 , 1 , 1685, "IsOnPlayerMemoriesSeasonAcorn" )}, // 思い出機能|どんぐりをその日初めて取得したがON? + {0x696, new EventFlagPlayer(0 , 1 , 1686, "IsOnPlayerMemoriesSeasonPinecone" )}, // 思い出機能|まつぼっくりをその日初めて取得したがON? + {0x697, new EventFlagPlayer(0 , 1 , 1687, "WHERWAREN_NoticeAbout_ResortPlanner" )}, // OneRoom|ツクッターの初回ダイアログを見終わったか? + {0x698, new EventFlagPlayer(0 , 1 , 1688, "WHEREAREN_PlayingContentsToday" )}, // OneRoom|今日OneRoomを遊んだか + {0x699, new EventFlagPlayer(0 , 1 , 1689, "WHEREAREN_PlayedContentsBefore" )}, // OneRoom|前回OneRoomを遊んだか + {0x69A, new EventFlagPlayer(0 , 1 , 1690, "MuseumPosterTodayflagbug" )}, // フータ/博物館コンプポスター|ムシのポスターもらった? + {0x69B, new EventFlagPlayer(0 , 1 , 1691, "MuseumPosterTodayflagfish" )}, // フータ/博物館コンプポスター|サカナのポスターもらった? + {0x69C, new EventFlagPlayer(0 , 1 , 1692, "MuseumPosterTodayflagfossil" )}, // フータ/博物館コンプポスター|かせきのポスターもらった? + {0x69D, new EventFlagPlayer(0 , 1 , 1693, "MuseumPosterTodayflagpainting" )}, // フータ/博物館コンプポスター|美術品のポスターもらった? + {0x69E, new EventFlagPlayer(0 , 1 , 1694, "MuseumPosterTodayflagsea" )}, // フータ/博物館コンプポスター|海の幸のポスターもらった? + {0x69F, new EventFlagPlayer(0 , 1 , 1695, "WHEREAREN_RcoHeardRemakeWS" )}, // たぬきち|飛行場でリメイク体験会の話を聞いた + {0x6A0, new EventFlagPlayer(0 , 1 , 1696, "IsOnPlayerMemoriesMushSplendid" )}, // 思い出機能|りっぱなキノコをその日初めて取得したがON? + {0x6A1, new EventFlagPlayer(0 , 1 , 1697, "IsOnPlayerMemoriesMushRound" )}, // 思い出機能|まるいキノコをその日初めて取得したがON? + {0x6A2, new EventFlagPlayer(0 , 1 , 1698, "IsOnPlayerMemoriesMushSlender" )}, // 思い出機能|ほそいキノコをその日初めて取得したがON? + {0x6A3, new EventFlagPlayer(0 , 1 , 1699, "IsOnPlayerMemoriesMushFlat" )}, // 思い出機能|ひらたいキノコをその日初めて取得したがON? + {0x6A4, new EventFlagPlayer(0 , 1 , 1700, "IsOnPlayerMemoriesMushRare" )}, // 思い出機能|めずらしいキノコをその日初めて取得したがON? + {0x6A5, new EventFlagPlayer(0 , 1 , 1701, "RejectedTips" )}, // 徹底ライフサポート(Tips)受け取り拒否設定がON? + {0x6A6, new EventFlagPlayer(0 , 1 , 1702, "UnlockBuyRcoOnePieceAerobics" )}, // ラジオ体操|レオタードをタヌポートにも陳列 + {0x6A7, new EventFlagPlayer(0 , 1 , 1703, "UnlockBuyRcoYogaMat" )}, // ラジオ体操|ヨガマットをタヌポートにも陳列 + {0x6AA, new EventFlagPlayer(0 , 1 , 1706, "DodSelectWherearenFromBeginning" )}, // モーリー|「お仕事に行く」の説明を他の件と一緒に聞いた + {0x6AB, new EventFlagPlayer(0 , 1 , 1707, "EquipDustClothWithGateOpen" )}, // まごころ雑巾|開門中にまごころ雑巾を装備のダイアログを見た? + {0x6AD, new EventFlagPlayer(0 , 1 , 1709, "WHEREAREN_NoticeAboutFirstPublication_ResortPlanner")}, // OneRoom|マイページにて「施工事例から選んでね」ダイアログを一度表示したかどうか? + {0x6AE, new EventFlagPlayer(0 , 1 , 1710, "TalkAboutNpcHouseCoordeHint" )}, // たぬきち|NPC家コーデ内装初回説明したか? + {0x6AF, new EventFlagPlayer(0 , 10 , 1711, "NpcHouseCoordinateTodayCount" )}, // たぬきち|NPC家コーデの当日内回数チェックカウンタ + {0x6B0, new EventFlagPlayer(0 , 1 , 1712, "PublicAnnouncement_MarinsuitHint" )}, // 島内放送|マリンスーツのヒントを聞いたか? + {0x6B1, new EventFlagPlayer(0 , 1 , 1713, "WHEREAREN_NoticeAboutSNSShare" )}, // OneRoom|ツクッター初回掲載後のSN共有の説明を見た? + {0x6B2, new EventFlagPlayer(0 , 10 , 1714, "PlanPalmSeedOnSand" )}, // Tips|やしのみを砂浜に植えた回数 + {0x6B3, new EventFlagPlayer(0 , 10 , 1715, "PlanBambooshoot" )}, // Tips|たけのこを植えた回数 + {0x6B4, new EventFlagPlayer(0 , 1 , 1716, "PlayerDoneEating" )}, // Tips|料理を1回以上「食べる」をした + {0x6B5, new EventFlagPlayer(0 , 10 , 1717, "OpenUIMenuLoadTipsCount" )}, // Tips|徹底ライフサポートUIを開いた回数 + {0x6B6, new EventFlagPlayer(0 , 1 , 1718, "PlayerUsedChangeStick" )}, // Tips|変身ステッキを使ったことがあるか + {0x6B7, new EventFlagPlayer(0 , 1 , 1719, "ScanAmiiboInCafe" )}, // Tips|喫茶店でAmiibo読み込みを行った + {0x6B8, new EventFlagPlayer(0 , 1 , 1720, "ScanAmiiboInPhotoStudio" )}, // Tips|撮影スタジオでAmiibo読み込みを行った + {0x6B9, new EventFlagPlayer(0 , 1 , 1721, "RequestedAlpRemake" )}, // Tips|カイゾーにリメイクを依頼した + {0x6BA, new EventFlagPlayer(0 , 1 , 1722, "RequestedAlpUniqueRemake" )}, // Tips|カイゾーにカイゾーにしかできないリメイクを依頼した + {0x6BB, new EventFlagPlayer(0 , 1 , 1723, "AlreadyCheckedFirstTips1" )}, // 初回用固定Tips1を見た + {0x6BC, new EventFlagPlayer(0 , 1 , 1724, "AlreadyCheckedFirstTips2" )}, // 初回用固定Tips2を見た + {0x6BD, new EventFlagPlayer(0 , 1 , 1725, "AlreadyCheckedOneRoomFirstTips1" )}, // OneRoom権利獲得後初回固定Tips1を見た + {0x6BE, new EventFlagPlayer(0 , 1 , 1726, "SloFirstTalkCommune" )}, // レイジ|コミューン島で初対面会話した? + {0x6BF, new EventFlagPlayer(0 , 5 , 1727, "SalmonCookingRecipeCount" )}, // DIY|レシピ1つ覚えた後、サケを釣り上げた回数をカウント + {0x6C0, new EventFlagPlayer(0 , 1 , 1728, "StandByCallByRcoNpcHouseCoodinate" )}, // 電話デモ|たぬきちNPC家エディット導入入電するか? + {0x6C1, new EventFlagPlayer(0 , 1 , 1729, "RcoCoordinateUnlockWithPhoneCall" )}, // たぬきち|NPC家エディット解禁電話聞いたか? + {0x6C2, new EventFlagPlayer(0 , 3 , 1730, "SloVegetableCount" )}, // レイジ|野菜の苗を買い物した回数 + {0x6C3, new EventFlagPlayer(0 , 1 , 1731, "SloBuyVegetableToday" )}, // レイジ|今日野菜の買い物したか + {0x6C4, new EventFlagPlayer(0 , 1 , 1732, "SloBuyToday" )}, // レイジ|今日レイジから買い物したか? + {0x6C6, new EventFlagPlayer(0 , 1 , 1734, "WHEREAREN_IsSnsShareCanceled" )}, // OneRoom|デイリー表示される掲載後のSNSShareをキャンセルしたか? + {0x6C8, new EventFlagPlayer(0 , 1 , 1736, "OtgTipsUnlockGardenEdit" )}, // Tips|2件目庭(季節変更、時間帯変更、庭エディット解禁) + {0x6C9, new EventFlagPlayer(0 , 1 , 1737, "OtgTipsComplete1stOrder" )}, // Tips|1件目完了(オーディオ家具解禁) + {0x6CA, new EventFlagPlayer(0 , 1 , 1738, "RcoBuildMovingPurchase_v200" )}, // たぬきち|v2.0.0で何らかの移設費用支払った? + {0x6CB, new EventFlagPlayer(0 , 1 , 1739, "SendLetterBuildMovingPricedown" )}, // たぬきち|移設費用値下げの手紙送った? + {0x6CC, new EventFlagPlayer(0 , 1 , 1740, "ReturnMyHomeMoving8000PMoving" )}, // たぬきち|Pだけ引越しで返金されたマイホーム移設費用は8000ベル? + {0x6CD, new EventFlagPlayer(0 , 1 , 1741, "OtgTipsUnlockWorkingTable" )}, // Tips|6件目完了(2FDIY作業台解禁) + {0x6CE, new EventFlagPlayer(0 , 1 , 1742, "WHEREAREN_UnlockMessageBottleAfter" )}, // Tips|ウェアラン諸島でメッセージボトル解禁されてから1成長処理経過 + {0x6CF, new EventFlagPlayer(0 , 1 , 1743, "OtgTipsCompleteSchoolBuild" )}, // Tips|学校完成(キャストUI、施設リフォーム解禁) + {0x6D0, new EventFlagPlayer(0 , 1 , 1744, "OtgTipsCompleteSloSchoolEvent" )}, // Tips|レイジの授業完了(交配花の一部解禁) + {0x6D1, new EventFlagPlayer(0 , 1 , 1745, "RcoOfficeBuiltLetter" )}, // 案内所完成の案内手紙投函された + {0x6D2, new EventFlagPlayer(0 , 1 , 1746, "WatchedRcoAnnouceAfter200ver" )}, // 2.0.0以降verでたぬきち島内放送を見た + {0x6D3, new EventFlagPlayer(0 , 1 , 1747, "OtgTipsComplete2ndFacilityBuild" )}, // Tips|カフェ/レストラン少なくともどちらかが完成 + {0x6D4, new EventFlagPlayer(0 , 1 , 1748, "OtgTipsUnlockDIYFtrCatalog" )}, // Tips|DIYしたことある家具のカタログ解禁 + {0x6D5, new EventFlagPlayer(0 , 1 , 1749, "ScanAmiiboInTanuport" )}, // Tips|タヌポートでAmiibo読み込みを行った + {0x6D6, new EventFlagPlayer(0 , 1 , 1750, "OtgTipsUnlockHouseShare" )}, // Tips|シェアハウス解禁 + {0x6D7, new EventFlagPlayer(0 , 1 , 1751, "OtgTipsCompleteCafeBuild" )}, // Tips|カフェ完成 + {0x6D8, new EventFlagPlayer(0 , 1 , 1752, "OtgTipsCompleteRestaulantBuild" )}, // Tips|レストラン完成 + {0x6D9, new EventFlagPlayer(0 , 1 , 1753, "OtgTipsCompleteHospitalBuild" )}, // Tips|病院完成 + {0x6DA, new EventFlagPlayer(0 , 1 , 1754, "OtgTipsCompleteBoutiqueBuild" )}, // Tips|アパレルショップ完成 + {0x6DB, new EventFlagPlayer(0 , 1 , 1755, "OtgTipsCompleteHospitalDonation" )}, // Tips|病院の募金が完了した + {0x6DC, new EventFlagPlayer(0 , 1 , 1756, "OtgTipsBuildEitherCafeRestaulant" )}, // Tips|カフェ/レストランどちらかが未完成 + {0x6DD, new EventFlagPlayer(0 , 1 , 1757, "WHEREAREN_SeqAvailableAmiiboDone" )}, // Tips|amiibo読取機解禁イベントを見た? + {0x6DE, new EventFlagPlayer(0 , 2 , 1758, "BocFirstMail" )}, // ウリ|商店が建ったときの手紙を出したか? + {0x6DF, new EventFlagPlayer(0 , 1 , 1759, "OtgTipsExplainManCatalog" )}, // Tips|ナッティーカタログ解禁説明聞いた? + {0x6E0, new EventFlagPlayer(0 , 1 , 1760, "OtgTipsUnlockATM" )}, // Tips|事務所ATM解禁した? + {0x6E1, new EventFlagPlayer(0 , 1 , 1761, "CommuneATMChkToday" )}, // コミューン|今日ATMをチェックした? + {0x6E2, new EventFlagPlayer(0 , 1 , 1762, "SpnCommuneATMNoticeDone" )}, // パニエル|ATMについて喋った? + {0x6E3, new EventFlagPlayer(0 , 1 , 1763, "RcoTalkAboutNpcHouseEditOfficeBuild" )}, // たぬきち|Pだけ引越し後案内所完成したら、NPC家コーデの解禁告知するか? + {0x6E4, new EventFlagPlayer(0 , 1 , 1764, "RcoPMovingUnlockNpcEditWithPhoneCall" )}, // たぬきち|入電は聞いたがNPC家コーデを解禁せずにPだけ引越しした + {0x6E5, new EventFlagPlayer(0 , 1 , 1765, "WHERWAREN_NoticeAbout_ResortPlannerRevisit" )}, // OneRoom|訪問機能の説明ダイアログを見た? + {0x6E6, new EventFlagPlayer(0 , 1 , 1766, "PublicAnnoucement_EvNotice_Carnival" )}, // 島内放送|カーニバルの予告を聞いたか? + {0x6E7, new EventFlagPlayer(0 , 1 , 1767, "WHEREAREN_OtgVisitThisIsland" )}, // 今住んでる島でOneRoomの解禁イベントを見た + {0x6E8, new EventFlagPlayer(0 , 1 , 1768, "DocUnlockSpnOtgDirectRoute" )}, // ロドリー|直行便解禁会話見た? + {0x6E9, new EventFlagPlayer(0 , 1 , 1769, "UnlockCatalogPokiBag" )}, // カタログ|ポキ袋をスタジオやOneRoomのカタログで解禁 + {0x6EA, new EventFlagPlayer(0 , 1 , 1770, "PAnnounceFishingEvNotice_Jan" )}, // 島内放送|釣り大会の予告を聞いたか(1月) + {0x6EB, new EventFlagPlayer(0 , 1 , 1771, "PAnnounceFishingEvNotice_Apr" )}, // 島内放送|釣り大会の予告を聞いたか(4月) + {0x6EC, new EventFlagPlayer(0 , 1 , 1772, "PAnnounceFishingEvNotice_Jul" )}, // 島内放送|釣り大会の予告を聞いたか(7月) + {0x6ED, new EventFlagPlayer(0 , 1 , 1773, "PAnnounceFishingEvNotice_Oct" )}, // 島内放送|釣り大会の予告を聞いたか(10月) + {0x6EE, new EventFlagPlayer(0 , 1 , 1774, "PAnnounceInsectEvNotice_1" )}, // 島内放送|ムシとり大会の予告を聞いたか① + {0x6EF, new EventFlagPlayer(0 , 1 , 1775, "PAnnounceInsectEvNotice_2" )}, // 島内放送|ムシとり大会の予告を聞いたか② + {0x6F0, new EventFlagPlayer(0 , 1 , 1776, "PAnnounceInsectEvNotice_3" )}, // 島内放送|ムシとり大会の予告を聞いたか③ + {0x6F1, new EventFlagPlayer(0 , 1 , 1777, "PAnnounceInsectEvNotice_4" )}, // 島内放送|ムシとり大会の予告を聞いたか④ + {0x6F2, new EventFlagPlayer(0 , 1 , 1778, "PAnnounceFireWorksEvNotice" )}, // 島内放送|花火大会の予告を聞いたか + {0x6F3, new EventFlagPlayer(0 , 1 , 1779, "PAnnounceCountdownEvNotice" )}, // 島内放送|大晦日の予告を聞いたか + {0x6F4, new EventFlagPlayer(0 , 1 , 1780, "StandByPhoneCallMayDayTour" )}, // 電話デモ|メーデー告知の入電するか? + {0x6F7, new EventFlagPlayer(0 , 1 , 1783, "DrinkCoffeeToday" )}, // 喫茶ハトの巣|今日コーヒーを飲んだか(実績用) + {0x6F8, new EventFlagPlayer(0 , 1 , 1784, "RcoTipsPurchaseBoxUsed" )}, // Tips|買取BOX使ったことある? + {0x6F9, new EventFlagPlayer(0 , 1 , 1785, "SloExplainbush" )}, // レイジ|低木について個別に説明するか? + {0x6FA, new EventFlagPlayer(0 , 1 , 1786, "SloRecommendbush" )}, // レイジ|コミューン島今週のおすすめの低木を伝えたか + {0x6FB, new EventFlagPlayer(0 , 2 , 1787, "PMovingTmpDustCloth" )}, // プレイヤーだけ引越し|まごころ雑巾をP引越し時に一時的に使えなくするためのtmpフラグ + {0x6FC, new EventFlagPlayer(0 , 1 , 1788, "RcoTipsRcoMachineLoginBonus" )}, // Tips|タヌポートログボのTips出す? + }; + + private const string Unknown = "???"; + + public static string GetName(ushort index, short count, IReadOnlyDictionary str) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + { + string name = val.Name; + if (str.TryGetValue(name, out var translated)) + name = translated; + return $"{index:00} - {name} = {count}"; + } + return $"{index:00} - {Unknown} = {count}"; + } + + public static string GetName(ushort index, short count) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + return $"{index:00} - {val.Name} = {count}"; + return $"{index:00} - {Unknown} = {count}"; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Records/EventFlagVillager.cs b/NHSE.Core/Structures/Records/EventFlagVillager.cs index 77c6e63..a31fd1e 100644 --- a/NHSE.Core/Structures/Records/EventFlagVillager.cs +++ b/NHSE.Core/Structures/Records/EventFlagVillager.cs @@ -1,110 +1,109 @@ using System.Collections.Generic; // ReSharper disable StringLiteralTypo -namespace NHSE.Core +namespace NHSE.Core; + +public class EventFlagVillager : INamedValue { - public class EventFlagVillager : INamedValue + public readonly short Value1; + public readonly short Value2; + + public ushort Index { get; } + public string Name { get; } + + public EventFlagVillager(short v1, short v2, ushort index, string name) { - public readonly short Value1; - public readonly short Value2; - - public ushort Index { get; } - public string Name { get; } - - public EventFlagVillager(short v1, short v2, ushort index, string name) - { - Name = name; - Index = index; - Value1 = v1; - Value2 = v2; - } - - public static readonly IReadOnlyDictionary List = new Dictionary - { - {0x000, new EventFlagVillager(0 , 200 , 0000, "NnpcHouseLoan" )}, // ローン返済カウント - {0x001, new EventFlagVillager(0 , 1 , 0001, "NnpcHouseBuildOk" )}, // NPCテント建て替え許可 - {0x002, new EventFlagVillager(0 , 1 , 0002, "NnpcHouseBuilt" )}, // NPCの家建て替え済み - {0x003, new EventFlagVillager(0 , 1 , 0003, "CoordinateUpdate" )}, // 家具配置更新済か - {0x004, new EventFlagVillager(0 , 1 , 0004, "Is3rdNpc" )}, // 3人目のNPCか? - {0x005, new EventFlagVillager(0 , 1 , 0005, "MoveInCompletion" )}, // 引越し完了済みか - {0x006, new EventFlagVillager(0 , 10 , 0006, "LastFtrNum" )}, // 最後に配置した家具の数 - {0x007, new EventFlagVillager(10, 10 , 0007, "MoveRoomIndex" )}, // ダンボール部屋表示に使用したテンプレート番号 - {0x008, new EventFlagVillager(0 , 1 , 0008, "PlayerNamePhrase" )}, // 口癖はプレイヤーが設定したものか - {0x009, new EventFlagVillager(0 , 2 , 0009, "AbandonedHouse" )}, // 自宅を空き家状態にするか - {0x00A, new EventFlagVillager(0 , 1 , 0010, "InputPhrase" )}, // 口癖を設定した事あるか - {0x00C, new EventFlagVillager(0 , 1 , 0012, "TalkLifeStart1P1st" )}, // React_1P_Lifestart発生したか - {0x00E, new EventFlagVillager(0 , 1 , 0014, "FromSettlerQuest" )}, // 住人移住クエストで来たNPCか - {0x00F, new EventFlagVillager(0 , 1 , 0015, "ChangeFirstWall" )}, // 初期住人用壁紙を変更したか - {0x010, new EventFlagVillager(0 , 1 , 0016, "ChangeFirstFloor" )}, // 初期住人用床板を変更したか - {0x012, new EventFlagVillager(0 , 1 , 0018, "GetFirstVillagerWallFtr1" )}, // 初期住人用壁掛け家具1を入手したか - {0x013, new EventFlagVillager(0 , 1 , 0019, "GetFirstVillagerWallFtr2" )}, // 初期住人用壁掛け家具2を入手したか - {0x014, new EventFlagVillager(0 , 2 , 0020, "UseAudioType" )}, // 今日使用するオーディオ家具の種類 - {0x015, new EventFlagVillager(0 , 3 , 0021, "TalkTransitionTimes" )}, // 序盤→日常移行会話を呼んだ回数 - {0x016, new EventFlagVillager(0 , 1 , 0022, "FinishTalkTransition" )}, // 序盤→日常移行会話を聞き終えたか - {0x017, new EventFlagVillager(0 , 3 , 0023, "OutdoorCatnap" )}, // 深夜屋外でのうたた寝判定状況 - {0x018, new EventFlagVillager(0 , 1 , 0024, "ForceMoveOut" )}, // 強制的に転出させられるフラグ - {0x019, new EventFlagVillager(0 , 4 , 0025, "EarlyOrLate" )}, // 早起き・夜更かしフラグ - {0x01A, new EventFlagVillager(0 , 16 , 0026, "ContinuousNormalDay" )}, // 平常活動の連続日数 - {0x01B, new EventFlagVillager(0 , 1 , 0027, "React1stNpcPresent" )}, // React_1P_Lifestartのプレゼント装備の反応発生したか - {0x01C, new EventFlagVillager(0 , 1 , 0028, "IsReFabricSmartPhone" )}, // スマホ柄に汎用布地を使うか? - {0x01D, new EventFlagVillager(0 , 1 , 0029, "MarketBuildingSupport" )}, // お店の資材集め応援会話発生したか? - {0x020, new EventFlagVillager(0 , 1 , 0032, "NnpcHouseBuiltToday" )}, // NPCの家建て替え済み当日 - {0x023, new EventFlagVillager(0 , 1 , 0035, "AppE_Happen1st" )}, // このNPCの評判UP応援アプローチ会話発生済か? - {0x024, new EventFlagVillager(0 , 1 , 0036, "AppE_GetItem1st" )}, // このNPCの評判UP応援アイテムもらったことあるか? - {0x025, new EventFlagVillager(0 , 1 , 0037, "AppE_Rep_HappenToday" )}, // 今日このNPCの評判UP応援アプローチ会話発生済か? - {0x026, new EventFlagVillager(0 , 1 , 0038, "AppE_WelcomoMigrants" )}, // このNPCはAppE_WelcomoMigrants発生済か? - {0x028, new EventFlagVillager(0 , 1 , 0040, "AppE_WelcomeMigrantsToday" )}, // このNPCのAppE_WelcomeMigrants発生当日か? - {0x029, new EventFlagVillager(0 , 10 , 0041, "MoveInOrder" )}, // 土地売約済み状態のNPCの転入順 - {0x02A, new EventFlagVillager(0 , 1 , 0042, "EquipEasterWear" )}, // イースター用装備にする - {0x02B, new EventFlagVillager(0 , 10 , 0043, "ForceMoveOutVillagerIndex" )}, // 強制転出に指定した住人番号 - {0x02C, new EventFlagVillager(0 , 1 , 0044, "DisplayJuneBridePresent" )}, // ジューンブライド | 絵皿を飾るか? - {0x02D, new EventFlagVillager(0 , 7 , 0045, "ProgressDaysJuneBrideParty" )}, // ジューンブライド | 結婚パーティに参加してからの経過日数 - {0x031, new EventFlagVillager(0 , 6 , 0049, "EnableConvTalkDaysCount" )}, // 会話のフリを解禁するまでの日数 - {0x032, new EventFlagVillager(0 , 29 , 0050, "WantIngredients" )}, // ハーベスト|要求する食材 - {0x033, new EventFlagVillager(0 , 29 , 0051, "BeforeGiveIngredients" )}, // ハーベスト|直前にくれた食材 - {0x034, new EventFlagVillager(0 , 29 , 0052, "BeforeWantIngredients" )}, // ハーベスト|直前に要求した食材 - {0x036, new EventFlagVillager(0 , 300 , 0054, "XmasEveWakeUpMinute" )}, // クリスマス|起床時刻制御用 - {0x037, new EventFlagVillager(0 , 1 , 0055, "EquipChristmasWear" )}, // クリスマス用装備にする - {0x038, new EventFlagVillager(0 , 2 , 0056, "HarvestGiveHint1" )}, // ハーベスト|1品目の隠し食材ヒント出したら1か2をセット - {0x039, new EventFlagVillager(0 , 2 , 0057, "HarvestGiveHint2" )}, // ハーベスト|2品目の隠し食材ヒント出したら1か2をセット - {0x03A, new EventFlagVillager(0 , 2 , 0058, "HarvestGiveHint3" )}, // ハーベスト|3品目の隠し食材ヒント出したら1か2をセット - {0x03B, new EventFlagVillager(0 , 2 , 0059, "HarvestGiveHint4" )}, // ハーベスト|4品目の隠し食材ヒント出したら1か2をセット - {0x03D, new EventFlagVillager(0 , 3 , 0061, "CarnivalFeatherColor" )}, // カーニバル|欲しがる羽の色 - {0x03E, new EventFlagVillager(0 , 10 , 0062, "DisplayValentinePresent" )}, // バレンタインデー|飾られるブーケの種類 - {0x040, new EventFlagVillager(0 , 1 , 0064, "HarvestDemoEndWait" )}, // ハーベスト|デモ終了待機中か? - {0x041, new EventFlagVillager(0 , 1 , 0065, "WoreNewYearHat" )}, // カウントダウン|ニューイヤーハットを被った - {0x042, new EventFlagVillager(0 , 1 , 0066, "HarvestDemoStateNow" )}, // ハーベスト|デモ参加状態か? - {0x045, new EventFlagVillager(0 , 3 , 0069, "CoordinateDIYStatus" )}, // OneRoom | 家コーディネートの作業台の状態 - {0x046, new EventFlagVillager(0 , 36 , 0070, "WearItemLayer1LayoutLimit" )}, // 成長処理家具入替時の装備品の二層目配置候補上限数 - {0x047, new EventFlagVillager(0 , 1 , 0071, "CookingInDIYSchedule" )}, // DIY予定の時間に料理をするか - {0x048, new EventFlagVillager(0 , 3000, 0072, "MuseumCafeExitTime" )}, // 喫茶ハトの巣|ランダム来店撤収時刻 - {0x049, new EventFlagVillager(0 , 1 , 0073, "HouseReset" )}, // 案内所で自宅リセットされた - {0x04A, new EventFlagVillager(0 , 3 , 0074, "ReserveDIYStatus" )}, // 家コーディネートの作業台の状態予約 - {0x04B, new EventFlagVillager(0 , 3 , 0075, "AudioShuffleState" )}, // 編集された部屋のオーディオのシャッフル設定 - {0x04C, new EventFlagVillager(0 , 3 , 0076, "IslandKitchenStandPos" )}, // 調理行動時アイランドキッチンの正面側に立つか - }; - - private const string Unknown = "???"; - - public static string GetName(ushort index, uint count, IReadOnlyDictionary str) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - { - string name = val.Name; - if (str.TryGetValue(name, out var translated)) - name = translated; - return $"{index:00} - {name} = {count}"; - } - return $"{index:00} - {Unknown} = {count}"; - } - - public static string GetName(ushort index, uint count) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - return $"{index:00} - {val.Name} = {count}"; - return $"{index:00} - {Unknown} = {count}"; - } + Name = name; + Index = index; + Value1 = v1; + Value2 = v2; } -} + + public static readonly IReadOnlyDictionary List = new Dictionary + { + {0x000, new EventFlagVillager(0 , 200 , 0000, "NnpcHouseLoan" )}, // ローン返済カウント + {0x001, new EventFlagVillager(0 , 1 , 0001, "NnpcHouseBuildOk" )}, // NPCテント建て替え許可 + {0x002, new EventFlagVillager(0 , 1 , 0002, "NnpcHouseBuilt" )}, // NPCの家建て替え済み + {0x003, new EventFlagVillager(0 , 1 , 0003, "CoordinateUpdate" )}, // 家具配置更新済か + {0x004, new EventFlagVillager(0 , 1 , 0004, "Is3rdNpc" )}, // 3人目のNPCか? + {0x005, new EventFlagVillager(0 , 1 , 0005, "MoveInCompletion" )}, // 引越し完了済みか + {0x006, new EventFlagVillager(0 , 10 , 0006, "LastFtrNum" )}, // 最後に配置した家具の数 + {0x007, new EventFlagVillager(10, 10 , 0007, "MoveRoomIndex" )}, // ダンボール部屋表示に使用したテンプレート番号 + {0x008, new EventFlagVillager(0 , 1 , 0008, "PlayerNamePhrase" )}, // 口癖はプレイヤーが設定したものか + {0x009, new EventFlagVillager(0 , 2 , 0009, "AbandonedHouse" )}, // 自宅を空き家状態にするか + {0x00A, new EventFlagVillager(0 , 1 , 0010, "InputPhrase" )}, // 口癖を設定した事あるか + {0x00C, new EventFlagVillager(0 , 1 , 0012, "TalkLifeStart1P1st" )}, // React_1P_Lifestart発生したか + {0x00E, new EventFlagVillager(0 , 1 , 0014, "FromSettlerQuest" )}, // 住人移住クエストで来たNPCか + {0x00F, new EventFlagVillager(0 , 1 , 0015, "ChangeFirstWall" )}, // 初期住人用壁紙を変更したか + {0x010, new EventFlagVillager(0 , 1 , 0016, "ChangeFirstFloor" )}, // 初期住人用床板を変更したか + {0x012, new EventFlagVillager(0 , 1 , 0018, "GetFirstVillagerWallFtr1" )}, // 初期住人用壁掛け家具1を入手したか + {0x013, new EventFlagVillager(0 , 1 , 0019, "GetFirstVillagerWallFtr2" )}, // 初期住人用壁掛け家具2を入手したか + {0x014, new EventFlagVillager(0 , 2 , 0020, "UseAudioType" )}, // 今日使用するオーディオ家具の種類 + {0x015, new EventFlagVillager(0 , 3 , 0021, "TalkTransitionTimes" )}, // 序盤→日常移行会話を呼んだ回数 + {0x016, new EventFlagVillager(0 , 1 , 0022, "FinishTalkTransition" )}, // 序盤→日常移行会話を聞き終えたか + {0x017, new EventFlagVillager(0 , 3 , 0023, "OutdoorCatnap" )}, // 深夜屋外でのうたた寝判定状況 + {0x018, new EventFlagVillager(0 , 1 , 0024, "ForceMoveOut" )}, // 強制的に転出させられるフラグ + {0x019, new EventFlagVillager(0 , 4 , 0025, "EarlyOrLate" )}, // 早起き・夜更かしフラグ + {0x01A, new EventFlagVillager(0 , 16 , 0026, "ContinuousNormalDay" )}, // 平常活動の連続日数 + {0x01B, new EventFlagVillager(0 , 1 , 0027, "React1stNpcPresent" )}, // React_1P_Lifestartのプレゼント装備の反応発生したか + {0x01C, new EventFlagVillager(0 , 1 , 0028, "IsReFabricSmartPhone" )}, // スマホ柄に汎用布地を使うか? + {0x01D, new EventFlagVillager(0 , 1 , 0029, "MarketBuildingSupport" )}, // お店の資材集め応援会話発生したか? + {0x020, new EventFlagVillager(0 , 1 , 0032, "NnpcHouseBuiltToday" )}, // NPCの家建て替え済み当日 + {0x023, new EventFlagVillager(0 , 1 , 0035, "AppE_Happen1st" )}, // このNPCの評判UP応援アプローチ会話発生済か? + {0x024, new EventFlagVillager(0 , 1 , 0036, "AppE_GetItem1st" )}, // このNPCの評判UP応援アイテムもらったことあるか? + {0x025, new EventFlagVillager(0 , 1 , 0037, "AppE_Rep_HappenToday" )}, // 今日このNPCの評判UP応援アプローチ会話発生済か? + {0x026, new EventFlagVillager(0 , 1 , 0038, "AppE_WelcomoMigrants" )}, // このNPCはAppE_WelcomoMigrants発生済か? + {0x028, new EventFlagVillager(0 , 1 , 0040, "AppE_WelcomeMigrantsToday" )}, // このNPCのAppE_WelcomeMigrants発生当日か? + {0x029, new EventFlagVillager(0 , 10 , 0041, "MoveInOrder" )}, // 土地売約済み状態のNPCの転入順 + {0x02A, new EventFlagVillager(0 , 1 , 0042, "EquipEasterWear" )}, // イースター用装備にする + {0x02B, new EventFlagVillager(0 , 10 , 0043, "ForceMoveOutVillagerIndex" )}, // 強制転出に指定した住人番号 + {0x02C, new EventFlagVillager(0 , 1 , 0044, "DisplayJuneBridePresent" )}, // ジューンブライド | 絵皿を飾るか? + {0x02D, new EventFlagVillager(0 , 7 , 0045, "ProgressDaysJuneBrideParty" )}, // ジューンブライド | 結婚パーティに参加してからの経過日数 + {0x031, new EventFlagVillager(0 , 6 , 0049, "EnableConvTalkDaysCount" )}, // 会話のフリを解禁するまでの日数 + {0x032, new EventFlagVillager(0 , 29 , 0050, "WantIngredients" )}, // ハーベスト|要求する食材 + {0x033, new EventFlagVillager(0 , 29 , 0051, "BeforeGiveIngredients" )}, // ハーベスト|直前にくれた食材 + {0x034, new EventFlagVillager(0 , 29 , 0052, "BeforeWantIngredients" )}, // ハーベスト|直前に要求した食材 + {0x036, new EventFlagVillager(0 , 300 , 0054, "XmasEveWakeUpMinute" )}, // クリスマス|起床時刻制御用 + {0x037, new EventFlagVillager(0 , 1 , 0055, "EquipChristmasWear" )}, // クリスマス用装備にする + {0x038, new EventFlagVillager(0 , 2 , 0056, "HarvestGiveHint1" )}, // ハーベスト|1品目の隠し食材ヒント出したら1か2をセット + {0x039, new EventFlagVillager(0 , 2 , 0057, "HarvestGiveHint2" )}, // ハーベスト|2品目の隠し食材ヒント出したら1か2をセット + {0x03A, new EventFlagVillager(0 , 2 , 0058, "HarvestGiveHint3" )}, // ハーベスト|3品目の隠し食材ヒント出したら1か2をセット + {0x03B, new EventFlagVillager(0 , 2 , 0059, "HarvestGiveHint4" )}, // ハーベスト|4品目の隠し食材ヒント出したら1か2をセット + {0x03D, new EventFlagVillager(0 , 3 , 0061, "CarnivalFeatherColor" )}, // カーニバル|欲しがる羽の色 + {0x03E, new EventFlagVillager(0 , 10 , 0062, "DisplayValentinePresent" )}, // バレンタインデー|飾られるブーケの種類 + {0x040, new EventFlagVillager(0 , 1 , 0064, "HarvestDemoEndWait" )}, // ハーベスト|デモ終了待機中か? + {0x041, new EventFlagVillager(0 , 1 , 0065, "WoreNewYearHat" )}, // カウントダウン|ニューイヤーハットを被った + {0x042, new EventFlagVillager(0 , 1 , 0066, "HarvestDemoStateNow" )}, // ハーベスト|デモ参加状態か? + {0x045, new EventFlagVillager(0 , 3 , 0069, "CoordinateDIYStatus" )}, // OneRoom | 家コーディネートの作業台の状態 + {0x046, new EventFlagVillager(0 , 36 , 0070, "WearItemLayer1LayoutLimit" )}, // 成長処理家具入替時の装備品の二層目配置候補上限数 + {0x047, new EventFlagVillager(0 , 1 , 0071, "CookingInDIYSchedule" )}, // DIY予定の時間に料理をするか + {0x048, new EventFlagVillager(0 , 3000, 0072, "MuseumCafeExitTime" )}, // 喫茶ハトの巣|ランダム来店撤収時刻 + {0x049, new EventFlagVillager(0 , 1 , 0073, "HouseReset" )}, // 案内所で自宅リセットされた + {0x04A, new EventFlagVillager(0 , 3 , 0074, "ReserveDIYStatus" )}, // 家コーディネートの作業台の状態予約 + {0x04B, new EventFlagVillager(0 , 3 , 0075, "AudioShuffleState" )}, // 編集された部屋のオーディオのシャッフル設定 + {0x04C, new EventFlagVillager(0 , 3 , 0076, "IslandKitchenStandPos" )}, // 調理行動時アイランドキッチンの正面側に立つか + }; + + private const string Unknown = "???"; + + public static string GetName(ushort index, uint count, IReadOnlyDictionary str) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + { + string name = val.Name; + if (str.TryGetValue(name, out var translated)) + name = translated; + return $"{index:00} - {name} = {count}"; + } + return $"{index:00} - {Unknown} = {count}"; + } + + public static string GetName(ushort index, uint count) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + return $"{index:00} - {val.Name} = {count}"; + return $"{index:00} - {Unknown} = {count}"; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Records/EventFlagVillagerMemoryPlayer.cs b/NHSE.Core/Structures/Records/EventFlagVillagerMemoryPlayer.cs index 1e096e3..ff6f8f4 100644 --- a/NHSE.Core/Structures/Records/EventFlagVillagerMemoryPlayer.cs +++ b/NHSE.Core/Structures/Records/EventFlagVillagerMemoryPlayer.cs @@ -1,213 +1,212 @@ using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public class EventFlagVillagerMemoryPlayer : INamedValue { - public class EventFlagVillagerMemoryPlayer : INamedValue + public readonly byte Initial; + public readonly byte Maximum; + + public ushort Index { get; } + public string Name { get; } + + public EventFlagVillagerMemoryPlayer(byte init, byte max, ushort index, string name) { - public readonly byte Initial; - public readonly byte Maximum; - - public ushort Index { get; } - public string Name { get; } - - public EventFlagVillagerMemoryPlayer(byte init, byte max, ushort index, string name) - { - Name = name; - Index = index; - Initial = init; - Maximum = max; - } - - public static readonly IReadOnlyDictionary List = new Dictionary - { - {0x00, new EventFlagVillagerMemoryPlayer(0 , 1 , 000, "TalkFreeMultiDayEventNow" )}, // (ボツ)今、期間型イベント用のFreeFを聞いたか? - {0x01, new EventFlagVillagerMemoryPlayer(0 , 7 , 001, "ContinuousTalkDays" )}, // 何日連続で話しかけられたか - {0x02, new EventFlagVillagerMemoryPlayer(0 , 1 , 002, "SameLand" )}, // 同じ村に住んでいたことがあるか - {0x03, new EventFlagVillagerMemoryPlayer(0 , 1 , 003, "SetGreeting" )}, // 挨拶を設定したことがある - {0x04, new EventFlagVillagerMemoryPlayer(0 , 1 , 004, "EasterGetRecipeFlag" )}, // イースター|今日このNPCからアイテムを受け取った - {0x05, new EventFlagVillagerMemoryPlayer(0 , 1 , 005, "TalkProgressMuseumBuilt2" )}, // 博物館2への拡張に関するFreeH_Progressを聞いたか? - {0x06, new EventFlagVillagerMemoryPlayer(0 , 1 , 006, "NextMoveOutTalk" )}, // 引越ししたい会話したか - {0x07, new EventFlagVillagerMemoryPlayer(0 , 1 , 007, "TalkMoveOut" )}, // 引越していく状態で会話したか - {0x08, new EventFlagVillagerMemoryPlayer(0 , 7 , 008, "VisitCount" )}, // そのプレイヤーの家に行った回数 - {0x09, new EventFlagVillagerMemoryPlayer(0 , 7 , 009, "VisitedCount" )}, // そのプレイヤーが家に来た回数 - {0x0A, new EventFlagVillagerMemoryPlayer(25, 255, 010, "Friendship" )}, // 親密度 - {0x0B, new EventFlagVillagerMemoryPlayer(0 , 9 , 011, "TalkCountToday" )}, // 今日の会話回数(通算) - {0x0C, new EventFlagVillagerMemoryPlayer(0 , 7 , 012, "TalkCountInNpcHouseToday" )}, // 今日NPCの家での会話回数 - {0x0D, new EventFlagVillagerMemoryPlayer(0 , 1 , 013, "HasAcquaintanceship" )}, // 面識ありか - {0x0E, new EventFlagVillagerMemoryPlayer(0 , 1 , 014, "SitBenchFlag" )}, // NPCをベンチに座らせる - {0x0F, new EventFlagVillagerMemoryPlayer(0 , 1 , 015, "TalkInDream" )}, // 今回の夢の中への訪問で話をしたか - {0x10, new EventFlagVillagerMemoryPlayer(0 , 64 , 016, "HalloweenGiveCandyCount" )}, // ハロウィン|今日このNPCにアメをあげた回数 - {0x11, new EventFlagVillagerMemoryPlayer(0 , 255, 017, "PastCountFromLastVisitPlayerHouse" )}, // 最後にP宅を訪問してからの経過日数 - {0x12, new EventFlagVillagerMemoryPlayer(0 , 1 , 018, "TalkedAsSameVillageResident" )}, // 同じ村の住人として会話した - {0x13, new EventFlagVillagerMemoryPlayer(0 , 1 , 019, "InputGreeting" )}, // 挨拶を設定した - {0x14, new EventFlagVillagerMemoryPlayer(0 , 1 , 020, "InputPhraseMemory" )}, // 口癖を設定した - {0x15, new EventFlagVillagerMemoryPlayer(0 , 1 , 021, "InputNickname" )}, // ニックネームを設定した - {0x16, new EventFlagVillagerMemoryPlayer(0 , 1 , 022, "GEventTalkBeforeFlag" )}, // イベント共通|イベント前に会話した? - {0x17, new EventFlagVillagerMemoryPlayer(0 , 1 , 023, "GEventTalkProgressFlag" )}, // イベント共通|イベント中に会話した? - {0x18, new EventFlagVillagerMemoryPlayer(0 , 1 , 024, "GEventTalkAfterFlag" )}, // イベント共通|イベント後に会話した? - {0x19, new EventFlagVillagerMemoryPlayer(0 , 1 , 025, "InduceFailFlag" )}, // 勧誘失敗フラグ - {0x1A, new EventFlagVillagerMemoryPlayer(0 , 1 , 026, "InduceFailAlreadyInduced" )}, // 勧誘失敗理由|既に転入枠に勧誘されたNPCがいる - {0x1B, new EventFlagVillagerMemoryPlayer(0 , 1 , 027, "InduceFailSameNpcLiving" )}, // 勧誘失敗理由|同名NPCが村に住んでいる - {0x1C, new EventFlagVillagerMemoryPlayer(0 , 1 , 028, "InduceFailSameNpcMoveIn" )}, // 勧誘失敗理由|同名NPCが転入確定状態 - {0x1D, new EventFlagVillagerMemoryPlayer(0 , 1 , 029, "IsReceiptWrappingItem" )}, // プレゼントできるアイテムを受け取った - {0x1E, new EventFlagVillagerMemoryPlayer(0 , 1 , 030, "BirhdayNPresentFlag" )}, // NPC誕生日|プレゼント渡した? - {0x1F, new EventFlagVillagerMemoryPlayer(0 , 1 , 031, "NicknameOriginal" )}, // ニックネーム設定本人 - {0x20, new EventFlagVillagerMemoryPlayer(0 , 1 , 032, "BirhdayNTalkInFlag" )}, // NPC誕生日|家に入ったときの会話した? - {0x21, new EventFlagVillagerMemoryPlayer(0 , 1 , 033, "BirhdayNTalkFlag" )}, // NPC誕生日|誕生会で会話した? - {0x22, new EventFlagVillagerMemoryPlayer(0 , 1 , 034, "BirhdayNTalkOutFlag" )}, // NPC誕生日|家から出たときの会話した? - {0x23, new EventFlagVillagerMemoryPlayer(0 , 1 , 035, "BirhdayPTalkFlag" )}, // プレイヤ誕生日|おめでとう会話した? - {0x24, new EventFlagVillagerMemoryPlayer(0 , 1 , 036, "BirhdayPCupcakeFlag" )}, // プレイヤ誕生日|カップケーキ渡した? - {0x25, new EventFlagVillagerMemoryPlayer(0 , 1 , 037, "FriendOfHostPC" )}, // ホストPCのフレンドとして訪問した - {0x26, new EventFlagVillagerMemoryPlayer(0 , 1 , 038, "TalkClothesPToday" )}, // 今日ClothesPを見たか? - {0x27, new EventFlagVillagerMemoryPlayer(0 , 1 , 039, "TalkedDuringSick" )}, // 病気中に会話した - {0x28, new EventFlagVillagerMemoryPlayer(0 , 1 , 040, "InduceFailVillagerMax" )}, // 勧誘失敗理由|住人数が既に上限 - {0x29, new EventFlagVillagerMemoryPlayer(0 , 1 , 041, "FirstMeetGreetAtThisVillage" )}, // この村で初対面の挨拶をした - {0x2A, new EventFlagVillagerMemoryPlayer(0 , 1 , 042, "MoveCancelTalk" )}, // 引越し中止の報告したか - {0x2B, new EventFlagVillagerMemoryPlayer(0 , 1 , 043, "BirthdayPAttendance" )}, // プレイヤ誕生日|出席していた - {0x2C, new EventFlagVillagerMemoryPlayer(0 , 255, 044, "TalkCountInHouseToday" )}, // 室内で会話した回数 (訪問クエスト中) - {0x2D, new EventFlagVillagerMemoryPlayer(0 , 1 , 045, "TalkClothesNToday" )}, // 今日ClothesNを見たか? - {0x2E, new EventFlagVillagerMemoryPlayer(0 , 1 , 046, "TalkWantToday" )}, // 今日Wantを聞いたか? - {0x2F, new EventFlagVillagerMemoryPlayer(0 , 1 , 047, "InduceFailSellPlaceNothing" )}, // 勧誘失敗理由|売り土地が無い - {0x30, new EventFlagVillagerMemoryPlayer(0 , 1 , 048, "IsPlayedQuestVisitN" )}, // 訪問Nをクリアした事ある? - {0x31, new EventFlagVillagerMemoryPlayer(0 , 1 , 049, "AcquaintanceshipFlagOff" )}, // 面識フラグを立てない - {0x32, new EventFlagVillagerMemoryPlayer(0 , 1 , 050, "InducementAtMovingDay" )}, // 転出当日に勧誘された - {0x33, new EventFlagVillagerMemoryPlayer(0 , 1 , 051, "ChokeOffMoveOut" )}, // 引越を引き止められた - {0x34, new EventFlagVillagerMemoryPlayer(0 , 1 , 052, "InducementFlag" )}, // 勧誘されて来たか - {0x35, new EventFlagVillagerMemoryPlayer(0 , 1 , 053, "ApproachQuestOrdered" )}, // アプローチ経由でのクエスト発注か? - {0x37, new EventFlagVillagerMemoryPlayer(0 , 255, 055, "ContinuousTalkCount" )}, // 連続会話回数 - {0x38, new EventFlagVillagerMemoryPlayer(0 , 255, 056, "Again2Count" )}, // XX_Again2を聞いた回数 - {0x39, new EventFlagVillagerMemoryPlayer(0 , 1 , 057, "TalkDIY" )}, // DIY会話をした - {0x3A, new EventFlagVillagerMemoryPlayer(0 , 5 , 058, "HalloweenDIYGetItem" )}, // DIYしている時の報酬アイテムは? - {0x3B, new EventFlagVillagerMemoryPlayer(0 , 1 , 059, "NewYearGreetingFlag" )}, // 新年(1月1日)のあいさつをした - {0x3C, new EventFlagVillagerMemoryPlayer(0 , 1 , 060, "GotRecipeorMaterial" )}, // DIYレシピか素材をもらった - {0x3D, new EventFlagVillagerMemoryPlayer(0 , 1 , 061, "GotMaterialItemFull" )}, // 素材をもらうときもちものがいっぱいだった - {0x3E, new EventFlagVillagerMemoryPlayer(0 , 1 , 062, "MailedVisitPLayout" )}, // 訪問Pで手紙を投函した - {0x3F, new EventFlagVillagerMemoryPlayer(0 , 1 , 063, "FirstMeetGreetAtThisVillageToday" )}, // この村で初対面の挨拶をした当日 - {0x40, new EventFlagVillagerMemoryPlayer(0 , 1 , 064, "ReceivedFirstPresent" )}, // NPCから初めてPresentを貰った - {0x41, new EventFlagVillagerMemoryPlayer(0 , 1 , 065, "BanClothesN1Today" )}, // ClothesN1:今日は禁止 - {0x42, new EventFlagVillagerMemoryPlayer(0 , 1 , 066, "BanClothesN2Now" )}, // ClothesN2:今は禁止 - {0x43, new EventFlagVillagerMemoryPlayer(0 , 1 , 067, "BanClothesN1Now" )}, // ClothesN1:今は禁止 - {0x44, new EventFlagVillagerMemoryPlayer(0 , 1 , 068, "TalkWeekNow" )}, // 今、Weekを聞いたか? - {0x45, new EventFlagVillagerMemoryPlayer(0 , 1 , 069, "TalkQuestionsNow" )}, // 今、Questionsを聞いたか? - {0x46, new EventFlagVillagerMemoryPlayer(0 , 1 , 070, "TalkAlwaysNow" )}, // 今、Alwaysを聞いたか? - {0x47, new EventFlagVillagerMemoryPlayer(0 , 1 , 071, "TalkAlwaysABNow" )}, // 今、AlwaysABを聞いたか? - {0x48, new EventFlagVillagerMemoryPlayer(0 , 1 , 072, "TalkWeatherSPNow" )}, // 今、WeatherSPを聞いたか? - {0x49, new EventFlagVillagerMemoryPlayer(0 , 1 , 073, "TalkWeatherNow" )}, // 今、Weatherを聞いたか? - {0x4A, new EventFlagVillagerMemoryPlayer(0 , 1 , 074, "TalkSeasonsNow" )}, // 今、Seasonsを聞いたか? - {0x4B, new EventFlagVillagerMemoryPlayer(0 , 1 , 075, "TalkSpotSPNow" )}, // 今、SpotSPを聞いたか? - {0x4C, new EventFlagVillagerMemoryPlayer(0 , 1 , 076, "TalkSpotNow" )}, // 今、Spotを聞いたか? - {0x4E, new EventFlagVillagerMemoryPlayer(0 , 1 , 078, "TalkItemNNow" )}, // 今、ItemNを聞いたか? - {0x4F, new EventFlagVillagerMemoryPlayer(0 , 1 , 079, "TalkItemPNow" )}, // 今、ItemPを聞いたか? - {0x50, new EventFlagVillagerMemoryPlayer(0 , 1 , 080, "TalkRumorOActionToday" )}, // (ボツ)今日RumorOP_Action(同じ島の住人P)を聞いたか? - {0x51, new EventFlagVillagerMemoryPlayer(0 , 1 , 081, "TalkRumorVActionToday" )}, // 今日RumorOP_Action(ビジター)を聞いたか? - {0x52, new EventFlagVillagerMemoryPlayer(0 , 1 , 082, "TalkRumorOFavoriteToday" )}, // 今日RumorO_Favoriteを聞いたか? - {0x53, new EventFlagVillagerMemoryPlayer(0 , 1 , 083, "TalkRumorNToday" )}, // 今日このNPCからRumorN1を聞いたか? - {0x54, new EventFlagVillagerMemoryPlayer(0 , 1 , 084, "TalkFreeMovingNow" )}, // 今、FreeD_Movingを聞いたか? - {0x55, new EventFlagVillagerMemoryPlayer(0 , 1 , 085, "TalkFreeEventNow" )}, // 今日FreeE_Eventを聞いたか? - {0x56, new EventFlagVillagerMemoryPlayer(0 , 1 , 086, "TalkSnpcNow" )}, // 今日Snpcを聞いたか? - {0x57, new EventFlagVillagerMemoryPlayer(0 , 1 , 087, "TalkFreeFNow" )}, // 今、FreeFを聞いたか? - {0x58, new EventFlagVillagerMemoryPlayer(0 , 1 , 088, "TalkFreeGNow" )}, // 今、FreeGを聞いたか? - {0x59, new EventFlagVillagerMemoryPlayer(0 , 1 , 089, "FireworksCannotGetNnpcItemFlag" )}, // 花火大会|このNPCから受け取り損ねたアイテムがある? - {0x5A, new EventFlagVillagerMemoryPlayer(0 , 1 , 090, "TalkHHAToday" )}, // 今日FreeE_HHAを聞いたか? - {0x5B, new EventFlagVillagerMemoryPlayer(0 , 5 , 091, "TalkReSelectLast" )}, // 再抽選前に聞いたファイル識別番号 - {0x5C, new EventFlagVillagerMemoryPlayer(0 , 1 , 092, "HHABuildCelebraition" )}, // 増築祝いの手紙を出した - {0x5D, new EventFlagVillagerMemoryPlayer(0 , 1 , 093, "ChineseNewYearGreetingFlag" )}, // 旧正月のあいさつをした - {0x5E, new EventFlagVillagerMemoryPlayer(0 , 1 , 094, "TalkFreeZodiacNow" )}, // 今、FreeF_NewYear_Zodiacを聞いたか? - {0x5F, new EventFlagVillagerMemoryPlayer(0 , 1 , 095, "TalkProgressNpcHouseBuilt" )}, // 初期NPCの家に関するFreeH_Progressを聞いたか? - {0x60, new EventFlagVillagerMemoryPlayer(0 , 1 , 096, "TalkProgressMyHouseBuilt" )}, // 現在プレイヤーの家に関するFreeH_Progressを聞いたか? - {0x61, new EventFlagVillagerMemoryPlayer(0 , 1 , 097, "TalkProgressMyHouseBuilt2" )}, // 現在プレイヤーの家(地下室完成)に関するFreeH_Progressを聞いたか? - {0x62, new EventFlagVillagerMemoryPlayer(0 , 1 , 098, "TalkProgressMigrantsQuest" )}, // 移住クエストに関するFreeH_Progressを聞いたか? - {0x63, new EventFlagVillagerMemoryPlayer(0 , 1 , 099, "TalkProgressHelpBuildShop" )}, // 商店の木材集めに関するFreeH_Progressを聞いたか? - {0x64, new EventFlagVillagerMemoryPlayer(0 , 1 , 100, "TalkProgressOfficeBuilt" )}, // 案内所の完成に関するFreeH_Progressを聞いたか? - {0x65, new EventFlagVillagerMemoryPlayer(0 , 1 , 101, "TalkProgressShopBuilt" )}, // 商店の完成に関するFreeH_Progressを聞いたか? - {0x66, new EventFlagVillagerMemoryPlayer(0 , 1 , 102, "TalkProgressShopBuilt2" )}, // 商店の拡張に関するFreeH_Progressを聞いたか? - {0x67, new EventFlagVillagerMemoryPlayer(0 , 1 , 103, "TalkProgressMuseumTent" )}, // フータのテントに関するFreeH_Progressを聞いたか? - {0x68, new EventFlagVillagerMemoryPlayer(0 , 1 , 104, "TalkProgressMuseumBuilt" )}, // 博物館の完成に関するFreeH_Progressを聞いたか? - {0x69, new EventFlagVillagerMemoryPlayer(0 , 1 , 105, "TalkProgressTailorBuilt" )}, // 仕立て屋の完成に関するFreeH_Progressを聞いたか? - {0x6A, new EventFlagVillagerMemoryPlayer(0 , 1 , 106, "TalkProgressBridgeBuilt" )}, // 初めての橋の完成に関するFreeH_Progressを聞いたか? - {0x6B, new EventFlagVillagerMemoryPlayer(0 , 1 , 107, "TalkProgressSlopeBuilt" )}, // 初めての坂の完成に関するFreeH_Progressを聞いたか? - {0x6C, new EventFlagVillagerMemoryPlayer(0 , 1 , 108, "TalkProgressOtherPlayerMoveIn" )}, // 他プレイヤーの移住に関するFreeH_Progressを聞いたか? - {0x6D, new EventFlagVillagerMemoryPlayer(0 , 1 , 109, "TalkRumorPActionToday" )}, // (ボツ)今日RumorP_Action(現在プレイヤー)を聞いたか? - {0x6E, new EventFlagVillagerMemoryPlayer(0 , 1 , 110, "FirstNpcEarlyAcquaintanceFlag" )}, // NPC宅がテントだった頃からの知り合い? - {0x6F, new EventFlagVillagerMemoryPlayer(0 , 1 , 111, "TalkSickCured" )}, // Curedを聞いたか? - {0x70, new EventFlagVillagerMemoryPlayer(0 , 1 , 112, "StandingUpFlag" )}, // NPCを立たせる - {0x71, new EventFlagVillagerMemoryPlayer(0 , 1 , 113, "StoodUpFlag" )}, // NPCが立った - {0x72, new EventFlagVillagerMemoryPlayer(0 , 1 , 114, "TalkBeefaceToday" )}, // 今日BeeFaceを聞いたか? - {0x73, new EventFlagVillagerMemoryPlayer(0 , 1 , 115, "TalkItchingToday" )}, // 今日Itchingを聞いたか? - {0x74, new EventFlagVillagerMemoryPlayer(0 , 1 , 116, "TalkEarlyLateToday" )}, // 今日EarlyLateを聞いたか? - {0x75, new EventFlagVillagerMemoryPlayer(0 , 1 , 117, "FinishVisitPToday" )}, // 今日訪問Pクエストをしたか? - {0x76, new EventFlagVillagerMemoryPlayer(0 , 1 , 118, "FinishVisitNToday" )}, // 今日訪問Nクエストをしたか? - {0x77, new EventFlagVillagerMemoryPlayer(0 , 1 , 119, "OrderQuest" )}, // クエストを発注or達成した - {0x78, new EventFlagVillagerMemoryPlayer(0 , 1 , 120, "FirstGreetingAtNpcHome" )}, // 引越し当日のダンボール自宅でNPCと初対面会話をした(自分の村) - {0x79, new EventFlagVillagerMemoryPlayer(0 , 1 , 121, "AppF_MoveinGiftOccured" )}, // 引越し挨拶アプローチ会話発生済か? - {0x7A, new EventFlagVillagerMemoryPlayer(0 , 1 , 122, "UncollectedFishishTreasureHunt" )}, // 宝未回収でクエスト終了した - {0x7B, new EventFlagVillagerMemoryPlayer(0 , 7 , 123, "TalkCountInFacilityToday" )}, // 今日の会話回数(施設用) - {0x7C, new EventFlagVillagerMemoryPlayer(0 , 1 , 124, "FriendshipBecomeAcqHToday" )}, // 今日親密度が知人(高)に到達した - {0x7D, new EventFlagVillagerMemoryPlayer(0 , 1 , 125, "FriendshipBecomeAcqH" )}, // 親密度が知人(高)に到達済み - {0x7E, new EventFlagVillagerMemoryPlayer(0 , 3 , 126, "DC_NPCBirthdayFlag" )}, // NPC誕生日|おでかけ先の村でもらうお返しの種類 - {0x7F, new EventFlagVillagerMemoryPlayer(0 , 1 , 127, "EasterCannotGetNnpcRecipeFlag" )}, // イースター|このNPCから受け取り損ねたアイテムがある? - {0x81, new EventFlagVillagerMemoryPlayer(0 , 1 , 129, "HalloweenTerrifyFlag" )}, // ハロウィン|今日パンプキングの恰好で脅かした? - {0x82, new EventFlagVillagerMemoryPlayer(0 , 1 , 130, "HalloweenGetCandyFlag" )}, // ハロウィン|今日このNPCからアメもらった? - {0x83, new EventFlagVillagerMemoryPlayer(0 , 1 , 131, "FireworksGetItemFlag" )}, // 花火大会|このNPCからリアクション会話で花火を受け取った - {0x84, new EventFlagVillagerMemoryPlayer(0 , 1 , 132, "HaloweenTalkThisSceneFalg" )}, // ハロウィン|このシーンで会話した? - {0x85, new EventFlagVillagerMemoryPlayer(0 , 1 , 133, "HaloweenGetCandyThisSceneFalg" )}, // ハロウィン|このシーンでアメもらった? - {0x88, new EventFlagVillagerMemoryPlayer(0 , 1 , 136, "HalloweenLastNotGetFlag" )}, // ハロウィン|最後の会話で報酬アイテムもらえなかった? - {0x89, new EventFlagVillagerMemoryPlayer(0 , 16 , 137, "HalloweenLastNotGetItem" )}, // ハロウィン|最後の会話でもらえなかった報酬アイテム - {0x8A, new EventFlagVillagerMemoryPlayer(0 , 1 , 138, "HarvestItemExchangeToday" )}, // ハーベスト|物々交換を1度でも行ったか? - {0x8B, new EventFlagVillagerMemoryPlayer(0 , 1 , 139, "ChristmasSantaPresentsFlag" )}, // サンタミッションのプレゼントを受け取ったか? - {0x8C, new EventFlagVillagerMemoryPlayer(0 , 1 , 140, "ChristmasSantaPresentsNoGetFlag" )}, // サンタミッションのお返しが持ち物一杯で受け取れなかった? - {0x8D, new EventFlagVillagerMemoryPlayer(0 , 1 , 141, "ChristmasSantaPresentsReturnFlag" )}, // サンタミッションでプレゼント渡したらお返しくれたか? - {0x8E, new EventFlagVillagerMemoryPlayer(0 , 1 , 142, "ChristmasGiftExchangeFlag" )}, // そのNPCとプレゼント交換をしたか? - {0x8F, new EventFlagVillagerMemoryPlayer(0 , 8 , 143, "ChristmasExchangeItemType" )}, // クリスマス|プレゼント交換であげたプレゼントの種類 - {0x90, new EventFlagVillagerMemoryPlayer(0 , 1 , 144, "ChristmasCosJudgeFlag" )}, // イブにサンタの恰好をしているか? - {0x91, new EventFlagVillagerMemoryPlayer(0 , 1 , 145, "ChristmasCannotGetNnpcItemFlag" )}, // クリスマス|このNPCから受け取り損ねたアイテムがある? - {0x92, new EventFlagVillagerMemoryPlayer(0 , 1 , 146, "ChristmasAfterMesFlag" )}, // クリスマス(25日)に専用会話を聞いた? - {0x93, new EventFlagVillagerMemoryPlayer(0 , 1 , 147, "ChristmasWrappingGiftNoGetFlag" )}, // クリスマス|持ち物一杯でラッピングペーパーを受け取り損ねた? - {0x94, new EventFlagVillagerMemoryPlayer(0 , 8 , 148, "ChristmasSantaPresentItemType" )}, // クリスマス|サンタミッションであげたプレゼントの種類 - {0x95, new EventFlagVillagerMemoryPlayer(0 , 8 , 149, "ChristmasExchangeRemakeId" )}, // クリスマス|プレゼント交換であげたプレゼントのリメイクID - {0x96, new EventFlagVillagerMemoryPlayer(0 , 8 , 150, "ChristmasSantaPresentRemakeId" )}, // クリスマス|サンタミッションであげたプレゼントのリメイクID - {0x97, new EventFlagVillagerMemoryPlayer(0 , 1 , 151, "CarnvalTalkWithoutFeatherFlag" )}, // 一般NPC/カーニバル|はねを持たずに会話した? - {0x98, new EventFlagVillagerMemoryPlayer(0 , 1 , 152, "CarnvalExchangeFeatherFlag" )}, // 一般NPC/カーニバル|このNPCとはね交換した? - {0x99, new EventFlagVillagerMemoryPlayer(0 , 1 , 153, "CarnvalTalkOutdoorFlag" )}, // 一般NPC/カーニバル|今日屋外で会話した? - {0x9A, new EventFlagVillagerMemoryPlayer(0 , 1 , 154, "CarnvalExchangeFeatherTalkFlag" )}, // 一般NPC/カーニバル|このNPCとはね交換の会話をした? - {0x9B, new EventFlagVillagerMemoryPlayer(0 , 1 , 155, "ValentinePresentFlag" )}, // バレンタイン|バレンタインのプレゼント渡した? - {0x9C, new EventFlagVillagerMemoryPlayer(0 , 1 , 156, "EasterTalkOutdoorFlag" )}, // 一般NPC/イースター|今日屋外で会話した? - {0x9D, new EventFlagVillagerMemoryPlayer(0 , 1 , 157, "EasterExchangeEggFlag" )}, // 一般NPC/イースターこのNPCとたまご交換した? - {0x9E, new EventFlagVillagerMemoryPlayer(0 , 1 , 158, "EasterExchangeEggTalkFlag" )}, // 一般NPC/イースター|このNPCとたまご交換の会話をした? - {0x9F, new EventFlagVillagerMemoryPlayer(0 , 1 , 159, "EasterCannotGetNnpcIsRecipeFlag" )}, // イースター|このNPCから受け取り損ねたのはレシピか - {0xA0, new EventFlagVillagerMemoryPlayer(0 , 1 , 160, "TodayReserveCoordinateHouseInterior" )}, // NPC家コーデ|今日NPCの家の内装の提案をしたか? - {0xA1, new EventFlagVillagerMemoryPlayer(0 , 1 , 161, "TodayReserveCoordinateHouseExterior" )}, // NPC家コーデ|今日NPCの家の外観の提案をしたか? - {0xA2, new EventFlagVillagerMemoryPlayer(0 , 1 , 162, "TodayCompleteCoordinateHouseInterior" )}, // NPC家コーデ|今日NPCの家に提案した内装が反映されたか? - {0xA3, new EventFlagVillagerMemoryPlayer(0 , 1 , 163, "TodayCompleteCoordinateHouseExterior" )}, // NPC家コーデ|今日NPCの家に提案した外観が反映されたか? - {0xA4, new EventFlagVillagerMemoryPlayer(0 , 1 , 164, "InteriorCoordinator" )}, // NPC家コーデ|現在の内装を提案した - {0xA5, new EventFlagVillagerMemoryPlayer(0 , 1 , 165, "ExteriorCoordinator" )}, // NPC家コーデ|現在の外観を提案した - {0xA6, new EventFlagVillagerMemoryPlayer(0 , 1 , 166, "TodayHeardReactTalkAboutCoordinateHouse" )}, // NPC家コーデ|今日、コーディネート提案に関するリアクション会話聞いた - {0xA7, new EventFlagVillagerMemoryPlayer(0 , 1 , 167, "WHEREAREN_VisitWherearenWithPlayer" )}, // OneRoom|おみやげチョコレートを受け取ってウェアラン諸島に行ったことがあるか? - {0xA8, new EventFlagVillagerMemoryPlayer(0 , 1 , 168, "TalkProgressMuseumBuiltCafe" )}, // 博物館(カフェ)への拡張に関するFreeH_Progressを聞いたか? - {0xA9, new EventFlagVillagerMemoryPlayer(0 , 1 , 169, "WHEREAREN_GetChocolate" )}, // OneRoom|おみやげチョコレートを受け取ったことがあるか? - }; - - private const string Unknown = "???"; - - public static string GetName(ushort index, uint count, IReadOnlyDictionary str) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - { - string name = val.Name; - if (str.TryGetValue(name, out var translated)) - name = translated; - return $"{index:00} - {name} = {count}"; - } - return $"{index:00} - {Unknown} = {count}"; - } - - public static string GetName(ushort index, uint count) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - return $"{index:00} - {val.Name} = {count}"; - return $"{index:00} - {Unknown} = {count}"; - } + Name = name; + Index = index; + Initial = init; + Maximum = max; } -} + + public static readonly IReadOnlyDictionary List = new Dictionary + { + {0x00, new EventFlagVillagerMemoryPlayer(0 , 1 , 000, "TalkFreeMultiDayEventNow" )}, // (ボツ)今、期間型イベント用のFreeFを聞いたか? + {0x01, new EventFlagVillagerMemoryPlayer(0 , 7 , 001, "ContinuousTalkDays" )}, // 何日連続で話しかけられたか + {0x02, new EventFlagVillagerMemoryPlayer(0 , 1 , 002, "SameLand" )}, // 同じ村に住んでいたことがあるか + {0x03, new EventFlagVillagerMemoryPlayer(0 , 1 , 003, "SetGreeting" )}, // 挨拶を設定したことがある + {0x04, new EventFlagVillagerMemoryPlayer(0 , 1 , 004, "EasterGetRecipeFlag" )}, // イースター|今日このNPCからアイテムを受け取った + {0x05, new EventFlagVillagerMemoryPlayer(0 , 1 , 005, "TalkProgressMuseumBuilt2" )}, // 博物館2への拡張に関するFreeH_Progressを聞いたか? + {0x06, new EventFlagVillagerMemoryPlayer(0 , 1 , 006, "NextMoveOutTalk" )}, // 引越ししたい会話したか + {0x07, new EventFlagVillagerMemoryPlayer(0 , 1 , 007, "TalkMoveOut" )}, // 引越していく状態で会話したか + {0x08, new EventFlagVillagerMemoryPlayer(0 , 7 , 008, "VisitCount" )}, // そのプレイヤーの家に行った回数 + {0x09, new EventFlagVillagerMemoryPlayer(0 , 7 , 009, "VisitedCount" )}, // そのプレイヤーが家に来た回数 + {0x0A, new EventFlagVillagerMemoryPlayer(25, 255, 010, "Friendship" )}, // 親密度 + {0x0B, new EventFlagVillagerMemoryPlayer(0 , 9 , 011, "TalkCountToday" )}, // 今日の会話回数(通算) + {0x0C, new EventFlagVillagerMemoryPlayer(0 , 7 , 012, "TalkCountInNpcHouseToday" )}, // 今日NPCの家での会話回数 + {0x0D, new EventFlagVillagerMemoryPlayer(0 , 1 , 013, "HasAcquaintanceship" )}, // 面識ありか + {0x0E, new EventFlagVillagerMemoryPlayer(0 , 1 , 014, "SitBenchFlag" )}, // NPCをベンチに座らせる + {0x0F, new EventFlagVillagerMemoryPlayer(0 , 1 , 015, "TalkInDream" )}, // 今回の夢の中への訪問で話をしたか + {0x10, new EventFlagVillagerMemoryPlayer(0 , 64 , 016, "HalloweenGiveCandyCount" )}, // ハロウィン|今日このNPCにアメをあげた回数 + {0x11, new EventFlagVillagerMemoryPlayer(0 , 255, 017, "PastCountFromLastVisitPlayerHouse" )}, // 最後にP宅を訪問してからの経過日数 + {0x12, new EventFlagVillagerMemoryPlayer(0 , 1 , 018, "TalkedAsSameVillageResident" )}, // 同じ村の住人として会話した + {0x13, new EventFlagVillagerMemoryPlayer(0 , 1 , 019, "InputGreeting" )}, // 挨拶を設定した + {0x14, new EventFlagVillagerMemoryPlayer(0 , 1 , 020, "InputPhraseMemory" )}, // 口癖を設定した + {0x15, new EventFlagVillagerMemoryPlayer(0 , 1 , 021, "InputNickname" )}, // ニックネームを設定した + {0x16, new EventFlagVillagerMemoryPlayer(0 , 1 , 022, "GEventTalkBeforeFlag" )}, // イベント共通|イベント前に会話した? + {0x17, new EventFlagVillagerMemoryPlayer(0 , 1 , 023, "GEventTalkProgressFlag" )}, // イベント共通|イベント中に会話した? + {0x18, new EventFlagVillagerMemoryPlayer(0 , 1 , 024, "GEventTalkAfterFlag" )}, // イベント共通|イベント後に会話した? + {0x19, new EventFlagVillagerMemoryPlayer(0 , 1 , 025, "InduceFailFlag" )}, // 勧誘失敗フラグ + {0x1A, new EventFlagVillagerMemoryPlayer(0 , 1 , 026, "InduceFailAlreadyInduced" )}, // 勧誘失敗理由|既に転入枠に勧誘されたNPCがいる + {0x1B, new EventFlagVillagerMemoryPlayer(0 , 1 , 027, "InduceFailSameNpcLiving" )}, // 勧誘失敗理由|同名NPCが村に住んでいる + {0x1C, new EventFlagVillagerMemoryPlayer(0 , 1 , 028, "InduceFailSameNpcMoveIn" )}, // 勧誘失敗理由|同名NPCが転入確定状態 + {0x1D, new EventFlagVillagerMemoryPlayer(0 , 1 , 029, "IsReceiptWrappingItem" )}, // プレゼントできるアイテムを受け取った + {0x1E, new EventFlagVillagerMemoryPlayer(0 , 1 , 030, "BirhdayNPresentFlag" )}, // NPC誕生日|プレゼント渡した? + {0x1F, new EventFlagVillagerMemoryPlayer(0 , 1 , 031, "NicknameOriginal" )}, // ニックネーム設定本人 + {0x20, new EventFlagVillagerMemoryPlayer(0 , 1 , 032, "BirhdayNTalkInFlag" )}, // NPC誕生日|家に入ったときの会話した? + {0x21, new EventFlagVillagerMemoryPlayer(0 , 1 , 033, "BirhdayNTalkFlag" )}, // NPC誕生日|誕生会で会話した? + {0x22, new EventFlagVillagerMemoryPlayer(0 , 1 , 034, "BirhdayNTalkOutFlag" )}, // NPC誕生日|家から出たときの会話した? + {0x23, new EventFlagVillagerMemoryPlayer(0 , 1 , 035, "BirhdayPTalkFlag" )}, // プレイヤ誕生日|おめでとう会話した? + {0x24, new EventFlagVillagerMemoryPlayer(0 , 1 , 036, "BirhdayPCupcakeFlag" )}, // プレイヤ誕生日|カップケーキ渡した? + {0x25, new EventFlagVillagerMemoryPlayer(0 , 1 , 037, "FriendOfHostPC" )}, // ホストPCのフレンドとして訪問した + {0x26, new EventFlagVillagerMemoryPlayer(0 , 1 , 038, "TalkClothesPToday" )}, // 今日ClothesPを見たか? + {0x27, new EventFlagVillagerMemoryPlayer(0 , 1 , 039, "TalkedDuringSick" )}, // 病気中に会話した + {0x28, new EventFlagVillagerMemoryPlayer(0 , 1 , 040, "InduceFailVillagerMax" )}, // 勧誘失敗理由|住人数が既に上限 + {0x29, new EventFlagVillagerMemoryPlayer(0 , 1 , 041, "FirstMeetGreetAtThisVillage" )}, // この村で初対面の挨拶をした + {0x2A, new EventFlagVillagerMemoryPlayer(0 , 1 , 042, "MoveCancelTalk" )}, // 引越し中止の報告したか + {0x2B, new EventFlagVillagerMemoryPlayer(0 , 1 , 043, "BirthdayPAttendance" )}, // プレイヤ誕生日|出席していた + {0x2C, new EventFlagVillagerMemoryPlayer(0 , 255, 044, "TalkCountInHouseToday" )}, // 室内で会話した回数 (訪問クエスト中) + {0x2D, new EventFlagVillagerMemoryPlayer(0 , 1 , 045, "TalkClothesNToday" )}, // 今日ClothesNを見たか? + {0x2E, new EventFlagVillagerMemoryPlayer(0 , 1 , 046, "TalkWantToday" )}, // 今日Wantを聞いたか? + {0x2F, new EventFlagVillagerMemoryPlayer(0 , 1 , 047, "InduceFailSellPlaceNothing" )}, // 勧誘失敗理由|売り土地が無い + {0x30, new EventFlagVillagerMemoryPlayer(0 , 1 , 048, "IsPlayedQuestVisitN" )}, // 訪問Nをクリアした事ある? + {0x31, new EventFlagVillagerMemoryPlayer(0 , 1 , 049, "AcquaintanceshipFlagOff" )}, // 面識フラグを立てない + {0x32, new EventFlagVillagerMemoryPlayer(0 , 1 , 050, "InducementAtMovingDay" )}, // 転出当日に勧誘された + {0x33, new EventFlagVillagerMemoryPlayer(0 , 1 , 051, "ChokeOffMoveOut" )}, // 引越を引き止められた + {0x34, new EventFlagVillagerMemoryPlayer(0 , 1 , 052, "InducementFlag" )}, // 勧誘されて来たか + {0x35, new EventFlagVillagerMemoryPlayer(0 , 1 , 053, "ApproachQuestOrdered" )}, // アプローチ経由でのクエスト発注か? + {0x37, new EventFlagVillagerMemoryPlayer(0 , 255, 055, "ContinuousTalkCount" )}, // 連続会話回数 + {0x38, new EventFlagVillagerMemoryPlayer(0 , 255, 056, "Again2Count" )}, // XX_Again2を聞いた回数 + {0x39, new EventFlagVillagerMemoryPlayer(0 , 1 , 057, "TalkDIY" )}, // DIY会話をした + {0x3A, new EventFlagVillagerMemoryPlayer(0 , 5 , 058, "HalloweenDIYGetItem" )}, // DIYしている時の報酬アイテムは? + {0x3B, new EventFlagVillagerMemoryPlayer(0 , 1 , 059, "NewYearGreetingFlag" )}, // 新年(1月1日)のあいさつをした + {0x3C, new EventFlagVillagerMemoryPlayer(0 , 1 , 060, "GotRecipeorMaterial" )}, // DIYレシピか素材をもらった + {0x3D, new EventFlagVillagerMemoryPlayer(0 , 1 , 061, "GotMaterialItemFull" )}, // 素材をもらうときもちものがいっぱいだった + {0x3E, new EventFlagVillagerMemoryPlayer(0 , 1 , 062, "MailedVisitPLayout" )}, // 訪問Pで手紙を投函した + {0x3F, new EventFlagVillagerMemoryPlayer(0 , 1 , 063, "FirstMeetGreetAtThisVillageToday" )}, // この村で初対面の挨拶をした当日 + {0x40, new EventFlagVillagerMemoryPlayer(0 , 1 , 064, "ReceivedFirstPresent" )}, // NPCから初めてPresentを貰った + {0x41, new EventFlagVillagerMemoryPlayer(0 , 1 , 065, "BanClothesN1Today" )}, // ClothesN1:今日は禁止 + {0x42, new EventFlagVillagerMemoryPlayer(0 , 1 , 066, "BanClothesN2Now" )}, // ClothesN2:今は禁止 + {0x43, new EventFlagVillagerMemoryPlayer(0 , 1 , 067, "BanClothesN1Now" )}, // ClothesN1:今は禁止 + {0x44, new EventFlagVillagerMemoryPlayer(0 , 1 , 068, "TalkWeekNow" )}, // 今、Weekを聞いたか? + {0x45, new EventFlagVillagerMemoryPlayer(0 , 1 , 069, "TalkQuestionsNow" )}, // 今、Questionsを聞いたか? + {0x46, new EventFlagVillagerMemoryPlayer(0 , 1 , 070, "TalkAlwaysNow" )}, // 今、Alwaysを聞いたか? + {0x47, new EventFlagVillagerMemoryPlayer(0 , 1 , 071, "TalkAlwaysABNow" )}, // 今、AlwaysABを聞いたか? + {0x48, new EventFlagVillagerMemoryPlayer(0 , 1 , 072, "TalkWeatherSPNow" )}, // 今、WeatherSPを聞いたか? + {0x49, new EventFlagVillagerMemoryPlayer(0 , 1 , 073, "TalkWeatherNow" )}, // 今、Weatherを聞いたか? + {0x4A, new EventFlagVillagerMemoryPlayer(0 , 1 , 074, "TalkSeasonsNow" )}, // 今、Seasonsを聞いたか? + {0x4B, new EventFlagVillagerMemoryPlayer(0 , 1 , 075, "TalkSpotSPNow" )}, // 今、SpotSPを聞いたか? + {0x4C, new EventFlagVillagerMemoryPlayer(0 , 1 , 076, "TalkSpotNow" )}, // 今、Spotを聞いたか? + {0x4E, new EventFlagVillagerMemoryPlayer(0 , 1 , 078, "TalkItemNNow" )}, // 今、ItemNを聞いたか? + {0x4F, new EventFlagVillagerMemoryPlayer(0 , 1 , 079, "TalkItemPNow" )}, // 今、ItemPを聞いたか? + {0x50, new EventFlagVillagerMemoryPlayer(0 , 1 , 080, "TalkRumorOActionToday" )}, // (ボツ)今日RumorOP_Action(同じ島の住人P)を聞いたか? + {0x51, new EventFlagVillagerMemoryPlayer(0 , 1 , 081, "TalkRumorVActionToday" )}, // 今日RumorOP_Action(ビジター)を聞いたか? + {0x52, new EventFlagVillagerMemoryPlayer(0 , 1 , 082, "TalkRumorOFavoriteToday" )}, // 今日RumorO_Favoriteを聞いたか? + {0x53, new EventFlagVillagerMemoryPlayer(0 , 1 , 083, "TalkRumorNToday" )}, // 今日このNPCからRumorN1を聞いたか? + {0x54, new EventFlagVillagerMemoryPlayer(0 , 1 , 084, "TalkFreeMovingNow" )}, // 今、FreeD_Movingを聞いたか? + {0x55, new EventFlagVillagerMemoryPlayer(0 , 1 , 085, "TalkFreeEventNow" )}, // 今日FreeE_Eventを聞いたか? + {0x56, new EventFlagVillagerMemoryPlayer(0 , 1 , 086, "TalkSnpcNow" )}, // 今日Snpcを聞いたか? + {0x57, new EventFlagVillagerMemoryPlayer(0 , 1 , 087, "TalkFreeFNow" )}, // 今、FreeFを聞いたか? + {0x58, new EventFlagVillagerMemoryPlayer(0 , 1 , 088, "TalkFreeGNow" )}, // 今、FreeGを聞いたか? + {0x59, new EventFlagVillagerMemoryPlayer(0 , 1 , 089, "FireworksCannotGetNnpcItemFlag" )}, // 花火大会|このNPCから受け取り損ねたアイテムがある? + {0x5A, new EventFlagVillagerMemoryPlayer(0 , 1 , 090, "TalkHHAToday" )}, // 今日FreeE_HHAを聞いたか? + {0x5B, new EventFlagVillagerMemoryPlayer(0 , 5 , 091, "TalkReSelectLast" )}, // 再抽選前に聞いたファイル識別番号 + {0x5C, new EventFlagVillagerMemoryPlayer(0 , 1 , 092, "HHABuildCelebraition" )}, // 増築祝いの手紙を出した + {0x5D, new EventFlagVillagerMemoryPlayer(0 , 1 , 093, "ChineseNewYearGreetingFlag" )}, // 旧正月のあいさつをした + {0x5E, new EventFlagVillagerMemoryPlayer(0 , 1 , 094, "TalkFreeZodiacNow" )}, // 今、FreeF_NewYear_Zodiacを聞いたか? + {0x5F, new EventFlagVillagerMemoryPlayer(0 , 1 , 095, "TalkProgressNpcHouseBuilt" )}, // 初期NPCの家に関するFreeH_Progressを聞いたか? + {0x60, new EventFlagVillagerMemoryPlayer(0 , 1 , 096, "TalkProgressMyHouseBuilt" )}, // 現在プレイヤーの家に関するFreeH_Progressを聞いたか? + {0x61, new EventFlagVillagerMemoryPlayer(0 , 1 , 097, "TalkProgressMyHouseBuilt2" )}, // 現在プレイヤーの家(地下室完成)に関するFreeH_Progressを聞いたか? + {0x62, new EventFlagVillagerMemoryPlayer(0 , 1 , 098, "TalkProgressMigrantsQuest" )}, // 移住クエストに関するFreeH_Progressを聞いたか? + {0x63, new EventFlagVillagerMemoryPlayer(0 , 1 , 099, "TalkProgressHelpBuildShop" )}, // 商店の木材集めに関するFreeH_Progressを聞いたか? + {0x64, new EventFlagVillagerMemoryPlayer(0 , 1 , 100, "TalkProgressOfficeBuilt" )}, // 案内所の完成に関するFreeH_Progressを聞いたか? + {0x65, new EventFlagVillagerMemoryPlayer(0 , 1 , 101, "TalkProgressShopBuilt" )}, // 商店の完成に関するFreeH_Progressを聞いたか? + {0x66, new EventFlagVillagerMemoryPlayer(0 , 1 , 102, "TalkProgressShopBuilt2" )}, // 商店の拡張に関するFreeH_Progressを聞いたか? + {0x67, new EventFlagVillagerMemoryPlayer(0 , 1 , 103, "TalkProgressMuseumTent" )}, // フータのテントに関するFreeH_Progressを聞いたか? + {0x68, new EventFlagVillagerMemoryPlayer(0 , 1 , 104, "TalkProgressMuseumBuilt" )}, // 博物館の完成に関するFreeH_Progressを聞いたか? + {0x69, new EventFlagVillagerMemoryPlayer(0 , 1 , 105, "TalkProgressTailorBuilt" )}, // 仕立て屋の完成に関するFreeH_Progressを聞いたか? + {0x6A, new EventFlagVillagerMemoryPlayer(0 , 1 , 106, "TalkProgressBridgeBuilt" )}, // 初めての橋の完成に関するFreeH_Progressを聞いたか? + {0x6B, new EventFlagVillagerMemoryPlayer(0 , 1 , 107, "TalkProgressSlopeBuilt" )}, // 初めての坂の完成に関するFreeH_Progressを聞いたか? + {0x6C, new EventFlagVillagerMemoryPlayer(0 , 1 , 108, "TalkProgressOtherPlayerMoveIn" )}, // 他プレイヤーの移住に関するFreeH_Progressを聞いたか? + {0x6D, new EventFlagVillagerMemoryPlayer(0 , 1 , 109, "TalkRumorPActionToday" )}, // (ボツ)今日RumorP_Action(現在プレイヤー)を聞いたか? + {0x6E, new EventFlagVillagerMemoryPlayer(0 , 1 , 110, "FirstNpcEarlyAcquaintanceFlag" )}, // NPC宅がテントだった頃からの知り合い? + {0x6F, new EventFlagVillagerMemoryPlayer(0 , 1 , 111, "TalkSickCured" )}, // Curedを聞いたか? + {0x70, new EventFlagVillagerMemoryPlayer(0 , 1 , 112, "StandingUpFlag" )}, // NPCを立たせる + {0x71, new EventFlagVillagerMemoryPlayer(0 , 1 , 113, "StoodUpFlag" )}, // NPCが立った + {0x72, new EventFlagVillagerMemoryPlayer(0 , 1 , 114, "TalkBeefaceToday" )}, // 今日BeeFaceを聞いたか? + {0x73, new EventFlagVillagerMemoryPlayer(0 , 1 , 115, "TalkItchingToday" )}, // 今日Itchingを聞いたか? + {0x74, new EventFlagVillagerMemoryPlayer(0 , 1 , 116, "TalkEarlyLateToday" )}, // 今日EarlyLateを聞いたか? + {0x75, new EventFlagVillagerMemoryPlayer(0 , 1 , 117, "FinishVisitPToday" )}, // 今日訪問Pクエストをしたか? + {0x76, new EventFlagVillagerMemoryPlayer(0 , 1 , 118, "FinishVisitNToday" )}, // 今日訪問Nクエストをしたか? + {0x77, new EventFlagVillagerMemoryPlayer(0 , 1 , 119, "OrderQuest" )}, // クエストを発注or達成した + {0x78, new EventFlagVillagerMemoryPlayer(0 , 1 , 120, "FirstGreetingAtNpcHome" )}, // 引越し当日のダンボール自宅でNPCと初対面会話をした(自分の村) + {0x79, new EventFlagVillagerMemoryPlayer(0 , 1 , 121, "AppF_MoveinGiftOccured" )}, // 引越し挨拶アプローチ会話発生済か? + {0x7A, new EventFlagVillagerMemoryPlayer(0 , 1 , 122, "UncollectedFishishTreasureHunt" )}, // 宝未回収でクエスト終了した + {0x7B, new EventFlagVillagerMemoryPlayer(0 , 7 , 123, "TalkCountInFacilityToday" )}, // 今日の会話回数(施設用) + {0x7C, new EventFlagVillagerMemoryPlayer(0 , 1 , 124, "FriendshipBecomeAcqHToday" )}, // 今日親密度が知人(高)に到達した + {0x7D, new EventFlagVillagerMemoryPlayer(0 , 1 , 125, "FriendshipBecomeAcqH" )}, // 親密度が知人(高)に到達済み + {0x7E, new EventFlagVillagerMemoryPlayer(0 , 3 , 126, "DC_NPCBirthdayFlag" )}, // NPC誕生日|おでかけ先の村でもらうお返しの種類 + {0x7F, new EventFlagVillagerMemoryPlayer(0 , 1 , 127, "EasterCannotGetNnpcRecipeFlag" )}, // イースター|このNPCから受け取り損ねたアイテムがある? + {0x81, new EventFlagVillagerMemoryPlayer(0 , 1 , 129, "HalloweenTerrifyFlag" )}, // ハロウィン|今日パンプキングの恰好で脅かした? + {0x82, new EventFlagVillagerMemoryPlayer(0 , 1 , 130, "HalloweenGetCandyFlag" )}, // ハロウィン|今日このNPCからアメもらった? + {0x83, new EventFlagVillagerMemoryPlayer(0 , 1 , 131, "FireworksGetItemFlag" )}, // 花火大会|このNPCからリアクション会話で花火を受け取った + {0x84, new EventFlagVillagerMemoryPlayer(0 , 1 , 132, "HaloweenTalkThisSceneFalg" )}, // ハロウィン|このシーンで会話した? + {0x85, new EventFlagVillagerMemoryPlayer(0 , 1 , 133, "HaloweenGetCandyThisSceneFalg" )}, // ハロウィン|このシーンでアメもらった? + {0x88, new EventFlagVillagerMemoryPlayer(0 , 1 , 136, "HalloweenLastNotGetFlag" )}, // ハロウィン|最後の会話で報酬アイテムもらえなかった? + {0x89, new EventFlagVillagerMemoryPlayer(0 , 16 , 137, "HalloweenLastNotGetItem" )}, // ハロウィン|最後の会話でもらえなかった報酬アイテム + {0x8A, new EventFlagVillagerMemoryPlayer(0 , 1 , 138, "HarvestItemExchangeToday" )}, // ハーベスト|物々交換を1度でも行ったか? + {0x8B, new EventFlagVillagerMemoryPlayer(0 , 1 , 139, "ChristmasSantaPresentsFlag" )}, // サンタミッションのプレゼントを受け取ったか? + {0x8C, new EventFlagVillagerMemoryPlayer(0 , 1 , 140, "ChristmasSantaPresentsNoGetFlag" )}, // サンタミッションのお返しが持ち物一杯で受け取れなかった? + {0x8D, new EventFlagVillagerMemoryPlayer(0 , 1 , 141, "ChristmasSantaPresentsReturnFlag" )}, // サンタミッションでプレゼント渡したらお返しくれたか? + {0x8E, new EventFlagVillagerMemoryPlayer(0 , 1 , 142, "ChristmasGiftExchangeFlag" )}, // そのNPCとプレゼント交換をしたか? + {0x8F, new EventFlagVillagerMemoryPlayer(0 , 8 , 143, "ChristmasExchangeItemType" )}, // クリスマス|プレゼント交換であげたプレゼントの種類 + {0x90, new EventFlagVillagerMemoryPlayer(0 , 1 , 144, "ChristmasCosJudgeFlag" )}, // イブにサンタの恰好をしているか? + {0x91, new EventFlagVillagerMemoryPlayer(0 , 1 , 145, "ChristmasCannotGetNnpcItemFlag" )}, // クリスマス|このNPCから受け取り損ねたアイテムがある? + {0x92, new EventFlagVillagerMemoryPlayer(0 , 1 , 146, "ChristmasAfterMesFlag" )}, // クリスマス(25日)に専用会話を聞いた? + {0x93, new EventFlagVillagerMemoryPlayer(0 , 1 , 147, "ChristmasWrappingGiftNoGetFlag" )}, // クリスマス|持ち物一杯でラッピングペーパーを受け取り損ねた? + {0x94, new EventFlagVillagerMemoryPlayer(0 , 8 , 148, "ChristmasSantaPresentItemType" )}, // クリスマス|サンタミッションであげたプレゼントの種類 + {0x95, new EventFlagVillagerMemoryPlayer(0 , 8 , 149, "ChristmasExchangeRemakeId" )}, // クリスマス|プレゼント交換であげたプレゼントのリメイクID + {0x96, new EventFlagVillagerMemoryPlayer(0 , 8 , 150, "ChristmasSantaPresentRemakeId" )}, // クリスマス|サンタミッションであげたプレゼントのリメイクID + {0x97, new EventFlagVillagerMemoryPlayer(0 , 1 , 151, "CarnvalTalkWithoutFeatherFlag" )}, // 一般NPC/カーニバル|はねを持たずに会話した? + {0x98, new EventFlagVillagerMemoryPlayer(0 , 1 , 152, "CarnvalExchangeFeatherFlag" )}, // 一般NPC/カーニバル|このNPCとはね交換した? + {0x99, new EventFlagVillagerMemoryPlayer(0 , 1 , 153, "CarnvalTalkOutdoorFlag" )}, // 一般NPC/カーニバル|今日屋外で会話した? + {0x9A, new EventFlagVillagerMemoryPlayer(0 , 1 , 154, "CarnvalExchangeFeatherTalkFlag" )}, // 一般NPC/カーニバル|このNPCとはね交換の会話をした? + {0x9B, new EventFlagVillagerMemoryPlayer(0 , 1 , 155, "ValentinePresentFlag" )}, // バレンタイン|バレンタインのプレゼント渡した? + {0x9C, new EventFlagVillagerMemoryPlayer(0 , 1 , 156, "EasterTalkOutdoorFlag" )}, // 一般NPC/イースター|今日屋外で会話した? + {0x9D, new EventFlagVillagerMemoryPlayer(0 , 1 , 157, "EasterExchangeEggFlag" )}, // 一般NPC/イースターこのNPCとたまご交換した? + {0x9E, new EventFlagVillagerMemoryPlayer(0 , 1 , 158, "EasterExchangeEggTalkFlag" )}, // 一般NPC/イースター|このNPCとたまご交換の会話をした? + {0x9F, new EventFlagVillagerMemoryPlayer(0 , 1 , 159, "EasterCannotGetNnpcIsRecipeFlag" )}, // イースター|このNPCから受け取り損ねたのはレシピか + {0xA0, new EventFlagVillagerMemoryPlayer(0 , 1 , 160, "TodayReserveCoordinateHouseInterior" )}, // NPC家コーデ|今日NPCの家の内装の提案をしたか? + {0xA1, new EventFlagVillagerMemoryPlayer(0 , 1 , 161, "TodayReserveCoordinateHouseExterior" )}, // NPC家コーデ|今日NPCの家の外観の提案をしたか? + {0xA2, new EventFlagVillagerMemoryPlayer(0 , 1 , 162, "TodayCompleteCoordinateHouseInterior" )}, // NPC家コーデ|今日NPCの家に提案した内装が反映されたか? + {0xA3, new EventFlagVillagerMemoryPlayer(0 , 1 , 163, "TodayCompleteCoordinateHouseExterior" )}, // NPC家コーデ|今日NPCの家に提案した外観が反映されたか? + {0xA4, new EventFlagVillagerMemoryPlayer(0 , 1 , 164, "InteriorCoordinator" )}, // NPC家コーデ|現在の内装を提案した + {0xA5, new EventFlagVillagerMemoryPlayer(0 , 1 , 165, "ExteriorCoordinator" )}, // NPC家コーデ|現在の外観を提案した + {0xA6, new EventFlagVillagerMemoryPlayer(0 , 1 , 166, "TodayHeardReactTalkAboutCoordinateHouse" )}, // NPC家コーデ|今日、コーディネート提案に関するリアクション会話聞いた + {0xA7, new EventFlagVillagerMemoryPlayer(0 , 1 , 167, "WHEREAREN_VisitWherearenWithPlayer" )}, // OneRoom|おみやげチョコレートを受け取ってウェアラン諸島に行ったことがあるか? + {0xA8, new EventFlagVillagerMemoryPlayer(0 , 1 , 168, "TalkProgressMuseumBuiltCafe" )}, // 博物館(カフェ)への拡張に関するFreeH_Progressを聞いたか? + {0xA9, new EventFlagVillagerMemoryPlayer(0 , 1 , 169, "WHEREAREN_GetChocolate" )}, // OneRoom|おみやげチョコレートを受け取ったことがあるか? + }; + + private const string Unknown = "???"; + + public static string GetName(ushort index, uint count, IReadOnlyDictionary str) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + { + string name = val.Name; + if (str.TryGetValue(name, out var translated)) + name = translated; + return $"{index:00} - {name} = {count}"; + } + return $"{index:00} - {Unknown} = {count}"; + } + + public static string GetName(ushort index, uint count) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + return $"{index:00} - {val.Name} = {count}"; + return $"{index:00} - {Unknown} = {count}"; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Records/INamedValue.cs b/NHSE.Core/Structures/Records/INamedValue.cs index d68051b..9b95283 100644 --- a/NHSE.Core/Structures/Records/INamedValue.cs +++ b/NHSE.Core/Structures/Records/INamedValue.cs @@ -1,8 +1,7 @@ -namespace NHSE.Core +namespace NHSE.Core; + +public interface INamedValue { - public interface INamedValue - { - string Name { get; } - ushort Index { get; } - } -} + string Name { get; } + ushort Index { get; } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Records/LifeSupportAchievement.cs b/NHSE.Core/Structures/Records/LifeSupportAchievement.cs index fda66fb..abca671 100644 --- a/NHSE.Core/Structures/Records/LifeSupportAchievement.cs +++ b/NHSE.Core/Structures/Records/LifeSupportAchievement.cs @@ -1,218 +1,214 @@ using System; using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Multi-milestone definition for tracking game-play achievements. +/// +public class LifeSupportAchievement : INamedValue { /// - /// Multi-milestone definition for tracking game-play achievements. + /// Amount of milestones an achievement can have. /// - public class LifeSupportAchievement : INamedValue + public const int MilestoneMax = 6; + + public readonly short FlagLand; + public readonly short FlagPlayer; + + public ushort Index { get; } + public string Name { get; } + + /// Total number of milestones for this achievement type. + public readonly int AchievementCount; + + /// First Milestone's Satisfaction Threshold + public readonly uint Threshold1; + + /// Second Milestone's Satisfaction Threshold + public readonly uint Threshold2; + + /// Third Milestone's Satisfaction Threshold + public readonly uint Threshold3; + + /// Fourth Milestone's Satisfaction Threshold + public readonly uint Threshold4; + + /// Fifth Milestone's Satisfaction Threshold + public readonly uint Threshold5; + + public LifeSupportAchievement(ushort index, byte max, uint t1, uint t2, uint t3, uint t4, uint t5, short land, short player, string name) { - /// - /// Amount of milestones an achievement can have. - /// - public const int MilestoneMax = 6; - - public readonly short FlagLand; - public readonly short FlagPlayer; - - public ushort Index { get; } - public string Name { get; } - - /// Total number of milestones for this achievement type. - public readonly int AchievementCount; - - /// First Milestone's Satisfaction Threshold - public readonly uint Threshold1; - - /// Second Milestone's Satisfaction Threshold - public readonly uint Threshold2; - - /// Third Milestone's Satisfaction Threshold - public readonly uint Threshold3; - - /// Fourth Milestone's Satisfaction Threshold - public readonly uint Threshold4; - - /// Fifth Milestone's Satisfaction Threshold - public readonly uint Threshold5; - - public LifeSupportAchievement(ushort index, byte max, uint t1, uint t2, uint t3, uint t4, uint t5, short land, short player, string name) - { - Index = index; - AchievementCount = max; - Threshold1 = t1; - Threshold2 = t2; - Threshold3 = t3; - Threshold4 = t4; - Threshold5 = t5; - FlagLand = land; - FlagPlayer = player; - Name = name; - } - - public uint MaxThreshold => Math.Max(Threshold1, Math.Max(Threshold2, Math.Max(Threshold3, Math.Max(Threshold4, Threshold5)))); - - /// - /// Gets the Milestone Threshold - /// - /// Milestone index - /// Zero if the milestone does not have a threshold - public uint GetThresholdValue(in int index) - { - return index switch - { - 0 => Threshold1, - 1 => Threshold2, - 2 => Threshold3, - 3 => Threshold4, - 4 => Threshold5, - _ => 0, - }; - } - - /// - /// Checks if the Milestone is satisfied. - /// - /// Milestone index - /// Value stored for the entry - /// True if the milestone is satisfied, false if not. - public bool GetIsSatisfied(in int index, in uint count) - { - if ((uint)index >= MilestoneMax) - throw new ArgumentOutOfRangeException(nameof(index)); - - // Threshold value milestone - var threshold = GetThresholdValue(index); - if (threshold != 0) - return count >= threshold; - - // Bit-toggle milestone - var bit = (count >> index) & 1; - return bit != 0; - } - - private const string Unknown = "???"; - - public static readonly IReadOnlyDictionary List = new Dictionary - { - {0x00, new LifeSupportAchievement(000, 5, 0010, 0100, 0500, 2000, 5000, 3, -1, "CatchFish" )}, // サカナを釣った - {0x01, new LifeSupportAchievement(001, 5, 0010, 0100, 0500, 2000, 5000, 3, -1, "CatchInsect" )}, // ムシを捕まえた - {0x02, new LifeSupportAchievement(002, 3, 0010, 0050, 0100, 0000, 0000, -1, -1, "CatchFishContinuously" )}, // 連続で釣りを成功させた回数の最高記録 - {0x03, new LifeSupportAchievement(003, 5, 0010, 0020, 0040, 0060, 0080, -1, -1, "FillFishList" )}, // サカナ図鑑を埋めた - {0x04, new LifeSupportAchievement(004, 5, 0010, 0020, 0040, 0060, 0080, -1, -1, "FillInsectList" )}, // ムシ図鑑を埋めた - {0x05, new LifeSupportAchievement(005, 5, 0005, 0020, 0050, 0100, 0300, -1, -1, "ShootDownBalloon" )}, // ふうせんを撃ち落とした - {0x06, new LifeSupportAchievement(006, 5, 0010, 0050, 0100, 0200, 0300, 3, -1, "PlantFlowerSeed" )}, // 花の種を植えた - {0x07, new LifeSupportAchievement(007, 6, 0000, 0000, 0000, 0000, 0000, -1, -1, "PlantFruit" )}, // 6種類のフルーツを植えた - {0x08, new LifeSupportAchievement(008, 3, 0005, 0010, 0030, 0000, 0000, -1, -1, "PlantTreeSeedling" )}, // 木の苗を植えた - {0x09, new LifeSupportAchievement(009, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BuyKabu" )}, // カブを買った - {0x0A, new LifeSupportAchievement(010, 5, 1000, 10000, 100000, 1000000, 10000000, -1, -1, "HowmuchSellKabu" )}, // カブで得た累計利益 - {0x0B, new LifeSupportAchievement(011, 5, 5000, 50000, 500000, 2000000, 5000000, -1, -1, "HowmuchBuyItem" )}, // これまでの買い物総額 - {0x0C, new LifeSupportAchievement(012, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BuyItemRcm" )}, // まめきちの店で買い物した - {0x0D, new LifeSupportAchievement(013, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "SellItemRcm" )}, // まめきちの店で売った - {0x0E, new LifeSupportAchievement(014, 5, 0005, 0020, 0050, 0100, 0200, -1, -1, "RemakeFurniture" )}, // リメイクをした - {0x0F, new LifeSupportAchievement(015, 5, 0100, 0200, 0300, 0400, 0500, -1, -1, "FillCatalog" )}, // カタログの項目数 - {0x10, new LifeSupportAchievement(016, 5, 0001, 0020, 0050, 0100, 0200, -1, -1, "BuyItemCatalog" )}, // 通販を利用した - {0x11, new LifeSupportAchievement(017, 5, 0001, 0010, 0030, 0060, 0100, -1, -1, "GotoTotakekeShow" )}, // とたけけのライブを観た - {0x12, new LifeSupportAchievement(018, 3, 0001, 0005, 0010, 0000, 0000, -1, -1, "VisitAnotherIsland" )}, // よその島へのおでかけした - {0x13, new LifeSupportAchievement(019, 3, 0001, 0005, 0010, 0000, 0000, -1, -1, "InviteFriend" )}, // 島にフレンドを招いた - {0x15, new LifeSupportAchievement(021, 5, 0003, 0020, 0050, 0100, 0300, -1, -1, "DayPlayed" )}, // 活動日数 - {0x17, new LifeSupportAchievement(023, 5, 0010, 0050, 0100, 0500, 1000, -1, -1, "WaterPlant" )}, // 水やりをした - {0x18, new LifeSupportAchievement(024, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BeStungbyWasp" )}, // ハチに刺された - {0x19, new LifeSupportAchievement(025, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "CatchSeminonukegara" )}, // セミのぬけがらを取った - {0x1A, new LifeSupportAchievement(026, 3, 0001, 0005, 0010, 0000, 0000, -1, -1, "CatchNomi" )}, // ノミを取ってあげた - {0x1B, new LifeSupportAchievement(027, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BeStungbyPoisonousInsect" )}, // こわいムシで気絶した - {0x1F, new LifeSupportAchievement(031, 5, 0001, 0010, 0020, 0030, 0042, -1, -1, "FillReactionList" )}, // リアクションを覚えた - {0x20, new LifeSupportAchievement(032, 3, 0003, 0010, 0020, 0000, 0000, -1, -1, "CatchTrash" )}, // ゴミを釣った - {0x21, new LifeSupportAchievement(033, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "PayImmigrationCost" )}, // 移住費用を支払った - {0x22, new LifeSupportAchievement(034, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "RepayLoan" )}, // ローンを完済した - {0x23, new LifeSupportAchievement(035, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "UseMydesign" )}, // マイデザインを使った - {0x24, new LifeSupportAchievement(036, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "UseMydesignPRO" )}, // マイデザインPROを使った - {0x25, new LifeSupportAchievement(037, 5, 0050, 0200, 1000, 2000, 3000, -1, -1, "SellWeed" )}, // 雑草を引き取ってもらった - {0x27, new LifeSupportAchievement(039, 6, 0000, 0000, 0000, 0000, 0000, -1, -1, "CollectGoldTool" )}, // 6種類の金の道具を集めた - {0x28, new LifeSupportAchievement(040, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "GetSRankonHHA" )}, // HHAでSを取った - {0x29, new LifeSupportAchievement(041, 4, 0000, 0000, 0000, 0000, 0000, -1, -1, "AttendFishingConvention" )}, // 釣り大会に春夏秋冬参加した - {0x2A, new LifeSupportAchievement(042, 4, 0000, 0000, 0000, 0000, 0000, -1, -1, "AttendInsectConvention" )}, // ムシとり大会に6~9月参加した - {0x2B, new LifeSupportAchievement(043, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "HelpGul" )}, // ジョニーを助けた - {0x2C, new LifeSupportAchievement(044, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "HelpGst" )}, // ゆうたろうを助けた - {0x2D, new LifeSupportAchievement(045, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "MakePerfectSnowball" )}, // 最高のゆきだるまを作った - {0x2E, new LifeSupportAchievement(046, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "ReachMyBirthday" )}, // 誕生日を迎えた - {0x2F, new LifeSupportAchievement(047, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "CelebrateVillagersBithday" )}, // 村民の誕生日を祝ってあげた - {0x30, new LifeSupportAchievement(048, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "AttendCountdownParty" )}, // カウントダウンに参加した - {0x31, new LifeSupportAchievement(049, 5, 0001, 0020, 0050, 0100, 0200, -1, -1, "BreakTool" )}, // 道具を壊した - {0x32, new LifeSupportAchievement(050, 5, 0005, 0020, 0050, 0100, 0200, -1, -1, "SendLetter" )}, // 手紙を送った - {0x33, new LifeSupportAchievement(051, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "MakePitfall" )}, // 落とし穴を作った - {0x34, new LifeSupportAchievement(052, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "FallintoPitfall" )}, // 落とし穴に落ちた - {0x35, new LifeSupportAchievement(053, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "ImmigratetoIsland" )}, // 島に移住した - {0x36, new LifeSupportAchievement(054, 3, 0001, 0002, 0003, 0000, 0000, -1, -1, "BeFriendwithVillager" )}, // どうぶつとなかよしになった - {0x37, new LifeSupportAchievement(055, 5, 0010, 0050, 0100, 0150, 0200, -1, -1, "FillRecipeList" )}, // 集めたレシピの数 - {0x38, new LifeSupportAchievement(056, 1, 1000, 0000, 0000, 0000, 0000, -1, -1, "BootPhone" )}, // スマホを起動した(上級) - {0x39, new LifeSupportAchievement(057, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "StrikeRock8Times" )}, // コイン岩を8連打した - {0x3A, new LifeSupportAchievement(058, 5, 0005, 0050, 0200, 1000, 3000, -1, 320, "AchieveAppQuest" )}, // 村活クエストを達成した - {0x3B, new LifeSupportAchievement(059, 5, 0001, 0010, 0050, 0100, 0300, -1, -1, "AchieveVillagersQuest" )}, // どうぶつのお願いを聞いた - {0x3C, new LifeSupportAchievement(060, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DigBell" )}, // ベルを掘り出した - {0x3D, new LifeSupportAchievement(061, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DigFossil" )}, // 化石を掘り出した - {0x3E, new LifeSupportAchievement(062, 5, 0005, 0030, 0100, 0300, 0500, -1, -1, "JudgeFossil" )}, // 化石を鑑定した - {0x3F, new LifeSupportAchievement(063, 5, 0005, 0020, 0050, 0100, 0200, 66, -1, "DigShell" )}, // 潮干狩りをした - {0x40, new LifeSupportAchievement(064, 1, 0010, 0000, 0000, 0000, 0000, 3, -1, "PutFurnitureOutside" )}, // 外に家具を置いた - {0x43, new LifeSupportAchievement(067, 5, 0020, 0100, 0500, 2000, 5000, -1, -1, "StrikeWood" )}, // 木からもくざいを出した - {0x44, new LifeSupportAchievement(068, 5, 0001, 0010, 0020, 0030, 0050, 3, -1, "GreetAllVillager" )}, // 村民全員とあいさつをした - {0x45, new LifeSupportAchievement(069, 5, 0010, 0050, 0200, 0500, 1000, 3, -1, "SellShell" )}, // 貝殻を売った - {0x46, new LifeSupportAchievement(070, 5, 0020, 0100, 0500, 1000, 3000, 3, -1, "SellFruit" )}, // フルーツを売った - {0x47, new LifeSupportAchievement(071, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "CatchBeeContinuously" )}, // ハチを5連続捕まえた - {0x48, new LifeSupportAchievement(072, 5, 0005, 0050, 0200, 1000, 3000, -1, -1, "DIYTool" )}, // 道具をDIYした - {0x49, new LifeSupportAchievement(073, 5, 0005, 0050, 0200, 1000, 3000, -1, -1, "DIYFurniture" )}, // 家具をDIYした - {0x4B, new LifeSupportAchievement(075, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "TakePicture" )}, // カメラで写真を撮った - {0x4C, new LifeSupportAchievement(076, 1, 0010, 0000, 0000, 0000, 0000, -1, -1, "BootPhoneBeginner" )}, // スマホを起動した(初級) - {0x4D, new LifeSupportAchievement(077, 5, 0020, 0050, 0100, 0200, 0300, -1, -1, "HouseStorageItem" )}, // 家の倉庫に収納したアイテムの数 - {0x4E, new LifeSupportAchievement(078, 5, 0005, 0015, 0030, 0100, 0150, -1, -1, "PlaceFurnitureMyHouse" )}, // 家に飾っている家具の数 - {0x4F, new LifeSupportAchievement(079, 5, 0001, 0010, 0020, 0050, 0100, -1, -1, "FallFurnitureLeaf" )}, // 木を揺すって家具(葉っぱ)を落とした回数 - {0x50, new LifeSupportAchievement(080, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DropPresentinWater" )}, // 風船のプレゼントを撃ち水の中に落とした - {0x51, new LifeSupportAchievement(081, 3, 0001, 0003, 0005, 0000, 0000, -1, -1, "ReformMyHome" )}, // マイホームをリフォームした - {0x52, new LifeSupportAchievement(082, 5, 0001, 0002, 0005, 0006, 0007, -1, -1, "ExtendMyHome" )}, // マイホームを増築した - {0x53, new LifeSupportAchievement(083, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "PostMessageBoard" )}, // 自分の島の掲示板に書き込む - {0x54, new LifeSupportAchievement(084, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "UseCloset" )}, // クローゼットで着替える - {0x55, new LifeSupportAchievement(085, 3, 0001, 0030, 0200, 0000, 0000, -1, -1, "PrayShootingStar" )}, // 流れ星に祈る - {0x56, new LifeSupportAchievement(086, 2, 0000, 0000, 0000, 0000, 0000, 59, -1, "ChangeSymbol" )}, // 島の旗、島メロを変える - {0x57, new LifeSupportAchievement(087, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "UpdatePassport" )}, // パスポートを更新した - {0x58, new LifeSupportAchievement(088, 3, 0000, 0000, 0000, 0000, 0000, -1, 513, "ModifyIsland" )}, // 各地形造成をやってみた - {0x59, new LifeSupportAchievement(089, 1, 0020, 0000, 0000, 0000, 0000, -1, 478, "BuildFence" )}, // 柵を置く - {0x5A, new LifeSupportAchievement(090, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DonateFake" )}, // 寄贈しようとした美術品が贋作だった - {0x5B, new LifeSupportAchievement(091, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "BuyatTsunekichiShop" )}, // いなりマーケットで芸術品を買った - {0x5C, new LifeSupportAchievement(092, 3, 0001, 0005, 0020, 0000, 0000, -1, -1, "PlantBushSeedling" )}, // 各種低木の苗を植えた - {0x5F, new LifeSupportAchievement(095, 5, 0005, 0010, 0020, 0030, 0040, -1, -1, "FillSeafoodList" )}, // 海の幸図鑑を埋めた数 - {0x60, new LifeSupportAchievement(096, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "GiveScallopsToSeo" )}, // ラコスケにホタテを渡した回数 - {0x62, new LifeSupportAchievement(098, 5, 0005, 0050, 0250, 1000, 2500, -1, -1, "CatchSeafood" )}, // 海の幸をGETした回数 - {0x64, new LifeSupportAchievement(100, 5, 0005, 0020, 0050, 0100, 0200, -1, -1, "PlantVegetableSeedling" )}, // 野菜の苗を植えた回数 - {0x66, new LifeSupportAchievement(102, 5, 0010, 0050, 0150, 0500, 1000, -1, -1, "HarvestVegetable" )}, // 野菜を収穫した個数 - {0x67, new LifeSupportAchievement(103, 5, 0003, 0010, 0020, 0030, 0050, -1, -1, "VisitKappeiTour" )}, // カッペイツアーに行った回数 - {0x68, new LifeSupportAchievement(104, 3, 0005, 0015, 0020, 0000, 0000, -1, -1, "FillGyroidList" )}, // ハニワのカタログ数 - {0x69, new LifeSupportAchievement(105, 3, 0010, 0030, 0050, 0000, 0000, -1, -1, "FillCookingList" )}, // 料理レシピ習得数 - {0x6A, new LifeSupportAchievement(106, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DigGyroid" )}, // 島でハニワを掘り出した - {0x6B, new LifeSupportAchievement(107, 5, 0005, 0030, 0100, 0300, 0500, -1, -1, "CookFood" )}, // 料理した回数 - {0x6C, new LifeSupportAchievement(108, 5, 0005, 0010, 0020, 0030, 0050, -1, -1, "DrinkCoffee" )}, // 喫茶店でコーヒーを飲んだ回数 - {0x6D, new LifeSupportAchievement(109, 5, 0003, 0010, 0020, 0030, 0050, -1, -1, "JoinRadioGymnastics" )}, // ラジオ体操した回数 - }; - - public static string GetName(int index, uint count, IReadOnlyDictionary str) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - { - string name = val.Name; - if (str.TryGetValue(name, out var translated)) - name = translated; - return $"{index:00} - {name} = {count}"; - } - return $"{index:00} - {Unknown} = {count}"; - } - - public static string GetName(int index, uint count) - { - var dict = List; - if (dict.TryGetValue(index, out var val)) - return $"{index:00} - {val.Name} = {count}"; - return $"{index:00} - {Unknown} = {count}"; - } + Index = index; + AchievementCount = max; + Threshold1 = t1; + Threshold2 = t2; + Threshold3 = t3; + Threshold4 = t4; + Threshold5 = t5; + FlagLand = land; + FlagPlayer = player; + Name = name; } -} + + public uint MaxThreshold => Math.Max(Threshold1, Math.Max(Threshold2, Math.Max(Threshold3, Math.Max(Threshold4, Threshold5)))); + + /// + /// Gets the Milestone Threshold + /// + /// Milestone index + /// Zero if the milestone does not have a threshold + public uint GetThresholdValue(in int index) => index switch + { + 0 => Threshold1, + 1 => Threshold2, + 2 => Threshold3, + 3 => Threshold4, + 4 => Threshold5, + _ => 0, + }; + + /// + /// Checks if the Milestone is satisfied. + /// + /// Milestone index + /// Value stored for the entry + /// True if the milestone is satisfied, false if not. + public bool GetIsSatisfied(in int index, in uint count) + { + if ((uint)index >= MilestoneMax) + throw new ArgumentOutOfRangeException(nameof(index)); + + // Threshold value milestone + var threshold = GetThresholdValue(index); + if (threshold != 0) + return count >= threshold; + + // Bit-toggle milestone + var bit = (count >> index) & 1; + return bit != 0; + } + + private const string Unknown = "???"; + + public static readonly IReadOnlyDictionary List = new Dictionary + { + {0x00, new(000, 5, 0010, 0100, 0500, 2000, 5000, 3, -1, "CatchFish" )}, // サカナを釣った + {0x01, new(001, 5, 0010, 0100, 0500, 2000, 5000, 3, -1, "CatchInsect" )}, // ムシを捕まえた + {0x02, new(002, 3, 0010, 0050, 0100, 0000, 0000, -1, -1, "CatchFishContinuously" )}, // 連続で釣りを成功させた回数の最高記録 + {0x03, new(003, 5, 0010, 0020, 0040, 0060, 0080, -1, -1, "FillFishList" )}, // サカナ図鑑を埋めた + {0x04, new(004, 5, 0010, 0020, 0040, 0060, 0080, -1, -1, "FillInsectList" )}, // ムシ図鑑を埋めた + {0x05, new(005, 5, 0005, 0020, 0050, 0100, 0300, -1, -1, "ShootDownBalloon" )}, // ふうせんを撃ち落とした + {0x06, new(006, 5, 0010, 0050, 0100, 0200, 0300, 3, -1, "PlantFlowerSeed" )}, // 花の種を植えた + {0x07, new(007, 6, 0000, 0000, 0000, 0000, 0000, -1, -1, "PlantFruit" )}, // 6種類のフルーツを植えた + {0x08, new(008, 3, 0005, 0010, 0030, 0000, 0000, -1, -1, "PlantTreeSeedling" )}, // 木の苗を植えた + {0x09, new(009, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BuyKabu" )}, // カブを買った + {0x0A, new(010, 5, 1000, 10000, 100000, 1000000, 10000000, -1, -1, "HowmuchSellKabu" )}, // カブで得た累計利益 + {0x0B, new(011, 5, 5000, 50000, 500000, 2000000, 5000000, -1, -1, "HowmuchBuyItem" )}, // これまでの買い物総額 + {0x0C, new(012, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BuyItemRcm" )}, // まめきちの店で買い物した + {0x0D, new(013, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "SellItemRcm" )}, // まめきちの店で売った + {0x0E, new(014, 5, 0005, 0020, 0050, 0100, 0200, -1, -1, "RemakeFurniture" )}, // リメイクをした + {0x0F, new(015, 5, 0100, 0200, 0300, 0400, 0500, -1, -1, "FillCatalog" )}, // カタログの項目数 + {0x10, new(016, 5, 0001, 0020, 0050, 0100, 0200, -1, -1, "BuyItemCatalog" )}, // 通販を利用した + {0x11, new(017, 5, 0001, 0010, 0030, 0060, 0100, -1, -1, "GotoTotakekeShow" )}, // とたけけのライブを観た + {0x12, new(018, 3, 0001, 0005, 0010, 0000, 0000, -1, -1, "VisitAnotherIsland" )}, // よその島へのおでかけした + {0x13, new(019, 3, 0001, 0005, 0010, 0000, 0000, -1, -1, "InviteFriend" )}, // 島にフレンドを招いた + {0x15, new(021, 5, 0003, 0020, 0050, 0100, 0300, -1, -1, "DayPlayed" )}, // 活動日数 + {0x17, new(023, 5, 0010, 0050, 0100, 0500, 1000, -1, -1, "WaterPlant" )}, // 水やりをした + {0x18, new(024, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BeStungbyWasp" )}, // ハチに刺された + {0x19, new(025, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "CatchSeminonukegara" )}, // セミのぬけがらを取った + {0x1A, new(026, 3, 0001, 0005, 0010, 0000, 0000, -1, -1, "CatchNomi" )}, // ノミを取ってあげた + {0x1B, new(027, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BeStungbyPoisonousInsect" )}, // こわいムシで気絶した + {0x1F, new(031, 5, 0001, 0010, 0020, 0030, 0042, -1, -1, "FillReactionList" )}, // リアクションを覚えた + {0x20, new(032, 3, 0003, 0010, 0020, 0000, 0000, -1, -1, "CatchTrash" )}, // ゴミを釣った + {0x21, new(033, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "PayImmigrationCost" )}, // 移住費用を支払った + {0x22, new(034, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "RepayLoan" )}, // ローンを完済した + {0x23, new(035, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "UseMydesign" )}, // マイデザインを使った + {0x24, new(036, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "UseMydesignPRO" )}, // マイデザインPROを使った + {0x25, new(037, 5, 0050, 0200, 1000, 2000, 3000, -1, -1, "SellWeed" )}, // 雑草を引き取ってもらった + {0x27, new(039, 6, 0000, 0000, 0000, 0000, 0000, -1, -1, "CollectGoldTool" )}, // 6種類の金の道具を集めた + {0x28, new(040, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "GetSRankonHHA" )}, // HHAでSを取った + {0x29, new(041, 4, 0000, 0000, 0000, 0000, 0000, -1, -1, "AttendFishingConvention" )}, // 釣り大会に春夏秋冬参加した + {0x2A, new(042, 4, 0000, 0000, 0000, 0000, 0000, -1, -1, "AttendInsectConvention" )}, // ムシとり大会に6~9月参加した + {0x2B, new(043, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "HelpGul" )}, // ジョニーを助けた + {0x2C, new(044, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "HelpGst" )}, // ゆうたろうを助けた + {0x2D, new(045, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "MakePerfectSnowball" )}, // 最高のゆきだるまを作った + {0x2E, new(046, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "ReachMyBirthday" )}, // 誕生日を迎えた + {0x2F, new(047, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "CelebrateVillagersBithday" )}, // 村民の誕生日を祝ってあげた + {0x30, new(048, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "AttendCountdownParty" )}, // カウントダウンに参加した + {0x31, new(049, 5, 0001, 0020, 0050, 0100, 0200, -1, -1, "BreakTool" )}, // 道具を壊した + {0x32, new(050, 5, 0005, 0020, 0050, 0100, 0200, -1, -1, "SendLetter" )}, // 手紙を送った + {0x33, new(051, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "MakePitfall" )}, // 落とし穴を作った + {0x34, new(052, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "FallintoPitfall" )}, // 落とし穴に落ちた + {0x35, new(053, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "ImmigratetoIsland" )}, // 島に移住した + {0x36, new(054, 3, 0001, 0002, 0003, 0000, 0000, -1, -1, "BeFriendwithVillager" )}, // どうぶつとなかよしになった + {0x37, new(055, 5, 0010, 0050, 0100, 0150, 0200, -1, -1, "FillRecipeList" )}, // 集めたレシピの数 + {0x38, new(056, 1, 1000, 0000, 0000, 0000, 0000, -1, -1, "BootPhone" )}, // スマホを起動した(上級) + {0x39, new(057, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "StrikeRock8Times" )}, // コイン岩を8連打した + {0x3A, new(058, 5, 0005, 0050, 0200, 1000, 3000, -1, 320, "AchieveAppQuest" )}, // 村活クエストを達成した + {0x3B, new(059, 5, 0001, 0010, 0050, 0100, 0300, -1, -1, "AchieveVillagersQuest" )}, // どうぶつのお願いを聞いた + {0x3C, new(060, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DigBell" )}, // ベルを掘り出した + {0x3D, new(061, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DigFossil" )}, // 化石を掘り出した + {0x3E, new(062, 5, 0005, 0030, 0100, 0300, 0500, -1, -1, "JudgeFossil" )}, // 化石を鑑定した + {0x3F, new(063, 5, 0005, 0020, 0050, 0100, 0200, 66, -1, "DigShell" )}, // 潮干狩りをした + {0x40, new(064, 1, 0010, 0000, 0000, 0000, 0000, 3, -1, "PutFurnitureOutside" )}, // 外に家具を置いた + {0x43, new(067, 5, 0020, 0100, 0500, 2000, 5000, -1, -1, "StrikeWood" )}, // 木からもくざいを出した + {0x44, new(068, 5, 0001, 0010, 0020, 0030, 0050, 3, -1, "GreetAllVillager" )}, // 村民全員とあいさつをした + {0x45, new(069, 5, 0010, 0050, 0200, 0500, 1000, 3, -1, "SellShell" )}, // 貝殻を売った + {0x46, new(070, 5, 0020, 0100, 0500, 1000, 3000, 3, -1, "SellFruit" )}, // フルーツを売った + {0x47, new(071, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "CatchBeeContinuously" )}, // ハチを5連続捕まえた + {0x48, new(072, 5, 0005, 0050, 0200, 1000, 3000, -1, -1, "DIYTool" )}, // 道具をDIYした + {0x49, new(073, 5, 0005, 0050, 0200, 1000, 3000, -1, -1, "DIYFurniture" )}, // 家具をDIYした + {0x4B, new(075, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "TakePicture" )}, // カメラで写真を撮った + {0x4C, new(076, 1, 0010, 0000, 0000, 0000, 0000, -1, -1, "BootPhoneBeginner" )}, // スマホを起動した(初級) + {0x4D, new(077, 5, 0020, 0050, 0100, 0200, 0300, -1, -1, "HouseStorageItem" )}, // 家の倉庫に収納したアイテムの数 + {0x4E, new(078, 5, 0005, 0015, 0030, 0100, 0150, -1, -1, "PlaceFurnitureMyHouse" )}, // 家に飾っている家具の数 + {0x4F, new(079, 5, 0001, 0010, 0020, 0050, 0100, -1, -1, "FallFurnitureLeaf" )}, // 木を揺すって家具(葉っぱ)を落とした回数 + {0x50, new(080, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DropPresentinWater" )}, // 風船のプレゼントを撃ち水の中に落とした + {0x51, new(081, 3, 0001, 0003, 0005, 0000, 0000, -1, -1, "ReformMyHome" )}, // マイホームをリフォームした + {0x52, new(082, 5, 0001, 0002, 0005, 0006, 0007, -1, -1, "ExtendMyHome" )}, // マイホームを増築した + {0x53, new(083, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "PostMessageBoard" )}, // 自分の島の掲示板に書き込む + {0x54, new(084, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "UseCloset" )}, // クローゼットで着替える + {0x55, new(085, 3, 0001, 0030, 0200, 0000, 0000, -1, -1, "PrayShootingStar" )}, // 流れ星に祈る + {0x56, new(086, 2, 0000, 0000, 0000, 0000, 0000, 59, -1, "ChangeSymbol" )}, // 島の旗、島メロを変える + {0x57, new(087, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "UpdatePassport" )}, // パスポートを更新した + {0x58, new(088, 3, 0000, 0000, 0000, 0000, 0000, -1, 513, "ModifyIsland" )}, // 各地形造成をやってみた + {0x59, new(089, 1, 0020, 0000, 0000, 0000, 0000, -1, 478, "BuildFence" )}, // 柵を置く + {0x5A, new(090, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DonateFake" )}, // 寄贈しようとした美術品が贋作だった + {0x5B, new(091, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "BuyatTsunekichiShop" )}, // いなりマーケットで芸術品を買った + {0x5C, new(092, 3, 0001, 0005, 0020, 0000, 0000, -1, -1, "PlantBushSeedling" )}, // 各種低木の苗を植えた + {0x5F, new(095, 5, 0005, 0010, 0020, 0030, 0040, -1, -1, "FillSeafoodList" )}, // 海の幸図鑑を埋めた数 + {0x60, new(096, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "GiveScallopsToSeo" )}, // ラコスケにホタテを渡した回数 + {0x62, new(098, 5, 0005, 0050, 0250, 1000, 2500, -1, -1, "CatchSeafood" )}, // 海の幸をGETした回数 + {0x64, new(100, 5, 0005, 0020, 0050, 0100, 0200, -1, -1, "PlantVegetableSeedling" )}, // 野菜の苗を植えた回数 + {0x66, new(102, 5, 0010, 0050, 0150, 0500, 1000, -1, -1, "HarvestVegetable" )}, // 野菜を収穫した個数 + {0x67, new(103, 5, 0003, 0010, 0020, 0030, 0050, -1, -1, "VisitKappeiTour" )}, // カッペイツアーに行った回数 + {0x68, new(104, 3, 0005, 0015, 0020, 0000, 0000, -1, -1, "FillGyroidList" )}, // ハニワのカタログ数 + {0x69, new(105, 3, 0010, 0030, 0050, 0000, 0000, -1, -1, "FillCookingList" )}, // 料理レシピ習得数 + {0x6A, new(106, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DigGyroid" )}, // 島でハニワを掘り出した + {0x6B, new(107, 5, 0005, 0030, 0100, 0300, 0500, -1, -1, "CookFood" )}, // 料理した回数 + {0x6C, new(108, 5, 0005, 0010, 0020, 0030, 0050, -1, -1, "DrinkCoffee" )}, // 喫茶店でコーヒーを飲んだ回数 + {0x6D, new(109, 5, 0003, 0010, 0020, 0030, 0050, -1, -1, "JoinRadioGymnastics" )}, // ラジオ体操した回数 + }; + + public static string GetName(int index, uint count, IReadOnlyDictionary str) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + { + string name = val.Name; + if (str.TryGetValue(name, out var translated)) + name = translated; + return $"{index:00} - {name} = {count}"; + } + return $"{index:00} - {Unknown} = {count}"; + } + + public static string GetName(int index, uint count) + { + var dict = List; + if (dict.TryGetValue(index, out var val)) + return $"{index:00} - {val.Name} = {count}"; + return $"{index:00} - {Unknown} = {count}"; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/TurnipStonk.cs b/NHSE.Core/Structures/TurnipStonk.cs index c789d04..a54435a 100644 --- a/NHSE.Core/Structures/TurnipStonk.cs +++ b/NHSE.Core/Structures/TurnipStonk.cs @@ -1,49 +1,48 @@ using System.ComponentModel; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Sequential, Size = SIZE)] +public class TurnipStonk // GSaveShopKabu { - [StructLayout(LayoutKind.Sequential, Size = SIZE)] - public class TurnipStonk // GSaveShopKabu - { - public const int SIZE = 0x44; + public const int SIZE = 0x44; - private const string Buy = nameof(Buy); - private const string Sell = nameof(Sell); - private const string Info = nameof(Info); + private const string Buy = nameof(Buy); + private const string Sell = nameof(Sell); + private const string Info = nameof(Info); - [Category(Buy)] public uint BuyPrice { get; set; } // KaburibaKabuka + [Category(Buy)] public uint BuyPrice { get; set; } // KaburibaKabuka - [Category(Sell)] public uint SellSundayAM { get; set; } - [Category(Sell)] public uint SellSundayPM { get; set; } + [Category(Sell)] public uint SellSundayAM { get; set; } + [Category(Sell)] public uint SellSundayPM { get; set; } - [Category(Sell)] public uint SellMondayAM { get; set; } - [Category(Sell)] public uint SellMondayPM { get; set; } + [Category(Sell)] public uint SellMondayAM { get; set; } + [Category(Sell)] public uint SellMondayPM { get; set; } - [Category(Sell)] public uint SellTuesdayAM { get; set; } - [Category(Sell)] public uint SellTuesdayPM { get; set; } + [Category(Sell)] public uint SellTuesdayAM { get; set; } + [Category(Sell)] public uint SellTuesdayPM { get; set; } - [Category(Sell)] public uint SellWednesdayAM { get; set; } - [Category(Sell)] public uint SellWednesdayPM { get; set; } + [Category(Sell)] public uint SellWednesdayAM { get; set; } + [Category(Sell)] public uint SellWednesdayPM { get; set; } - [Category(Sell)] public uint SellThursdayAM { get; set; } - [Category(Sell)] public uint SellThursdayPM { get; set; } + [Category(Sell)] public uint SellThursdayAM { get; set; } + [Category(Sell)] public uint SellThursdayPM { get; set; } - [Category(Sell)] public uint SellFridayAM { get; set; } - [Category(Sell)] public uint SellFridayPM { get; set; } + [Category(Sell)] public uint SellFridayAM { get; set; } + [Category(Sell)] public uint SellFridayPM { get; set; } - [Category(Sell)] public uint SellSaturdayAM { get; set; } - [Category(Sell)] public uint SellSaturdayPM { get; set; } + [Category(Sell)] public uint SellSaturdayAM { get; set; } + [Category(Sell)] public uint SellSaturdayPM { get; set; } - [Category(Info)] public TurnipPattern Pattern { get; set; } // KabukaPattern - [Category(Info)] public uint FeverStart { get; set; } - } - - public enum TurnipPattern : uint - { - Fluctuating, - LargeSpike, - Decreasing, - SmallSpike, - } + [Category(Info)] public TurnipPattern Pattern { get; set; } // KabukaPattern + [Category(Info)] public uint FeverStart { get; set; } } + +public enum TurnipPattern : uint +{ + Fluctuating, + LargeSpike, + Decreasing, + SmallSpike, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/GSaveMemory.cs b/NHSE.Core/Structures/Villager/GSaveMemory.cs index 115059a..7129c39 100644 --- a/NHSE.Core/Structures/Villager/GSaveMemory.cs +++ b/NHSE.Core/Structures/Villager/GSaveMemory.cs @@ -1,79 +1,80 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +public class GSaveMemory : IVillagerOrigin { - public class GSaveMemory : IVillagerOrigin + public const int SIZE = 0x5F0; + + public readonly Memory Raw; + public Span Data => Raw.Span; + + public GSaveMemory(Memory data) => Raw = data; + + public GSavePlayerId PlayerId { - public const int SIZE = 0x5F0; + get => Data[..GSavePlayerId.SIZE].ToStructure(); + set => value.ToBytes().CopyTo(Data); + } - public readonly byte[] Data; + public uint TownID + { + get => ReadUInt32LittleEndian(Data); + set => WriteUInt32LittleEndian(Data, value); + } - public GSaveMemory(byte[] data) => Data = data; + public string TownName + { + get => StringUtil.GetString(Data, 0x04, 10); + set => StringUtil.GetBytes(value, 10).CopyTo(Data[0x04..]); + } + public Span GetTownIdentity() => Data[..(4 + 20)]; - public GSavePlayerId PlayerId - { - get => Data.Slice(0, GSavePlayerId.SIZE).ToStructure(); - set => value.ToBytes().CopyTo(Data, 0); - } + public uint PlayerID + { + get => ReadUInt32LittleEndian(Data[0x1C..]); + set => WriteUInt32LittleEndian(Data[0x1C..], value); + } - public uint TownID - { - get => BitConverter.ToUInt32(Data, 0x00); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); - } + public string PlayerName + { + get => StringUtil.GetString(Data, 0x20, 10); + set => StringUtil.GetBytes(value, 10).CopyTo(Data[0x20..]); + } - public string TownName - { - get => StringUtil.GetString(Data, 0x04, 10); - set => StringUtil.GetBytes(value, 10).CopyTo(Data, 0x04); - } - public byte[] GetTownIdentity() => Data.Slice(0x00, 4 + 20); + public Span GetPlayerIdentity() => Data.Slice(0x1C, 4 + 20); - public uint PlayerID - { - get => BitConverter.ToUInt32(Data, 0x1C); - set => BitConverter.GetBytes(value).CopyTo(Data, 0x1C); - } + public byte[] GetEventFlags() => Data.Slice(0x38, 0x100).ToArray(); + public void SetEventFlags(byte[] value) => value.CopyTo(Data[0x38..]); - public string PlayerName - { - get => StringUtil.GetString(Data, 0x20, 10); - set => StringUtil.GetBytes(value, 10).CopyTo(Data, 0x20); - } + public byte Friendship { get => Data[0x38 + 10]; set => Data[0x38 + 10] = value; } - public byte[] GetPlayerIdentity() => Data.Slice(0x1C, 4 + 20); + public string NickName + { + get => StringUtil.GetString(Data, 0x138, 10); + set => StringUtil.GetBytes(value, 10).CopyTo(Data[0x138..]); + } - public byte[] GetEventFlags() => Data.Slice(0x38, 0x100); - public void SetEventFlags(byte[] value) => value.CopyTo(Data, 0x38); + private const int GreetingCount = 11; + public string GetGreeting(in int index) + { + var offset = GetGreetingOffset(index); + return StringUtil.GetString(Data, offset, 22); // s_f6bf402b char16[48]. Render limit in-game is 22 char16s + } - public byte Friendship { get => Data[0x38 + 10]; set => Data[0x38 + 10] = value; } + private static int GetGreetingOffset(in int index) + { + if ((uint)index >= GreetingCount) + throw new ArgumentOutOfRangeException(nameof(index)); + return 0x14C + (0x60 * index); + } - public string NickName - { - get => StringUtil.GetString(Data, 0x138, 10); - set => StringUtil.GetBytes(value, 10).CopyTo(Data, 0x138); - } + public void SetGreeting(string value, int index) + { + var offset = GetGreetingOffset(index); + StringUtil.GetBytes(value, 47).CopyTo(Data[offset..]); + } - private const int GreetingCount = 11; - public string GetGreeting(in int index) - { - var offset = GetGreetingOffset(index); - return StringUtil.GetString(Data, offset, 22); // s_f6bf402b char16[48]. Render limit in-game is 22 char16s - } - - private static int GetGreetingOffset(in int index) - { - if ((uint)index >= GreetingCount) - throw new ArgumentOutOfRangeException(nameof(index)); - return 0x14C + (0x60 * index); - } - - public void SetGreeting(string value, int index) - { - var offset = GetGreetingOffset(index); - StringUtil.GetBytes(value, 47).CopyTo(Data, offset); - } - - public GSaveDate GreetingSetDate { get => Data.Slice(0x56C, GSaveDate.SIZE).ToStructure(); set => value.ToBytes().CopyTo(Data, 0x56C); } - }; -} + public GSaveDate GreetingSetDate { get => Data.Slice(0x56C, GSaveDate.SIZE).ToStructure(); set => value.ToBytes().CopyTo(Data[0x56C..]); } +}; \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/IHouseInfo.cs b/NHSE.Core/Structures/Villager/IHouseInfo.cs index de45f34..4ed2b0d 100644 --- a/NHSE.Core/Structures/Villager/IHouseInfo.cs +++ b/NHSE.Core/Structures/Villager/IHouseInfo.cs @@ -1,29 +1,28 @@ -namespace NHSE.Core -{ - public interface IHouseInfo - { - uint HouseLevel { get; set; } - WallType WallUniqueID { get; set; } - RoofType RoofUniqueID { get; set; } - DoorKind DoorUniqueID { get; set; } - WallType OrderWallUniqueID { get; set; } - RoofType OrderRoofUniqueID { get; set; } - DoorKind OrderDoorUniqueID { get; set; } - Item DoorDecoItemName { get; set; } - } +namespace NHSE.Core; - public static class HouseInfoExtensions - { - public static void CopyFrom(this IHouseInfo dest, IHouseInfo src) - { - dest.HouseLevel = src.HouseLevel; - dest.WallUniqueID = src.WallUniqueID; - dest.RoofUniqueID = src.RoofUniqueID; - dest.DoorUniqueID = src.DoorUniqueID; - dest.OrderWallUniqueID = src.OrderWallUniqueID; - dest.OrderRoofUniqueID = src.OrderRoofUniqueID; - dest.OrderDoorUniqueID = src.OrderDoorUniqueID; - dest.DoorDecoItemName = src.DoorDecoItemName; - } - } +public interface IHouseInfo +{ + uint HouseLevel { get; set; } + WallType WallUniqueID { get; set; } + RoofType RoofUniqueID { get; set; } + DoorKind DoorUniqueID { get; set; } + WallType OrderWallUniqueID { get; set; } + RoofType OrderRoofUniqueID { get; set; } + DoorKind OrderDoorUniqueID { get; set; } + Item DoorDecoItemName { get; set; } } + +public static class HouseInfoExtensions +{ + public static void CopyFrom(this IHouseInfo dest, IHouseInfo src) + { + dest.HouseLevel = src.HouseLevel; + dest.WallUniqueID = src.WallUniqueID; + dest.RoofUniqueID = src.RoofUniqueID; + dest.DoorUniqueID = src.DoorUniqueID; + dest.OrderWallUniqueID = src.OrderWallUniqueID; + dest.OrderRoofUniqueID = src.OrderRoofUniqueID; + dest.OrderDoorUniqueID = src.OrderDoorUniqueID; + dest.DoorDecoItemName = src.DoorDecoItemName; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/IPlayerHouse.cs b/NHSE.Core/Structures/Villager/IPlayerHouse.cs index 851b7b2..9b28bfb 100644 --- a/NHSE.Core/Structures/Villager/IPlayerHouse.cs +++ b/NHSE.Core/Structures/Villager/IPlayerHouse.cs @@ -1,16 +1,16 @@ -namespace NHSE.Core -{ - public interface IPlayerHouse : IHouseInfo - { - /// Returns the inner data buffer of the object, flushing any pending changes. - byte[] Write(); +using System; - sbyte NPC1 { get; set; } - sbyte NPC2 { get; set; } - string Extension { get; } - short[] GetEventFlags(); - void SetEventFlags(short[] value); - IPlayerRoom GetRoom(int roomIndex); - void SetRoom(int roomIndex, IPlayerRoom room); - } -} +namespace NHSE.Core; + +public interface IPlayerHouse : IHouseInfo +{ + /// Returns the inner data buffer of the object, flushing any pending changes. + byte[] Write(); + + sbyte NPC1 { get; set; } + sbyte NPC2 { get; set; } + string Extension { get; } + Span EventFlags { get; } + IPlayerRoom GetRoom(int roomIndex); + void SetRoom(int roomIndex, IPlayerRoom room); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/IPlayerRoom.cs b/NHSE.Core/Structures/Villager/IPlayerRoom.cs index db82b29..610dba0 100644 --- a/NHSE.Core/Structures/Villager/IPlayerRoom.cs +++ b/NHSE.Core/Structures/Villager/IPlayerRoom.cs @@ -1,14 +1,13 @@ using System.Collections.Generic; -namespace NHSE.Core -{ - public interface IPlayerRoom - { - /// Returns the inner data buffer of the object, flushing any pending changes. - byte[] Write(); +namespace NHSE.Core; - string Extension { get; } - RoomItemLayer[] GetItemLayers(); - void SetItemLayers(IReadOnlyList value); - } -} +public interface IPlayerRoom +{ + /// Returns the inner data buffer of the object, flushing any pending changes. + byte[] Write(); + + string Extension { get; } + RoomItemLayer[] GetItemLayers(); + void SetItemLayers(IReadOnlyList value); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/IVillager.cs b/NHSE.Core/Structures/Villager/IVillager.cs index 04a5f18..591c215 100644 --- a/NHSE.Core/Structures/Villager/IVillager.cs +++ b/NHSE.Core/Structures/Villager/IVillager.cs @@ -1,47 +1,47 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Exposes all interact-able values for a villager. +/// +public interface IVillager : IVillagerOrigin { - /// - /// Exposes all interact-able values for a villager. - /// - public interface IVillager : IVillagerOrigin - { - byte Species { get; set; } - byte Variant { get; set; } - VillagerPersonality Personality { get; set; } - string InternalName { get; } - string CatchPhrase { get; set; } + byte Species { get; set; } + byte Variant { get; set; } + VillagerPersonality Personality { get; set; } + string InternalName { get; } + string CatchPhrase { get; set; } - IReadOnlyList WearStockList { get; set; } - IReadOnlyList FtrStockList { get; set; } + IReadOnlyList WearStockList { get; set; } + IReadOnlyList FtrStockList { get; set; } - byte BirthType { get; set; } - byte InducementType { get; set; } - byte MoveType { get; set; } - bool MovingOut { get; set; } - int Gender { get; } + byte BirthType { get; set; } + byte InducementType { get; set; } + byte MoveType { get; set; } + bool MovingOut { get; set; } + int Gender { get; } - GSaveRoomFloorWall Room { get; set; } - DesignPatternPRO Design { get; set; } + GSaveRoomFloorWall Room { get; set; } + DesignPatternPRO Design { get; set; } - public byte DIYEndHour { get; set; } - public byte DIYEndMinute { get; set; } - public byte DIYEndSecond { get; set; } - public ushort DIYRecipeIndex { get; set; } + public byte DIYEndHour { get; set; } + public byte DIYEndMinute { get; set; } + public byte DIYEndSecond { get; set; } + public ushort DIYRecipeIndex { get; set; } - GSaveMemory GetMemory(int index); - GSaveMemory[] GetMemories(); - void SetMemory(GSaveMemory memory, int index); - void SetMemories(IReadOnlyList memories); + GSaveMemory GetMemory(int index); + GSaveMemory[] GetMemories(); + void SetMemory(GSaveMemory memory, int index); + void SetMemories(IReadOnlyList memories); - ushort[] GetEventFlagsSave(); - void SetEventFlagsSave(ushort[] value); + ushort[] GetEventFlagsSave(); + void SetEventFlagsSave(ReadOnlySpan value); - void SetFriendshipAll(byte value = byte.MaxValue); + void SetFriendshipAll(byte value = byte.MaxValue); - /// Returns the inner data buffer of the object, flushing any pending changes. - byte[] Write(); - string Extension { get; } - } -} + /// Returns the inner data buffer of the object, flushing any pending changes. + byte[] Write(); + string Extension { get; } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/IVillagerHouse.cs b/NHSE.Core/Structures/Villager/IVillagerHouse.cs index 6569fa5..ea8f160 100644 --- a/NHSE.Core/Structures/Villager/IVillagerHouse.cs +++ b/NHSE.Core/Structures/Villager/IVillagerHouse.cs @@ -1,13 +1,12 @@ -namespace NHSE.Core -{ - public interface IVillagerHouse : IHouseInfo - { - /// Returns the inner data buffer of the object, flushing any pending changes. - byte[] Write(); +namespace NHSE.Core; - sbyte NPC1 { get; set; } - sbyte NPC2 { get; set; } - string Extension { get; } - sbyte BuildPlayer { get; } - } -} +public interface IVillagerHouse : IHouseInfo +{ + /// Returns the inner data buffer of the object, flushing any pending changes. + byte[] Write(); + + sbyte NPC1 { get; set; } + sbyte NPC2 { get; set; } + string Extension { get; } + sbyte BuildPlayer { get; } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/IVillagerOrigin.cs b/NHSE.Core/Structures/Villager/IVillagerOrigin.cs index 1d462aa..8dd90ef 100644 --- a/NHSE.Core/Structures/Villager/IVillagerOrigin.cs +++ b/NHSE.Core/Structures/Villager/IVillagerOrigin.cs @@ -1,58 +1,57 @@ -using System.Linq; +using System; -namespace NHSE.Core +namespace NHSE.Core; + +public interface IVillagerOrigin { - public interface IVillagerOrigin + string PlayerName { get; } + string TownName { get; } + Span GetTownIdentity(); + Span GetPlayerIdentity(); +} + +public static class VillagerOriginExtensions +{ + public static bool IsOriginatedFrom(this IVillagerOrigin visit, IVillagerOrigin host) { - string PlayerName { get; } - string TownName { get; } - byte[] GetTownIdentity(); - byte[] GetPlayerIdentity(); + return visit.IsSameTown(host) && visit.IsSamePlayer(host); } - public static class VillagerOriginExtensions + public static bool IsSameTown(this IVillagerOrigin visit, IVillagerOrigin host) { - public static bool IsOriginatedFrom(this IVillagerOrigin visit, IVillagerOrigin host) - { - return visit.IsSameTown(host) && visit.IsSamePlayer(host); - } + var hostTown = host.GetTownIdentity(); + var visitTown = visit.GetTownIdentity(); + return hostTown.SequenceEqual(visitTown); + } - public static bool IsSameTown(this IVillagerOrigin visit, IVillagerOrigin host) - { - var hostTown = host.GetTownIdentity(); - var visitTown = visit.GetTownIdentity(); - return hostTown.SequenceEqual(visitTown); - } + public static bool IsSamePlayer(this IVillagerOrigin visit, IVillagerOrigin host) + { + var hostPlayer = host.GetPlayerIdentity(); + var visitPlayer = visit.GetPlayerIdentity(); + return hostPlayer.SequenceEqual(visitPlayer); + } - public static bool IsSamePlayer(this IVillagerOrigin visit, IVillagerOrigin host) - { - var hostPlayer = host.GetPlayerIdentity(); - var visitPlayer = visit.GetPlayerIdentity(); - return hostPlayer.SequenceEqual(visitPlayer); - } + public static void ChangeOrigins(this IVillagerOrigin visit, IVillagerOrigin host, Span visitData) + { + visit.ChangeToHostTown(host, visitData); + visit.ChangeToHostPlayer(host, visitData); + } - public static void ChangeOrigins(this IVillagerOrigin visit, IVillagerOrigin host, byte[] visitData) - { - visit.ChangeToHostTown(host, visitData); - visit.ChangeToHostPlayer(host, visitData); - } + private static void ChangeToHostTown(this IVillagerOrigin visit, IVillagerOrigin host, Span visitData) + { + var hostTown = host.GetTownIdentity(); + var visitTown = visit.GetTownIdentity(); + if (hostTown.SequenceEqual(visitTown)) + return; + visitData.ReplaceOccurrences(visitTown, hostTown); + } - private static void ChangeToHostTown(this IVillagerOrigin visit, IVillagerOrigin host, byte[] visitData) - { - var hostTown = host.GetTownIdentity(); - var visitTown = visit.GetTownIdentity(); - if (hostTown.SequenceEqual(visitTown)) - return; - visitData.ReplaceOccurrences(visitTown, hostTown); - } - - private static void ChangeToHostPlayer(this IVillagerOrigin visit, IVillagerOrigin host, byte[] visitData) - { - var hostPlayer = host.GetPlayerIdentity(); - var visitPlayer = visit.GetPlayerIdentity(); - if (hostPlayer.SequenceEqual(visitPlayer)) - return; - visitData.ReplaceOccurrences(visitPlayer, hostPlayer); - } + private static void ChangeToHostPlayer(this IVillagerOrigin visit, IVillagerOrigin host, Span visitData) + { + var hostPlayer = host.GetPlayerIdentity(); + var visitPlayer = visit.GetPlayerIdentity(); + if (hostPlayer.SequenceEqual(visitPlayer)) + return; + visitData.ReplaceOccurrences(visitPlayer, hostPlayer); } } \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/PlayerHouse1.cs b/NHSE.Core/Structures/Villager/PlayerHouse1.cs index 9f486ac..d8f304e 100644 --- a/NHSE.Core/Structures/Villager/PlayerHouse1.cs +++ b/NHSE.Core/Structures/Villager/PlayerHouse1.cs @@ -1,100 +1,97 @@ using System; +using System.Runtime.InteropServices; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +public class PlayerHouse1 : IPlayerHouse { - public class PlayerHouse1 : IPlayerHouse + public const int SIZE = 0x26400; + public virtual string Extension => "nhph"; + + public readonly Memory Raw; + public Span Data => Raw.Span; + + public PlayerHouse1(Memory data) => Raw = data; + + public byte[] Write() => Data.ToArray(); + + public uint HouseLevel { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); } + public WallType WallUniqueID { get => (WallType)ReadUInt16LittleEndian(Data[0x04..]); set => WriteUInt16LittleEndian(Data[0x04..], (ushort)value); } + public RoofType RoofUniqueID { get => (RoofType)ReadUInt16LittleEndian(Data[0x06..]); set => WriteUInt16LittleEndian(Data[0x06..], (ushort)value); } + public DoorKind DoorUniqueID { get => (DoorKind)ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], (ushort)value); } + public WallType OrderWallUniqueID { get => (WallType)ReadUInt16LittleEndian(Data[0x0A..]); set => WriteUInt16LittleEndian(Data[0x0A..], (ushort)value); } + public RoofType OrderRoofUniqueID { get => (RoofType)ReadUInt16LittleEndian(Data[0x0C..]); set => WriteUInt16LittleEndian(Data[0x0C..], (ushort)value); } + public DoorKind OrderDoorUniqueID { get => (DoorKind)ReadUInt16LittleEndian(Data[0x0E..]); set => WriteUInt16LittleEndian(Data[0x0E..], (ushort)value); } + + public EncryptedInt32 Loan { - public const int SIZE = 0x26400; - public virtual string Extension => "nhph"; - - public readonly byte[] Data; - public PlayerHouse1(byte[] data) => Data = data; - - public byte[] Write() => Data; - - public uint HouseLevel { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); } - public WallType WallUniqueID { get => (WallType)BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x04); } - public RoofType RoofUniqueID { get => (RoofType)BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x06); } - public DoorKind DoorUniqueID { get => (DoorKind)BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); } - public WallType OrderWallUniqueID { get => (WallType)BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); } - public RoofType OrderRoofUniqueID { get => (RoofType)BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); } - public DoorKind OrderDoorUniqueID { get => (DoorKind)BitConverter.ToUInt16(Data, 0x0E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E); } - - public EncryptedInt32 Loan - { - get => EncryptedInt32.Read(Data, 0x10); - set => value.Write(Data, 0x10); - } - - public EncryptedInt32 Unknown - { - get => EncryptedInt32.Read(Data, 0x18); - set => value.Write(Data, 0x18); - } - - public short[] GetEventFlags() - { - var result = new short[0x100 / 2]; - Buffer.BlockCopy(Data, 0x20, result, 0, result.Length * sizeof(short)); - return result; - } - - public void SetEventFlags(short[] value) => Buffer.BlockCopy(value, 0, Data, 0x20, value.Length * sizeof(short)); - - public const int MaxRoom = 6; - public const int RoomStart = 0x120; - - public virtual IPlayerRoom GetRoom(int roomIndex) - { - if ((uint)roomIndex >= MaxRoom) - throw new ArgumentOutOfRangeException(nameof(roomIndex)); - - var data = Data.Slice(RoomStart + (roomIndex * PlayerRoom1.SIZE), PlayerRoom1.SIZE); - return new PlayerRoom1(data); - } - - public virtual void SetRoom(int roomIndex, IPlayerRoom room) - { - if ((uint)roomIndex >= MaxRoom) - throw new ArgumentOutOfRangeException(nameof(roomIndex)); - - room.Write().CopyTo(Data, RoomStart + (roomIndex * PlayerRoom1.SIZE)); - } - - public sbyte NPC1 { get => (sbyte)Data[0x263D0]; set => Data[0x263D0] = (byte)value; } - public sbyte NPC2 { get => (sbyte)Data[0x263D1]; set => Data[0x263D1] = (byte)value; } - - // 2 bytes padding - - public Item DoorDecoItemName - { - get => Data.Slice(0x263D4, 8).ToClass(); - set => value.ToBytesClass().CopyTo(Data, 0x263D4); - } - - public bool PlayerHouseFlag { get => Data[0x263DC] != 0; set => Data[0x263DC] = (byte)(value ? 1 : 0); } - - public Item PostItemName - { - get => Data.Slice(0x263E0, 8).ToClass(); - set => value.ToBytesClass().CopyTo(Data, 0x263E0); - } - - public Item OrderPostItemName - { - get => Data.Slice(0x263E8, 8).ToClass(); - set => value.ToBytesClass().CopyTo(Data, 0x263E8); - } - - // cockroach @ 0x263f0 -- meh - public PlayerHouse2 Upgrade() - { - var data = new byte[PlayerHouse2.SIZE]; - Data.Slice(0x0, 0x120).CopyTo(data, 0); // HouseLevel -> EventFlag - for (int i = 0; i < MaxRoom; i++) - ((PlayerRoom1)GetRoom(i)).Upgrade().Write().CopyTo(data, 0x120 + (i * PlayerRoom2.SIZE)); // RoomList - Data.Slice(0x263D0, 0x30).CopyTo(data, 0x289F8); // PlayerList -> Cockroach - return new PlayerHouse2(data); - } + get => EncryptedInt32.Read(Data[0x10..]); + set => value.Write(Data[0x10..]); } -} + + public EncryptedInt32 Unknown + { + get => EncryptedInt32.Read(Data[0x18..]); + set => value.Write(Data[0x18..]); + } + + public Span EventFlags => MemoryMarshal.Cast(Data.Slice(0x20, 0x100)); + + public const int MaxRoom = 6; + public const int RoomStart = 0x120; + + public virtual IPlayerRoom GetRoom(int roomIndex) + { + if ((uint)roomIndex >= MaxRoom) + throw new ArgumentOutOfRangeException(nameof(roomIndex)); + + var data = Data.Slice(RoomStart + (roomIndex * PlayerRoom1.SIZE), PlayerRoom1.SIZE); + return new PlayerRoom1(data.ToArray()); + } + + public virtual void SetRoom(int roomIndex, IPlayerRoom room) + { + if ((uint)roomIndex >= MaxRoom) + throw new ArgumentOutOfRangeException(nameof(roomIndex)); + + var dest = Data.Slice(RoomStart + (roomIndex * PlayerRoom1.SIZE), PlayerRoom1.SIZE); + room.Write().CopyTo(dest); + } + + public sbyte NPC1 { get => (sbyte)Data[0x263D0]; set => Data[0x263D0] = (byte)value; } + public sbyte NPC2 { get => (sbyte)Data[0x263D1]; set => Data[0x263D1] = (byte)value; } + + // 2 bytes padding + + public Item DoorDecoItemName + { + get => Data.Slice(0x263D4, 8).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[0x263D4..]); + } + + public bool PlayerHouseFlag { get => Data[0x263DC] != 0; set => Data[0x263DC] = (byte)(value ? 1 : 0); } + + public Item PostItemName + { + get => Data.Slice(0x263E0, 8).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[0x263E0..]); + } + + public Item OrderPostItemName + { + get => Data.Slice(0x263E8, 8).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[0x263E8..]); + } + + // cockroach @ 0x263f0 -- meh + public PlayerHouse2 Upgrade() + { + var data = new byte[PlayerHouse2.SIZE]; + Data[..0x120].CopyTo(data.AsSpan(0)); // HouseLevel -> EventFlag + for (int i = 0; i < MaxRoom; i++) + ((PlayerRoom1)GetRoom(i)).Upgrade().Write().CopyTo(data.AsSpan(0x120 + (i * PlayerRoom2.SIZE))); // RoomList + Data.Slice(0x263D0, 0x30).CopyTo(data.AsSpan(0x289F8)); // PlayerList -> Cockroach + return new PlayerHouse2(data); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/PlayerHouse2.cs b/NHSE.Core/Structures/Villager/PlayerHouse2.cs index 093bccb..4144380 100644 --- a/NHSE.Core/Structures/Villager/PlayerHouse2.cs +++ b/NHSE.Core/Structures/Villager/PlayerHouse2.cs @@ -1,66 +1,66 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +public class PlayerHouse2 : PlayerHouse1 { - public class PlayerHouse2 : PlayerHouse1 + public new const int SIZE = 0x28A28; + public override string Extension => "nhph2"; + + public PlayerHouse2(Memory data) : base(data) { } + + public override IPlayerRoom GetRoom(int roomIndex) { - public new const int SIZE = 0x28A28; - public override string Extension => "nhph2"; + if ((uint)roomIndex >= MaxRoom) + throw new ArgumentOutOfRangeException(nameof(roomIndex)); - public PlayerHouse2(byte[] data) : base(data) { } - - public override IPlayerRoom GetRoom(int roomIndex) - { - if ((uint)roomIndex >= MaxRoom) - throw new ArgumentOutOfRangeException(nameof(roomIndex)); - - var data = Data.Slice(RoomStart + (roomIndex * PlayerRoom2.SIZE), PlayerRoom2.SIZE); - return new PlayerRoom2(data); - } - - public override void SetRoom(int roomIndex, IPlayerRoom room) - { - if ((uint)roomIndex >= MaxRoom) - throw new ArgumentOutOfRangeException(nameof(roomIndex)); - - room.Write().CopyTo(Data, RoomStart + (roomIndex * PlayerRoom2.SIZE)); - } - - public new sbyte NPC1 { get => (sbyte)Data[0x289F8]; set => Data[0x289F8] = (byte)value; } - public new sbyte NPC2 { get => (sbyte)Data[0x289F9]; set => Data[0x289F9] = (byte)value; } - - // 2 bytes padding - - public new Item DoorDecoItemName - { - get => Data.Slice(0x289FC, 8).ToClass(); - set => value.ToBytesClass().CopyTo(Data, 0x289FC); - } - - public new bool PlayerHouseFlag { get => Data[0x28A04] != 0; set => Data[0x28A04] = (byte)(value ? 1 : 0); } - - public new Item PostItemName - { - get => Data.Slice(0x28A08, 8).ToClass(); - set => value.ToBytesClass().CopyTo(Data, 0x28A08); - } - - public new Item OrderPostItemName - { - get => Data.Slice(0x28A10, 8).ToClass(); - set => value.ToBytesClass().CopyTo(Data, 0x28A10); - } - - // cockroach @ 0x28A18 -- meh - - public PlayerHouse1 Downgrade() - { - var data = new byte[PlayerHouse1.SIZE]; - Data.Slice(0x0, 0x120).CopyTo(data, 0); // HouseLevel -> EventFlag - for (int i = 0; i < MaxRoom; i++) - ((PlayerRoom2)GetRoom(i)).Downgrade().Data.CopyTo(data, 0x120 + i * PlayerRoom1.SIZE); // RoomList - Data.Slice(0x289F8, 0x30).CopyTo(data, 0x263D0); // PlayerList -> Cockroach - return new PlayerHouse1(data); - } + var data = Data.Slice(RoomStart + (roomIndex * PlayerRoom2.SIZE), PlayerRoom2.SIZE); + return new PlayerRoom2(data.ToArray()); } -} + + public override void SetRoom(int roomIndex, IPlayerRoom room) + { + if ((uint)roomIndex >= MaxRoom) + throw new ArgumentOutOfRangeException(nameof(roomIndex)); + + var dest = Data.Slice(RoomStart + (roomIndex * PlayerRoom2.SIZE), PlayerRoom2.SIZE); + room.Write().CopyTo(dest); + } + + public new sbyte NPC1 { get => (sbyte)Data[0x289F8]; set => Data[0x289F8] = (byte)value; } + public new sbyte NPC2 { get => (sbyte)Data[0x289F9]; set => Data[0x289F9] = (byte)value; } + + // 2 bytes padding + + public new Item DoorDecoItemName + { + get => Data.Slice(0x289FC, 8).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[0x289FC..]); + } + + public new bool PlayerHouseFlag { get => Data[0x28A04] != 0; set => Data[0x28A04] = (byte)(value ? 1 : 0); } + + public new Item PostItemName + { + get => Data.Slice(0x28A08, 8).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[0x28A08..]); + } + + public new Item OrderPostItemName + { + get => Data.Slice(0x28A10, 8).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[0x28A10..]); + } + + // cockroach @ 0x28A18 -- meh + + public PlayerHouse1 Downgrade() + { + var data = new byte[PlayerHouse1.SIZE]; + Data[..0x120].CopyTo(data); // HouseLevel -> EventFlag + for (int i = 0; i < MaxRoom; i++) + ((PlayerRoom2)GetRoom(i)).Downgrade().Data.CopyTo(data.AsSpan(0x120 + (i * PlayerRoom1.SIZE))); // RoomList + Data.Slice(0x289F8, 0x30).CopyTo(data.AsSpan(0x263D0)); // PlayerList -> Cockroach + return new PlayerHouse1(data); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/PlayerHouseConverter.cs b/NHSE.Core/Structures/Villager/PlayerHouseConverter.cs index e0eca1e..eaefffe 100644 --- a/NHSE.Core/Structures/Villager/PlayerHouseConverter.cs +++ b/NHSE.Core/Structures/Villager/PlayerHouseConverter.cs @@ -1,73 +1,74 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// Converts Player House objects to different revisions. +/// +public static class PlayerHouseConverter { /// - /// Converts Player House objects to different revisions. + /// Checks to see if the matches any of the House object sizes. /// - public static class PlayerHouseConverter + /// Size of the byte array that might represent a House object. + /// True if it matches any size. + public static bool IsHouse(int size) { - /// - /// Checks to see if the matches any of the House object sizes. - /// - /// Size of the byte array that might represent a House object. - /// True if it matches any size. - public static bool IsHouse(int size) - { - return size == PlayerHouse1.SIZE || size == PlayerHouse2.SIZE; - } - - /// - /// Checks to see if the input can be converted to the size. - /// - /// Current house file size - /// Expected house file size - /// True if can be converted, false if no conversion available. - public static bool IsCompatible(int size, int expect) - { - return expect switch - { - // Can convert to any format - PlayerHouse1.SIZE or PlayerHouse2.SIZE => IsHouse(size), - // No conversion available - _ => false, - }; - } - - /// - /// Converts the House data format to another format. - /// - /// - /// Before calling this method, check that a conversion method exists via and that the length of the is not the same as what you . - /// If the sizes are the same, it will return the input . - /// If no conversion path exists, it will return the input . - /// - /// Current format - /// Target size - /// Converted data - public static byte[] GetCompatible(byte[] data, int expect) - { - if (data.Length == expect) - return data; - - return expect switch - { - PlayerHouse1.SIZE when data.Length == PlayerHouse2.SIZE => Convert21(data), - PlayerHouse2.SIZE when data.Length == PlayerHouse1.SIZE => Convert12(data), - _ => data, - }; - } - - /// - /// Converts a object byte array to a - /// - /// object byte array - /// object byte array - private static byte[] Convert12(byte[] h1) => new PlayerHouse1(h1).Upgrade().Data; - - /// - /// Converts a object byte array to a - /// - /// object byte array - /// object byte array - private static byte[] Convert21(byte[] h2) => new PlayerHouse2(h2).Downgrade().Data; + return size is PlayerHouse1.SIZE or PlayerHouse2.SIZE; } -} + + /// + /// Checks to see if the input can be converted to the size. + /// + /// Current house file size + /// Expected house file size + /// True if can be converted, false if no conversion available. + public static bool IsCompatible(int size, int expect) + { + return expect switch + { + // Can convert to any format + PlayerHouse1.SIZE or PlayerHouse2.SIZE => IsHouse(size), + // No conversion available + _ => false, + }; + } + + /// + /// Converts the House data format to another format. + /// + /// + /// Before calling this method, check that a conversion method exists via and that the length of the is not the same as what you . + /// If the sizes are the same, it will return the input . + /// If no conversion path exists, it will return the input . + /// + /// Current format + /// Target size + /// Converted data + public static byte[] GetCompatible(byte[] data, int expect) + { + if (data.Length == expect) + return data; + + return expect switch + { + PlayerHouse1.SIZE when data.Length == PlayerHouse2.SIZE => Convert21(data), + PlayerHouse2.SIZE when data.Length == PlayerHouse1.SIZE => Convert12(data), + _ => data, + }; + } + + /// + /// Converts a object byte array to a + /// + /// object byte array + /// object byte array + private static byte[] Convert12(Memory h1) => new PlayerHouse1(h1).Upgrade().Write(); + + /// + /// Converts a object byte array to a + /// + /// object byte array + /// object byte array + private static byte[] Convert21(Memory h2) => new PlayerHouse2(h2).Downgrade().Write(); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/PlayerRoom1.cs b/NHSE.Core/Structures/Villager/PlayerRoom1.cs index 35f247f..92a7e3a 100644 --- a/NHSE.Core/Structures/Villager/PlayerRoom1.cs +++ b/NHSE.Core/Structures/Villager/PlayerRoom1.cs @@ -1,48 +1,50 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public class PlayerRoom1 : IPlayerRoom { - public class PlayerRoom1 : IPlayerRoom + public const int SIZE = 0x65C8; + public virtual string Extension => "nhpr"; + + public readonly Memory Raw; + public Span Data => Raw.Span; + + public PlayerRoom1(Memory data) => Raw = data; + + public byte[] Write() => Data.ToArray(); + + /* + s_d8bc748b ItemLayerList[8]; // @0x0 size 0xc80, align 4 + s_c20a4615 ItemSwitchList[8]; // @0x6400 size 0x34, align 4 + GSaveAudioInfo AudioInfo; // @0x65a0 size 0x4, align 2 + GSaveRoomFloorWall RoomFloorWall; // @0x65a4 size 0x24, align 4 + */ + + public const int LayerCount = 8; + public RoomItemLayer[] GetItemLayers() => RoomItemLayer.GetArray(Data[..(LayerCount * RoomItemLayer.SIZE)].ToArray()); + public void SetItemLayers(IReadOnlyList value) => RoomItemLayer.SetArray(value).AsSpan().CopyTo(Data); + + public bool GetIsActive(int layer, int x, int y) => FlagUtil.GetFlag(Data, 0x6400 + (layer * 0x34), (y * 20) + x); + public void SetIsActive(int layer, int x, int y, bool value = true) => FlagUtil.SetFlag(Data, 0x6400 + (layer * 0x34), (y * 20) + x, value); + + public GSaveAudioInfo AudioInfo { - public const int SIZE = 0x65C8; - public virtual string Extension => "nhpr"; - - public readonly byte[] Data; - public PlayerRoom1(byte[] data) => Data = data; - - public byte[] Write() => Data; - - /* - s_d8bc748b ItemLayerList[8]; // @0x0 size 0xc80, align 4 - s_c20a4615 ItemSwitchList[8]; // @0x6400 size 0x34, align 4 - GSaveAudioInfo AudioInfo; // @0x65a0 size 0x4, align 2 - GSaveRoomFloorWall RoomFloorWall; // @0x65a4 size 0x24, align 4 - */ - - public const int LayerCount = 8; - public RoomItemLayer[] GetItemLayers() => RoomItemLayer.GetArray(Data.Slice(0, LayerCount * RoomItemLayer.SIZE)); - public void SetItemLayers(IReadOnlyList value) => RoomItemLayer.SetArray(value).CopyTo(Data, 0); - - public bool GetIsActive(int layer, int x, int y) => FlagUtil.GetFlag(Data, 0x6400 + (layer * 0x34), (y * 20) + x); - public void SetIsActive(int layer, int x, int y, bool value = true) => FlagUtil.SetFlag(Data, 0x6400 + (layer * 0x34), (y * 20) + x, value); - - public GSaveAudioInfo AudioInfo - { - get => Data.Slice(0x65A0, GSaveAudioInfo.SIZE).ToStructure(); - set => value.ToBytes().CopyTo(Data, 0x65A0); - } - - public GSaveRoomFloorWall RoomFloorWall - { - get => Data.Slice(0x65A4, GSaveRoomFloorWall.SIZE).ToStructure(); - set => value.ToBytes().CopyTo(Data, 0x65A4); - } - - public PlayerRoom2 Upgrade() - { - var data = new byte[PlayerRoom2.SIZE]; - Data.CopyTo(data, 0); - return new PlayerRoom2(data); - } + get => Data.Slice(0x65A0, GSaveAudioInfo.SIZE).ToStructure(); + set => value.ToBytes().CopyTo(Data[0x65A0..]); } -} + + public GSaveRoomFloorWall RoomFloorWall + { + get => Data.Slice(0x65A4, GSaveRoomFloorWall.SIZE).ToStructure(); + set => value.ToBytes().CopyTo(Data[0x65A4..]); + } + + public PlayerRoom2 Upgrade() + { + var data = new byte[PlayerRoom2.SIZE]; + Data.CopyTo(data); + return new PlayerRoom2(data); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/PlayerRoom2.cs b/NHSE.Core/Structures/Villager/PlayerRoom2.cs index 1f5b320..8098a87 100644 --- a/NHSE.Core/Structures/Villager/PlayerRoom2.cs +++ b/NHSE.Core/Structures/Villager/PlayerRoom2.cs @@ -2,94 +2,93 @@ using System.ComponentModel; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +public class PlayerRoom2 : PlayerRoom1 { - public class PlayerRoom2 : PlayerRoom1 + public new const int SIZE = 0x6C24; + public new virtual string Extension => "nhpr2"; + + public PlayerRoom2(Memory data) : base(data) { } + + /* + s_665e9093 ExtraEffectLayerList[2]; // @0x65c8 size 0x320, align 2 + GSaveMusicBoxInfo MusicBoxInfo; // @0x6c08 size 0x4, align 2 + u8 SoundAmbient; // @0x6c0c size 0x1, align 1 + u8 gap_6c0d[3]; + s_e13a81f4 _cfb139b9; // @0x6c10 size 0x14, align 4 + */ + + public s_665e9093[] ExtraEffectLayerList { - public new const int SIZE = 0x6C24; - public new virtual string Extension => "nhpr2"; - - public PlayerRoom2(byte[] data) : base(data) { } - - /* - s_665e9093 ExtraEffectLayerList[2]; // @0x65c8 size 0x320, align 2 - GSaveMusicBoxInfo MusicBoxInfo; // @0x6c08 size 0x4, align 2 - u8 SoundAmbient; // @0x6c0c size 0x1, align 1 - u8 gap_6c0d[3]; - s_e13a81f4 _cfb139b9; // @0x6c10 size 0x14, align 4 - */ - - public s_665e9093[] ExtraEffectLayerList + get { - get + var result = new s_665e9093[2]; + for (int i = 0; i < result.Length; i++) { - var result = new s_665e9093[2]; - for (int i = 0; i < result.Length; i++) - { - var slice = Data.Slice(0x65C8 + i * s_665e9093.SIZE, s_665e9093.SIZE); - result[i] = slice.ToStructure(); - } - return result; - } - - set - { - for (int i = 0; i < value.Length; i++) - value[i].ToBytes().CopyTo(Data, 0x65C8 + i * s_665e9093.SIZE); + var slice = Data.Slice(0x65C8 + (i * s_665e9093.SIZE), s_665e9093.SIZE); + result[i] = slice.ToStructure(); } + return result; } - public GSaveMusicBoxInfo MusicBoxInfo + set { - get => Data.Slice(0x6C08, GSaveMusicBoxInfo.SIZE).ToStructure(); - set => value.ToBytes().CopyTo(Data, 0x6C08); - } - - public SoundAmbientKind SoundAmbientUniqueID { get => (SoundAmbientKind)Data[0x6C0C]; set => Data[0x6C0C]= (byte)value; } - - // 3 bytes padding - - public s_e13a81f4 _cfb139b9 - { - get => Data.Slice(0x6C10, s_e13a81f4.SIZE).ToStructure(); - set => value.ToBytes().CopyTo(Data, 0x6C10); - } - - public PlayerRoom1 Downgrade() - { - var result = new byte[PlayerRoom1.SIZE]; - Array.Copy(Data, result, PlayerRoom1.SIZE); - return new PlayerRoom1(result); + for (int i = 0; i < value.Length; i++) + value[i].ToBytes().CopyTo(Data[(0x65C8 + (i * s_665e9093.SIZE))..]); } } -#pragma warning disable CS8618, CA1815, CA1819, IDE1006, RCS1170 - [StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct s_665e9093 + public GSaveMusicBoxInfo MusicBoxInfo { - public const int SIZE = 0x320; /* 0x320 big, align 2 */ - - [field: MarshalAs(UnmanagedType.LPArray, SizeConst = 400)] - public GSaveItemExtraEffect[] ItemExtraEffectBuffer { get; set; } // @0x0 size 0x2, align 2 + get => Data.Slice(0x6C08, GSaveMusicBoxInfo.SIZE).ToStructure(); + set => value.ToBytes().CopyTo(Data[0x6C08..]); } - [StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveItemExtraEffect - { - public const int SIZE = 0x2; /* 0x2 big, align 2 */ + public SoundAmbientKind SoundAmbientUniqueID { get => (SoundAmbientKind)Data[0x6C0C]; set => Data[0x6C0C]= (byte)value; } - public ushort InnerData { get; set; } // @0x0 size 0x2, align 2 + // 3 bytes padding + + public s_e13a81f4 _cfb139b9 + { + get => Data.Slice(0x6C10, s_e13a81f4.SIZE).ToStructure(); + set => value.ToBytes().CopyTo(Data[0x6C10..]); } - [StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveMusicBoxInfo + public PlayerRoom1 Downgrade() { - public const int SIZE = 0x4; /* 0x4 big, align 2 */ - - public ushort PlayingAudioMusicID { get; set; } // @0x0 size 0x2, align 2 - public byte _749b78c2 { get; set; } // @0x2 size 0x1, align 1 + var result = new byte[PlayerRoom1.SIZE]; + Data[..PlayerRoom1.SIZE].CopyTo(result); + return new PlayerRoom1(result); } } + +#pragma warning disable CS8618, CA1815, CA1819, IDE1006, RCS1170 +[StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct s_665e9093 +{ + public const int SIZE = 0x320; /* 0x320 big, align 2 */ + + [field: MarshalAs(UnmanagedType.LPArray, SizeConst = 400)] + public GSaveItemExtraEffect[] ItemExtraEffectBuffer { get; set; } // @0x0 size 0x2, align 2 +} + +[StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveItemExtraEffect +{ + public const int SIZE = 0x2; /* 0x2 big, align 2 */ + + public ushort InnerData { get; set; } // @0x0 size 0x2, align 2 +} + +[StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveMusicBoxInfo +{ + public const int SIZE = 0x4; /* 0x4 big, align 2 */ + + public ushort PlayingAudioMusicID { get; set; } // @0x0 size 0x2, align 2 + public byte _749b78c2 { get; set; } // @0x2 size 0x1, align 1 +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/PlayerRoomConverter.cs b/NHSE.Core/Structures/Villager/PlayerRoomConverter.cs index bfffa17..e6e2b7d 100644 --- a/NHSE.Core/Structures/Villager/PlayerRoomConverter.cs +++ b/NHSE.Core/Structures/Villager/PlayerRoomConverter.cs @@ -1,73 +1,72 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Converts Player Room objects to different revisions. +/// +public static class PlayerRoomConverter { /// - /// Converts Player Room objects to different revisions. + /// Checks to see if the matches any of the Room object sizes. /// - public static class PlayerRoomConverter + /// Size of the byte array that might represent a Room object. + /// True if it matches any size. + public static bool IsRoom(int size) { - /// - /// Checks to see if the matches any of the Room object sizes. - /// - /// Size of the byte array that might represent a Room object. - /// True if it matches any size. - public static bool IsRoom(int size) - { - return size == PlayerRoom1.SIZE || size == PlayerRoom2.SIZE; - } - - /// - /// Checks to see if the input can be converted to the size. - /// - /// Current room file size - /// Expected room file size - /// True if can be converted, false if no conversion available. - public static bool IsCompatible(int size, int expect) - { - return expect switch - { - // Can convert to any format - PlayerRoom1.SIZE or PlayerRoom2.SIZE => IsRoom(size), - // No conversion available - _ => false, - }; - } - - /// - /// Converts the Room data format to another format. - /// - /// - /// Before calling this method, check that a conversion method exists via and that the length of the is not the same as what you . - /// If the sizes are the same, it will return the input . - /// If no conversion path exists, it will return the input . - /// - /// Current format - /// Target size - /// Converted data - public static byte[] GetCompatible(byte[] data, int expect) - { - if (data.Length == expect) - return data; - - return expect switch - { - PlayerRoom1.SIZE when data.Length == PlayerRoom2.SIZE => Convert21(data), - PlayerRoom2.SIZE when data.Length == PlayerRoom1.SIZE => Convert12(data), - _ => data, - }; - } - - /// - /// Converts a object byte array to a - /// - /// object byte array - /// object byte array - private static byte[] Convert12(byte[] h1) => new PlayerRoom1(h1).Upgrade().Write(); - - /// - /// Converts a object byte array to a - /// - /// object byte array - /// object byte array - private static byte[] Convert21(byte[] h2) => new PlayerRoom2(h2).Downgrade().Write(); + return size is PlayerRoom1.SIZE or PlayerRoom2.SIZE; } -} + + /// + /// Checks to see if the input can be converted to the size. + /// + /// Current room file size + /// Expected room file size + /// True if can be converted, false if no conversion available. + public static bool IsCompatible(int size, int expect) + { + return expect switch + { + // Can convert to any format + PlayerRoom1.SIZE or PlayerRoom2.SIZE => IsRoom(size), + // No conversion available + _ => false, + }; + } + + /// + /// Converts the Room data format to another format. + /// + /// + /// Before calling this method, check that a conversion method exists via and that the length of the is not the same as what you . + /// If the sizes are the same, it will return the input . + /// If no conversion path exists, it will return the input . + /// + /// Current format + /// Target size + /// Converted data + public static byte[] GetCompatible(byte[] data, int expect) + { + if (data.Length == expect) + return data; + + return expect switch + { + PlayerRoom1.SIZE when data.Length == PlayerRoom2.SIZE => Convert21(data), + PlayerRoom2.SIZE when data.Length == PlayerRoom1.SIZE => Convert12(data), + _ => data, + }; + } + + /// + /// Converts a object byte array to a + /// + /// object byte array + /// object byte array + private static byte[] Convert12(byte[] h1) => new PlayerRoom1(h1).Upgrade().Write(); + + /// + /// Converts a object byte array to a + /// + /// object byte array + /// object byte array + private static byte[] Convert21(byte[] h2) => new PlayerRoom2(h2).Downgrade().Write(); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/Villager1.cs b/NHSE.Core/Structures/Villager/Villager1.cs index fcb8982..b298c32 100644 --- a/NHSE.Core/Structures/Villager/Villager1.cs +++ b/NHSE.Core/Structures/Villager/Villager1.cs @@ -1,136 +1,143 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Villager object format from 1.0 to update 1.4 +/// +public sealed class Villager1 : IVillager { - /// - /// Villager object format from 1.0 to update 1.4 - /// - public sealed class Villager1 : IVillager + public const int SIZE = 0x12AB0; + public string Extension => "nhv"; + + public readonly Memory Raw; + public Span Data => Raw.Span; + public Villager1(Memory data) => Raw = data; + public byte[] Write() => Data.ToArray(); + + public byte Species { get => Data[0]; set => Data[0] = value; } + public byte Variant { get => Data[1]; set => Data[1] = value; } + public VillagerPersonality Personality { get => (VillagerPersonality)Data[2]; set => Data[2] = (byte)value; } + + public string TownName => GetMemory(0).TownName; + public Span GetTownIdentity() => GetMemory(0).GetTownIdentity(); + public string PlayerName => GetMemory(0).PlayerName; + public Span GetPlayerIdentity() => GetMemory(0).GetPlayerIdentity(); + + public const int PlayerMemoryCount = 8; + + public GSaveMemory GetMemory(int index) { - public const int SIZE = 0x12AB0; - public string Extension => "nhv"; + if ((uint) index >= PlayerMemoryCount) + throw new ArgumentOutOfRangeException(nameof(index)); - public readonly byte[] Data; - public Villager1(byte[] data) => Data = data; - public byte[] Write() => Data; + var bytes = Raw.Slice(0x4 + (index * GSaveMemory.SIZE), GSaveMemory.SIZE); + return new GSaveMemory(bytes); + } - public byte Species { get => Data[0]; set => Data[0] = value; } - public byte Variant { get => Data[1]; set => Data[1] = value; } - public VillagerPersonality Personality { get => (VillagerPersonality)Data[2]; set => Data[2] = (byte)value; } + public GSaveMemory[] GetMemories() + { + var memories = new GSaveMemory[PlayerMemoryCount]; + for (int i = 0; i < memories.Length; i++) + memories[i] = GetMemory(i); + return memories; + } - public string TownName => GetMemory(0).TownName; - public byte[] GetTownIdentity() => GetMemory(0).GetTownIdentity(); - public string PlayerName => GetMemory(0).PlayerName; - public byte[] GetPlayerIdentity() => GetMemory(0).GetPlayerIdentity(); + public void SetMemory(GSaveMemory memory, int index) + { + if ((uint)index >= PlayerMemoryCount) + throw new ArgumentOutOfRangeException(nameof(index)); - public const int PlayerMemoryCount = 8; + memory.Data.CopyTo(Data[(0x4 + (index * GSaveMemory.SIZE))..]); + } - public GSaveMemory GetMemory(int index) + public void SetMemories(IReadOnlyList memories) + { + for (int i = 0; i < memories.Count; i++) + SetMemory(memories[i], i); + } + + public string CatchPhrase + { + get => StringUtil.GetString(Data, 0xFFE8 + 0x2C, 2 * 12); + set => StringUtil.GetBytes(value, 2 * 12).CopyTo(Data[(0xFFE8 + 0x2C)..]); + } + + private const int WearCount = 24; + + public IReadOnlyList WearStockList + { + get => VillagerItem.GetArray(Data.Slice(0x101CC, WearCount * VillagerItem.SIZE)); + set => VillagerItem.SetArray(value).CopyTo(Data[0x101CC..]); + } + + private const int FurnitureCount = 32; + + public IReadOnlyList FtrStockList + { + get => VillagerItem.GetArray(Data.Slice(0x105EC, FurnitureCount * VillagerItem.SIZE)); + set => VillagerItem.SetArray(value).CopyTo(Data[0x105EC..]); + } + + // State Flags + public byte BirthType { get => Data[0x11EF8]; set => Data[0x11EF8] = value; } + public byte InducementType { get => Data[0x11EF9]; set => Data[0x11EF9] = value; } + public byte MoveType { get => Data[0x11EFA]; set => Data[0x11EFA] = value; } + public bool MovingOut { get => (MoveType & 2) == 2; set => MoveType = (byte)((MoveType & ~2) | (value ? 2 : 0)); } + + // EventFlagsNPCSaveParam + private const int EventFlagsSaveCount = 0x100; // Future-proof allocation! Release version used <20% of the amount allocated. + + public ushort[] GetEventFlagsSave() + { + var value = new ushort[EventFlagsSaveCount]; + MemoryMarshal.Cast(Data.Slice(0x11EFC, EventFlagsSaveCount * sizeof(ushort))).CopyTo(value); + return value; + } + + public void SetEventFlagsSave(ReadOnlySpan value) + { + MemoryMarshal.Cast(value).CopyTo(Data[0x11EFC..]); + } + + public override string ToString() => InternalName; + public string InternalName => VillagerUtil.GetInternalVillagerName((VillagerSpecies) Species, Variant); + public int Gender => ((int)Personality / 4) & 1; // 0 = M, 1 = F + + public GSaveRoomFloorWall Room + { + get => Data.Slice(0x12100, GSaveRoomFloorWall.SIZE).ToStructure(); + set => value.ToBytes().CopyTo(Data[0x12100..]); + } + + public DesignPatternPRO Design + { + get => new(Raw.Slice(0x12128, DesignPatternPRO.SIZE)); + set => value.Data.CopyTo(Data[0x12128..]); + } + + public byte DIYEndHour { get => Data[0x129D1]; set => Data[0x129D1] = value; } + public byte DIYEndMinute { get => Data[0x129D2]; set => Data[0x129D2] = value; } + public byte DIYEndSecond { get => Data[0x129D3]; set => Data[0x129D3] = value; } + + public ushort DIYRecipeIndex + { + get => ReadUInt16LittleEndian(Data[0x129D4..]); + set => WriteUInt16LittleEndian(Data[0x129D4..], value); + } + + public void SetFriendshipAll(byte value = byte.MaxValue) + { + for (int i = 0; i < PlayerMemoryCount; i++) { - if ((uint) index >= PlayerMemoryCount) - throw new ArgumentOutOfRangeException(nameof(index)); - - var bytes = Data.Slice(0x4 + (index * GSaveMemory.SIZE), GSaveMemory.SIZE); - return new GSaveMemory(bytes); - } - - public GSaveMemory[] GetMemories() - { - var memories = new GSaveMemory[PlayerMemoryCount]; - for (int i = 0; i < memories.Length; i++) - memories[i] = GetMemory(i); - return memories; - } - - public void SetMemory(GSaveMemory memory, int index) - { - if ((uint)index >= PlayerMemoryCount) - throw new ArgumentOutOfRangeException(nameof(index)); - - memory.Data.CopyTo(Data, 0x4 + (index * GSaveMemory.SIZE)); - } - - public void SetMemories(IReadOnlyList memories) - { - for (int i = 0; i < memories.Count; i++) - SetMemory(memories[i], i); - } - - public string CatchPhrase - { - get => StringUtil.GetString(Data, 0xFFE8 + 0x2C, 2 * 12); - set => StringUtil.GetBytes(value, 2 * 12).CopyTo(Data, 0xFFE8 + 0x2C); - } - - private const int WearCount = 24; - - public IReadOnlyList WearStockList - { - get => VillagerItem.GetArray(Data.Slice(0x101CC, WearCount * VillagerItem.SIZE)); - set => VillagerItem.SetArray(value).CopyTo(Data, 0x101CC); - } - - private const int FurnitureCount = 32; - - public IReadOnlyList FtrStockList - { - get => VillagerItem.GetArray(Data.Slice(0x105EC, FurnitureCount * VillagerItem.SIZE)); - set => VillagerItem.SetArray(value).CopyTo(Data, 0x105EC); - } - - // State Flags - public byte BirthType { get => Data[0x11EF8]; set => Data[0x11EF8] = value; } - public byte InducementType { get => Data[0x11EF9]; set => Data[0x11EF9] = value; } - public byte MoveType { get => Data[0x11EFA]; set => Data[0x11EFA] = value; } - public bool MovingOut { get => (MoveType & 2) == 2; set => MoveType = (byte)((MoveType & ~2) | (value ? 2 : 0)); } - - // EventFlagsNPCSaveParam - private const int EventFlagsSaveCount = 0x100; // Future-proof allocation! Release version used <20% of the amount allocated. - - public ushort[] GetEventFlagsSave() - { - var value = new ushort[EventFlagsSaveCount]; - Buffer.BlockCopy(Data, 0x11EFC, value, 0, sizeof(ushort) * value.Length); - return value; - } - - public void SetEventFlagsSave(ushort[] value) - { - Buffer.BlockCopy(value, 0, Data, 0x11EFC, sizeof(ushort) * value.Length); - } - - public override string ToString() => InternalName; - public string InternalName => VillagerUtil.GetInternalVillagerName((VillagerSpecies) Species, Variant); - public int Gender => ((int)Personality / 4) & 1; // 0 = M, 1 = F - - public GSaveRoomFloorWall Room - { - get => Data.Slice(0x12100, GSaveRoomFloorWall.SIZE).ToStructure(); - set => value.ToBytes().CopyTo(Data, 0x12100); - } - - public DesignPatternPRO Design - { - get => new(Data.Slice(0x12128, DesignPatternPRO.SIZE)); - set => value.Data.CopyTo(Data, 0x12128); - } - - public byte DIYEndHour { get => Data[0x129D1]; set => Data[0x129D1] = value; } - public byte DIYEndMinute { get => Data[0x129D2]; set => Data[0x129D2] = value; } - public byte DIYEndSecond { get => Data[0x129D3]; set => Data[0x129D3] = value; } - public ushort DIYRecipeIndex { get => BitConverter.ToUInt16(Data, 0x129D4); set => BitConverter.GetBytes(value).CopyTo(Data, 0x129D4); } - - public void SetFriendshipAll(byte value = byte.MaxValue) - { - for (int i = 0; i < PlayerMemoryCount; i++) - { - var m = GetMemory(i); - if (string.IsNullOrEmpty(m.PlayerName)) - continue; - m.Friendship = value; - SetMemory(m, i); - } + var m = GetMemory(i); + if (string.IsNullOrEmpty(m.PlayerName)) + continue; + m.Friendship = value; + SetMemory(m, i); } } -} +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/Villager2.cs b/NHSE.Core/Structures/Villager/Villager2.cs index 9ffafa8..0a2fb0b 100644 --- a/NHSE.Core/Structures/Villager/Villager2.cs +++ b/NHSE.Core/Structures/Villager/Villager2.cs @@ -1,136 +1,143 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Villager object format starting with update 1.5 +/// +public sealed class Villager2 : IVillager { - /// - /// Villager object format starting with update 1.5 - /// - public sealed class Villager2 : IVillager + public const int SIZE = 0x13230; // + 160*0xC (0x780) -- GSaveLightMemory increased size. + public string Extension => "nhv2"; + + public readonly Memory Raw; + public Span Data => Raw.Span; + public Villager2(Memory data) => Raw = data; + public byte[] Write() => Data.ToArray(); + + public byte Species { get => Data[0]; set => Data[0] = value; } + public byte Variant { get => Data[1]; set => Data[1] = value; } + public VillagerPersonality Personality { get => (VillagerPersonality)Data[2]; set => Data[2] = (byte)value; } + + public string TownName => GetMemory(0).TownName; + public Span GetTownIdentity() => GetMemory(0).GetTownIdentity(); + public string PlayerName => GetMemory(0).PlayerName; + public Span GetPlayerIdentity() => GetMemory(0).GetPlayerIdentity(); + + public const int PlayerMemoryCount = 8; + + public GSaveMemory GetMemory(int index) { - public const int SIZE = 0x13230; // + 160*0xC (0x780) -- GSaveLightMemory increased size. - public string Extension => "nhv2"; + if ((uint)index >= PlayerMemoryCount) + throw new ArgumentOutOfRangeException(nameof(index)); - public readonly byte[] Data; - public Villager2(byte[] data) => Data = data; - public byte[] Write() => Data; + var bytes = Raw.Slice(0x4 + (index * GSaveMemory.SIZE), GSaveMemory.SIZE); + return new GSaveMemory(bytes); + } - public byte Species { get => Data[0]; set => Data[0] = value; } - public byte Variant { get => Data[1]; set => Data[1] = value; } - public VillagerPersonality Personality { get => (VillagerPersonality)Data[2]; set => Data[2] = (byte)value; } + public GSaveMemory[] GetMemories() + { + var memories = new GSaveMemory[PlayerMemoryCount]; + for (int i = 0; i < memories.Length; i++) + memories[i] = GetMemory(i); + return memories; + } - public string TownName => GetMemory(0).TownName; - public byte[] GetTownIdentity() => GetMemory(0).GetTownIdentity(); - public string PlayerName => GetMemory(0).PlayerName; - public byte[] GetPlayerIdentity() => GetMemory(0).GetPlayerIdentity(); + public void SetMemory(GSaveMemory memory, int index) + { + if ((uint)index >= PlayerMemoryCount) + throw new ArgumentOutOfRangeException(nameof(index)); - public const int PlayerMemoryCount = 8; + memory.Data.CopyTo(Data[(0x4 + (index * GSaveMemory.SIZE))..]); + } - public GSaveMemory GetMemory(int index) + public void SetMemories(IReadOnlyList memories) + { + for (int i = 0; i < memories.Count; i++) + SetMemory(memories[i], i); + } + + public string CatchPhrase + { + get => StringUtil.GetString(Data, 0x10768 + 0x2C, 2 * 12); + set => StringUtil.GetBytes(value, 2 * 12).CopyTo(Data[(0x10768 + 0x2C)..]); + } + + private const int WearCount = 24; + + public IReadOnlyList WearStockList + { + get => VillagerItem.GetArray(Data.Slice(0x1094c, WearCount * VillagerItem.SIZE)); + set => VillagerItem.SetArray(value).CopyTo(Data[0x1094c..]); + } + + private const int FurnitureCount = 32; + + public IReadOnlyList FtrStockList + { + get => VillagerItem.GetArray(Data.Slice(0x10d6c, FurnitureCount * VillagerItem.SIZE)); + set => VillagerItem.SetArray(value).CopyTo(Data[0x10d6c..]); + } + + // State Flags + public byte BirthType { get => Data[0x12678]; set => Data[0x12678] = value; } + public byte InducementType { get => Data[0x12679]; set => Data[0x12679] = value; } + public byte MoveType { get => Data[0x1267a]; set => Data[0x1267a] = value; } + public bool MovingOut { get => (MoveType & 2) == 2; set => MoveType = (byte)((MoveType & ~2) | (value ? 2 : 0)); } + + // EventFlagsNPCSaveParam + private const int EventFlagsSaveCount = 0x100; // Future-proof allocation! Release version used <20% of the amount allocated. + + public ushort[] GetEventFlagsSave() + { + var value = new ushort[EventFlagsSaveCount]; + MemoryMarshal.Cast(Data.Slice(0x1267c, EventFlagsSaveCount * sizeof(ushort))).CopyTo(value); + return value; + } + + public void SetEventFlagsSave(ReadOnlySpan value) + { + MemoryMarshal.Cast(value).CopyTo(Data[0x1267c..]); + } + + public override string ToString() => InternalName; + public string InternalName => VillagerUtil.GetInternalVillagerName((VillagerSpecies)Species, Variant); + public int Gender => ((int)Personality / 4) & 1; // 0 = M, 1 = F + + public GSaveRoomFloorWall Room + { + get => Data.Slice(0x12880, GSaveRoomFloorWall.SIZE).ToStructure(); + set => value.ToBytes().CopyTo(Data[0x12880..]); + } + + public DesignPatternPRO Design + { + get => new(Raw.Slice(0x128a8, DesignPatternPRO.SIZE)); + set => value.Data.CopyTo(Data[0x128a8..]); + } + + public byte DIYEndHour { get => Data[0x13151]; set => Data[0x13151] = value; } + public byte DIYEndMinute { get => Data[0x13152]; set => Data[0x13152] = value; } + public byte DIYEndSecond { get => Data[0x13153]; set => Data[0x13153] = value; } + + public ushort DIYRecipeIndex + { + get => ReadUInt16LittleEndian(Data[0x13154..]); + set => WriteUInt16LittleEndian(Data[0x13154..], value); + } + + public void SetFriendshipAll(byte value = byte.MaxValue) + { + for (int i = 0; i < PlayerMemoryCount; i++) { - if ((uint)index >= PlayerMemoryCount) - throw new ArgumentOutOfRangeException(nameof(index)); - - var bytes = Data.Slice(0x4 + (index * GSaveMemory.SIZE), GSaveMemory.SIZE); - return new GSaveMemory(bytes); - } - - public GSaveMemory[] GetMemories() - { - var memories = new GSaveMemory[PlayerMemoryCount]; - for (int i = 0; i < memories.Length; i++) - memories[i] = GetMemory(i); - return memories; - } - - public void SetMemory(GSaveMemory memory, int index) - { - if ((uint)index >= PlayerMemoryCount) - throw new ArgumentOutOfRangeException(nameof(index)); - - memory.Data.CopyTo(Data, 0x4 + (index * GSaveMemory.SIZE)); - } - - public void SetMemories(IReadOnlyList memories) - { - for (int i = 0; i < memories.Count; i++) - SetMemory(memories[i], i); - } - - public string CatchPhrase - { - get => StringUtil.GetString(Data, 0x10768 + 0x2C, 2 * 12); - set => StringUtil.GetBytes(value, 2 * 12).CopyTo(Data, 0x10768 + 0x2C); - } - - private const int WearCount = 24; - - public IReadOnlyList WearStockList - { - get => VillagerItem.GetArray(Data.Slice(0x1094c, WearCount * VillagerItem.SIZE)); - set => VillagerItem.SetArray(value).CopyTo(Data, 0x1094c); - } - - private const int FurnitureCount = 32; - - public IReadOnlyList FtrStockList - { - get => VillagerItem.GetArray(Data.Slice(0x10d6c, FurnitureCount * VillagerItem.SIZE)); - set => VillagerItem.SetArray(value).CopyTo(Data, 0x10d6c); - } - - // State Flags - public byte BirthType { get => Data[0x12678]; set => Data[0x12678] = value; } - public byte InducementType { get => Data[0x12679]; set => Data[0x12679] = value; } - public byte MoveType { get => Data[0x1267a]; set => Data[0x1267a] = value; } - public bool MovingOut { get => (MoveType & 2) == 2; set => MoveType = (byte)((MoveType & ~2) | (value ? 2 : 0)); } - - // EventFlagsNPCSaveParam - private const int EventFlagsSaveCount = 0x100; // Future-proof allocation! Release version used <20% of the amount allocated. - - public ushort[] GetEventFlagsSave() - { - var value = new ushort[EventFlagsSaveCount]; - Buffer.BlockCopy(Data, 0x1267c, value, 0, sizeof(ushort) * value.Length); - return value; - } - - public void SetEventFlagsSave(ushort[] value) - { - Buffer.BlockCopy(value, 0, Data, 0x1267c, sizeof(ushort) * value.Length); - } - - public override string ToString() => InternalName; - public string InternalName => VillagerUtil.GetInternalVillagerName((VillagerSpecies)Species, Variant); - public int Gender => ((int)Personality / 4) & 1; // 0 = M, 1 = F - - public GSaveRoomFloorWall Room - { - get => Data.Slice(0x12880, GSaveRoomFloorWall.SIZE).ToStructure(); - set => value.ToBytes().CopyTo(Data, 0x12880); - } - - public DesignPatternPRO Design - { - get => new(Data.Slice(0x128a8, DesignPatternPRO.SIZE)); - set => value.Data.CopyTo(Data, 0x128a8); - } - - public byte DIYEndHour { get => Data[0x13151]; set => Data[0x13151] = value; } - public byte DIYEndMinute { get => Data[0x13152]; set => Data[0x13152] = value; } - public byte DIYEndSecond { get => Data[0x13153]; set => Data[0x13153] = value; } - public ushort DIYRecipeIndex { get => BitConverter.ToUInt16(Data, 0x13154); set => BitConverter.GetBytes(value).CopyTo(Data, 0x13154); } - - public void SetFriendshipAll(byte value = byte.MaxValue) - { - for (int i = 0; i < PlayerMemoryCount; i++) - { - var m = GetMemory(i); - if (string.IsNullOrEmpty(m.PlayerName)) - continue; - m.Friendship = value; - SetMemory(m, i); - } + var m = GetMemory(i); + if (string.IsNullOrEmpty(m.PlayerName)) + continue; + m.Friendship = value; + SetMemory(m, i); } } -} +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/VillagerConverter.cs b/NHSE.Core/Structures/Villager/VillagerConverter.cs index c0c46ad..2256353 100644 --- a/NHSE.Core/Structures/Villager/VillagerConverter.cs +++ b/NHSE.Core/Structures/Villager/VillagerConverter.cs @@ -1,121 +1,120 @@ using System; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Converts Villager objects to different revisions. +/// +public static class VillagerConverter { /// - /// Converts Villager objects to different revisions. + /// Checks to see if the matches any of the Villager object sizes. /// - public static class VillagerConverter + /// Size of the byte array that might represent a Villager object. + /// True if it matches any size. + public static bool IsVillager(int size) { - /// - /// Checks to see if the matches any of the Villager object sizes. - /// - /// Size of the byte array that might represent a Villager object. - /// True if it matches any size. - public static bool IsVillager(int size) - { - return size == Villager1.SIZE || size == Villager2.SIZE; - } - - /// - /// Checks to see if the input can be converted to the size. - /// - /// Current villager file size - /// Expected villager file size - /// True if can be converted, false if no conversion available. - public static bool IsCompatible(int size, int expect) - { - return expect switch - { - // Can convert to any format - Villager1.SIZE or Villager2.SIZE => IsVillager(size), - // No conversion available - _ => false, - }; - } - - /// - /// Converts the Villager data format to another format. - /// - /// - /// Before calling this method, check that a conversion method exists via and that the length of the is not the same as what you . - /// If the sizes are the same, it will return the input . - /// If no conversion path exists, it will return the input . - /// - /// Current format - /// Target size - /// Converted data - public static byte[] GetCompatible(byte[] data, int expect) - { - if (data.Length == expect) - return data; - - return expect switch - { - Villager1.SIZE when data.Length == Villager2.SIZE => Convert21(data), - Villager2.SIZE when data.Length == Villager1.SIZE => Convert12(data), - _ => data - }; - } - - /// - /// Converts a object byte array to a - /// - /// object byte array - /// object byte array - public static byte[] Convert12(byte[] v1) - { - // In v1.5, the GSaveLightMemory object structure increased in size by 0xC bytes. - // To convert to v1.5 format, we need to expand each of those entries within our structure. - - byte[] v2 = new byte[Villager2.SIZE]; - - // Copy pre-GSaveLightMemory[160] - Array.Copy(v1, 0, v2, 0, 0x2f84); - - // Copy each entry, with each adding 0xC empty bytes. - for (int i = 0; i < 160; i++) - { - var src = 0x2f84 + (0x14C * i); - var dest = 0x2f84 + (0x158 * i); - - Array.Copy(v1, src, v2, dest, 0x14C); - } - - // Copy after-GSaveLightMemory[160] - Array.Copy(v1, 0xff04, v2, 0x10684, v1.Length - 0xff04); - - return v2; - } - - /// - /// Converts a object byte array to a - /// - /// object byte array - /// object byte array - public static byte[] Convert21(byte[] v2) - { - // In v1.5, the GSaveLightMemory object structure increased in size by 0xC bytes. - // To revert back to Version 1.4, we need to truncate each of those entries within our structure. - - byte[] v1 = new byte[Villager1.SIZE]; - - // Copy pre-GSaveLightMemory[160] - Array.Copy(v2, 0, v1, 0, 0x2f84); - - // Copy each entry, with each skipping last 0xC bytes. - for (int i = 0; i < 160; i++) - { - var src = 0x2f84 + (0x14C * i); - var dest = 0x2f84 + (0x158 * i); - - Array.Copy(v2, dest, v1, src, 0x14C); - } - - // Copy after-GSaveLightMemory[160] - Array.Copy(v2, 0x10684, v1, 0xff04, v2.Length - 0x10684); - - return v1; - } + return size is Villager1.SIZE or Villager2.SIZE; } -} + + /// + /// Checks to see if the input can be converted to the size. + /// + /// Current villager file size + /// Expected villager file size + /// True if can be converted, false if no conversion available. + public static bool IsCompatible(int size, int expect) + { + return expect switch + { + // Can convert to any format + Villager1.SIZE or Villager2.SIZE => IsVillager(size), + // No conversion available + _ => false, + }; + } + + /// + /// Converts the Villager data format to another format. + /// + /// + /// Before calling this method, check that a conversion method exists via and that the length of the is not the same as what you . + /// If the sizes are the same, it will return the input . + /// If no conversion path exists, it will return the input . + /// + /// Current format + /// Target size + /// Converted data + public static byte[] GetCompatible(byte[] data, int expect) + { + if (data.Length == expect) + return data; + + return expect switch + { + Villager1.SIZE when data.Length == Villager2.SIZE => Convert21(data), + Villager2.SIZE when data.Length == Villager1.SIZE => Convert12(data), + _ => data + }; + } + + /// + /// Converts a object byte array to a + /// + /// object byte array + /// object byte array + public static byte[] Convert12(byte[] v1) + { + // In v1.5, the GSaveLightMemory object structure increased in size by 0xC bytes. + // To convert to v1.5 format, we need to expand each of those entries within our structure. + + byte[] v2 = new byte[Villager2.SIZE]; + + // Copy pre-GSaveLightMemory[160] + Array.Copy(v1, 0, v2, 0, 0x2f84); + + // Copy each entry, with each adding 0xC empty bytes. + for (int i = 0; i < 160; i++) + { + var src = 0x2f84 + (0x14C * i); + var dest = 0x2f84 + (0x158 * i); + + Array.Copy(v1, src, v2, dest, 0x14C); + } + + // Copy after-GSaveLightMemory[160] + Array.Copy(v1, 0xff04, v2, 0x10684, v1.Length - 0xff04); + + return v2; + } + + /// + /// Converts a object byte array to a + /// + /// object byte array + /// object byte array + public static byte[] Convert21(byte[] v2) + { + // In v1.5, the GSaveLightMemory object structure increased in size by 0xC bytes. + // To revert back to Version 1.4, we need to truncate each of those entries within our structure. + + byte[] v1 = new byte[Villager1.SIZE]; + + // Copy pre-GSaveLightMemory[160] + Array.Copy(v2, 0, v1, 0, 0x2f84); + + // Copy each entry, with each skipping last 0xC bytes. + for (int i = 0; i < 160; i++) + { + var src = 0x2f84 + (0x14C * i); + var dest = 0x2f84 + (0x158 * i); + + Array.Copy(v2, dest, v1, src, 0x14C); + } + + // Copy after-GSaveLightMemory[160] + Array.Copy(v2, 0x10684, v1, 0xff04, v2.Length - 0x10684); + + return v1; + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/VillagerHouse1.cs b/NHSE.Core/Structures/Villager/VillagerHouse1.cs index 4607dd3..9318c37 100644 --- a/NHSE.Core/Structures/Villager/VillagerHouse1.cs +++ b/NHSE.Core/Structures/Villager/VillagerHouse1.cs @@ -1,47 +1,48 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +public class VillagerHouse1 : IVillagerHouse { - public class VillagerHouse1 : IVillagerHouse + public const int SIZE = 0x1D4; + public const int ItemCount = 36; + public virtual string Extension => "nhvh"; + + public readonly Memory Raw; + public VillagerHouse1(Memory raw) => Raw = raw; + public Span Data => Raw.Span; + + public byte[] Write() => Data.ToArray(); + + public uint HouseLevel { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); } + public uint HouseStatus { get => ReadUInt32LittleEndian(Data[0x04..]); set => WriteUInt32LittleEndian(Data[0x04..], value); } + public WallType WallUniqueID { get => (WallType)ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], (ushort)value); } + public RoofType RoofUniqueID { get => (RoofType)ReadUInt16LittleEndian(Data[0x0A..]); set => WriteUInt16LittleEndian(Data[0x0A..], (ushort)value); } + public DoorKind DoorUniqueID { get => (DoorKind)ReadUInt16LittleEndian(Data[0x0C..]); set => WriteUInt16LittleEndian(Data[0x0C..], (ushort)value); } + public WallType OrderWallUniqueID { get => (WallType)ReadUInt16LittleEndian(Data[0x0E..]); set => WriteUInt16LittleEndian(Data[0x0E..], (ushort)value); } + public RoofType OrderRoofUniqueID { get => (RoofType)ReadUInt16LittleEndian(Data[0x10..]); set => WriteUInt16LittleEndian(Data[0x10..], (ushort)value); } + public DoorKind OrderDoorUniqueID { get => (DoorKind)ReadUInt16LittleEndian(Data[0x12..]); set => WriteUInt16LittleEndian(Data[0x12..], (ushort)value); } + + public Item DoorDecoItemName { - public const int SIZE = 0x1D4; - public const int ItemCount = 36; - public virtual string Extension => "nhvh"; - - public readonly byte[] Data; - public VillagerHouse1(byte[] data) => Data = data; - - public byte[] Write() => Data; - - public uint HouseLevel { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); } - public uint HouseStatus { get => BitConverter.ToUInt32(Data, 0x04); set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); } - public WallType WallUniqueID { get => (WallType)BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); } - public RoofType RoofUniqueID { get => (RoofType)BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); } - public DoorKind DoorUniqueID { get => (DoorKind)BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); } - public WallType OrderWallUniqueID { get => (WallType)BitConverter.ToUInt16(Data, 0x0E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E); } - public RoofType OrderRoofUniqueID { get => (RoofType)BitConverter.ToUInt16(Data, 0x10); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x10); } - public DoorKind OrderDoorUniqueID { get => (DoorKind)BitConverter.ToUInt16(Data, 0x12); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x12); } - - public Item DoorDecoItemName - { - get => Data.Slice(0x1C8, 8).ToClass(); - set => value.ToBytesClass().CopyTo(Data, 0x1C8); - } - - public sbyte NPC1 { get => (sbyte)Data[0x1C4]; set => Data[0x1C4] = (byte)value; } - public sbyte NPC2 { get => (sbyte)Data[0x1C5]; set => Data[0x1C5] = (byte)value; } - - public sbyte BuildPlayer { get => (sbyte)Data[0x1D0]; set => Data[0x1D0] = (byte)value; } - - public VillagerHouse2 Upgrade() - { - var data = new byte[VillagerHouse2.SIZE]; - var empty = Item.NONE.ToBytes(); - Data.CopyTo(data, 0); - for (int i = 0; i < 236; i++) - empty.CopyTo(data, 0x1D8 + (i * 0xC)); - VillagerHouse2.Footer.CopyTo(data, 0x1270); - return new VillagerHouse2(data); - } + get => Data.Slice(0x1C8, 8).ToArray().ToClass(); + set => value.ToBytesClass().CopyTo(Data[0x1C8..]); } -} + + public sbyte NPC1 { get => (sbyte)Data[0x1C4]; set => Data[0x1C4] = (byte)value; } + public sbyte NPC2 { get => (sbyte)Data[0x1C5]; set => Data[0x1C5] = (byte)value; } + + public sbyte BuildPlayer { get => (sbyte)Data[0x1D0]; set => Data[0x1D0] = (byte)value; } + + public VillagerHouse2 Upgrade() + { + var data = new byte[VillagerHouse2.SIZE]; + var empty = Item.NONE.ToBytes(); + Data.CopyTo(data); + for (int i = 0; i < 236; i++) + empty.CopyTo(data, 0x1D8 + (i * 0xC)); + VillagerHouse2.Footer.CopyTo(data.AsSpan(0x1270)); + return new VillagerHouse2(data); + } +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/VillagerHouse2.cs b/NHSE.Core/Structures/Villager/VillagerHouse2.cs index 8266d88..29cc5bb 100644 --- a/NHSE.Core/Structures/Villager/VillagerHouse2.cs +++ b/NHSE.Core/Structures/Villager/VillagerHouse2.cs @@ -1,135 +1,135 @@ using System; using System.ComponentModel; using System.Runtime.InteropServices; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +public class VillagerHouse2 : VillagerHouse1 { - public class VillagerHouse2 : VillagerHouse1 + public new const int SIZE = 0x12E8; + public override string Extension => "nhvh2"; + + public VillagerHouse2(Memory data) : base(data) { } + + // 0x1D4-0x12DB -- 0x1108 sized structure + // 0x12DC -- 8 byte item + // 0x12E4 -- 1 byte + + public s_f9acc222 ReadCustom() => Data.Slice(0x1D4, s_f9acc222.SIZE).ToStructure(); + public void WriteCustom(s_f9acc222 value) => value.ToBytes().CopyTo(Data[0x1D4..]); + + public Item ExtraItem { - public new const int SIZE = 0x12E8; - public override string Extension => "nhvh2"; - - public VillagerHouse2(byte[] data) : base(data) { } - - // 0x1D4-0x12DB -- 0x1108 sized structure - // 0x12DC -- 8 byte item - // 0x12E4 -- 1 byte - - public s_f9acc222 ReadCustom() => Data.Slice(0x1D4, s_f9acc222.SIZE).ToStructure(); - public void WriteCustom(s_f9acc222 value) => value.ToBytes().CopyTo(Data, 0x1D4); - - public Item ExtraItem - { - get => new(BitConverter.ToUInt64(Data, 0x12DC)); - set => BitConverter.GetBytes(value.RawValue).CopyTo(Data, 0x12DC); - } - - public byte Flag { get => Data[0x12E4]; set => Data[0x12E4] = value; } - - public VillagerHouse1 Downgrade() - { - var result = new byte[VillagerHouse1.SIZE]; - Data.CopyTo(result, 0); - return new VillagerHouse1(result); - } - - internal static readonly byte[] Footer = - { - 0x4B, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9B, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x40, - 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; + get => new(ReadUInt64LittleEndian(Data[0x12DC..])); + set => WriteUInt64LittleEndian(Data[0x12DC..], value.RawValue); } + public byte Flag { get => Data[0x12E4]; set => Data[0x12E4] = value; } + + public VillagerHouse1 Downgrade() + { + var result = new byte[VillagerHouse1.SIZE]; + Data.CopyTo(result); + return new VillagerHouse1(result); + } + + internal static ReadOnlySpan Footer => + [ + 0x4B, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9B, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x40, + 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ]; +} + #pragma warning disable CS8618, CA1815, CA1819, IDE1006, RCS1170 - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct s_f9acc222 - { - public const int SIZE = 0x1108; /* 0x1108 big, align 4 */ - public byte _599b2c0c { get; set; } // @0x0 size 0x1, align 1 - public s_e74059db _7ec757ba { get; set; } // @0x4 size 0xb10, align 4 - public s_a7a72585 _9d2fe4d0 { get; set; } // @0xb14 size 0x588, align 2 - public GSaveRoomFloorWall RoomFloorWall { get; set; } // @0x109c size 0x24, align 4 - public s_e13a81f4 _cfb139b9 { get; set; } // @0x10c0 size 0x14, align 4 - public GSaveItemName _428c13b4 { get; set; } // @0x10d4 size 0x8, align 4 - public GSaveItemName _eb46f399 { get; set; } // @0x10dc size 0x8, align 4 - public GSaveAudioRegister AudioRegister { get; set; } // @0x10e4 size 0x20, align 4 - public byte _81845564 { get; set; } // @0x1104 size 0x1, align 1 - } - - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct s_e13a81f4 - { - public const int SIZE = 0x14; /* 0x14 big, align 4 */ - public byte _ba0f8ef3 { get; set; } // @0x0 size 0x1, align 1 - public byte _99bc9d5c { get; set; } // @0x1 size 0x1, align 1 - public byte _7dd80307 { get; set; } // @0x2 size 0x1, align 1 - public byte Reserve { get; set; } // @0x3 size 0x1, align 1 - public ushort InfoBit { get; set; } // @0x4 size 0x2, align 2 - public ushort _da6790dc { get; set; } // @0x6 size 0x2, align 2 - public float _a5b1bb4b { get; set; } // @0x8 size 0x4, align 4 - public ushort _bb77b980 { get; set; } // @0xc size 0x2, align 2 - public ushort _f32a8316 { get; set; } // @0xe size 0x2, align 2 - public ushort _cec1a6ec { get; set; } // @0x10 size 0x2, align 2 - public ushort _c3971e28 { get; set; } // @0x12 size 0x2, align 2 - } - - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct GSaveAudioRegister - { - public const int SIZE = 0x20;/* 0x20 big, align 4 */ - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public uint[] RegisterBitList { get; set; } // @0x0 size 0x20, align 4 - } - - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct s_e74059db - { - public const int SIZE = 0xB10; /* 0xb10 big, align 4 */ - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 236)] - public s_c642ef36[] _7ec757ba { get; set; } // @0x0 size 0xc, align 4 - } - - [StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct s_a7a72585 - { - public const int SIZE = 0x588; /* 0x588 big, align 2 */ - - [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 236)] - public s_bd80e9c8[] _9d2fe4d0 { get; set; } // @0x0 size 0x6, align 2 - } - - [StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct s_bd80e9c8 - { - public const int SIZE = 0x6; /* 0x6 big, align 2 */ - public ushort _c929122c { get; set; } // @0x0 size 0x2, align 2 - public sbyte _2814d70c { get; set; } // @0x2 size 0x1, align 1 - public sbyte _3dbac09d { get; set; } // @0x3 size 0x1, align 1 - public sbyte Layer { get; set; } // @0x4 size 0x1, align 1 - } - - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] - [TypeConverter(typeof(ValueTypeTypeConverter))] - public struct s_c642ef36 - { - public const int SIZE = 0xC; /* 0xc big, align 4 */ - public GSaveItemName Item { get; set; } // @0x0 size 0x8, align 4 - public sbyte _2814d70c { get; set; } // @0x8 size 0x1, align 1 - public sbyte _3dbac09d { get; set; } // @0x9 size 0x1, align 1 - public sbyte Layer { get; set; } // @0xa size 0x1, align 1 - public byte Buffer { get; set; } // @0xb size 0x1, align 1 - } +[StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct s_f9acc222 +{ + public const int SIZE = 0x1108; /* 0x1108 big, align 4 */ + public byte _599b2c0c { get; set; } // @0x0 size 0x1, align 1 + public s_e74059db _7ec757ba { get; set; } // @0x4 size 0xb10, align 4 + public s_a7a72585 _9d2fe4d0 { get; set; } // @0xb14 size 0x588, align 2 + public GSaveRoomFloorWall RoomFloorWall { get; set; } // @0x109c size 0x24, align 4 + public s_e13a81f4 _cfb139b9 { get; set; } // @0x10c0 size 0x14, align 4 + public GSaveItemName _428c13b4 { get; set; } // @0x10d4 size 0x8, align 4 + public GSaveItemName _eb46f399 { get; set; } // @0x10dc size 0x8, align 4 + public GSaveAudioRegister AudioRegister { get; set; } // @0x10e4 size 0x20, align 4 + public byte _81845564 { get; set; } // @0x1104 size 0x1, align 1 } + +[StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct s_e13a81f4 +{ + public const int SIZE = 0x14; /* 0x14 big, align 4 */ + public byte _ba0f8ef3 { get; set; } // @0x0 size 0x1, align 1 + public byte _99bc9d5c { get; set; } // @0x1 size 0x1, align 1 + public byte _7dd80307 { get; set; } // @0x2 size 0x1, align 1 + public byte Reserve { get; set; } // @0x3 size 0x1, align 1 + public ushort InfoBit { get; set; } // @0x4 size 0x2, align 2 + public ushort _da6790dc { get; set; } // @0x6 size 0x2, align 2 + public float _a5b1bb4b { get; set; } // @0x8 size 0x4, align 4 + public ushort _bb77b980 { get; set; } // @0xc size 0x2, align 2 + public ushort _f32a8316 { get; set; } // @0xe size 0x2, align 2 + public ushort _cec1a6ec { get; set; } // @0x10 size 0x2, align 2 + public ushort _c3971e28 { get; set; } // @0x12 size 0x2, align 2 +} + +[StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct GSaveAudioRegister +{ + public const int SIZE = 0x20;/* 0x20 big, align 4 */ + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public uint[] RegisterBitList { get; set; } // @0x0 size 0x20, align 4 +} + +[StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct s_e74059db +{ + public const int SIZE = 0xB10; /* 0xb10 big, align 4 */ + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 236)] + public s_c642ef36[] _7ec757ba { get; set; } // @0x0 size 0xc, align 4 +} + +[StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct s_a7a72585 +{ + public const int SIZE = 0x588; /* 0x588 big, align 2 */ + + [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 236)] + public s_bd80e9c8[] _9d2fe4d0 { get; set; } // @0x0 size 0x6, align 2 +} + +[StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct s_bd80e9c8 +{ + public const int SIZE = 0x6; /* 0x6 big, align 2 */ + public ushort _c929122c { get; set; } // @0x0 size 0x2, align 2 + public sbyte _2814d70c { get; set; } // @0x2 size 0x1, align 1 + public sbyte _3dbac09d { get; set; } // @0x3 size 0x1, align 1 + public sbyte Layer { get; set; } // @0x4 size 0x1, align 1 +} + +[StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)] +[TypeConverter(typeof(ValueTypeTypeConverter))] +public struct s_c642ef36 +{ + public const int SIZE = 0xC; /* 0xc big, align 4 */ + public GSaveItemName Item { get; set; } // @0x0 size 0x8, align 4 + public sbyte _2814d70c { get; set; } // @0x8 size 0x1, align 1 + public sbyte _3dbac09d { get; set; } // @0x9 size 0x1, align 1 + public sbyte Layer { get; set; } // @0xa size 0x1, align 1 + public byte Buffer { get; set; } // @0xb size 0x1, align 1 +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/VillagerHouseConverter.cs b/NHSE.Core/Structures/Villager/VillagerHouseConverter.cs index 94c2f87..21c6d25 100644 --- a/NHSE.Core/Structures/Villager/VillagerHouseConverter.cs +++ b/NHSE.Core/Structures/Villager/VillagerHouseConverter.cs @@ -1,73 +1,74 @@ -namespace NHSE.Core +using System; + +namespace NHSE.Core; + +/// +/// Converts Villager House objects to different revisions. +/// +public static class VillagerHouseConverter { /// - /// Converts Villager House objects to different revisions. + /// Checks to see if the matches any of the House object sizes. /// - public static class VillagerHouseConverter + /// Size of the byte array that might represent a House object. + /// True if it matches any size. + public static bool IsHouse(int size) { - /// - /// Checks to see if the matches any of the House object sizes. - /// - /// Size of the byte array that might represent a House object. - /// True if it matches any size. - public static bool IsHouse(int size) - { - return size == VillagerHouse1.SIZE || size == VillagerHouse2.SIZE; - } - - /// - /// Checks to see if the input can be converted to the size. - /// - /// Current house file size - /// Expected house file size - /// True if can be converted, false if no conversion available. - public static bool IsCompatible(int size, int expect) - { - return expect switch - { - // Can convert to any format - VillagerHouse1.SIZE or VillagerHouse2.SIZE => IsHouse(size), - // No conversion available - _ => false, - }; - } - - /// - /// Converts the House data format to another format. - /// - /// - /// Before calling this method, check that a conversion method exists via and that the length of the is not the same as what you . - /// If the sizes are the same, it will return the input . - /// If no conversion path exists, it will return the input . - /// - /// Current format - /// Target size - /// Converted data - public static byte[] GetCompatible(byte[] data, int expect) - { - if (data.Length == expect) - return data; - - return expect switch - { - VillagerHouse1.SIZE when data.Length == VillagerHouse2.SIZE => Convert21(data), - VillagerHouse2.SIZE when data.Length == VillagerHouse1.SIZE => Convert12(data), - _ => data, - }; - } - - /// - /// Converts a object byte array to a - /// - /// object byte array - /// object byte array - private static byte[] Convert12(byte[] h1) => new VillagerHouse1(h1).Upgrade().Data; - - /// - /// Converts a object byte array to a - /// - /// object byte array - /// object byte array - private static byte[] Convert21(byte[] h2) => new VillagerHouse2(h2).Downgrade().Data; + return size is VillagerHouse1.SIZE or VillagerHouse2.SIZE; } -} + + /// + /// Checks to see if the input can be converted to the size. + /// + /// Current house file size + /// Expected house file size + /// True if can be converted, false if no conversion available. + public static bool IsCompatible(int size, int expect) + { + return expect switch + { + // Can convert to any format + VillagerHouse1.SIZE or VillagerHouse2.SIZE => IsHouse(size), + // No conversion available + _ => false, + }; + } + + /// + /// Converts the House data format to another format. + /// + /// + /// Before calling this method, check that a conversion method exists via and that the length of the is not the same as what you . + /// If the sizes are the same, it will return the input . + /// If no conversion path exists, it will return the input . + /// + /// Current format + /// Target size + /// Converted data + public static Memory GetCompatible(Memory data, int expect) + { + if (data.Length == expect) + return data; + + return expect switch + { + VillagerHouse1.SIZE when data.Length == VillagerHouse2.SIZE => Convert21(data), + VillagerHouse2.SIZE when data.Length == VillagerHouse1.SIZE => Convert12(data), + _ => data, + }; + } + + /// + /// Converts a object byte array to a + /// + /// object byte array + /// object byte array + private static byte[] Convert12(Memory h1) => new VillagerHouse1(h1).Upgrade().Write(); + + /// + /// Converts a object byte array to a + /// + /// object byte array + /// object byte array + private static byte[] Convert21(Memory h2) => new VillagerHouse2(h2).Downgrade().Write(); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/VillagerHouseItem.cs b/NHSE.Core/Structures/Villager/VillagerHouseItem.cs index 9b6625e..532c375 100644 --- a/NHSE.Core/Structures/Villager/VillagerHouseItem.cs +++ b/NHSE.Core/Structures/Villager/VillagerHouseItem.cs @@ -1,28 +1,29 @@ -using System.Runtime.InteropServices; +using System; +using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +[StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] +public struct VillagerHouseItem // GFtrData + : IEquatable { - [StructLayout(LayoutKind.Explicit, Size = SIZE, Pack = 1)] - public struct VillagerHouseItem // GFtrData - { - public const int SIZE = 0xC; + public const int SIZE = 0xC; - [field: FieldOffset(0x0)] public ushort ItemId { get; set; } - [field: FieldOffset(0x2)] public byte Flags0 { get; set; } - [field: FieldOffset(0x3)] public byte Flags1 { get; set; } - [field: FieldOffset(0x4)] public ushort Count { get; set; } - [field: FieldOffset(0x6)] public ushort UseCount { get; set; } + [field: FieldOffset(0x0)] public ushort ItemId { get; set; } + [field: FieldOffset(0x2)] public byte Flags0 { get; set; } + [field: FieldOffset(0x3)] public byte Flags1 { get; set; } + [field: FieldOffset(0x4)] public ushort Count { get; set; } + [field: FieldOffset(0x6)] public ushort UseCount { get; set; } - [field: FieldOffset(0x8)] public byte UnitX { get; set; } - [field: FieldOffset(0x9)] public byte UnitY { get; set; } - [field: FieldOffset(0xA)] public byte Direction { get; set; } - [field: FieldOffset(0xB)] public byte Layer { get; set; } + [field: FieldOffset(0x8)] public byte UnitX { get; set; } + [field: FieldOffset(0x9)] public byte UnitY { get; set; } + [field: FieldOffset(0xA)] public byte Direction { get; set; } + [field: FieldOffset(0xB)] public byte Layer { get; set; } - // ReSharper disable once NonReadonlyMemberInGetHashCode - public override int GetHashCode() => ItemId; - public override bool Equals(object obj) => obj is VillagerHouseItem i && i.Equals(this); - public bool Equals(VillagerHouseItem obj) => obj.ItemId == ItemId && obj.Flags0 == Flags0 && obj.Flags1 == Flags1; - public static bool operator ==(VillagerHouseItem left, VillagerHouseItem right) => left.Equals(right); - public static bool operator !=(VillagerHouseItem left, VillagerHouseItem right) => !(left == right); - } -} + // ReSharper disable once NonReadonlyMemberInGetHashCode + public readonly override int GetHashCode() => ItemId; + public readonly override bool Equals(object? obj) => obj is VillagerHouseItem i && i.Equals(this); + public readonly bool Equals(VillagerHouseItem obj) => obj.ItemId == ItemId && obj.Flags0 == Flags0 && obj.Flags1 == Flags1; + public static bool operator ==(VillagerHouseItem left, VillagerHouseItem right) => left.Equals(right); + public static bool operator !=(VillagerHouseItem left, VillagerHouseItem right) => !(left == right); +} \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/VillagerPersonality.cs b/NHSE.Core/Structures/Villager/VillagerPersonality.cs index abc407b..8c6078c 100644 --- a/NHSE.Core/Structures/Villager/VillagerPersonality.cs +++ b/NHSE.Core/Structures/Villager/VillagerPersonality.cs @@ -1,15 +1,14 @@ -namespace NHSE.Core +namespace NHSE.Core; + +public enum VillagerPersonality : byte { - public enum VillagerPersonality : byte - { - Lazy, - Jock, - Cranky, - Smug, - Normal, - Peppy, - Snooty, - Uchi, - None, - } + Lazy, + Jock, + Cranky, + Smug, + Normal, + Peppy, + Snooty, + Uchi, + None, } \ No newline at end of file diff --git a/NHSE.Core/Structures/Villager/VillagerUtil.cs b/NHSE.Core/Structures/Villager/VillagerUtil.cs index 388364f..02827fd 100644 --- a/NHSE.Core/Structures/Villager/VillagerUtil.cs +++ b/NHSE.Core/Structures/Villager/VillagerUtil.cs @@ -1,47 +1,46 @@ -namespace NHSE.Core -{ - public static class VillagerUtil - { - public static string GetInternalVillagerName(VillagerSpecies species, int variant) => $"{species}{variant:00}"; - } +namespace NHSE.Core; - public enum VillagerSpecies - { - ant = 0, - bea = 1, - brd = 2, - bul = 3, - cat = 4, - cbr = 5, - chn = 6, - cow = 7, - crd = 8, - der = 9, - dog = 10, - duk = 11, - elp = 12, - flg = 13, - goa = 14, - gor = 15, - ham = 16, - hip = 17, - hrs = 18, - kal = 19, - kgr = 20, - lon = 21, - mnk = 22, - mus = 23, - ocp = 24, - ost = 25, - pbr = 26, - pgn = 27, - pig = 28, - rbt = 29, - rhn = 30, - shp = 31, - squ = 32, - tig = 33, - wol = 34, - non = 35, - } +public static class VillagerUtil +{ + public static string GetInternalVillagerName(VillagerSpecies species, int variant) => $"{species}{variant:00}"; } + +public enum VillagerSpecies +{ + ant = 0, + bea = 1, + brd = 2, + bul = 3, + cat = 4, + cbr = 5, + chn = 6, + cow = 7, + crd = 8, + der = 9, + dog = 10, + duk = 11, + elp = 12, + flg = 13, + goa = 14, + gor = 15, + ham = 16, + hip = 17, + hrs = 18, + kal = 19, + kgr = 20, + lon = 21, + mnk = 22, + mus = 23, + ocp = 24, + ost = 25, + pbr = 26, + pgn = 27, + pig = 28, + rbt = 29, + rhn = 30, + shp = 31, + squ = 32, + tig = 33, + wol = 34, + non = 35, +} \ No newline at end of file diff --git a/NHSE.Core/Structures/XorShift128.cs b/NHSE.Core/Structures/XorShift128.cs index 300dfeb..95224f6 100644 --- a/NHSE.Core/Structures/XorShift128.cs +++ b/NHSE.Core/Structures/XorShift128.cs @@ -1,38 +1,37 @@ -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Xorshift128 RNG Implementation (xor128) +/// +/// +internal ref struct XorShift128 { + private uint a, b, c, d; + private const int Mersenne = 0x6C078965; + /// - /// Xorshift128 RNG Implementation (xor128) - /// + /// Initialize the generator from a seed. /// - internal ref struct XorShift128 + /// Ticks, usually. + public XorShift128(uint seed) { - private uint a, b, c, d; - private const int Mersenne = 0x6C078965; - - /// - /// Initialize the generator from a seed. - /// - /// Ticks, usually. - public XorShift128(uint seed) - { - // Unrolled Mersenne Twister initialization loop - a = (Mersenne * (seed ^ (seed >> 30))) + 1; - b = (Mersenne * ( a ^ ( a >> 30))) + 2; - c = (Mersenne * ( b ^ ( b >> 30))) + 3; - d = (Mersenne * ( c ^ ( c >> 30))) + 4; - } - - public uint GetU32() - { - uint t = a; - a = b; - b = c; - c = d; - t ^= t << 11; - t ^= t >> 8; - return d = t ^ d ^ (d >> 19); - } - - public ulong GetU64() => ((ulong)GetU32() << 32) | GetU32(); + // Unrolled Mersenne Twister initialization loop + a = (Mersenne * (seed ^ (seed >> 30))) + 1; + b = (Mersenne * ( a ^ ( a >> 30))) + 2; + c = (Mersenne * ( b ^ ( b >> 30))) + 3; + d = (Mersenne * ( c ^ ( c >> 30))) + 4; } -} + + public uint GetU32() + { + uint t = a; + a = b; + b = c; + c = d; + t ^= t << 11; + t ^= t >> 8; + return d = t ^ d ^ (d >> 19); + } + + public ulong GetU64() => ((ulong)GetU32() << 32) | GetU32(); +} \ No newline at end of file diff --git a/NHSE.Core/Util/ArrayUtil.cs b/NHSE.Core/Util/ArrayUtil.cs index 6dc7fdb..6143469 100644 --- a/NHSE.Core/Util/ArrayUtil.cs +++ b/NHSE.Core/Util/ArrayUtil.cs @@ -1,216 +1,26 @@ using System; -using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Array reusable logic +/// +public static class ArrayUtil { - /// - /// Array reusable logic - /// - public static class ArrayUtil + public static int ReplaceOccurrences(this Span array, ReadOnlySpan pattern, ReadOnlySpan swap) { - public static byte[] Slice(this byte[] src, int offset, int length) + int count = 0; + int ofs = 0; + while (true) { - byte[] data = new byte[length]; - Buffer.BlockCopy(src, offset, data, 0, data.Length); - return data; - } + var index = array[ofs..].IndexOf(pattern); + if (index == -1) + return count; + ofs += index; - public static byte[] SliceEnd(this byte[] src, int offset) - { - int length = src.Length - offset; - byte[] data = new byte[length]; - Buffer.BlockCopy(src, offset, data, 0, data.Length); - return data; - } - - public static T[] Slice(this T[] src, int offset, int length) - { - var data = new T[length]; - Array.Copy(src, offset, data, 0, data.Length); - return data; - } - - public static T[] SliceEnd(this T[] src, int offset) - { - int length = src.Length - offset; - var data = new T[length]; - Array.Copy(src, offset, data, 0, data.Length); - return data; - } - - public static bool WithinRange(int value, int min, int max) => min <= value && value < max; - - public static T[][] Split(this T[] data, int size) - { - var result = new T[data.Length / size][]; - for (int i = 0; i < data.Length; i += size) - result[i / size] = data.Slice(i, size); - return result; - } - - public static IEnumerable EnumerateSplit(T[] bin, int size, int start = 0) - { - for (int i = start; i < bin.Length; i += size) - yield return bin.Slice(i, size); - } - - public static IEnumerable EnumerateSplit(T[] bin, int size, int start, int end) - { - if (end < 0) - end = bin.Length; - for (int i = start; i < end; i += size) - yield return bin.Slice(i, size); - } - - public static bool[] GitBitFlagArray(byte[] data, int offset, int count) - { - bool[] result = new bool[count]; - for (int i = 0; i < result.Length; i++) - result[i] = (data[offset + (i >> 3)] >> (i & 7) & 0x1) == 1; - return result; - } - - public static void SetBitFlagArray(byte[] data, int offset, bool[] value) - { - for (int i = 0; i < value.Length; i++) - { - var ofs = offset + (i >> 3); - var mask = (1 << (i & 7)); - if (value[i]) - data[ofs] |= (byte)mask; - else - data[ofs] &= (byte)~mask; - } - } - - public static byte[] SetBitFlagArray(bool[] value) - { - byte[] data = new byte[value.Length / 8]; - SetBitFlagArray(data, 0, value); - return data; - } - - /// - /// Copies a list to the destination list, with an option to copy to a starting point. - /// - /// Source list to copy from - /// Destination list/array - /// Criteria for skipping a slot - /// Starting point to copy to - /// Count of copied. - public static int CopyTo(this IEnumerable list, IList dest, Func skip, int start = 0) - { - int ctr = start; - int skipped = 0; - foreach (var z in list) - { - // seek forward to next open slot - int next = FindNextValidIndex(dest, skip, ctr); - if (next == -1) - break; - skipped += next - ctr; - ctr = next; - dest[ctr++] = z; - } - return ctr - start - skipped; - } - - public static int FindNextValidIndex(IList dest, Func skip, int ctr) - { - while (true) - { - if ((uint)ctr >= dest.Count) - return -1; - var exist = dest[ctr]; - if (exist == null || !skip(exist)) - return ctr; - ctr++; - } - } - - /// - /// Copies an list to the destination list, with an option to copy to a starting point. - /// - /// Typed object to copy - /// Source list to copy from - /// Destination list/array - /// Starting point to copy to - /// Count of copied. - public static int CopyTo(this IEnumerable list, IList dest, int start = 0) - { - int ctr = start; - foreach (var z in list) - { - if ((uint)ctr >= dest.Count) - break; - dest[ctr++] = z; - } - return ctr - start; - } - - public static T[] ConcatAll(params T[][] arr) - { - int len = 0; - foreach (var a in arr) - len += a.Length; - - var result = new T[len]; - - int ctr = 0; - foreach (var a in arr) - { - a.CopyTo(result, ctr); - ctr += a.Length; - } - - return result; - } - - /// - /// Finds a provided within the supplied . - /// - /// Array to look in - /// Pattern to look for - /// 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) - { - 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; - } - } - } - - public static int ReplaceOccurrences(this byte[] array, byte[] pattern, byte[] swap) - { - int count = 0; - while (true) - { - int ofs = IndexOfBytes(array, pattern); - if (ofs == -1) - return count; - swap.CopyTo(array, ofs); - ++count; - } + swap.CopyTo(array[ofs..]); + ofs += swap.Length; // skip past swapped data + ++count; } } -} +} \ No newline at end of file diff --git a/NHSE.Core/Util/ComboItem.cs b/NHSE.Core/Util/ComboItem.cs index 3e182fb..bdc154b 100644 --- a/NHSE.Core/Util/ComboItem.cs +++ b/NHSE.Core/Util/ComboItem.cs @@ -1,86 +1,88 @@ using System; using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Key Value pair for a displayed and underlying value. +/// +public record ComboItem(string Text, int Value); + +public static class ComboItemUtil { - /// - /// Key Value pair for a displayed and underlying value. - /// - public record ComboItem(string Text, int Value); - - public static class ComboItemUtil + public static List GetArray(ReadOnlySpan items) { - public static List GetArray(string[] items) + var result = new List(items.Length / 2); + for (int i = 0; i < items.Length; i++) { - var result = new List(items.Length / 2); - for (int i = 0; i < items.Length; i++) - { - var text = items[i]; - if (text.Length == 0) - continue; - var item = new ComboItem(text, i); - result.Add(item); - } - - return result; + var text = items[i]; + if (text.Length == 0) + continue; + var item = new ComboItem(text, i); + result.Add(item); } - public static List GetArray(Type t) where T : struct, IFormattable - { - var names = Enum.GetNames(t); - var values = (T[])Enum.GetValues(t); + return result; + } - var acres = new List(names.Length); - for (int i = 0; i < names.Length; i++) - acres.Add(new ComboItem($"{names[i]} - {values[i]:X}", (ushort)(object)values[i])); - acres.SortByText(); - return acres; + public static List GetArray(Type t) where T : struct, IFormattable + { + var names = Enum.GetNames(t); + var values = (T[])Enum.GetValues(t); + + var acres = new List(names.Length); + for (int i = 0; i < names.Length; i++) + acres.Add(new ComboItem($"{names[i]} - {values[i]:X}", (ushort)(object)values[i])); + acres.SortByText(); + return acres; + } + + public static List GetArray(ReadOnlySpan values, ReadOnlySpan names) + { + var result = new List(values.Length); + foreach (var value in values) + { + var text = names[value]; + var item = new ComboItem(text, value); + result.Add(item); } - public static List GetArray(IReadOnlyList values, string[] names) - { - var result = new List(values.Count); - foreach (var value in values) - { - var text = names[value]; - var item = new ComboItem(text, value); - result.Add(item); - } + return result; + } - return result; + public static void Add(this List storage, IReadOnlyList tuples, Dictionary translate) + { + int initial = storage.Count; + storage.Capacity = storage.Count + tuples.Count; + foreach (var kvp in tuples) + { + var translated = translate.TryGetValue(kvp.Name, out var t) ? t : kvp.Name; + var item = new ComboItem(translated, kvp.Index); + storage.Add(item); } + storage.Sort(initial, storage.Count - initial, Comparer); + } - public static void Add(this List storage, IReadOnlyList tuples, Dictionary translate) + public static string ToStringList(this List arr, bool includeValues) + { + string format = string.Empty; + foreach (var ci in arr) + format += includeValues ? $"{ci.Text} ({ci.Value:X})\n" : $"{ci.Text}\n"; + return format; + } + + public static void SortByText(this List arr) => arr.Sort(Comparer); + + private static readonly FunctorComparer Comparer = + new((a, b) => string.CompareOrdinal(a.Text, b.Text)); + + private sealed class FunctorComparer(Comparison Comparison) : IComparer where T : notnull + { + public int Compare(T? x, T? y) { - int initial = storage.Count; - storage.Capacity = storage.Count + tuples.Count; - foreach (var kvp in tuples) - { - var translated = translate.TryGetValue(kvp.Name, out var t) ? t : kvp.Name; - var item = new ComboItem(translated, kvp.Index); - storage.Add(item); - } - storage.Sort(initial, storage.Count - initial, Comparer); - } - - public static string ToStringList(this List arr, bool includeValues) - { - string format = string.Empty; - foreach (var ci in arr) - format += includeValues ? $"{ci.Text} ({ci.Value:X})\n" : $"{ci.Text}\n"; - return format; - } - - public static void SortByText(this List arr) => arr.Sort(Comparer); - - private static readonly FunctorComparer Comparer = - new((a, b) => string.CompareOrdinal(a.Text, b.Text)); - - private sealed class FunctorComparer : IComparer - { - private readonly Comparison Comparison; - public FunctorComparer(Comparison comparison) => Comparison = comparison; - public int Compare(T x, T y) => Comparison(x, y); + if (x is null) + return y is null ? 0 : -1; + return y is null ? 1 : Comparison(x, y); } } -} +} \ No newline at end of file diff --git a/NHSE.Core/Util/EnumUtil.cs b/NHSE.Core/Util/EnumUtil.cs index 925000f..e71906a 100644 --- a/NHSE.Core/Util/EnumUtil.cs +++ b/NHSE.Core/Util/EnumUtil.cs @@ -1,31 +1,29 @@ using System; using System.Collections.Generic; -namespace NHSE.Core +namespace NHSE.Core; + +public static class EnumUtil { - public static class EnumUtil + public static KeyValuePair GetEnumList() where T : struct, Enum { - public static KeyValuePair GetEnumList() where T : Enum - { - var type = typeof(T); - var name = type.Name; - var values = GetTypeValues(type); - return new KeyValuePair(name, values); - } - - private static string[] GetTypeValues(Type type) where T : Enum - { - var arr = (T[])Enum.GetValues(type); - var result = new string[arr.Length]; - for (int i = 0; i < arr.Length; i++) - result[i] = GetSummary(arr[i]); - return result; - } - - private static string GetSummary(T z) where T : Enum - { - int x = Convert.ToInt32(z); - return $"{z} = {x}"; - } + var name = typeof(T).Name; + var values = GetTypeValues(); + return new KeyValuePair(name, values); } -} + + private static string[] GetTypeValues() where T : struct, Enum + { + var arr = Enum.GetValues(); + var result = new string[arr.Length]; + for (int i = 0; i < arr.Length; i++) + result[i] = GetSummary(arr[i]); + return result; + } + + private static string GetSummary(T z) where T : Enum + { + int x = Convert.ToInt32(z); + return $"{z} = {x}"; + } +} \ No newline at end of file diff --git a/NHSE.Core/Util/FlagUtil.cs b/NHSE.Core/Util/FlagUtil.cs index 1518a41..d93df2a 100644 --- a/NHSE.Core/Util/FlagUtil.cs +++ b/NHSE.Core/Util/FlagUtil.cs @@ -1,23 +1,24 @@ -namespace NHSE.Core -{ - /// - /// Utility logic for dealing with bitflags in a byte array. - /// - public static class FlagUtil - { - public static bool GetFlag(byte[] arr, int offset, int bitIndex) - { - var b = arr[offset + (bitIndex >> 3)]; - var mask = 1 << (bitIndex & 7); - return (b & mask) != 0; - } +using System; - public static void SetFlag(byte[] arr, int offset, int bitIndex, bool value) - { - offset += (bitIndex >> 3); - bitIndex &= 7; // ensure bit access is 0-7 - arr[offset] &= (byte)~(1 << bitIndex); - arr[offset] |= (byte)((value ? 1 : 0) << bitIndex); - } +namespace NHSE.Core; + +/// +/// Utility logic for dealing with bitflags in a byte array. +/// +public static class FlagUtil +{ + public static bool GetFlag(ReadOnlySpan arr, int offset, int bitIndex) + { + var b = arr[offset + (bitIndex >> 3)]; + var mask = 1 << (bitIndex & 7); + return (b & mask) != 0; + } + + public static void SetFlag(Span arr, int offset, int bitIndex, bool value) + { + offset += (bitIndex >> 3); + bitIndex &= 7; // ensure bit access is 0-7 + arr[offset] &= (byte)~(1 << bitIndex); + arr[offset] |= (byte)((value ? 1 : 0) << bitIndex); } } \ No newline at end of file diff --git a/NHSE.Core/Util/FrameworkUtil.cs b/NHSE.Core/Util/FrameworkUtil.cs deleted file mode 100644 index 6cab66c..0000000 --- a/NHSE.Core/Util/FrameworkUtil.cs +++ /dev/null @@ -1,36 +0,0 @@ -#if !NET5 -#pragma warning disable -// ReSharper disable once UnusedType.Global - -namespace System.Runtime.CompilerServices -{ - using Diagnostics; - using Diagnostics.CodeAnalysis; - - /// - /// Reserved to be used by the compiler for tracking metadata. - /// This class should not be used by developers in source code. - /// - [ExcludeFromCodeCoverage, DebuggerNonUserCode] - internal static class IsExternalInit - { - } -} - -namespace System.Diagnostics.CodeAnalysis -{ - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] - internal sealed class NotNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - - /// Gets the return value condition. - public bool ReturnValue { get; } - } -} -#pragma warning restore -#endif \ No newline at end of file diff --git a/NHSE.Core/Util/RandUtil.cs b/NHSE.Core/Util/RandUtil.cs index 4e462cb..5b67e59 100644 --- a/NHSE.Core/Util/RandUtil.cs +++ b/NHSE.Core/Util/RandUtil.cs @@ -1,46 +1,40 @@ using System; using System.Collections.Generic; -using System.Threading; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Logic for providing random values +/// +public static class RandUtil { + // Multi-thread safe rand, ha + public static Random Rand => Random.Shared; + + public static uint Rand32() => Rand32(Rand); + public static uint Rand32(Random rnd) => (uint)rnd.Next(1 << 30) << 2 | (uint)rnd.Next(1 << 2); + /// - /// Logic for providing random values + /// Shuffles the order of items within a collection of items. /// - public static class RandUtil + /// Item type + /// Item collection + public static void Shuffle(IList items) => Shuffle(items, 0, items.Count, Rand); + + /// + /// Shuffles the order of items within a collection of items. + /// + /// Item type + /// Item collection + /// Starting position + /// Ending position + /// RNG object to use + public static void Shuffle(IList items, int start, int end, Random rnd) { - // Multi-thread safe rand, ha - public static Random Rand => _local.Value; - - private static readonly ThreadLocal _local = new(() => new Random()); - - public static uint Rand32() => Rand32(Rand); - public static uint Rand32(Random rnd) => (uint)rnd.Next(1 << 30) << 2 | (uint)rnd.Next(1 << 2); - - /// - /// Shuffles the order of items within a collection of items. - /// - /// Item type - /// Item collection - public static void Shuffle(IList items) => Shuffle(items, 0, items.Count, Rand); - - /// - /// Shuffles the order of items within a collection of items. - /// - /// Item type - /// Item collection - /// Starting position - /// Ending position - /// RNG object to use - public static void Shuffle(IList items, int start, int end, Random rnd) + for (int i = start; i < end; i++) { - for (int i = start; i < end; i++) - { - int index = i + rnd.Next(end - i); - T t = items[index]; - items[index] = items[i]; - items[i] = t; - } + int index = i + rnd.Next(end - i); + (items[index], items[i]) = (items[i], items[index]); } } } \ No newline at end of file diff --git a/NHSE.Core/Util/ReflectUtil.cs b/NHSE.Core/Util/ReflectUtil.cs index f2cfa40..0453a97 100644 --- a/NHSE.Core/Util/ReflectUtil.cs +++ b/NHSE.Core/Util/ReflectUtil.cs @@ -5,139 +5,220 @@ using System.Linq; using System.Reflection; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Utility class for reflection. +/// +public static class ReflectUtil { - public static class ReflectUtil + /// + /// Fetches the requested property from , and compares it to . + /// + /// Property to fetch + /// Object to fetch property from + /// Value to compare to + /// Comparison result + public static int CompareTo(this PropertyInfo pi, object obj, object value) { - public static bool IsValueEqual(this PropertyInfo pi, object obj, object value) + var v = pi.GetValue(obj, null); + var c = ConvertValue(value, pi.PropertyType); + if (v is null) + return 0; + if (c is IComparable c1 && v is IComparable c2) + return c2.CompareTo(c1); + return 0; + } + + public static void SetValue(PropertyInfo pi, object obj, object value) + { + var c = ConvertValue(value, pi.PropertyType); + pi.SetValue(obj, c, null); + } + + public static object? GetValue(object obj, string name) + { + if (obj.GetType().GetTypeInfo().TryGetPropertyInfo(name, out var pi)) + return pi.GetValue(obj, null); + return null; + } + + public static bool SetValue(object obj, string name, object value) + { + if (!obj.GetType().GetTypeInfo().TryGetPropertyInfo(name, out var pi)) + return false; + if (!pi.CanWrite) + return false; + pi.SetValue(obj, value); + return true; + } + + public static IEnumerable GetPropertiesStartWithPrefix(Type type, string prefix) + { + return type.GetTypeInfo().GetAllTypeInfo().SelectMany(GetAllProperties) + .Where(p => p.Name.StartsWith(prefix, StringComparison.Ordinal)) + .Select(p => p.Name) + .Distinct() + ; + } + + public static IEnumerable GetPropertiesCanWritePublic(Type type) + { + return GetAllPropertyInfoCanWritePublic(type).Select(p => p.Name) + .Distinct() + ; + } + + public static IEnumerable GetAllPropertyInfoCanWritePublic(Type type) + { + return type.GetTypeInfo().GetAllTypeInfo().SelectMany(GetAllProperties) + .Where(CanWritePublic); + } + + public static IEnumerable GetAllPropertyInfoPublic(Type type) + { + return type.GetTypeInfo().GetAllTypeInfo().SelectMany(GetAllProperties) + .Where(p => p.CanReadPublic() || p.CanWritePublic()); + } + + extension(PropertyInfo p) + { + private bool CanReadPublic() => p.CanRead && (p.GetMethod?.IsPublic ?? false); + private bool CanWritePublic() => p.CanWrite && (p.SetMethod?.IsPublic ?? false); + + public bool IsValueEqual(object obj, object? value) { - var v = pi.GetValue(obj, null); - var c = ConvertValue(value, pi.PropertyType); + var v = p.GetValue(obj, null); + if (v is null) + return value == null; + if (value is null) + return false; + var c = ConvertValue(value, p.PropertyType); return v.Equals(c); } + } - public static void SetValue(PropertyInfo pi, object obj, object value) + public static IEnumerable GetPropertiesPublic(Type type) + { + return GetAllPropertyInfoPublic(type).Select(p => p.Name) + .Distinct() + ; + } + + public static IEnumerable GetPropertiesCanWritePublicDeclared(Type type) + { + return type.GetTypeInfo().GetAllProperties() + .Where(CanWritePublic) + .Select(p => p.Name) + .Distinct() + ; + } + + private static object? ConvertValue(object value, Type type) + { + if (type == typeof(DateOnly?)) // Used for PKM.MetDate and other similar properties { - var c = ConvertValue(value, pi.PropertyType); - pi.SetValue(obj, c, null); + return DateOnly.TryParseExact(value.ToString(), "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateOnly dateValue) + ? new DateOnly?(dateValue) + : null; } - public static object? GetValue(object obj, string name) => GetPropertyInfo(obj.GetType().GetTypeInfo(), name)?.GetValue(obj); - public static void SetValue(object obj, string name, object value) => GetPropertyInfo(obj.GetType().GetTypeInfo(), name)?.SetValue(obj, value, null); - public static object GetValue(Type t, string propertyName) => t.GetTypeInfo().GetDeclaredProperty(propertyName).GetValue(null); - public static void SetValue(Type t, string propertyName, object value) => t.GetTypeInfo().GetDeclaredProperty(propertyName).SetValue(null, value); - - public static IEnumerable GetPropertiesStartWithPrefix(Type type, string prefix) + if (type.IsEnum) { - return type.GetTypeInfo().GetAllTypeInfo().SelectMany(GetAllProperties) - .Where(p => p.Name.StartsWith(prefix, StringComparison.Ordinal)) - .Select(p => p.Name) - .Distinct() - ; + var str = value.ToString() ?? string.Empty; + if (Enum.IsDefined(type, str) && int.TryParse(str, out var integer)) + return Convert.ChangeType(integer, type); + return Enum.Parse(type, str, true); } + // Convert.ChangeType is suitable for most things + return Convert.ChangeType(value, type); + } - public static IEnumerable GetPropertiesCanWritePublic(Type type) + extension(TypeInfo typeInfo) + { + public IEnumerable GetAllConstructors() => typeInfo.GetAll(ti => ti.DeclaredConstructors); + public IEnumerable GetAllEvents() => typeInfo.GetAll(ti => ti.DeclaredEvents); + public IEnumerable GetAllFields() => typeInfo.GetAll(ti => ti.DeclaredFields); + public IEnumerable GetAllMembers() => typeInfo.GetAll(ti => ti.DeclaredMembers); + public IEnumerable GetAllMethods() => typeInfo.GetAll(ti => ti.DeclaredMethods); + public IEnumerable GetAllNestedTypes() => typeInfo.GetAll(ti => ti.DeclaredNestedTypes); + public IEnumerable GetAllProperties() => typeInfo.GetAll(ti => ti.DeclaredProperties); + } + + public static IEnumerable GetAllTypeInfo(this TypeInfo? typeInfo) + { + while (typeInfo is not null) { - return GetAllPropertyInfoCanWritePublic(type).Select(p => p.Name) - .Distinct() - ; - } - - public static IEnumerable GetAllPropertyInfoCanWritePublic(Type type) - { - return type.GetTypeInfo().GetAllTypeInfo().SelectMany(GetAllProperties) - .Where(p => p.CanWrite && p.SetMethod.IsPublic); - } - - public static IEnumerable GetAllPropertyInfoPublic(Type type) - { - return type.GetTypeInfo().GetAllTypeInfo().SelectMany(GetAllProperties) - .Where(p => (p.CanRead && p.GetMethod.IsPublic) || (p.CanWrite && p.SetMethod.IsPublic)); - } - - public static IEnumerable GetPropertiesPublic(Type type) - { - return GetAllPropertyInfoPublic(type).Select(p => p.Name) - .Distinct() - ; - } - - public static IEnumerable GetPropertiesCanWritePublicDeclared(Type type) - { - return type.GetTypeInfo().GetAllProperties() - .Where(p => p.CanWrite && p.SetMethod.IsPublic) - .Select(p => p.Name) - .Distinct() - ; - } - - private static object? ConvertValue(object value, Type type) - { - if (type == typeof(DateTime?)) // Used for PKM.MetDate and other similar properties - { - return DateTime.TryParseExact(value.ToString(), "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dateValue) - ? new DateTime?(dateValue) - : null; - } - - // Convert.ChangeType is suitable for most things - return Convert.ChangeType(value, type); - } - - public static IEnumerable GetAllConstructors(this TypeInfo typeInfo) - => GetAll(typeInfo, ti => ti.DeclaredConstructors); - - public static IEnumerable GetAllEvents(this TypeInfo typeInfo) - => GetAll(typeInfo, ti => ti.DeclaredEvents); - - public static IEnumerable GetAllFields(this TypeInfo typeInfo) - => GetAll(typeInfo, ti => ti.DeclaredFields); - - public static IEnumerable GetAllMembers(this TypeInfo typeInfo) - => GetAll(typeInfo, ti => ti.DeclaredMembers); - - public static IEnumerable GetAllMethods(this TypeInfo typeInfo) - => GetAll(typeInfo, ti => ti.DeclaredMethods); - - public static IEnumerable GetAllNestedTypes(this TypeInfo typeInfo) - => GetAll(typeInfo, ti => ti.DeclaredNestedTypes); - - public static IEnumerable GetAllProperties(this TypeInfo typeInfo) - => GetAll(typeInfo, ti => ti.DeclaredProperties); - - public static IEnumerable GetAllTypeInfo(this TypeInfo? typeInfo) - { - while (typeInfo != null) - { - yield return typeInfo; - typeInfo = typeInfo.BaseType?.GetTypeInfo(); - } - } - - public static bool HasProperty(object obj, string name, [NotNullWhen(true)] out PropertyInfo? pi) => (pi = GetPropertyInfo(obj.GetType().GetTypeInfo(), name)) != null; - - public static PropertyInfo? GetPropertyInfo(this TypeInfo typeInfo, string name) - { - return typeInfo.GetAllTypeInfo().Select(t => t.GetDeclaredProperty(name)).FirstOrDefault(pi => pi != null); - } - - private static IEnumerable GetAll(this TypeInfo typeInfo, Func> accessor) - { - return GetAllTypeInfo(typeInfo).SelectMany(_ => accessor(typeInfo)); - } - - public static Dictionary GetAllConstantsOfType(this Type type) where T : struct - { - var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy); - var consts = fields.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T)); - return consts.ToDictionary(x => (T)x.GetRawConstantValue(), z => z.Name); - } - - public static Dictionary GetAllPropertiesOfType(this Type type, object obj) where T : class - { - var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); - var ofType = props.Where(fi => typeof(T).IsAssignableFrom(fi.PropertyType)); - return ofType.ToDictionary(x => (T)x.GetValue(obj), z => z.Name); + yield return typeInfo; + typeInfo = typeInfo.BaseType?.GetTypeInfo(); } } -} \ No newline at end of file + + /// + /// Checks if the has the requested property . + /// + /// Object to check for property existence. + /// Name of the property. + /// Reference to the property info for the object, if it exists. + /// True if it has property, and false if it does not have property. is null when returning false. + public static bool HasProperty(object obj, string name, [NotNullWhen(true)] out PropertyInfo? pi) + { + var type = obj.GetType(); + return type.GetTypeInfo().TryGetPropertyInfo(name, out pi); + } + + extension(TypeInfo typeInfo) + { + public bool TryGetPropertyInfo(string name, [NotNullWhen(true)] out PropertyInfo? pi) + { + foreach (var t in typeInfo.GetAllTypeInfo()) + { + pi = t.GetDeclaredProperty(name); + if (pi is not null) + return true; + foreach (var i in t.ImplementedInterfaces) + { + pi = i.GetTypeInfo().GetDeclaredProperty(name); + if (pi is not null) + return true; + } + } + pi = null; + return false; + } + + private IEnumerable GetAll(Func> accessor) + { + return typeInfo.GetAllTypeInfo().SelectMany(_ => accessor(typeInfo)); + } + } + + extension(Type type) + { + public Dictionary GetAllConstantsOfType() where T : struct + { + var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy); + var consts = fields.Where(fi => fi is { IsLiteral: true, IsInitOnly: false } && fi.FieldType == typeof(T)); + return consts.ToDictionary(z => (T)(z.GetRawConstantValue() ?? throw new NullReferenceException(nameof(z.Name))), z => z.Name); + } + + public Dictionary GetAllPropertiesOfType(object obj) where T : class + { + var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); + var result = new Dictionary(props.Length); + var requestType = typeof(T); + foreach (var pi in props) + { + if (!requestType.IsAssignableFrom(pi.PropertyType)) + continue; + + var name = pi.Name; + var value = pi.GetValue(obj); + if (value is not T t) + continue; + result.TryAdd(name, t); + } + return result; + } + } +} diff --git a/NHSE.Core/Util/ResourceUtil.cs b/NHSE.Core/Util/ResourceUtil.cs index 9a5cade..afd1fa2 100644 --- a/NHSE.Core/Util/ResourceUtil.cs +++ b/NHSE.Core/Util/ResourceUtil.cs @@ -1,87 +1,90 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; +using System.Resources; +using System.Runtime.InteropServices; +using System.Threading; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Logic for retrieving resources from the dll +/// +public static class ResourceUtil { - /// - /// Logic for retrieving resources from the dll - /// - public static class ResourceUtil + private static readonly Assembly thisAssembly = typeof(ResourceUtil).GetTypeInfo().Assembly; + private static readonly string[] manifestResourceNames = thisAssembly.GetManifestResourceNames(); + private static readonly Dictionary resourceNameMap = new(); + private static readonly Dictionary stringListCache = new(); + private static readonly Lock getStringListLoadLock = new(); + + public static string[] GetStringList(string fileName) { - private static readonly Assembly thisAssembly = typeof(ResourceUtil).GetTypeInfo().Assembly; - private static readonly string[] manifestResourceNames = thisAssembly.GetManifestResourceNames(); - private static readonly Dictionary resourceNameMap = new(); - private static readonly Dictionary stringListCache = new(); - private static readonly object getStringListLoadLock = new(); + if (IsStringListCached(fileName, out var result)) + return result; + var txt = GetStringResource(fileName); // Fetch File, \n to list. + return LoadStringList(fileName, txt); + } - public static string[] GetStringList(string fileName) + public static bool IsStringListCached(string fileName, [NotNullWhen(true)] out string[]? result) + { + lock (getStringListLoadLock) // Make sure only one thread can read the cache + return stringListCache.TryGetValue(fileName, out result); + } + + public static string[] LoadStringList(string file, string? txt) + { + if (txt == null) + return []; + string[] rawlist = txt.TrimEnd('\r', '\n').Split('\n'); + for (int i = 0; i < rawlist.Length; i++) + rawlist[i] = rawlist[i].TrimEnd('\r'); + + lock (getStringListLoadLock) // Make sure only one thread can write to the cache + stringListCache.TryAdd(file, rawlist); // Check cache again in case of race condition + + return (string[])rawlist.Clone(); + } + + public static string[] GetStringList(string fileName, string lang2char, string type = "text") => GetStringList($"{type}_{fileName}_{lang2char}"); + + public static byte[] GetBinaryResource(string name) + { + using var resource = thisAssembly.GetManifestResourceStream($"NHSE.Core.Resources.byte.{name}") + ?? throw new MissingManifestResourceException($"Resource not found: {name}"); + var buffer = new byte[resource.Length]; + _ = resource.Read(buffer, 0, (int)resource.Length); + return buffer; + } + + public static ushort[] GetBinaryResourceAsUshort(string name) + { + ReadOnlySpan byteBuffer = GetBinaryResource(name); + var result = MemoryMarshal.Cast(byteBuffer).ToArray(); + if (!BitConverter.IsLittleEndian) + ReverseEndianness(result, result); + return result; + + } + + public static string? GetStringResource(string name) + { + if (!resourceNameMap.TryGetValue(name, out var resname)) { - if (IsStringListCached(fileName, out var result)) - return result; - var txt = GetStringResource(fileName); // Fetch File, \n to list. - return LoadStringList(fileName, txt); - } - - public static bool IsStringListCached(string fileName, out string[] result) - { - lock (getStringListLoadLock) // Make sure only one thread can read the cache - return stringListCache.TryGetValue(fileName, out result); - } - - public static string[] LoadStringList(string file, string? txt) - { - if (txt == null) - return Array.Empty(); - string[] rawlist = txt.TrimEnd('\r', '\n').Split('\n'); - for (int i = 0; i < rawlist.Length; i++) - rawlist[i] = rawlist[i].TrimEnd('\r'); - - lock (getStringListLoadLock) // Make sure only one thread can write to the cache - { - if (!stringListCache.ContainsKey(file)) // Check cache again in case of race condition - stringListCache.Add(file, rawlist); - } - - return (string[])rawlist.Clone(); - } - - public static string[] GetStringList(string fileName, string lang2char, string type = "text") => GetStringList($"{type}_{fileName}_{lang2char}"); - - public static byte[] GetBinaryResource(string name) - { - using var resource = thisAssembly.GetManifestResourceStream($"NHSE.Core.Resources.byte.{name}"); - var buffer = new byte[resource.Length]; - resource.Read(buffer, 0, (int)resource.Length); - return buffer; - } - - public static ushort[] GetBinaryResourceAsUshort(string name) - { - var byteBuffer = GetBinaryResource(name); - var buffer = new ushort[byteBuffer.Length / 2]; - for (int i = 0; i < byteBuffer.Length / 2; i++) - buffer[i] = BitConverter.ToUInt16(byteBuffer, i*2); - return buffer; - } - - public static string? GetStringResource(string name) - { - if (!resourceNameMap.TryGetValue(name, out var resname)) - { - bool Match(string x) => x.StartsWith("NHSE.Core.Resources.text.") && x.EndsWith($"{name}.txt", StringComparison.OrdinalIgnoreCase); - resname = Array.Find(manifestResourceNames, Match); - if (resname == null) - return null; - resourceNameMap.Add(name, resname); - } - - using var resource = thisAssembly.GetManifestResourceStream(resname); - if (resource == null) + bool Match(string x) => x.StartsWith("NHSE.Core.Resources.text.") && x.EndsWith($"{name}.txt", StringComparison.OrdinalIgnoreCase); + resname = Array.Find(manifestResourceNames, Match); + if (resname == null) return null; - using var reader = new StreamReader(resource); - return reader.ReadToEnd(); + resourceNameMap.Add(name, resname); } + + using var resource = thisAssembly.GetManifestResourceStream(resname); + if (resource == null) + return null; + using var reader = new StreamReader(resource); + return reader.ReadToEnd(); } } \ No newline at end of file diff --git a/NHSE.Core/Util/StringUtil.cs b/NHSE.Core/Util/StringUtil.cs index ff83e0b..3420708 100644 --- a/NHSE.Core/Util/StringUtil.cs +++ b/NHSE.Core/Util/StringUtil.cs @@ -1,82 +1,79 @@ -using System.IO; +using System; +using System.IO; using System.Runtime.CompilerServices; using System.Text; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Logic for manipulating strings +/// +public static class StringUtil { /// - /// Logic for manipulating strings + /// Trims a string at the first instance of a 0x0000 terminator. /// - public static class StringUtil + /// String to trim. + /// Trimmed string. + public static string TrimFromZero(string input) => TrimFromFirst(input, '\0'); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static string TrimFromFirst(string input, char c) { - /// - /// Trims a string at the first instance of a 0x0000 terminator. - /// - /// String to trim. - /// Trimmed string. - public static string TrimFromZero(string input) => TrimFromFirst(input, '\0'); + int index = input.IndexOf(c); + return index < 0 ? input : input[..index]; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static string TrimFromFirst(string input, char c) - { - int index = input.IndexOf(c); - return index < 0 ? input : input.Substring(0, index); - } + public static string GetString(ReadOnlySpan data, int offset, int maxLength) + { + var slice = data.Slice(offset, maxLength * 2); + var str = Encoding.Unicode.GetString(slice); + return TrimFromZero(str); + } - public static string GetString(byte[] data, int offset, int maxLength) - { - var str = Encoding.Unicode.GetString(data, offset, maxLength * 2); - return TrimFromZero(str); - } + public static byte[] GetBytes(string value, int maxLength) + { + if (value.Length > maxLength) + value = value[..maxLength]; + else if (value.Length < maxLength) + value = value.PadRight(maxLength, '\0'); + return Encoding.Unicode.GetBytes(value); + } - public static byte[] GetBytes(string value, int maxLength) - { - if (value.Length > maxLength) - value = value.Substring(0, maxLength); - else if (value.Length < maxLength) - value = value.PadRight(maxLength, '\0'); - return Encoding.Unicode.GetBytes(value); - } + public static string CleanFileName(string fileName) + { + return string.Concat(fileName.Split(Path.GetInvalidFileNameChars())); + } - public static string CleanFileName(string fileName) - { - return string.Concat(fileName.Split(Path.GetInvalidFileNameChars())); - } - - /// - /// Parses the hex string into a , skipping all characters except for valid digits. - /// - /// Hex String to parse - /// Parsed value - public static uint GetHexValue(string value) - { - uint result = 0; - if (string.IsNullOrEmpty(value)) - return result; - - foreach (var c in value) - { - if (IsNum(c)) - { - result <<= 4; - result += (uint)(c - '0'); - } - else if (IsHexUpper(c)) - { - result <<= 4; - result += (uint)(c - 'A' + 10); - } - else if (IsHexLower(c)) - { - result <<= 4; - result += (uint)(c - 'a' + 10); - } - } + /// + /// Parses the hex string into a , skipping all characters except for valid digits. + /// + /// Hex String to parse + /// Parsed value + public static uint GetHexValue(ReadOnlySpan value) + { + uint result = 0; + if (value.Length == 0) return result; - } - private static bool IsNum(char c) => (uint)(c - '0') <= 9; - private static bool IsHexUpper(char c) => (uint)(c - 'A') <= 5; - private static bool IsHexLower(char c) => (uint)(c - 'a') <= 5; + foreach (var c in value) + { + if (char.IsAsciiDigit(c)) + { + result <<= 4; + result |= (uint)(c - '0'); + } + else if (char.IsAsciiHexDigitUpper(c)) + { + result <<= 4; + result |= (uint)(c - 'A' + 10); + } + else if (char.IsAsciiHexDigitLower(c)) + { + result <<= 4; + result |= (uint)(c - 'a' + 10); + } + } + return result; } } \ No newline at end of file diff --git a/NHSE.Core/Util/StructConverter.cs b/NHSE.Core/Util/StructConverter.cs index 5322b21..196dc78 100644 --- a/NHSE.Core/Util/StructConverter.cs +++ b/NHSE.Core/Util/StructConverter.cs @@ -1,94 +1,92 @@ -using System; +using System; using System.Collections.Generic; using System.Runtime.InteropServices; -namespace NHSE.Core +namespace NHSE.Core; + +/// +/// Logic for converting raw data to class/stack struct, and back to data. +/// +public static class StructConverter { - /// - /// Logic for converting raw data to class/stack struct, and back to data. - /// - public static class StructConverter + extension(byte[] data) { - public static T ToStructure(this byte[] bytes) where T : struct + public T ToStructure() where T : struct { - var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - try { return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); } + var handle = GCHandle.Alloc(data, GCHandleType.Pinned); + try { return Marshal.PtrToStructure(handle.AddrOfPinnedObject()); } finally { handle.Free(); } } - public static T ToClass(this byte[] bytes) where T : class + public T ToClass() where T : class { - var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - try { return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); } + var handle = GCHandle.Alloc(data, GCHandleType.Pinned); + try { return Marshal.PtrToStructure(handle.AddrOfPinnedObject())!; } finally { handle.Free(); } } + } - public static T ToStructure(this byte[] bytes, int offset, int length) where T : struct - { - var slice = bytes.Slice(offset, length); - return slice.ToStructure(); - } + extension(ReadOnlySpan data) + { + public T ToStructure() where T : struct => data.ToArray().ToStructure(); - public static T ToClass(this byte[] bytes, int offset, int length) where T : class - { - var slice = bytes.Slice(offset, length); - return slice.ToClass(); - } + public T ToStructure(int offset, int length) where T : struct => + data.Slice(offset, length).ToStructure(); - 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; - } - - public static T[] GetArray(this byte[] data, int size) where T : class + public T[] GetArray(int size) where T : class { var result = new T[data.Length / size]; for (int i = 0; i < result.Length; i++) - result[i] = data.Slice(i * size, size).ToClass(); + result[i] = data.Slice(i * size, size).ToArray().ToClass(); return result; } - public static byte[] SetArray(this IReadOnlyList data, int size) where T : class - { - var result = new byte[data.Count * size]; - for (int i = 0; i < data.Count; i++) - data[i].ToBytesClass().CopyTo(result, i * size); - return result; - } - - public static T[] GetArrayStructure(this byte[] data, int size) where T : struct + public T[] GetArrayStructure(int size) where T : struct { var result = new T[data.Length / size]; for (int i = 0; i < result.Length; i++) result[i] = data.Slice(i * size, size).ToStructure(); return result; } - - public static byte[] SetArrayStructure(this IReadOnlyList data, int size) where T : struct - { - var result = new byte[data.Count * size]; - for (int i = 0; i < data.Count; i++) - data[i].ToBytes().CopyTo(result, i * size); - return result; - } } -} + + 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; + } + + public static byte[] SetArray(this IReadOnlyList data, int size) where T : class + { + var result = new byte[data.Count * size]; + for (int i = 0; i < data.Count; i++) + data[i].ToBytesClass().CopyTo(result, i * size); + return result; + } + + public static byte[] SetArrayStructure(this ReadOnlySpan data, int size) where T : struct + { + var result = new byte[data.Length * size]; + for (int i = 0; i < data.Length; i++) + data[i].ToBytes().CopyTo(result, i * size); + return result; + } +} \ No newline at end of file diff --git a/NHSE.Injection/Injector/AutoInjector.cs b/NHSE.Injection/Injector/AutoInjector.cs index 8cef5e0..d17713c 100644 --- a/NHSE.Injection/Injector/AutoInjector.cs +++ b/NHSE.Injection/Injector/AutoInjector.cs @@ -1,69 +1,68 @@ using System; using System.Diagnostics; -namespace NHSE.Injection +namespace NHSE.Injection; + +public class AutoInjector { - public class AutoInjector + public readonly IDataInjector Injector; + private readonly Action AfterRead; + private readonly Action AfterWrite; + + public bool AutoInjectEnabled { private get; set; } + + public bool ValidateEnabled { - public readonly IDataInjector Injector; - private readonly Action AfterRead; - private readonly Action AfterWrite; + get => Injector.ValidateEnabled; + set => Injector.ValidateEnabled = value; + } - public bool AutoInjectEnabled { private get; set; } + public AutoInjector(IDataInjector inj, Action read, Action write) + { + Injector = inj; + AfterRead = read; + AfterWrite = write; + } - public bool ValidateEnabled + public void Validate() => Injector.Validate(); + + public InjectionResult Read(bool force = false) + { + if ((!AutoInjectEnabled && !force) || !Injector.Connected) + return InjectionResult.Skipped; + + try { - get => Injector.ValidateEnabled; - set => Injector.ValidateEnabled = value; + var result = Injector.Read(); + AfterRead(result); + return result; } - - public AutoInjector(IDataInjector inj, Action read, Action write) + catch (IndexOutOfRangeException ex) { - Injector = inj; - AfterRead = read; - AfterWrite = write; - } - - public void Validate() => Injector.Validate(); - - public InjectionResult Read(bool force = false) - { - if ((!AutoInjectEnabled && !force) || !Injector.Connected) - return InjectionResult.Skipped; - - try - { - var result = Injector.Read(); - AfterRead(result); - return result; - } - catch (IndexOutOfRangeException ex) - { - Debug.WriteLine(ex.Message); - return InjectionResult.FailConnectionError; - } - } - - public InjectionResult Write(bool force = false) - { - if ((!AutoInjectEnabled && !force) || !Injector.Connected) - return InjectionResult.Skipped; - try - { - var result = Injector.Write(); - AfterWrite(result); - return result; - } - catch (IndexOutOfRangeException ex) - { - Debug.WriteLine(ex.Message); - return InjectionResult.FailConnectionError; - } - } - - public void SetWriteOffset(in uint offset) - { - Injector.WriteOffset = offset; + Debug.WriteLine(ex.Message); + return InjectionResult.FailConnectionError; } } + + public InjectionResult Write(bool force = false) + { + if ((!AutoInjectEnabled && !force) || !Injector.Connected) + return InjectionResult.Skipped; + try + { + var result = Injector.Write(); + AfterWrite(result); + return result; + } + catch (IndexOutOfRangeException ex) + { + Debug.WriteLine(ex.Message); + return InjectionResult.FailConnectionError; + } + } + + public void SetWriteOffset(in uint offset) + { + Injector.WriteOffset = offset; + } } \ No newline at end of file diff --git a/NHSE.Injection/Injector/IDataInjector.cs b/NHSE.Injection/Injector/IDataInjector.cs index b22fcca..700db81 100644 --- a/NHSE.Injection/Injector/IDataInjector.cs +++ b/NHSE.Injection/Injector/IDataInjector.cs @@ -1,15 +1,16 @@ -namespace NHSE.Injection -{ - public interface IDataInjector - { - bool ReadValidate(out byte[] data); - InjectionResult Read(); - InjectionResult Write(); +using System; - bool Validate(); - bool Validate(byte[] data); - uint WriteOffset { set; } - bool Connected { get; } - bool ValidateEnabled { get; set; } - } +namespace NHSE.Injection; + +public interface IDataInjector +{ + bool ReadValidate(out byte[] data); + InjectionResult Read(); + InjectionResult Write(); + + bool Validate(); + bool Validate(ReadOnlySpan data); + uint WriteOffset { set; } + bool Connected { get; } + bool ValidateEnabled { get; set; } } \ No newline at end of file diff --git a/NHSE.Injection/Injector/IRAMReadWriter.cs b/NHSE.Injection/Injector/IRAMReadWriter.cs index f0a52ff..876500b 100644 --- a/NHSE.Injection/Injector/IRAMReadWriter.cs +++ b/NHSE.Injection/Injector/IRAMReadWriter.cs @@ -1,9 +1,8 @@ -namespace NHSE.Injection +namespace NHSE.Injection; + +public interface IRAMReadWriter { - public interface IRAMReadWriter - { - bool Connected { get; } - byte[] ReadBytes(uint offset, int length); - void WriteBytes(byte[] data, uint offset); - } + bool Connected { get; } + byte[] ReadBytes(uint offset, int length); + void WriteBytes(byte[] data, uint offset); } \ No newline at end of file diff --git a/NHSE.Injection/Injector/InjectionResult.cs b/NHSE.Injection/Injector/InjectionResult.cs index e585ddf..f724bfc 100644 --- a/NHSE.Injection/Injector/InjectionResult.cs +++ b/NHSE.Injection/Injector/InjectionResult.cs @@ -1,12 +1,11 @@ -namespace NHSE.Injection +namespace NHSE.Injection; + +public enum InjectionResult { - public enum InjectionResult - { - Skipped, - Success, - FailValidate, - FailConnectionError, - FailBadSize, - Same, - } -} + Skipped, + Success, + FailValidate, + FailConnectionError, + FailBadSize, + Same, +} \ No newline at end of file diff --git a/NHSE.Injection/NHSE.Injection.csproj b/NHSE.Injection/NHSE.Injection.csproj index 53f5dfe..4bb264a 100644 --- a/NHSE.Injection/NHSE.Injection.csproj +++ b/NHSE.Injection/NHSE.Injection.csproj @@ -1,9 +1,5 @@  - - net46;netstandard2.0 - - diff --git a/NHSE.Injection/PocketInjector.cs b/NHSE.Injection/PocketInjector.cs index 83d9b51..b8d1ad7 100644 --- a/NHSE.Injection/PocketInjector.cs +++ b/NHSE.Injection/PocketInjector.cs @@ -1,83 +1,82 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using NHSE.Core; -namespace NHSE.Injection +namespace NHSE.Injection; + +public class PocketInjector : IDataInjector { - public class PocketInjector : IDataInjector + private readonly IReadOnlyList Items; + private readonly IRAMReadWriter Bot; + public bool Connected => Bot.Connected; + + public uint WriteOffset { private get; set; } + public bool ValidateEnabled { get; set; } = true; + public bool SpoofInventoryWrite { get; set; } + private static readonly Item DroppableOnlyItem = new(0x9C9); // Gold nugget + + public PocketInjector(IReadOnlyList items, IRAMReadWriter bot) { - private readonly IReadOnlyList Items; - private readonly IRAMReadWriter Bot; - public bool Connected => Bot.Connected; - - public uint WriteOffset { private get; set; } - public bool ValidateEnabled { get; set; } = true; - public bool SpoofInventoryWrite { get; set; } = false; - private static readonly Item DroppableOnlyItem = new(0x9C9); // Gold nugget - - public PocketInjector(IReadOnlyList items, IRAMReadWriter bot) - { - Items = items; - Bot = bot; - } - - public bool ReadValidate(out byte[] data) - { - PlayerItemSet.GetOffsetLength(WriteOffset, out var offset, out var size); - data = Bot.ReadBytes(offset, size); - return Validate(data); - } - - private byte[]? LastData; - - public InjectionResult Read() - { - if (!ReadValidate(out var data)) - return InjectionResult.FailValidate; - - if (LastData?.SequenceEqual(data) == true) - return InjectionResult.Same; - - PlayerItemSet.ReadPlayerInventory(data, Items); - - LastData = data; - - return InjectionResult.Success; - } - - public InjectionResult Write() - { - if (!ReadValidate(out var data)) - return InjectionResult.FailValidate; - - var orig = (byte[])data.Clone(); - - var items = !SpoofInventoryWrite ? Items : Enumerable.Repeat(DroppableOnlyItem, Items.Count).ToArray(); - - PlayerItemSet.WritePlayerInventory(data, items); - - if (data.SequenceEqual(orig)) - return InjectionResult.Same; - - PlayerItemSet.GetOffsetLength(WriteOffset, out var offset, out var size); - if (size != data.Length) - return InjectionResult.FailBadSize; - - Bot.WriteBytes(data, offset); - - LastData = data; - - return InjectionResult.Success; - } - - public bool Validate() => ReadValidate(out _); - - public bool Validate(byte[] data) - { - if (!ValidateEnabled) - return true; - - return PlayerItemSet.ValidateItemBinary(data); - } + Items = items; + Bot = bot; } -} + + public bool ReadValidate(out byte[] data) + { + PlayerItemSet.GetOffsetLength(WriteOffset, out var offset, out var size); + data = Bot.ReadBytes(offset, size); + return Validate(data); + } + + private byte[]? LastData; + + public InjectionResult Read() + { + if (!ReadValidate(out var data)) + return InjectionResult.FailValidate; + + if (LastData?.SequenceEqual(data) == true) + return InjectionResult.Same; + + PlayerItemSet.ReadPlayerInventory(data, Items); + + LastData = data; + + return InjectionResult.Success; + } + + public InjectionResult Write() + { + if (!ReadValidate(out var data)) + return InjectionResult.FailValidate; + + var orig = (byte[])data.Clone(); + + var items = !SpoofInventoryWrite ? Items : Enumerable.Repeat(DroppableOnlyItem, Items.Count).ToArray(); + + PlayerItemSet.WritePlayerInventory(data, items); + + if (data.SequenceEqual(orig)) + return InjectionResult.Same; + + PlayerItemSet.GetOffsetLength(WriteOffset, out var offset, out var size); + if (size != data.Length) + return InjectionResult.FailBadSize; + + Bot.WriteBytes(data, offset); + + LastData = data; + + return InjectionResult.Success; + } + + public bool Validate() => ReadValidate(out _); + + public bool Validate(System.ReadOnlySpan data) + { + if (!ValidateEnabled) + return true; + + return PlayerItemSet.ValidateItemBinary(data); + } +} \ No newline at end of file diff --git a/NHSE.Injection/SysBot/Decoder.cs b/NHSE.Injection/SysBot/Decoder.cs index ab3b5cb..0de97c1 100644 --- a/NHSE.Injection/SysBot/Decoder.cs +++ b/NHSE.Injection/SysBot/Decoder.cs @@ -1,51 +1,50 @@ using System; -namespace NHSE.Injection +namespace NHSE.Injection; + +public static class Decoder { - public static class Decoder + private static bool IsNum(char c) => (uint)(c - '0') <= 9; + private static bool IsHexUpper(char c) => (uint)(c - 'A') <= 5; + + public static byte[] ConvertHexByteStringToBytes(byte[] bytes) { - private static bool IsNum(char c) => (uint)(c - '0') <= 9; - private static bool IsHexUpper(char c) => (uint)(c - 'A') <= 5; - - public static byte[] ConvertHexByteStringToBytes(byte[] bytes) + var dest = new byte[bytes.Length / 2]; + for (int i = 0; i < dest.Length; i++) { - var dest = new byte[bytes.Length / 2]; - for (int i = 0; i < dest.Length; i++) - { - int ofs = i * 2; - var _0 = (char)bytes[ofs + 0]; - var _1 = (char)bytes[ofs + 1]; - dest[i] = DecodeTuple(_0, _1); - } - return dest; + int ofs = i * 2; + var _0 = (char)bytes[ofs + 0]; + var _1 = (char)bytes[ofs + 1]; + dest[i] = DecodeTuple(_0, _1); } + return dest; + } - private static byte DecodeTuple(char _0, char _1) - { - byte result; - if (IsNum(_0)) - result = (byte)((_0 - '0') << 4); - else if (IsHexUpper(_0)) - result = (byte)((_0 - 'A' + 10) << 4); - else - throw new ArgumentOutOfRangeException(nameof(_0)); + private static byte DecodeTuple(char _0, char _1) + { + byte result; + if (IsNum(_0)) + result = (byte)((_0 - '0') << 4); + else if (IsHexUpper(_0)) + result = (byte)((_0 - 'A' + 10) << 4); + else + throw new ArgumentOutOfRangeException(nameof(_0)); - if (IsNum(_1)) - result |= (byte)(_1 - '0'); - else if (IsHexUpper(_1)) - result |= (byte)(_1 - 'A' + 10); - else - throw new ArgumentOutOfRangeException(nameof(_1)); - return result; - } + if (IsNum(_1)) + result |= (byte)(_1 - '0'); + else if (IsHexUpper(_1)) + result |= (byte)(_1 - 'A' + 10); + else + throw new ArgumentOutOfRangeException(nameof(_1)); + return result; + } - public static byte[] StringToByteArray(string hex) - { - int NumberChars = hex.Length; - byte[] bytes = new byte[NumberChars / 2]; - for (int i = 0; i < NumberChars; i += 2) - bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); - return bytes; - } + public static byte[] StringToByteArray(string hex) + { + int NumberChars = hex.Length; + byte[] bytes = new byte[NumberChars / 2]; + for (int i = 0; i < NumberChars; i += 2) + bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); + return bytes; } } \ No newline at end of file diff --git a/NHSE.Injection/SysBot/SwitchButton.cs b/NHSE.Injection/SysBot/SwitchButton.cs index 5c3be72..2a520cd 100644 --- a/NHSE.Injection/SysBot/SwitchButton.cs +++ b/NHSE.Injection/SysBot/SwitchButton.cs @@ -1,27 +1,26 @@ -namespace NHSE.Injection +namespace NHSE.Injection; + +/// +/// Controller Buttons +/// +public enum SwitchButton { - /// - /// Controller Buttons - /// - public enum SwitchButton - { - A, - B, - X, - Y, - RSTICK, - LSTICK, - L, - R, - ZL, - ZR, - PLUS, - MINUS, - DUP, - DDOWN, - DLEFT, - DRIGHT, - HOME, - CAPTURE, - } + A, + B, + X, + Y, + RSTICK, + LSTICK, + L, + R, + ZL, + ZR, + PLUS, + MINUS, + DUP, + DDOWN, + DLEFT, + DRIGHT, + HOME, + CAPTURE, } \ No newline at end of file diff --git a/NHSE.Injection/SysBot/SwitchCommand.cs b/NHSE.Injection/SysBot/SwitchCommand.cs index 8fec775..ae2d083 100644 --- a/NHSE.Injection/SysBot/SwitchCommand.cs +++ b/NHSE.Injection/SysBot/SwitchCommand.cs @@ -1,86 +1,85 @@ using System.Linq; using System.Text; -namespace NHSE.Injection +namespace NHSE.Injection; + +/// +/// Encodes commands for a to be sent as a array. +/// +public static class SwitchCommand { + private static readonly Encoding Encoder = Encoding.UTF8; + private static byte[] Encode(string command, bool addrn = true) => Encoder.GetBytes(addrn ? command + "\r\n" : command); + /// - /// Encodes commands for a to be sent as a array. + /// Removes the virtual controller from the bot. Allows physical controllers to control manually. /// - public static class SwitchCommand - { - private static readonly Encoding Encoder = Encoding.UTF8; - private static byte[] Encode(string command, bool addrn = true) => Encoder.GetBytes(addrn ? command + "\r\n" : command); + /// Encoded command bytes + public static byte[] DetachController() => Encode("detachController"); - /// - /// Removes the virtual controller from the bot. Allows physical controllers to control manually. - /// - /// Encoded command bytes - public static byte[] DetachController() => Encode("detachController"); + /// + /// Presses and releases a for 50ms. + /// + /// Button to click. + /// Press & Release timing is performed by the console automatically. + /// Encoded command bytes + public static byte[] Click(SwitchButton button) => Encode($"click {button}"); - /// - /// Presses and releases a for 50ms. - /// - /// Button to click. - /// Press & Release timing is performed by the console automatically. - /// Encoded command bytes - public static byte[] Click(SwitchButton button) => Encode($"click {button}"); + /// + /// Presses and does NOT release a . + /// + /// Button to hold. + /// Encoded command bytes + public static byte[] Hold(SwitchButton button) => Encode($"press {button}"); - /// - /// Presses and does NOT release a . - /// - /// Button to hold. - /// Encoded command bytes - public static byte[] Hold(SwitchButton button) => Encode($"press {button}"); + /// + /// Releases the held . + /// + /// Button to release. + /// Encoded command bytes + public static byte[] Release(SwitchButton button) => Encode($"release {button}"); - /// - /// Releases the held . - /// - /// Button to release. - /// Encoded command bytes - public static byte[] Release(SwitchButton button) => Encode($"release {button}"); + /// + /// Sets the specified to the desired and positions. + /// + /// Encoded command bytes + public static byte[] SetStick(SwitchStick stick, int x, int y) => Encode($"setStick {stick} {x} {y}"); - /// - /// Sets the specified to the desired and positions. - /// - /// Encoded command bytes - public static byte[] SetStick(SwitchStick stick, int x, int y) => Encode($"setStick {stick} {x} {y}"); + /// + /// Resets the specified to (0,0) + /// + /// Encoded command bytes + public static byte[] ResetStick(SwitchStick stick) => SetStick(stick, 0, 0); - /// - /// Resets the specified to (0,0) - /// - /// Encoded command bytes - public static byte[] ResetStick(SwitchStick stick) => SetStick(stick, 0, 0); + /// + /// Requests the Bot to send bytes from . + /// + /// Address of the data + /// Amount of bytes + /// Encoded command bytes + public static byte[] Peek(uint offset, int count) => Encode($"peek 0x{offset:X8} {count}"); - /// - /// Requests the Bot to send bytes from . - /// - /// Address of the data - /// Amount of bytes - /// Encoded command bytes - public static byte[] Peek(uint offset, int count) => Encode($"peek 0x{offset:X8} {count}"); + /// + /// Sends the Bot to be written to . + /// + /// Address of the data + /// Data to write + /// Encoded command bytes + public static byte[] Poke(uint offset, byte[] data) => Encode($"poke 0x{offset:X8} 0x{string.Concat(data.Select(z => $"{z:X2}"))}"); - /// - /// Sends the Bot to be written to . - /// - /// Address of the data - /// Data to write - /// Encoded command bytes - public static byte[] Poke(uint offset, byte[] data) => Encode($"poke 0x{offset:X8} 0x{string.Concat(data.Select(z => $"{z:X2}"))}"); + /// + /// (Without return) Requests the Bot to send bytes from . + /// + /// Address of the data + /// Amount of bytes + /// Encoded command bytes + public static byte[] PeekRaw(uint offset, int count) => Encode($"peek 0x{offset:X8} {count}", false); - /// - /// (Without return) Requests the Bot to send bytes from . - /// - /// Address of the data - /// Amount of bytes - /// Encoded command bytes - public static byte[] PeekRaw(uint offset, int count) => Encode($"peek 0x{offset:X8} {count}", false); - - /// - /// (Without return) Sends the Bot to be written to . - /// - /// Address of the data - /// Data to write - /// Encoded command bytes - public static byte[] PokeRaw(uint offset, byte[] data) => Encode($"poke 0x{offset:X8} 0x{string.Concat(data.Select(z => $"{z:X2}"))}", false); - } + /// + /// (Without return) Sends the Bot to be written to . + /// + /// Address of the data + /// Data to write + /// Encoded command bytes + public static byte[] PokeRaw(uint offset, byte[] data) => Encode($"poke 0x{offset:X8} 0x{string.Concat(data.Select(z => $"{z:X2}"))}", false); } \ No newline at end of file diff --git a/NHSE.Injection/SysBot/SwitchStick.cs b/NHSE.Injection/SysBot/SwitchStick.cs index 34dcdf5..4c01d23 100644 --- a/NHSE.Injection/SysBot/SwitchStick.cs +++ b/NHSE.Injection/SysBot/SwitchStick.cs @@ -1,11 +1,10 @@ -namespace NHSE.Injection +namespace NHSE.Injection; + +/// +/// Controller Stick differentiation +/// +public enum SwitchStick { - /// - /// Controller Stick differentiation - /// - public enum SwitchStick - { - LEFT, - RIGHT, - } + LEFT, + RIGHT, } \ No newline at end of file diff --git a/NHSE.Injection/SysBot/SysBot.cs b/NHSE.Injection/SysBot/SysBot.cs index 216a6f8..bd9a5c7 100644 --- a/NHSE.Injection/SysBot/SysBot.cs +++ b/NHSE.Injection/SysBot/SysBot.cs @@ -1,84 +1,83 @@ using System.Net.Sockets; using System.Threading; -namespace NHSE.Injection +namespace NHSE.Injection; + +public class SysBot : IRAMReadWriter { - public class SysBot : IRAMReadWriter + public string IP = "192.168.1.65"; + public int Port = 6000; + public Socket Connection = new(SocketType.Stream, ProtocolType.Tcp); + public bool Connected { get; private set; } + + private readonly Lock _sync = new(); + + public void Connect(string ip, int port) { - public string IP = "192.168.1.65"; - public int Port = 6000; - public Socket Connection = new(SocketType.Stream, ProtocolType.Tcp); - public bool Connected { get; private set; } - - private readonly object _sync = new(); - - public void Connect(string ip, int port) + IP = ip; + Port = port; + lock (_sync) { - IP = ip; - Port = port; - lock (_sync) - { - Connection = new Socket(SocketType.Stream, ProtocolType.Tcp); - Connection.Connect(IP, Port); - Connected = true; - } - } - - public void Disconnect() - { - lock (_sync) - { - Connection.Disconnect(false); - Connected = false; - } - } - - private int ReadInternal(byte[] buffer) - { - int br = Connection.Receive(buffer, 0, 1, SocketFlags.None); - while (buffer[br - 1] != (byte)'\n') - br += Connection.Receive(buffer, br, 1, SocketFlags.None); - return br; - } - - private int SendInternal(byte[] buffer) => Connection.Send(buffer); - - public int Read(byte[] buffer) - { - lock (_sync) - return ReadInternal(buffer); - } - - public byte[] ReadBytes(uint offset, int length) - { - lock (_sync) - { - var cmd = SwitchCommand.Peek(offset, length); - SendInternal(cmd); - - // give it time to push data back - Thread.Sleep((length / 256) + 100); - var buffer = new byte[(length * 2) + 1]; - var _ = ReadInternal(buffer); - return Decoder.ConvertHexByteStringToBytes(buffer); - } - } - - public void WriteBytes(byte[] data, uint offset) - { - lock (_sync) - { - SendInternal(SwitchCommand.Poke(offset, data)); - - // give it time to push data back - Thread.Sleep((data.Length / 256) + 100); - } + Connection = new Socket(SocketType.Stream, ProtocolType.Tcp); + Connection.Connect(IP, Port); + Connected = true; } } - public enum InjectionType + public void Disconnect() { - Generic, - Pouch, + lock (_sync) + { + Connection.Disconnect(false); + Connected = false; + } + } + + private int ReadInternal(byte[] buffer) + { + int br = Connection.Receive(buffer, 0, 1, SocketFlags.None); + while (buffer[br - 1] != (byte)'\n') + br += Connection.Receive(buffer, br, 1, SocketFlags.None); + return br; + } + + private int SendInternal(byte[] buffer) => Connection.Send(buffer); + + public int Read(byte[] buffer) + { + lock (_sync) + return ReadInternal(buffer); + } + + public byte[] ReadBytes(uint offset, int length) + { + lock (_sync) + { + var cmd = SwitchCommand.Peek(offset, length); + SendInternal(cmd); + + // give it time to push data back + Thread.Sleep((length / 256) + 100); + var buffer = new byte[(length * 2) + 1]; + _ = ReadInternal(buffer); + return Decoder.ConvertHexByteStringToBytes(buffer); + } + } + + public void WriteBytes(byte[] data, uint offset) + { + lock (_sync) + { + SendInternal(SwitchCommand.Poke(offset, data)); + + // give it time to push data back + Thread.Sleep((data.Length / 256) + 100); + } } } + +public enum InjectionType +{ + Generic, + Pouch, +} \ No newline at end of file diff --git a/NHSE.Injection/SysBot/USBBot.cs b/NHSE.Injection/SysBot/USBBot.cs index af169df..fee0a6d 100644 --- a/NHSE.Injection/SysBot/USBBot.cs +++ b/NHSE.Injection/SysBot/USBBot.cs @@ -2,163 +2,161 @@ using System.Threading; using LibUsbDotNet; using LibUsbDotNet.Main; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Injection +namespace NHSE.Injection; + +public class USBBot : IRAMReadWriter { - public class USBBot : IRAMReadWriter + private UsbDevice? SwDevice; + private UsbEndpointReader? reader; + private UsbEndpointWriter? writer; + + public bool Connected { get; private set; } + + private readonly Lock _sync = new(); + + public bool Connect() { - private UsbDevice? SwDevice; - private UsbEndpointReader? reader; - private UsbEndpointWriter? writer; - - public bool Connected { get; private set; } - - private readonly object _sync = new(); - - public bool Connect() + lock (_sync) { - lock (_sync) + // Find and open the usb device. + //SwDevice = UsbDevice.OpenUsbDevice(SwFinder); + foreach (UsbRegistry ur in UsbDevice.AllDevices) { - // Find and open the usb device. - //SwDevice = UsbDevice.OpenUsbDevice(SwFinder); - foreach (UsbRegistry ur in UsbDevice.AllDevices) - { - if (ur.Vid == 1406 && ur.Pid == 12288) - SwDevice = ur.Device; - } - //SwDevice = UsbDevice.OpenUsbDevice(MyUsbFinder); - - // If the device is open and ready - if (SwDevice == null) - { - throw new Exception("Device Not Found."); - } - - if (SwDevice.IsOpen) - SwDevice.Close(); - SwDevice.Open(); - - if (SwDevice is IUsbDevice wholeUsbDevice) - { - // This is a "whole" USB device. Before it can be used, - // the desired configuration and interface must be selected. - - // Select config #1 - wholeUsbDevice.SetConfiguration(1); - - // Claim interface #0. - bool resagain = wholeUsbDevice.ClaimInterface(0); - if (!resagain) - { - wholeUsbDevice.ReleaseInterface(0); - wholeUsbDevice.ClaimInterface(0); - } - } - else - { - Disconnect(); - throw new Exception("Device is using WinUSB driver. Use libusbK and create a filter"); - } - - // open read write endpoints 1. - reader = SwDevice.OpenEndpointReader(ReadEndpointID.Ep01); - writer = SwDevice.OpenEndpointWriter(WriteEndpointID.Ep01); - - Connected = true; - return true; + if (ur.Vid == 1406 && ur.Pid == 12288) + SwDevice = ur.Device; } - } + //SwDevice = UsbDevice.OpenUsbDevice(MyUsbFinder); - public void Disconnect() - { - lock (_sync) + // If the device is open and ready + if (SwDevice == null) { - if (SwDevice != null) - { - if (SwDevice.IsOpen) - { - if (SwDevice is IUsbDevice wholeUsbDevice) - wholeUsbDevice.ReleaseInterface(0); - SwDevice.Close(); - } - } - - reader?.Dispose(); - writer?.Dispose(); - Connected = false; + throw new Exception("Device Not Found."); } - } - private int ReadInternal(byte[] buffer) - { - byte[] sizeOfReturn = new byte[4]; + if (SwDevice.IsOpen) + SwDevice.Close(); + SwDevice.Open(); - //read size, no error checking as of yet, should be the required 368 bytes - if (reader == null) - throw new Exception("USB writer is null, you may have disconnected the device during previous function"); + if (SwDevice is IUsbDevice wholeUsbDevice) + { + // This is a "whole" USB device. Before it can be used, + // the desired configuration and interface must be selected. - reader.Read(sizeOfReturn, 5000, out _); + // Select config #1 + wholeUsbDevice.SetConfiguration(1); - //read stack - reader.Read(buffer, 5000, out var lenVal); - return lenVal; - } - - private int SendInternal(byte[] buffer) - { - if (writer == null) - throw new Exception("USB writer is null, you may have disconnected the device during previous function"); - - uint pack = (uint)buffer.Length + 2; - var ec = writer.Write(BitConverter.GetBytes(pack), 2000, out _); - if (ec != ErrorCode.None) + // Claim interface #0. + bool resagain = wholeUsbDevice.ClaimInterface(0); + if (!resagain) + { + wholeUsbDevice.ReleaseInterface(0); + wholeUsbDevice.ClaimInterface(0); + } + } + else { Disconnect(); - throw new Exception(UsbDevice.LastErrorString); + throw new Exception("Device is using WinUSB driver. Use libusbK and create a filter"); } - ec = writer.Write(buffer, 2000, out var l); - if (ec != ErrorCode.None) - { - Disconnect(); - throw new Exception(UsbDevice.LastErrorString); - } - return l; - } - public int Read(byte[] buffer) - { - lock (_sync) - { - return ReadInternal(buffer); - } - } + // open read write endpoints 1. + reader = SwDevice.OpenEndpointReader(ReadEndpointID.Ep01); + writer = SwDevice.OpenEndpointWriter(WriteEndpointID.Ep01); - public byte[] ReadBytes(uint offset, int length) - { - lock (_sync) - { - var cmd = SwitchCommand.PeekRaw(offset, length); - SendInternal(cmd); - - // give it time to push data back - Thread.Sleep((length / 256) + 100); - - var buffer = new byte[length]; - var _ = ReadInternal(buffer); - //return Decoder.ConvertHexByteStringToBytes(buffer); - return buffer; - } - } - - public void WriteBytes(byte[] data, uint offset) - { - lock (_sync) - { - SendInternal(SwitchCommand.PokeRaw(offset, data)); - - // give it time to push data back - Thread.Sleep((data.Length / 256) + 100); - } + Connected = true; + return true; } } -} + + public void Disconnect() + { + lock (_sync) + { + if (SwDevice is { IsOpen: true }) + { + if (SwDevice is IUsbDevice wholeUsbDevice) + wholeUsbDevice.ReleaseInterface(0); + SwDevice.Close(); + } + + reader?.Dispose(); + writer?.Dispose(); + Connected = false; + } + } + + private int ReadInternal(byte[] buffer) + { + //read size, no error checking yet, should be the required 368 bytes + if (reader == null) + throw new Exception("USB writer is null, you may have disconnected the device during previous function"); + + var sizeOfReturn = new byte[4]; + reader.Read(sizeOfReturn, 5000, out _); + + //read stack + reader.Read(buffer, 5000, out var lenVal); + return lenVal; + } + + private int SendInternal(byte[] buffer) + { + if (writer == null) + throw new Exception("USB writer is null, you may have disconnected the device during previous function"); + + uint pack = (uint)buffer.Length + 2; + var lengthBytes = new byte[sizeof(uint)]; + WriteUInt32LittleEndian(lengthBytes, pack); + var ec = writer.Write(lengthBytes, 2000, out _); + if (ec != ErrorCode.None) + { + Disconnect(); + throw new Exception(UsbDevice.LastErrorString); + } + ec = writer.Write(buffer, 2000, out var l); + if (ec != ErrorCode.None) + { + Disconnect(); + throw new Exception(UsbDevice.LastErrorString); + } + return l; + } + + public int Read(byte[] buffer) + { + lock (_sync) + { + return ReadInternal(buffer); + } + } + + public byte[] ReadBytes(uint offset, int length) + { + lock (_sync) + { + var cmd = SwitchCommand.PeekRaw(offset, length); + SendInternal(cmd); + + // give it time to push data back + Thread.Sleep((length / 256) + 100); + + var buffer = new byte[length]; + _ = ReadInternal(buffer); + //return Decoder.ConvertHexByteStringToBytes(buffer); + return buffer; + } + } + + public void WriteBytes(byte[] data, uint offset) + { + lock (_sync) + { + SendInternal(SwitchCommand.PokeRaw(offset, data)); + + // give it time to push data back + Thread.Sleep((data.Length / 256) + 100); + } + } +} \ No newline at end of file diff --git a/NHSE.Parsing/BCSV/BCSV.cs b/NHSE.Parsing/BCSV/BCSV.cs index c241544..575efe1 100644 --- a/NHSE.Parsing/BCSV/BCSV.cs +++ b/NHSE.Parsing/BCSV/BCSV.cs @@ -3,130 +3,133 @@ using System.Linq; using System.Text; using NHSE.Parsing.Properties; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class BCSV { - public class BCSV + public static readonly BCSVEnumDictionary EnumLookup = new(Resources.specs_130.Split('\n')); + public static bool DecodeColumnNames { private get; set; } = true; + + public const int MAGIC = 0x42435356; // BCSV + + public readonly uint EntryCount; + public readonly uint EntryLength; + public readonly ushort FieldCount; + public readonly bool HasBCSVHeader; + public readonly bool Flag2; + + public readonly uint Magic; + public readonly int Unknown; + public readonly int Unknown1; + public readonly int Unknown2; + + private readonly int FieldTableStart; + public readonly IReadOnlyList FieldOffsets; + + + public readonly Memory Raw; + private Span Data => Raw.Span; + + public BCSV(Memory raw) { - public static readonly BCSVEnumDictionary EnumLookup = new(Resources.specs_130.Split('\n')); - public static bool DecodeColumnNames { private get; set; } = true; + Raw = raw; - public const int MAGIC = 0x42435356; // BCSV - - public readonly byte[] Data; - - public readonly uint EntryCount; - public readonly uint EntryLength; - public readonly ushort FieldCount; - public readonly bool HasBCSVHeader; - public readonly bool Flag2; - - public readonly uint Magic; - public readonly int Unknown; - public readonly int Unknown1; - public readonly int Unknown2; - - private readonly int FieldTableStart; - public readonly IReadOnlyList FieldOffsets; - - public BCSV(byte[] data) + var span = Data; + EntryCount = ReadUInt32LittleEndian(span); + EntryLength = ReadUInt32LittleEndian(span[0x4..]); + FieldCount = ReadUInt16LittleEndian(span[0x8..]); + HasBCSVHeader = span[0xA] == 1; + Flag2 = span[0xB] == 1; + if (HasBCSVHeader) { - Data = data; - - EntryCount = BitConverter.ToUInt32(data, 0x0); - EntryLength = BitConverter.ToUInt32(data, 0x4); - FieldCount = BitConverter.ToUInt16(data, 0x8); - HasBCSVHeader = data[0xA] == 1; - Flag2 = data[0xB] == 1; - if (HasBCSVHeader) - { - Magic = BitConverter.ToUInt32(data, 0xC); - if (Magic != MAGIC) - throw new ArgumentException(nameof(Magic)); - Unknown = BitConverter.ToInt32(data, 0x10); - Unknown1 = BitConverter.ToInt32(data, 0x14); - Unknown2 = BitConverter.ToInt32(data, 0x18); - FieldTableStart = 0x1C; - } - else - { - FieldTableStart = 0x0C; - } - - var fields = new BCSVFieldParam[FieldCount]; - for (int i = 0; i < fields.Length; i++) - { - var ofs = FieldTableStart + (i * BCSVFieldParam.SIZE); - var ident = BitConverter.ToUInt32(data, ofs); - var fo = BitConverter.ToInt32(data, ofs + 4); - - fields[i] = new BCSVFieldParam(ident, fo, i); - } - - FieldOffsets = fields; + Magic = ReadUInt32LittleEndian(span[0xC..]); + if (Magic != MAGIC) + throw new ArgumentException(nameof(Magic)); + Unknown = ReadInt32LittleEndian(span[0x10..]); + Unknown1 = ReadInt32LittleEndian(span[0x14..]); + Unknown2 = ReadInt32LittleEndian(span[0x18..]); + FieldTableStart = 0x1C; + } + else + { + FieldTableStart = 0x0C; } - private int GetFirstEntryOffset() => FieldTableStart + (FieldCount * BCSVFieldParam.SIZE); - private int GetEntryOffset(int start, int entry) => start + (entry * (int)EntryLength); - - private string ReadFieldUnknownType(in int offset, in int fieldIndex) + var fields = new BCSVFieldParam[FieldCount]; + for (int i = 0; i < fields.Length; i++) { - var length = GetFieldLength(fieldIndex); - return length switch - { - 1 => Data[offset].ToString(), - 2 => BitConverter.ToInt16(Data, offset).ToString(), - 4 => EnumLookup[BitConverter.ToUInt32(Data, offset)], - 5 => $"0x{FiveByteLong(offset):X10}", - 8 => $"0x{BitConverter.ToUInt64(Data, offset):X16}", - _ => Encoding.UTF8.GetString(Data, offset, length), - }; + var ofs = FieldTableStart + (i * BCSVFieldParam.SIZE); + var ident = ReadUInt32LittleEndian(span[ofs..]); + var fo = ReadInt32LittleEndian(span[(ofs + 4)..]); + + fields[i] = new BCSVFieldParam(ident, fo, i); } - private ulong FiveByteLong(in int offset) + FieldOffsets = fields; + } + + private int GetFirstEntryOffset() => FieldTableStart + (FieldCount * BCSVFieldParam.SIZE); + private int GetEntryOffset(int start, int entry) => start + (entry * (int)EntryLength); + + private string ReadFieldUnknownType(in int offset, in int fieldIndex) + { + var length = GetFieldLength(fieldIndex); + return length switch { - var tmpBytes = new byte[8]; - Array.Copy(Data, offset, tmpBytes, 0, 5); - return BitConverter.ToUInt64(tmpBytes, 0); - } + 1 => Data[offset].ToString(), + 2 => ReadInt16LittleEndian(Data[offset..]).ToString(), + 4 => EnumLookup[ReadUInt32LittleEndian(Data[offset..])], + 5 => $"0x{FiveByteLong(offset):X10}", + 8 => $"0x{ReadUInt64LittleEndian(Data[offset..]):X16}", + _ => Encoding.UTF8.GetString(Data.Slice(offset, length)), + }; + } - private int GetFieldLength(in int i) + private ulong FiveByteLong(in int offset) + { + Span tmpBytes = stackalloc byte[8]; + Data.Slice(offset, 5).CopyTo(tmpBytes); + return ReadUInt64LittleEndian(tmpBytes); + } + + private int GetFieldLength(in int i) + { + var next = (i + 1 == FieldCount) ? (int)(EntryLength) : FieldOffsets[i + 1].Offset; + var ofs = FieldOffsets[i].Offset; + return next - ofs; + } + + public string[] ReadCSV(string delim = "\t") + { + var result = new string[EntryCount + 1]; + + if (DecodeColumnNames) + result[0] = string.Join(delim, FieldOffsets.Select(z => EnumLookup[z.ColumnKey])); + else + result[0] = string.Join(delim, FieldOffsets.Select(z => $"0x{z.ColumnKey:X8}")); + + var start = GetFirstEntryOffset(); + for (int entry = 0; entry < EntryCount; entry++) { - var next = (i + 1 == FieldCount) ? (int)(EntryLength) : FieldOffsets[i + 1].Offset; - var ofs = FieldOffsets[i].Offset; - return next - ofs; - } - - public string[] ReadCSV(string delim = "\t") - { - var result = new string[EntryCount + 1]; - - if (DecodeColumnNames) - result[0] = string.Join(delim, FieldOffsets.Select(z => EnumLookup[z.ColumnKey])); - else - result[0] = string.Join(delim, FieldOffsets.Select(z => $"0x{z.ColumnKey:X8}")); - - var start = GetFirstEntryOffset(); - for (int entry = 0; entry < EntryCount; entry++) - { - var ofs = GetEntryOffset(start, entry); - string[] fields = new string[FieldCount]; - for (int f = 0; f < fields.Length; f++) - { - var fo = ofs + FieldOffsets[f].Offset; - fields[f] = ReadFieldUnknownType(fo, f); - } - result[entry + 1] = string.Join(delim, fields); - } - - return result; - } - - public string ReadValue(int entry, BCSVFieldParam f) - { - var start = GetFirstEntryOffset(); var ofs = GetEntryOffset(start, entry); - return ReadFieldUnknownType(ofs + f.Offset, f.Index); + var fields = new string[FieldCount]; + for (int f = 0; f < fields.Length; f++) + { + var fo = ofs + FieldOffsets[f].Offset; + fields[f] = ReadFieldUnknownType(fo, f); + } + result[entry + 1] = string.Join(delim, fields); } + + return result; + } + + public string ReadValue(int entry, BCSVFieldParam f) + { + var start = GetFirstEntryOffset(); + var ofs = GetEntryOffset(start, entry); + return ReadFieldUnknownType(ofs + f.Offset, f.Index); } } \ No newline at end of file diff --git a/NHSE.Parsing/BCSV/BCSVConverter.cs b/NHSE.Parsing/BCSV/BCSVConverter.cs index f0deabd..728553f 100644 --- a/NHSE.Parsing/BCSV/BCSVConverter.cs +++ b/NHSE.Parsing/BCSV/BCSVConverter.cs @@ -3,41 +3,40 @@ using System.IO; using System.Linq; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public static class BCSVConverter { - public static class BCSVConverter + public static IReadOnlyDictionary GetFieldDictionary(this BCSV csv) { - public static IReadOnlyDictionary GetFieldDictionary(this BCSV csv) - { - return csv.FieldOffsets.ToDictionary(z => z.ColumnKey, z => z); - } + return csv.FieldOffsets.ToDictionary(z => z.ColumnKey, z => z); + } - public static void DumpAll(string path, string dest, string delim = "\t") + public static void DumpAll(string path, string dest, string delim = "\t") + { + var files = Directory.EnumerateFiles(path, "*.bcsv"); + Directory.CreateDirectory(dest); + foreach (var f in files) { - var files = Directory.EnumerateFiles(path, "*.bcsv"); - Directory.CreateDirectory(dest); - foreach (var f in files) - { - var fn = Path.GetFileNameWithoutExtension(f); - var df = Path.Combine(dest, $"{fn}.csv"); - Dump(f, df, delim); - } - } - - public static void Dump(string path, string dest, string delim = "\t") - { - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - var result = bcsv.ReadCSV(delim); - File.WriteAllLines(dest, result); - Console.WriteLine($"Dumped to CSV: {path}"); - } - - public static BCSV GetBCSV(string pathBCSV, string fn) - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - return new BCSV(data); + var fn = Path.GetFileNameWithoutExtension(f); + var df = Path.Combine(dest, $"{fn}.csv"); + Dump(f, df, delim); } } -} + + public static void Dump(string path, string dest, string delim = "\t") + { + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + var result = bcsv.ReadCSV(delim); + File.WriteAllLines(dest, result); + Console.WriteLine($"Dumped to CSV: {path}"); + } + + public static BCSV GetBCSV(string pathBCSV, string fn) + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + return new BCSV(data); + } +} \ No newline at end of file diff --git a/NHSE.Parsing/BCSV/BCSVEnumDictionary.cs b/NHSE.Parsing/BCSV/BCSVEnumDictionary.cs index ed568a1..abceb75 100644 --- a/NHSE.Parsing/BCSV/BCSVEnumDictionary.cs +++ b/NHSE.Parsing/BCSV/BCSVEnumDictionary.cs @@ -3,72 +3,71 @@ using System.Linq; using NHSE.Core; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class BCSVEnumDictionary { - public class BCSVEnumDictionary + private readonly Dictionary Lookup = []; + + public BCSVEnumDictionary(IEnumerable lines) { - private readonly Dictionary Lookup = new(); - - public BCSVEnumDictionary(IEnumerable lines) + foreach (var line in lines) { - foreach (var line in lines) - { - var trim = line.Trim(); - if (trim.StartsWith("(")) - AddEnumName(trim); - if (trim.Contains(" = ")) - AddColumnName(trim); - } + var trim = line.Trim(); + if (trim.StartsWith('(')) + AddEnumName(trim); + if (trim.Contains(" = ")) + AddColumnName(trim); } - - private void AddColumnName(string trim) - { - if (!trim.EndsWith(")")) - return; - if (trim.StartsWith("_")) - return; - - var text = trim.Split(new [] {" = "}, 0); - - var name = text[0]; - var value = text[1].Substring(text[1].IndexOf('(') + 1); - value = value.Substring(2, value.Length - 3); - var hex = StringUtil.GetHexValue(value); - - if (Lookup.TryGetValue(hex, out var exist)) - { - if (exist == name) - return; - Console.WriteLine($"Duplicate KVP: {exist} -- old, {name} -- new."); - return; - } - - Lookup.Add(hex, name); - } - - private void AddEnumName(string trim) - { - if (!trim.EndsWith("),")) - return; - - var text = trim.Split('\'')[1]; - if (text.Length == 0) - return; - - var hash = CRC32.Compute(text); - if (Lookup.TryGetValue(hash, out var exist)) - { - if (exist == text) - return; - Console.WriteLine($"Duplicate KVP: {exist} -- old, {text} -- new."); - return; - } - - Lookup.Add(hash, text); - } - - public IEnumerable Dump() => Lookup.Select(z => $"{z.Key:X8}\t{z.Value}"); - - public string this[uint key] => Lookup.TryGetValue(key, out var val) ? val : $"0x{key:X8}"; } -} + + private void AddColumnName(string trim) + { + if (!trim.EndsWith(')')) + return; + if (trim.StartsWith('_')) + return; + + var text = trim.Split(" = "); + + var name = text[0]; + var value = text[1][(text[1].IndexOf('(') + 1)..]; + var slice = value.AsSpan(2, value.Length - 3); + var hex = StringUtil.GetHexValue(slice); + + if (Lookup.TryGetValue(hex, out var exist)) + { + if (exist == name) + return; + Console.WriteLine($"Duplicate KVP: {exist} -- old, {name} -- new."); + return; + } + + Lookup.Add(hex, name); + } + + private void AddEnumName(string trim) + { + if (!trim.EndsWith("),")) + return; + + var text = trim.Split('\'')[1]; + if (text.Length == 0) + return; + + var hash = CRC32.Compute(text); + if (Lookup.TryGetValue(hash, out var exist)) + { + if (exist == text) + return; + Console.WriteLine($"Duplicate KVP: {exist} -- old, {text} -- new."); + return; + } + + Lookup.Add(hash, text); + } + + public IEnumerable Dump() => Lookup.Select(z => $"{z.Key:X8}\t{z.Value}"); + + public string this[uint key] => Lookup.TryGetValue(key, out var val) ? val : $"0x{key:X8}"; +} \ No newline at end of file diff --git a/NHSE.Parsing/BCSV/BCSVFieldParam.cs b/NHSE.Parsing/BCSV/BCSVFieldParam.cs index 9efebbb..d030116 100644 --- a/NHSE.Parsing/BCSV/BCSVFieldParam.cs +++ b/NHSE.Parsing/BCSV/BCSVFieldParam.cs @@ -1,17 +1,16 @@ -namespace NHSE.Parsing -{ - public class BCSVFieldParam - { - public const int SIZE = 8; - public readonly uint ColumnKey; - public readonly int Offset; - public readonly int Index; +namespace NHSE.Parsing; - public BCSVFieldParam(uint key, int offset, int index) - { - ColumnKey = key; - Offset = offset; - Index = index; - } +public class BCSVFieldParam +{ + public const int SIZE = 8; + public readonly uint ColumnKey; + public readonly int Offset; + public readonly int Index; + + public BCSVFieldParam(uint key, int offset, int index) + { + ColumnKey = key; + Offset = offset; + Index = index; } } \ No newline at end of file diff --git a/NHSE.Parsing/BCSV/CRC32.cs b/NHSE.Parsing/BCSV/CRC32.cs index 20326bc..6add299 100644 --- a/NHSE.Parsing/BCSV/CRC32.cs +++ b/NHSE.Parsing/BCSV/CRC32.cs @@ -1,62 +1,62 @@ -using System.Text; +using System; +using System.Text; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public static class CRC32 { - public static class CRC32 + private const uint Seed = 0xFFFFFFFF; + + #region Table + private static ReadOnlySpan Table => + [ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, + 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, + 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, + 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, + 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, + 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, + 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, + 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, + 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, + 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + ]; + #endregion + + public static uint Compute(string ascii) { - private const uint Seed = 0xFFFFFFFF; - - #region Table - private static readonly uint[] Table = - { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, - 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, - 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, - 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, - 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, - 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, - 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, - 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, - 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, - 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, - 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, - 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, - 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, - 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, - 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, - 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, - 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, - 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, - 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, - 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, - 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, - 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D - }; - #endregion - - public static uint Compute(string ascii) - { - var data = Encoding.ASCII.GetBytes(ascii); - return Compute(data); - } - - public static uint Compute(byte[] data) => Compute(data, 0, data.Length); - - public static uint Compute(byte[] data, int offset, int length) - { - uint crc = 0; - crc ^= Seed; - while (--length >= 0) - crc = Table[(crc ^ data[offset++]) & 0xFF] ^ (crc >> 8); - crc ^= Seed; - return crc; - } + var data = Encoding.ASCII.GetBytes(ascii); + return Compute(data); } -} + + public static uint Compute(ReadOnlySpan data) => Compute(data, 0, data.Length); + + public static uint Compute(ReadOnlySpan data, int offset, int length) + { + uint crc = 0; + crc ^= Seed; + while (--length >= 0) + crc = Table[(byte)((crc ^ data[offset++]) & 0xFF)] ^ (crc >> 8); + crc ^= Seed; + return crc; + } +} \ No newline at end of file diff --git a/NHSE.Parsing/GameBCSVDumper.cs b/NHSE.Parsing/GameBCSVDumper.cs index 7156ddf..bee54c7 100644 --- a/NHSE.Parsing/GameBCSVDumper.cs +++ b/NHSE.Parsing/GameBCSVDumper.cs @@ -6,850 +6,848 @@ using System.Linq; using NHSE.Core; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +/// +/// Converts files to other formats digestible by the program. +/// +public static class GameBCSVDumper { /// - /// Converts files to other formats digestible by the program. + /// Dumps everything the program uses to the provided , using the provided . /// - public static class GameBCSVDumper + /// Source of files. + /// Destination folder where the dumps will be saved. + /// Convert all files to CSV for easy viewing. + /// Change BCSV magic numbers to string if available + /// Delimiter when exporting the files + public static void UpdateDumps(string pathBCSV, string dest, bool csv = false, bool remapBCSV = true, string delim = "\t") { - /// - /// Dumps everything the program uses to the provided , using the provided . - /// - /// Source of files. - /// Destination folder where the dumps will be saved. - /// Convert all files to CSV for easy viewing. - /// Change BCSV magic numbers to string if available - /// Delimiter when exporting the files - public static void UpdateDumps(string pathBCSV, string dest, bool csv = false, bool remapBCSV = true, string delim = "\t") - { - ExtractInfo(pathBCSV, dest); + ExtractInfo(pathBCSV, dest); - if (csv) - UpdateCSV(pathBCSV, Path.Combine(dest, "csv"), remapBCSV, delim); + if (csv) + UpdateCSV(pathBCSV, Path.Combine(dest, "csv"), remapBCSV, delim); + } + + private static void ExtractInfo(string pathBCSV, string dest) + { + var itemNames = GameInfo.Strings.itemlist; + + void DumpS(string fn, IEnumerable lines, string dir = "text") + { + Directory.CreateDirectory(Path.Combine(dest, dir)); + File.WriteAllLines(Path.Combine(dest, dir, fn), lines); + Console.WriteLine($"Created {fn}"); } - private static void ExtractInfo(string pathBCSV, string dest) + void DumpB(string fn, byte[] bytes, string dir = "bin") { - var itemNames = GameInfo.Strings.itemlist; + Directory.CreateDirectory(Path.Combine(dest, dir)); + File.WriteAllBytes(Path.Combine(dest, dir, fn), bytes); + Console.WriteLine($"Created {fn}"); + } - void DumpS(string fn, IEnumerable lines, string dir = "text") + void DumpU(string fn, ushort[] ushorts, string dir = "bin") + { + Directory.CreateDirectory(Path.Combine(dest, dir)); + byte[] bytes = new byte[ushorts.Length * 2]; + Buffer.BlockCopy(ushorts, 0, bytes, 0, ushorts.Length * 2); + File.WriteAllBytes(Path.Combine(dest, dir, fn), bytes); + Console.WriteLine($"Created {fn}"); + } + + void DumpD(string fn, Dictionary dict, string dir = "text") where T : notnull + { + Directory.CreateDirectory(Path.Combine(dest, dir)); + var lines = dict.Select(z => $"{{{z.Key}, {z.Value:00000}}},"); + File.WriteAllLines(Path.Combine(dest, dir, fn), lines); + Console.WriteLine($"Created {fn}"); + } + + DumpS("bcsv_map.txt", BCSV.EnumLookup.Dump()); + DumpS("lifeSupportAchievement.txt", GetLifeSupportAchievementList(pathBCSV)); + DumpS("recipeDictionary.txt", GetRecipeList(pathBCSV)); + DumpS("outsideAcres.txt", GetAcreNames(pathBCSV)); + + DumpS("fish.txt", GetFishList(pathBCSV, itemNames)); + DumpS("dive.txt", GetDiveList(pathBCSV, itemNames)); + DumpS("bugs.txt", GetInsectList(pathBCSV, itemNames)); + DumpS("fossils.txt", GetFossilList(pathBCSV, itemNames)); + DumpS("eventFlagPlayer.txt", GetEventFlagNames(pathBCSV)); + DumpS("eventFlagHouse.txt", GetEventFlagHouse(pathBCSV)); + DumpS("eventFlagVillager.txt", GetVillagerEventFlagNames(pathBCSV)); + DumpS("eventFlagVillagerMemoryPlayer.txt", GetVillagerEventFlagNamesMemoryPlayer(pathBCSV)); + DumpS("eventFlagLand.txt", GetLandEventFlagNames(pathBCSV)); + + DumpS("ItemKind.txt", GetPossibleEnum(pathBCSV, "ItemParam.bcsv", 0xFC275E86)); + DumpS("ItemSize.txt", GetPossibleEnum(pathBCSV, "ItemParam.bcsv", 0xE06FB090)); + DumpS("ItemMenuIcon.txt", GetPossibleEnum(pathBCSV, "ItemParam.bcsv", 0x348D7B06)); + DumpS("PlantKind.txt", GetPossibleEnum(pathBCSV, "FgMainParam.bcsv", 0x48EF0398)); + DumpS("TerrainKind.txt", GetNumberedEnumValues(pathBCSV, "FieldLandMakingUnitModelParam.bcsv", 0x39B5A93D, 0x54706054)); + DumpS("BridgeKind.txt", GetNumberedEnumValues(pathBCSV, "StructureBridgeParam.bcsv", 0x39B5A93D, 0x54706054)); + DumpS("BridgeMaterial.txt", GetNumberedEnumValues(pathBCSV, "StructureBridgeTypeParam.bcsv", 0x68CF5938, 0x54706054)); + DumpS("SlopeKind.txt", GetNumberedEnumValues(pathBCSV, "StructureSlopeParam.bcsv", 0x39B5A93D, 0x54706054)); + DumpS("RoofKind.txt", GetNumberedEnumValues(pathBCSV, "StructureHouseRoofParam.bcsv", 0x39B5A93D, 0x54706054)); + DumpS("DoorKind.txt", GetNumberedEnumValues(pathBCSV, "StructureHouseDoorParam.bcsv", 0x39B5A93D, 0x54706054)); + DumpS("WallKind.txt", GetNumberedEnumValues(pathBCSV, "StructureHouseWallParam.bcsv", 0x39B5A93D, 0x54706054)); + + DumpD("ItemStack.txt", GetItemStackDict(pathBCSV)); + + DumpB("item_kind.bin", GetItemKindArray(pathBCSV)); + DumpB("item_size.bin", GetItemSizeArray(pathBCSV)); + DumpU("item_menuicon.bin", GetItemMenuIconArray(pathBCSV)); + DumpS("plants.txt", GetPlantedNames(pathBCSV)); + DumpS("item_size_dictionary.txt", GetItemSizeDictionary(pathBCSV)); + DumpS("item_remake.txt", GetItemRemakeDictionary(pathBCSV)); + DumpS("itemRemakeInfo.txt", GetItemRemakeColors(pathBCSV)); + } + + public static void UpdateCSV(string pathBCSV, string dest, bool remapColumns = false, string delim = "\t") + { + BCSV.DecodeColumnNames = remapColumns; + Directory.CreateDirectory(dest); + BCSVConverter.DumpAll(pathBCSV, dest, delim); + } + + private static HashSet GetPossibleEnumValues(string pathBCSV, string fn, uint key) + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + + var dict = bcsv.GetFieldDictionary(); + var fType = dict[key]; + + var types = new HashSet(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); + types.Add(type); + } + + return types; + } + + private static List GetNumberedEnumValues(string pathBCSV, string fn, uint keyName, uint keyValue) + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + + var dict = bcsv.GetFieldDictionary(); + var fType = dict[keyName]; + var fitemID = dict[keyValue]; + + var types = new List(); + var set = new Dictionary(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var iid = bcsv.ReadValue(i, fitemID); + var ival = ushort.Parse(iid); + var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); + if (set.TryGetValue(type, out var count)) { - Directory.CreateDirectory(Path.Combine(dest, dir)); - File.WriteAllLines(Path.Combine(dest, dir, fn), lines); - Console.WriteLine($"Created {fn}"); + count++; + set[type] = count; + type += $"_{count}"; + } + else + { + set.Add(type, 1); } - void DumpB(string fn, byte[] bytes, string dir = "bin") + types.Add($"{type} = 0x{ival:X2},"); + } + + return types; + } + + private static IEnumerable GetPossibleEnum(string pathBCSV, string fn, uint key) + { + var kinds = GetPossibleEnumValues(pathBCSV, fn, key); + var ordered = kinds.Order(); + return ordered.Select(z => $"{z},"); + } + + public static byte[] GetItemKindArray(string pathBCSV, string fn = "ItemParam.bcsv") + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + + var dict = bcsv.GetFieldDictionary(); + var fType = dict[0xFC275E86]; + var fID = dict[0x54706054]; + + var types = new Dictionary(); + ushort max = 0; + for (int i = 0; i < bcsv.EntryCount; i++) + { + var id = bcsv.ReadValue(i, fID); + var ival = ushort.Parse(id); + var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); + + if (!Enum.TryParse(type, out var k)) + throw new InvalidEnumArgumentException($"{type} is not a known enum value @ index {i}. Update the enum index first."); + types.Add(ival, k); + + if (ival > max) + max = ival; + } + + byte[] result = new byte[max + 1]; + foreach (var kvp in types) + result[kvp.Key] = (byte) kvp.Value; + + return result; + } + + public static byte[] GetItemSizeArray(string pathBCSV, string fn = "ItemParam.bcsv") + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + + var dict = bcsv.GetFieldDictionary(); + var fType = dict[0xE06FB090]; + var fID = dict[0x54706054]; + + var types = new Dictionary(); + ushort max = 0; + for (int i = 0; i < bcsv.EntryCount; i++) + { + var id = bcsv.ReadValue(i, fID); + var ival = ushort.Parse(id); + var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); + type = ItemSizeExtensions.EnumPrefix + type; // can't start with numbers + + if (!Enum.TryParse(type, out var k)) + throw new InvalidEnumArgumentException($"{type} is not a known enum value @ index {i}. Update the enum index first."); + types.Add(ival, k); + + if (ival > max) + max = ival; + } + + byte[] result = new byte[max + 1]; + foreach (var kvp in types) + result[kvp.Key] = (byte)kvp.Value; + + return result; + } + + public static Dictionary GetItemStackDict(string pathBCSV, string fn = "ItemKind.bcsv") + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + + var dict = bcsv.GetFieldDictionary(); + var fStack = dict[0x4C9BA961]; // MultiHoldMaxNum + var fKind = dict[0x87BF00E8]; // Label + + // clothing is split out more granularly in ItemKind and would cause errors + // since it's not likely to ever be stackable, we can skip + // none-type can be skipped and doesn't exist in ItemKind either + List skipLabels = + [ + "TopsDefault", + "Tops", + "OnePiece", + "MarineSuit", + "BottomsDefault", + "Bottoms", + "Shoes", + "None" + ]; + + var result = new Dictionary(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var stack = bcsv.ReadValue(i, fStack); + switch (stack) { - Directory.CreateDirectory(Path.Combine(dest, dir)); - File.WriteAllBytes(Path.Combine(dest, dir, fn), bytes); - Console.WriteLine($"Created {fn}"); + case "-1": // for some reason turnips have a stack value of -1, should be 10... + stack = "10"; + break; + case "0": // the game stores items that cannot be stacked as 0, so technically they stack to 1 + stack = "1"; + break; } - void DumpU(string fn, ushort[] ushorts, string dir = "bin") + var stackval = ushort.Parse(stack); + var kind = bcsv.ReadValue(i, fKind).TrimEnd('\0'); + if (skipLabels.Contains(kind)) + continue; + + kind = "Kind_" + kind; + if (!Enum.TryParse(kind, out var k)) + throw new InvalidEnumArgumentException($"{kind} is not a known enum value @ index {i}. Update the enum index first."); + result.Add(k, stackval); + } + + return result; + } + + public static ushort[] GetItemMenuIconArray(string pathBCSV, string fn = "ItemParam.bcsv") + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + + var dict = bcsv.GetFieldDictionary(); + var fType = dict[0x348D7B06]; + var fID = dict[0x54706054]; + + var types = new Dictionary(); + ushort max = 0; + for (int i = 0; i < bcsv.EntryCount; i++) + { + var id = bcsv.ReadValue(i, fID); + var ival = ushort.Parse(id); + var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); + + if (type.StartsWith("0x")) + type = $"_{type}"; // enum name can't start with number + + if (!Enum.TryParse(type, out var k)) + throw new InvalidEnumArgumentException($"{type} is not a known enum value @ index {i}. Update the {nameof(ItemMenuIconType)} enum index first."); + types.Add(ival, k); + + if (ival > max) + max = ival; + } + + ushort[] result = new ushort[max + 1]; + foreach (var kvp in types) + result[kvp.Key] = (ushort)kvp.Value; + + return result; + } + + public static string[] GetItemSizeDictionary(string pathBCSV, string fn = "ItemSize.bcsv") + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + + var dict = bcsv.GetFieldDictionary(); + + var fw = dict[0x16B8F524]; + var fh = dict[0xBCB13DAF]; + var fs = dict[0x87BF00E8]; + var fc = dict[0x977ADFCE]; + + var result = new string[bcsv.EntryCount]; + + const string prefix = nameof(ItemSizeType) + "." + ItemSizeExtensions.EnumPrefix; + for (int i = 0; i < bcsv.EntryCount; i++) + { + var w = bcsv.ReadValue(i, fw).TrimEnd('\0'); + var h = bcsv.ReadValue(i, fh).TrimEnd('\0'); + var s = bcsv.ReadValue(i, fs).TrimEnd('\0'); + var c = bcsv.ReadValue(i, fc).TrimEnd('\0'); + + result[i] = $"{{{prefix}{s,-12}, new ItemSize({w,2}, {h,2})}}, // {c}"; + } + + return result; + } + + public static List GetRecipeList(string pathBCSV, string fn = "RecipeCraftParam.bcsv") + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + + var dict = bcsv.GetFieldDictionary(); + var frecipe = dict[0x54706054]; + var fitemID = dict[0x89A3482C]; + + var items = GameInfo.Strings.itemlist; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var iid = bcsv.ReadValue(i, fitemID); + var ival = ushort.Parse(iid); + + var rid = bcsv.ReadValue(i, frecipe); + var rval = ushort.Parse(rid); + + var kvp = $"{{0x{rval:X3}, {ival:00000}}}, // {items[ival]}"; + result.Add(kvp); + } + + result.Sort(); + return result; + } + + public static List GetLifeSupportAchievementList(string pathBCSV, string fn = "EventFlagsLifeSupportAchievementParam.bcsv") + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + + var dict = bcsv.GetFieldDictionary(); + var findex = dict[0x54706054]; + var fname = dict[0x45F320F2]; + var fcomment = dict[0x85CF1615]; + var fLand = dict[0x3FE43170]; + var fPlayer = dict[0x4171A41D]; + + var fmaxLevel = dict[0x1BE772F0]; + var fThreshold1 = dict[0xCE0933FC]; + var fThreshold2 = dict[0x89A9492C]; + var fThreshold3 = dict[0xB4C9609C]; + var fThreshold4 = dict[0x06E9BC8C]; + var fThreshold5 = dict[0x3B89953C]; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + int readHex(BCSVFieldParam p) => int.Parse(bcsv.ReadValue(i, p)[2..], NumberStyles.HexNumber); + + var iid = bcsv.ReadValue(i, findex); + var index = ushort.Parse(iid); + + var land = readHex(fLand); + var player = readHex(fPlayer); + + var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); + var paddedName = $"\"{name}\"".PadRight(30, ' '); + + var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); + + var tmp = bcsv.ReadValue(i, fmaxLevel); + var max = ushort.Parse(tmp); + var t1 = readHex(fThreshold1); + var t2 = readHex(fThreshold2); + var t3 = readHex(fThreshold3); + var t4 = readHex(fThreshold4); + var t5 = readHex(fThreshold5); + + var values = $"{max}, {t1:0000}, {t2:0000}, {t3:0000}, {t4:0000}, {t5:0000}"; + + var v = $"new({index:000}, {values}, {land,3}, {player,3}, {paddedName})"; + var kvp = $"{{0x{index:X2}, {v}}}, // {comment}"; + result.Add(kvp); + } + + result.Sort(); + return result; + } + + public static IEnumerable GetInsectList(string pathBCSV, string fn = "InsectStatusParam.bcsv") + { + return GetItemList(pathBCSV, fn, 0x20CB67BC); + } + + public static IEnumerable GetFossilList(string pathBCSV, string fn = "MuseumFossilDonateInfo.bcsv") + { + return GetItemList(pathBCSV, fn, 0xB76B7D37); + } + + public static IEnumerable GetFishList(string pathBCSV, string fn = "FishStatusParam.bcsv") + { + return GetItemList(pathBCSV, fn, 0x20CB67BC); + } + + public static IEnumerable GetDiveList(string pathBCSV, string fn = "SeafoodStatusParam.bcsv") + { + return GetItemList(pathBCSV, fn, 0x20CB67BC); + } + + public static IEnumerable GetInsectList(string pathBCSV, IReadOnlyList items, string fn = "InsectStatusParam.bcsv") + { + var insects = GetInsectList(pathBCSV, fn); + return insects.Select(z => $"{z:00000}, // {items[z]}"); + } + + public static IEnumerable GetFishList(string pathBCSV, IReadOnlyList items, string fn = "FishStatusParam.bcsv") + { + var insects = GetFishList(pathBCSV, fn); + return insects.Select(z => $"{z:00000}, // {items[z]}"); + } + + public static IEnumerable GetDiveList(string pathBCSV, IReadOnlyList items, string fn = "SeafoodStatusParam.bcsv") + { + var insects = GetDiveList(pathBCSV, fn); + return insects.Select(z => $"{z:00000}, // {items[z]}"); + } + + public static IEnumerable GetFossilList(string pathBCSV, IReadOnlyList items, string fn = "MuseumFossilDonateInfo.bcsv") + { + var fossils = GetFossilList(pathBCSV, fn); + return fossils.Select(z => $"{z:00000}, // {items[z]}"); + } + + private static List GetItemList(string pathBCSV, string fn, uint keyItemIDColumn) + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + var dict = bcsv.GetFieldDictionary(); + var findex = dict[keyItemIDColumn]; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var iid = bcsv.ReadValue(i, findex); + var ival = ushort.Parse(iid); + result.Add(ival); + } + + result.Sort(); + return result; + } + + private static List GetAcreNames(string pathBCSV, string fn = "FieldOutsideParts.bcsv") + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + var dict = bcsv.GetFieldDictionary(); + var findex = dict[0x54706054]; + var fname = dict[0x39B5A93D]; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var iid = bcsv.ReadValue(i, findex); + var ival = ushort.Parse(iid); + + var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); + + var kvp = $"{{0x{ival:X2}, \"{name}\"}}, // {ival}"; + result.Add(kvp); + } + + result.Sort(); + return result; + } + + private static List GetPlantedNames(string pathBCSV, string fn = "FgMainParam.bcsv") + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + var dict = bcsv.GetFieldDictionary(); + var fType = dict[0x48EF0398]; + var fname = dict[0x87BF00E8]; + var findex = dict[0x54706054]; + var fcomment = dict[0x3F45F2BF]; + + var fdig = dict[0xF4678F13]; + var fpic = dict[0xB7A46956]; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var iid = bcsv.ReadValue(i, findex); + var ival = (ushort)short.Parse(iid); + + var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); + var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); + var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); + + var did = bcsv.ReadValue(i, fdig); + var dval = (ushort)short.Parse(did); + + var pid = bcsv.ReadValue(i, fpic); + var pval = (ushort)short.Parse(pid); + + if (!Enum.TryParse(type, out var k)) + throw new InvalidEnumArgumentException($"{type} is not a known enum value @ index {i}. Update the enum index first."); + + var strname = $"\"{name}\""; + var v = $"new {nameof(FieldItemDefinition)}({ival,-5}, {dval,-5}, {pval,-5}, {strname,-24}, {nameof(FieldItemKind)}.{k,-20})"; + var kvp = $"{{0x{ival:X}, {v}}}, // {comment}"; + result.Add(kvp); + } + + result.Sort(); + return result; + } + + private static List GetEventFlagNames(string pathBCSV, string fn = "EventFlagsPlayerParam.bcsv") + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + var dict = bcsv.GetFieldDictionary(); + var fv1 = dict[0x4C24F1CF]; + var fv2 = dict[0x344B17D7]; + var fname = dict[0x45F320F2]; + var findex = dict[0x54706054]; + var fcomment = dict[0x85CF1615]; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var iv1 = bcsv.ReadValue(i, fv1)[2..]; + var iv1a = short.Parse(iv1, NumberStyles.HexNumber); + + var iv2 = bcsv.ReadValue(i, fv2)[2..]; + var iv2a = short.Parse(iv2, NumberStyles.HexNumber); + + var iid = bcsv.ReadValue(i, findex); + var ival = (ushort)short.Parse(iid); + + var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); + var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); + + var paddedName = $"\"{name}\"".PadRight(45, ' '); + var v = $"new {nameof(EventFlagPlayer)}({iv1a,-2}, {iv2a,-4}, {ival:0000}, {paddedName})"; + var kvp = $"{{0x{ival:X3}, {v}}}, // {comment}"; + result.Add(kvp); + } + + result.Sort(); + return result; + } + + private static List GetEventFlagHouse(string pathBCSV, string fn = "EventFlagsHouseParam.bcsv") + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + var dict = bcsv.GetFieldDictionary(); + var findex = dict[0x54706054]; + + var fdefault = dict[0x4C24F1CF]; + var fmax = dict[0x344B17D7]; + var fname = dict[0x45F320F2]; + var fcomment = dict[0x85CF1615]; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var ivd = bcsv.ReadValue(i, fdefault)[2..]; + var vd = short.Parse(ivd, NumberStyles.HexNumber); + + var ivm = bcsv.ReadValue(i, fmax)[2..]; + var vm = short.Parse(ivm, NumberStyles.HexNumber); + + var iid = bcsv.ReadValue(i, findex); + var ival = (ushort)short.Parse(iid); + + var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); + var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); + + var paddedName = $"\"{name}\"".PadRight(45, ' '); + var v = $"new {nameof(EventFlagHouse)}({vd}, {vm,-5}, {ival:0000}, {paddedName})"; + var kvp = $"{{0x{ival:X3}, {v}}}, // {comment}"; + result.Add(kvp); + } + + result.Sort(); + return result; + } + + private static List GetVillagerEventFlagNames(string pathBCSV, string fn = "EventFlagsNpcSaveParam.bcsv") + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + var dict = bcsv.GetFieldDictionary(); + var fv1 = dict[0x4C24F1CF]; + var fv2 = dict[0x344B17D7]; + var fname = dict[0x45F320F2]; + var findex = dict[0x54706054]; + var fcomment = dict[0x85CF1615]; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var iv1 = bcsv.ReadValue(i, fv1)[2..]; + var iv1a = short.Parse(iv1, NumberStyles.HexNumber); + + var iv2 = bcsv.ReadValue(i, fv2)[2..]; + var iv2a = short.Parse(iv2, NumberStyles.HexNumber); + + var iid = bcsv.ReadValue(i, findex); + var ival = (ushort)short.Parse(iid); + + var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); + var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); + + var paddedName = $"\"{name}\"".PadRight(45, ' '); + var v = $"new {nameof(EventFlagVillager)}({iv1a,-2}, {iv2a,-4}, {ival:0000}, {paddedName})"; + var kvp = $"{{0x{ival:X3}, {v}}}, // {comment}"; + result.Add(kvp); + } + + result.Sort(); + return result; + } + + private static List GetVillagerEventFlagNamesMemoryPlayer(string pathBCSV, string fn = "EventFlagsNpcMemoryParam.bcsv") + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + var dict = bcsv.GetFieldDictionary(); + var finit = dict[0xD55938BD]; + var fmax = dict[0xBD7682F5]; + var fname = dict[0x45F320F2]; + var findex = dict[0x54706054]; + var fcomment = dict[0x85CF1615]; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var isinit = bcsv.ReadValue(i, finit); + var iinit = short.Parse(isinit); + + var ismax = bcsv.ReadValue(i, fmax); + var imax = short.Parse(ismax); + + var iid = bcsv.ReadValue(i, findex); + var index = (ushort)short.Parse(iid); + + var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); + var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); + + var paddedName = $"\"{name}\"".PadRight(45, ' '); + var v = $"new {nameof(EventFlagVillagerMemoryPlayer)}({iinit,-2}, {imax,-3}, {index:000}, {paddedName})"; + var kvp = $"{{0x{index:X2}, {v}}}, // {comment}"; + result.Add(kvp); + } + + result.Sort(); + return result; + } + + private static List GetLandEventFlagNames(string pathBCSV, string fn = "EventFlagsLandParam.bcsv") + { + var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); + var dict = bcsv.GetFieldDictionary(); + var fv1 = dict[0x4C24F1CF]; + var fv2 = dict[0x344B17D7]; + var fname = dict[0x45F320F2]; + var findex = dict[0x54706054]; + var fcomment = dict[0x85CF1615]; + + var result = new List(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var iv1 = bcsv.ReadValue(i, fv1)[2..]; + var iv1a = short.Parse(iv1, NumberStyles.HexNumber); + + var iv2 = bcsv.ReadValue(i, fv2)[2..]; + var iv2a = short.Parse(iv2, NumberStyles.HexNumber); + + var iid = bcsv.ReadValue(i, findex); + var ival = (ushort)short.Parse(iid); + + var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); + var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); + + var paddedName = $"\"{name}\"".PadRight(45, ' '); + var v = $"new {nameof(EventFlagLand)}({iv1a,-2}, {iv2a,-5}, {ival:0000}, {paddedName})"; + var kvp = $"{{0x{ival:X3}, {v}}}, // {comment}"; + result.Add(kvp); + } + + result.Sort(); + return result; + } + + public static IEnumerable GetItemRemakeDictionary(string pathBCSV, string fn = "ItemParam.bcsv") + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + + var dict = bcsv.GetFieldDictionary(); + var fID = dict[0x54706054]; + var fRid = dict[0xCB5EB33F]; + + var result = new Dictionary(); + for (int i = 0; i < bcsv.EntryCount; i++) + { + var rid = bcsv.ReadValue(i, fRid); + var rival = short.Parse(rid); + + if (rival < 0) + continue; + + var id = bcsv.ReadValue(i, fID); + var ival = ushort.Parse(id); + + result.Add(ival, rival); + } + + var str = GameInfo.Strings.itemlist; + return result.Select(z => $"{{{z.Key:00000}, {z.Value:0000}}}, // {str[z.Key]}"); + } + + public static IEnumerable GetItemRemakeColors(string pathBCSV, string fn = "ItemRemake.bcsv") + { + var path = Path.Combine(pathBCSV, fn); + var data = File.ReadAllBytes(path); + var bcsv = new BCSV(data); + + var dict = bcsv.GetFieldDictionary(); + + var fid = dict[0xFD9AF1E1]; // ItemUniqueID + //var fct = dict[0x29ECB129]; // RemakeKitNum + var rid = dict[0x54706054]; // UniqueID + // var unk = dict[0xD4F43B0B]; // + var b00 = dict[0x1B98FDF8]; // ReBodyPattern0Color0 + var b01 = dict[0xA3249A9D]; // ReBodyPattern0Color1 + var b10 = dict[0xF45A96C6]; // ReBodyPattern1Color0 + var b11 = dict[0x4CE6F1A3]; // ReBodyPattern1Color1 + var b20 = dict[0x1F6D2DC5]; // ReBodyPattern2Color0 + var b21 = dict[0xA7D14AA0]; // ReBodyPattern2Color1 + var b30 = dict[0xF0AF46FB]; // ReBodyPattern3Color0 + var b31 = dict[0x4813219E]; // ReBodyPattern3Color1 + var b40 = dict[0x12735D82]; // ReBodyPattern4Color0 + var b41 = dict[0xAACF3AE7]; // ReBodyPattern4Color1 + var b50 = dict[0xFDB136BC]; // ReBodyPattern5Color0 + var b51 = dict[0x450D51D9]; // ReBodyPattern5Color1 + var b60 = dict[0x16868DBF]; // ReBodyPattern6Color0 + var b61 = dict[0xAE3AEADA]; // ReBodyPattern6Color1 + var b70 = dict[0xF944E681]; // ReBodyPattern7Color0 + var b71 = dict[0x41F881E4]; // ReBodyPattern7Color1 + var bct = dict[0xB0304B0D]; // ReBodyPatternNum + var f00 = dict[0x545F8769]; // ReFabricPattern0Color0 + var f01 = dict[0xECE3E00C]; // ReFabricPattern0Color1 + var fvf = dict[0x62C23ED0]; // ReFabricPattern0VisibleOff + var f10 = dict[0xBB9DEC57]; // ReFabricPattern1Color0 + var f11 = dict[0x03218B32]; // ReFabricPattern1Color1 + var f20 = dict[0x50AA5754]; // ReFabricPattern2Color0 + var f21 = dict[0xE8163031]; // ReFabricPattern2Color1 + var f30 = dict[0xBF683C6A]; // ReFabricPattern3Color0 + var f31 = dict[0x07D45B0F]; // ReFabricPattern3Color1 + var f40 = dict[0x5DB42713]; // ReFabricPattern4Color0 + var f41 = dict[0xE5084076]; // ReFabricPattern4Color1 + var f50 = dict[0xB2764C2D]; // ReFabricPattern5Color0 + var f51 = dict[0x0ACA2B48]; // ReFabricPattern5Color1 + var f60 = dict[0x5941F72E]; // ReFabricPattern6Color0 + var f61 = dict[0xE1FD904B]; // ReFabricPattern6Color1 + var f70 = dict[0xB6839C10]; // ReFabricPattern7Color0 + var f71 = dict[0x0E3FFB75]; // ReFabricPattern7Color1 + + var str = GameInfo.Strings.itemlist; + BCSVFieldParam[] bc0 = [b00, b10, b20, b30, b40, b50, b60, b70]; + BCSVFieldParam[] bc1 = [b01, b11, b21, b31, b41, b51, b61, b71]; + BCSVFieldParam[] fc0 = [f00, f10, f20, f30, f40, f50, f60, f70]; + BCSVFieldParam[] fc1 = [f01, f11, f21, f31, f41, f51, f61, f71]; + + for (int i = 0; i < bcsv.EntryCount; i++) + { + var index = i; + int get(BCSVFieldParam f) { - Directory.CreateDirectory(Path.Combine(dest, dir)); - byte[] bytes = new byte[ushorts.Length * 2]; - Buffer.BlockCopy(ushorts, 0, bytes, 0, ushorts.Length * 2); - File.WriteAllBytes(Path.Combine(dest, dir, fn), bytes); - Console.WriteLine($"Created {fn}"); + var val = bcsv.ReadValue(index, f); + return int.Parse(val); } - void DumpD(string fn, Dictionary dict, string dir = "text") + string getArr(IEnumerable arr) { - Directory.CreateDirectory(Path.Combine(dest, dir)); - var lines = dict.Select(z => $"{{{z.Key}, {z.Value:00000}}},"); - File.WriteAllLines(Path.Combine(dest, dir, fn), lines); - Console.WriteLine($"Created {fn}"); + var entries = arr.Select(get).Select(z => z.ToString("00")); + var bytes = string.Join(", ", entries); + return $"[{bytes}]"; } - DumpS("bcsv_map.txt", BCSV.EnumLookup.Dump()); - DumpS("lifeSupportAchievement.txt", GetLifeSupportAchievementList(pathBCSV)); - DumpS("recipeDictionary.txt", GetRecipeList(pathBCSV)); - DumpS("outsideAcres.txt", GetAcreNames(pathBCSV)); + var vbc0 = getArr(bc0); + var vbc1 = getArr(bc1); + var vfc0 = getArr(fc0); + var vfc1 = getArr(fc1); - DumpS("fish.txt", GetFishList(pathBCSV, itemNames)); - DumpS("dive.txt", GetDiveList(pathBCSV, itemNames)); - DumpS("bugs.txt", GetInsectList(pathBCSV, itemNames)); - DumpS("fossils.txt", GetFossilList(pathBCSV, itemNames)); - DumpS("eventFlagPlayer.txt", GetEventFlagNames(pathBCSV)); - DumpS("eventFlagHouse.txt", GetEventFlagHouse(pathBCSV)); - DumpS("eventFlagVillager.txt", GetVillagerEventFlagNames(pathBCSV)); - DumpS("eventFlagVillagerMemoryPlayer.txt", GetVillagerEventFlagNamesMemoryPlayer(pathBCSV)); - DumpS("eventFlagLand.txt", GetLandEventFlagNames(pathBCSV)); + var vfvf = get(fvf) == 1; + var ct = get(bct); - DumpS("ItemKind.txt", GetPossibleEnum(pathBCSV, "ItemParam.bcsv", 0xFC275E86)); - DumpS("ItemSize.txt", GetPossibleEnum(pathBCSV, "ItemParam.bcsv", 0xE06FB090)); - DumpS("ItemMenuIcon.txt", GetPossibleEnum(pathBCSV, "ItemParam.bcsv", 0x348D7B06)); - DumpS("PlantKind.txt", GetPossibleEnum(pathBCSV, "FgMainParam.bcsv", 0x48EF0398)); - DumpS("TerrainKind.txt", GetNumberedEnumValues(pathBCSV, "FieldLandMakingUnitModelParam.bcsv", 0x39B5A93D, 0x54706054)); - DumpS("BridgeKind.txt", GetNumberedEnumValues(pathBCSV, "StructureBridgeParam.bcsv", 0x39B5A93D, 0x54706054)); - DumpS("BridgeMaterial.txt", GetNumberedEnumValues(pathBCSV, "StructureBridgeTypeParam.bcsv", 0x68CF5938, 0x54706054)); - DumpS("SlopeKind.txt", GetNumberedEnumValues(pathBCSV, "StructureSlopeParam.bcsv", 0x39B5A93D, 0x54706054)); - DumpS("RoofKind.txt", GetNumberedEnumValues(pathBCSV, "StructureHouseRoofParam.bcsv", 0x39B5A93D, 0x54706054)); - DumpS("DoorKind.txt", GetNumberedEnumValues(pathBCSV, "StructureHouseDoorParam.bcsv", 0x39B5A93D, 0x54706054)); - DumpS("WallKind.txt", GetNumberedEnumValues(pathBCSV, "StructureHouseWallParam.bcsv", 0x39B5A93D, 0x54706054)); + var vid = get(fid); + //var vct = get(fct); + var vrd = get(rid); - DumpD("ItemStack.txt", GetItemStackDict(pathBCSV)); - - DumpB("item_kind.bin", GetItemKindArray(pathBCSV)); - DumpB("item_size.bin", GetItemSizeArray(pathBCSV)); - DumpU("item_menuicon.bin", GetItemMenuIconArray(pathBCSV)); - DumpS("plants.txt", GetPlantedNames(pathBCSV)); - DumpS("item_size_dictionary.txt", GetItemSizeDictionary(pathBCSV)); - DumpS("item_remake.txt", GetItemRemakeDictionary(pathBCSV)); - DumpS("itemRemakeInfo.txt", GetItemRemakeColors(pathBCSV)); - } - - public static void UpdateCSV(string pathBCSV, string dest, bool remapColumns = false, string delim = "\t") - { - BCSV.DecodeColumnNames = remapColumns; - Directory.CreateDirectory(dest); - BCSVConverter.DumpAll(pathBCSV, dest, delim); - } - - private static IEnumerable GetPossibleEnumValues(string pathBCSV, string fn, uint key) - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - - var dict = bcsv.GetFieldDictionary(); - var fType = dict[key]; - - var types = new HashSet(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); - if (!types.Contains(type)) - types.Add(type); - } - - return types; - } - - private static IEnumerable GetNumberedEnumValues(string pathBCSV, string fn, uint keyName, uint keyValue) - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - - var dict = bcsv.GetFieldDictionary(); - var fType = dict[keyName]; - var fitemID = dict[keyValue]; - - var types = new List(); - var set = new Dictionary(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var iid = bcsv.ReadValue(i, fitemID); - var ival = ushort.Parse(iid); - var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); - if (set.TryGetValue(type, out var count)) - { - count++; - set[type] = count; - type += $"_{count}"; - } - else - { - set.Add(type, 1); - } - - types.Add($"{type} = 0x{ival:X2},"); - } - - return types; - } - - private static IEnumerable GetPossibleEnum(string pathBCSV, string fn, uint key) - { - var kinds = GetPossibleEnumValues(pathBCSV, fn, key); - var ordered = kinds.OrderBy(z => z); - return ordered.Select(z => $"{z},"); - } - - public static byte[] GetItemKindArray(string pathBCSV, string fn = "ItemParam.bcsv") - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - - var dict = bcsv.GetFieldDictionary(); - var fType = dict[0xFC275E86]; - var fID = dict[0x54706054]; - - var types = new Dictionary(); - ushort max = 0; - for (int i = 0; i < bcsv.EntryCount; i++) - { - var id = bcsv.ReadValue(i, fID); - var ival = ushort.Parse(id); - var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); - - if (!Enum.TryParse(type, out var k)) - throw new InvalidEnumArgumentException($"{type} is not a known enum value @ index {i}. Update the enum index first."); - types.Add(ival, k); - - if (ival > max) - max = ival; - } - - byte[] result = new byte[max + 1]; - foreach (var kvp in types) - result[kvp.Key] = (byte) kvp.Value; - - return result; - } - - public static byte[] GetItemSizeArray(string pathBCSV, string fn = "ItemParam.bcsv") - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - - var dict = bcsv.GetFieldDictionary(); - var fType = dict[0xE06FB090]; - var fID = dict[0x54706054]; - - var types = new Dictionary(); - ushort max = 0; - for (int i = 0; i < bcsv.EntryCount; i++) - { - var id = bcsv.ReadValue(i, fID); - var ival = ushort.Parse(id); - var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); - type = ItemSizeExtensions.EnumPrefix + type; // can't start with numbers - - if (!Enum.TryParse(type, out var k)) - throw new InvalidEnumArgumentException($"{type} is not a known enum value @ index {i}. Update the enum index first."); - types.Add(ival, k); - - if (ival > max) - max = ival; - } - - byte[] result = new byte[max + 1]; - foreach (var kvp in types) - result[kvp.Key] = (byte)kvp.Value; - - return result; - } - - public static Dictionary GetItemStackDict(string pathBCSV, string fn = "ItemKind.bcsv") - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - - var dict = bcsv.GetFieldDictionary(); - var fStack = dict[0x4C9BA961]; // MultiHoldMaxNum - var fKind = dict[0x87BF00E8]; // Label - - // clothing is split out more granularly in ItemKind and would cause errors - // since it's not likely to ever be stackable, we can skip - // none-type can be skipped and doesn't exist in ItemKind either - List skipLabels = new() - { - "TopsDefault", - "Tops", - "OnePiece", - "MarineSuit", - "BottomsDefault", - "Bottoms", - "Shoes", - "None" - }; - - var result = new Dictionary(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var stack = bcsv.ReadValue(i, fStack); - switch (stack) - { - case "-1": // for some reason turnips have a stack value of -1, should be 10... - stack = "10"; - break; - case "0": // the game stores items that cannot be stacked as 0, so technically they stack to 1 - stack = "1"; - break; - } - - var stackval = ushort.Parse(stack); - var kind = bcsv.ReadValue(i, fKind).TrimEnd('\0'); - if (skipLabels.Contains(kind)) - continue; - - kind = "Kind_" + kind; - if (!Enum.TryParse(kind, out var k)) - throw new InvalidEnumArgumentException($"{kind} is not a known enum value @ index {i}. Update the enum index first."); - result.Add(k, stackval); - } - - return result; - } - - public static ushort[] GetItemMenuIconArray(string pathBCSV, string fn = "ItemParam.bcsv") - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - - var dict = bcsv.GetFieldDictionary(); - var fType = dict[0x348D7B06]; - var fID = dict[0x54706054]; - - var types = new Dictionary(); - ushort max = 0; - for (int i = 0; i < bcsv.EntryCount; i++) - { - var id = bcsv.ReadValue(i, fID); - var ival = ushort.Parse(id); - var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); - - if (type.StartsWith("0x")) - type = $"_{type}"; // enum name can't start with number - - if (!Enum.TryParse(type, out var k)) - throw new InvalidEnumArgumentException($"{type} is not a known enum value @ index {i}. Update the {nameof(ItemMenuIconType)} enum index first."); - types.Add(ival, k); - - if (ival > max) - max = ival; - } - - ushort[] result = new ushort[max + 1]; - foreach (var kvp in types) - result[kvp.Key] = (ushort)kvp.Value; - - return result; - } - - public static string[] GetItemSizeDictionary(string pathBCSV, string fn = "ItemSize.bcsv") - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - - var dict = bcsv.GetFieldDictionary(); - - var fw = dict[0x16B8F524]; - var fh = dict[0xBCB13DAF]; - var fs = dict[0x87BF00E8]; - var fc = dict[0x977ADFCE]; - - string[] result = new string[bcsv.EntryCount]; - - const string prefix = nameof(ItemSizeType) + "." + ItemSizeExtensions.EnumPrefix; - for (int i = 0; i < bcsv.EntryCount; i++) - { - var w = bcsv.ReadValue(i, fw).TrimEnd('\0'); - var h = bcsv.ReadValue(i, fh).TrimEnd('\0'); - var s = bcsv.ReadValue(i, fs).TrimEnd('\0'); - var c = bcsv.ReadValue(i, fc).TrimEnd('\0'); - - result[i] = $"{{{prefix}{s,-12}, new ItemSize({w,2}, {h,2})}}, // {c}"; - } - - return result; - } - - public static List GetRecipeList(string pathBCSV, string fn = "RecipeCraftParam.bcsv") - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - - var dict = bcsv.GetFieldDictionary(); - var frecipe = dict[0x54706054]; - var fitemID = dict[0x89A3482C]; - - var items = GameInfo.Strings.itemlist; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var iid = bcsv.ReadValue(i, fitemID); - var ival = ushort.Parse(iid); - - var rid = bcsv.ReadValue(i, frecipe); - var rval = ushort.Parse(rid); - - var kvp = $"{{0x{rval:X3}, {ival:00000}}}, // {items[ival]}"; - result.Add(kvp); - } - - result.Sort(); - return result; - } - - public static List GetLifeSupportAchievementList(string pathBCSV, string fn = "EventFlagsLifeSupportAchievementParam.bcsv") - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - - var dict = bcsv.GetFieldDictionary(); - var findex = dict[0x54706054]; - var fname = dict[0x45F320F2]; - var fcomment = dict[0x85CF1615]; - var fLand = dict[0x3FE43170]; - var fPlayer = dict[0x4171A41D]; - - var fmaxLevel = dict[0x1BE772F0]; - var fThreshold1 = dict[0xCE0933FC]; - var fThreshold2 = dict[0x89A9492C]; - var fThreshold3 = dict[0xB4C9609C]; - var fThreshold4 = dict[0x06E9BC8C]; - var fThreshold5 = dict[0x3B89953C]; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - int readHex(BCSVFieldParam p) => int.Parse(bcsv.ReadValue(i, p).Substring(2), NumberStyles.HexNumber); - - var iid = bcsv.ReadValue(i, findex); - var index = ushort.Parse(iid); - - var land = readHex(fLand); - var player = readHex(fPlayer); - - var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); - var paddedName = $"\"{name}\"".PadRight(30, ' '); - - var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); - - var tmp = bcsv.ReadValue(i, fmaxLevel); - var max = ushort.Parse(tmp); - var t1 = readHex(fThreshold1); - var t2 = readHex(fThreshold2); - var t3 = readHex(fThreshold3); - var t4 = readHex(fThreshold4); - var t5 = readHex(fThreshold5); - - var values = $"{max}, {t1:0000}, {t2:0000}, {t3:0000}, {t4:0000}, {t5:0000}"; - - var v = $"new {nameof(LifeSupportAchievement)}({index:000}, {values}, {land,3}, {player,3}, {paddedName})"; - var kvp = $"{{0x{index:X2}, {v}}}, // {comment}"; - result.Add(kvp); - } - - result.Sort(); - return result; - } - - public static IEnumerable GetInsectList(string pathBCSV, string fn = "InsectStatusParam.bcsv") - { - return GetItemList(pathBCSV, fn, 0x20CB67BC); - } - - public static IEnumerable GetFossilList(string pathBCSV, string fn = "MuseumFossilDonateInfo.bcsv") - { - return GetItemList(pathBCSV, fn, 0xB76B7D37); - } - - public static IEnumerable GetFishList(string pathBCSV, string fn = "FishStatusParam.bcsv") - { - return GetItemList(pathBCSV, fn, 0x20CB67BC); - } - - public static IEnumerable GetDiveList(string pathBCSV, string fn = "SeafoodStatusParam.bcsv") - { - return GetItemList(pathBCSV, fn, 0x20CB67BC); - } - - public static IEnumerable GetInsectList(string pathBCSV, IReadOnlyList items, string fn = "InsectStatusParam.bcsv") - { - var insects = GetInsectList(pathBCSV, fn); - return insects.Select(z => $"{z:00000}, // {items[z]}"); - } - - public static IEnumerable GetFishList(string pathBCSV, IReadOnlyList items, string fn = "FishStatusParam.bcsv") - { - var insects = GetFishList(pathBCSV, fn); - return insects.Select(z => $"{z:00000}, // {items[z]}"); - } - - public static IEnumerable GetDiveList(string pathBCSV, IReadOnlyList items, string fn = "SeafoodStatusParam.bcsv") - { - var insects = GetDiveList(pathBCSV, fn); - return insects.Select(z => $"{z:00000}, // {items[z]}"); - } - - public static IEnumerable GetFossilList(string pathBCSV, IReadOnlyList items, string fn = "MuseumFossilDonateInfo.bcsv") - { - var fossils = GetFossilList(pathBCSV, fn); - return fossils.Select(z => $"{z:00000}, // {items[z]}"); - } - - private static IEnumerable GetItemList(string pathBCSV, string fn, uint keyItemIDColumn) - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - var dict = bcsv.GetFieldDictionary(); - var findex = dict[keyItemIDColumn]; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var iid = bcsv.ReadValue(i, findex); - var ival = ushort.Parse(iid); - result.Add(ival); - } - - result.Sort(); - return result; - } - - private static IEnumerable GetAcreNames(string pathBCSV, string fn = "FieldOutsideParts.bcsv") - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - var dict = bcsv.GetFieldDictionary(); - var findex = dict[0x54706054]; - var fname = dict[0x39B5A93D]; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var iid = bcsv.ReadValue(i, findex); - var ival = ushort.Parse(iid); - - var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); - - var kvp = $"{{0x{ival:X2}, \"{name}\"}}, // {ival}"; - result.Add(kvp); - } - - result.Sort(); - return result; - } - - private static IEnumerable GetPlantedNames(string pathBCSV, string fn = "FgMainParam.bcsv") - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - var dict = bcsv.GetFieldDictionary(); - var fType = dict[0x48EF0398]; - var fname = dict[0x87BF00E8]; - var findex = dict[0x54706054]; - var fcomment = dict[0x3F45F2BF]; - - var fdig = dict[0xF4678F13]; - var fpic = dict[0xB7A46956]; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var iid = bcsv.ReadValue(i, findex); - var ival = (ushort)short.Parse(iid); - - var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); - var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); - var type = bcsv.ReadValue(i, fType).TrimEnd('\0'); - - var did = bcsv.ReadValue(i, fdig); - var dval = (ushort)short.Parse(did); - - var pid = bcsv.ReadValue(i, fpic); - var pval = (ushort)short.Parse(pid); - - if (!Enum.TryParse(type, out var k)) - throw new InvalidEnumArgumentException($"{type} is not a known enum value @ index {i}. Update the enum index first."); - - var strname = $"\"{name}\""; - var v = $"new {nameof(FieldItemDefinition)}({ival,-5}, {dval,-5}, {pval,-5}, {strname,-24}, {nameof(FieldItemKind)}.{k,-20})"; - var kvp = $"{{0x{ival:X}, {v}}}, // {comment}"; - result.Add(kvp); - } - - result.Sort(); - return result; - } - - private static IEnumerable GetEventFlagNames(string pathBCSV, string fn = "EventFlagsPlayerParam.bcsv") - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - var dict = bcsv.GetFieldDictionary(); - var fv1 = dict[0x4C24F1CF]; - var fv2 = dict[0x344B17D7]; - var fname = dict[0x45F320F2]; - var findex = dict[0x54706054]; - var fcomment = dict[0x85CF1615]; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var iv1 = bcsv.ReadValue(i, fv1).Substring(2); - var iv1a = short.Parse(iv1, NumberStyles.HexNumber); - - var iv2 = bcsv.ReadValue(i, fv2).Substring(2); - var iv2a = short.Parse(iv2, NumberStyles.HexNumber); - - var iid = bcsv.ReadValue(i, findex); - var ival = (ushort)short.Parse(iid); - - var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); - var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); - - var paddedName = $"\"{name}\"".PadRight(45, ' '); - var v = $"new {nameof(EventFlagPlayer)}({iv1a,-2}, {iv2a,-4}, {ival:0000}, {paddedName})"; - var kvp = $"{{0x{ival:X3}, {v}}}, // {comment}"; - result.Add(kvp); - } - - result.Sort(); - return result; - } - - private static IEnumerable GetEventFlagHouse(string pathBCSV, string fn = "EventFlagsHouseParam.bcsv") - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - var dict = bcsv.GetFieldDictionary(); - var findex = dict[0x54706054]; - - var fdefault = dict[0x4C24F1CF]; - var fmax = dict[0x344B17D7]; - var fname = dict[0x45F320F2]; - var fcomment = dict[0x85CF1615]; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var ivd = bcsv.ReadValue(i, fdefault).Substring(2); - var vd = short.Parse(ivd, NumberStyles.HexNumber); - - var ivm = bcsv.ReadValue(i, fmax).Substring(2); - var vm = short.Parse(ivm, NumberStyles.HexNumber); - - var iid = bcsv.ReadValue(i, findex); - var ival = (ushort)short.Parse(iid); - - var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); - var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); - - var paddedName = $"\"{name}\"".PadRight(45, ' '); - var v = $"new {nameof(EventFlagHouse)}({vd}, {vm,-5}, {ival:0000}, {paddedName})"; - var kvp = $"{{0x{ival:X3}, {v}}}, // {comment}"; - result.Add(kvp); - } - - result.Sort(); - return result; - } - - private static IEnumerable GetVillagerEventFlagNames(string pathBCSV, string fn = "EventFlagsNpcSaveParam.bcsv") - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - var dict = bcsv.GetFieldDictionary(); - var fv1 = dict[0x4C24F1CF]; - var fv2 = dict[0x344B17D7]; - var fname = dict[0x45F320F2]; - var findex = dict[0x54706054]; - var fcomment = dict[0x85CF1615]; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var iv1 = bcsv.ReadValue(i, fv1).Substring(2); - var iv1a = short.Parse(iv1, NumberStyles.HexNumber); - - var iv2 = bcsv.ReadValue(i, fv2).Substring(2); - var iv2a = short.Parse(iv2, NumberStyles.HexNumber); - - var iid = bcsv.ReadValue(i, findex); - var ival = (ushort)short.Parse(iid); - - var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); - var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); - - var paddedName = $"\"{name}\"".PadRight(45, ' '); - var v = $"new {nameof(EventFlagVillager)}({iv1a,-2}, {iv2a,-4}, {ival:0000}, {paddedName})"; - var kvp = $"{{0x{ival:X3}, {v}}}, // {comment}"; - result.Add(kvp); - } - - result.Sort(); - return result; - } - - private static IEnumerable GetVillagerEventFlagNamesMemoryPlayer(string pathBCSV, string fn = "EventFlagsNpcMemoryParam.bcsv") - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - var dict = bcsv.GetFieldDictionary(); - var finit = dict[0xD55938BD]; - var fmax = dict[0xBD7682F5]; - var fname = dict[0x45F320F2]; - var findex = dict[0x54706054]; - var fcomment = dict[0x85CF1615]; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var isinit = bcsv.ReadValue(i, finit); - var iinit = short.Parse(isinit); - - var ismax = bcsv.ReadValue(i, fmax); - var imax = short.Parse(ismax); - - var iid = bcsv.ReadValue(i, findex); - var index = (ushort)short.Parse(iid); - - var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); - var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); - - var paddedName = $"\"{name}\"".PadRight(45, ' '); - var v = $"new {nameof(EventFlagVillagerMemoryPlayer)}({iinit,-2}, {imax,-3}, {index:000}, {paddedName})"; - var kvp = $"{{0x{index:X2}, {v}}}, // {comment}"; - result.Add(kvp); - } - - result.Sort(); - return result; - } - - private static IEnumerable GetLandEventFlagNames(string pathBCSV, string fn = "EventFlagsLandParam.bcsv") - { - var bcsv = BCSVConverter.GetBCSV(pathBCSV, fn); - var dict = bcsv.GetFieldDictionary(); - var fv1 = dict[0x4C24F1CF]; - var fv2 = dict[0x344B17D7]; - var fname = dict[0x45F320F2]; - var findex = dict[0x54706054]; - var fcomment = dict[0x85CF1615]; - - var result = new List(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var iv1 = bcsv.ReadValue(i, fv1).Substring(2); - var iv1a = short.Parse(iv1, NumberStyles.HexNumber); - - var iv2 = bcsv.ReadValue(i, fv2).Substring(2); - var iv2a = short.Parse(iv2, NumberStyles.HexNumber); - - var iid = bcsv.ReadValue(i, findex); - var ival = (ushort)short.Parse(iid); - - var name = bcsv.ReadValue(i, fname).TrimEnd('\0'); - var comment = bcsv.ReadValue(i, fcomment).TrimEnd('\0'); - - var paddedName = $"\"{name}\"".PadRight(45, ' '); - var v = $"new {nameof(EventFlagLand)}({iv1a,-2}, {iv2a,-5}, {ival:0000}, {paddedName})"; - var kvp = $"{{0x{ival:X3}, {v}}}, // {comment}"; - result.Add(kvp); - } - - result.Sort(); - return result; - } - - public static IEnumerable GetItemRemakeDictionary(string pathBCSV, string fn = "ItemParam.bcsv") - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - - var dict = bcsv.GetFieldDictionary(); - var fID = dict[0x54706054]; - var fRid = dict[0xCB5EB33F]; - - var result = new Dictionary(); - for (int i = 0; i < bcsv.EntryCount; i++) - { - var rid = bcsv.ReadValue(i, fRid); - var rival = short.Parse(rid); - - if (rival < 0) - continue; - - var id = bcsv.ReadValue(i, fID); - var ival = ushort.Parse(id); - - result.Add(ival, rival); - } - - var str = GameInfo.Strings.itemlist; - return result.Select(z => $"{{{z.Key:00000}, {z.Value:0000}}}, // {str[z.Key]}"); - } - - public static IEnumerable GetItemRemakeColors(string pathBCSV, string fn = "ItemRemake.bcsv") - { - var path = Path.Combine(pathBCSV, fn); - var data = File.ReadAllBytes(path); - var bcsv = new BCSV(data); - - var dict = bcsv.GetFieldDictionary(); - - var fid = dict[0xFD9AF1E1]; // ItemUniqueID - //var fct = dict[0x29ECB129]; // RemakeKitNum - var rid = dict[0x54706054]; // UniqueID - // var unk = dict[0xD4F43B0B]; // - var b00 = dict[0x1B98FDF8]; // ReBodyPattern0Color0 - var b01 = dict[0xA3249A9D]; // ReBodyPattern0Color1 - var b10 = dict[0xF45A96C6]; // ReBodyPattern1Color0 - var b11 = dict[0x4CE6F1A3]; // ReBodyPattern1Color1 - var b20 = dict[0x1F6D2DC5]; // ReBodyPattern2Color0 - var b21 = dict[0xA7D14AA0]; // ReBodyPattern2Color1 - var b30 = dict[0xF0AF46FB]; // ReBodyPattern3Color0 - var b31 = dict[0x4813219E]; // ReBodyPattern3Color1 - var b40 = dict[0x12735D82]; // ReBodyPattern4Color0 - var b41 = dict[0xAACF3AE7]; // ReBodyPattern4Color1 - var b50 = dict[0xFDB136BC]; // ReBodyPattern5Color0 - var b51 = dict[0x450D51D9]; // ReBodyPattern5Color1 - var b60 = dict[0x16868DBF]; // ReBodyPattern6Color0 - var b61 = dict[0xAE3AEADA]; // ReBodyPattern6Color1 - var b70 = dict[0xF944E681]; // ReBodyPattern7Color0 - var b71 = dict[0x41F881E4]; // ReBodyPattern7Color1 - var bct = dict[0xB0304B0D]; // ReBodyPatternNum - var f00 = dict[0x545F8769]; // ReFabricPattern0Color0 - var f01 = dict[0xECE3E00C]; // ReFabricPattern0Color1 - var fvf = dict[0x62C23ED0]; // ReFabricPattern0VisibleOff - var f10 = dict[0xBB9DEC57]; // ReFabricPattern1Color0 - var f11 = dict[0x03218B32]; // ReFabricPattern1Color1 - var f20 = dict[0x50AA5754]; // ReFabricPattern2Color0 - var f21 = dict[0xE8163031]; // ReFabricPattern2Color1 - var f30 = dict[0xBF683C6A]; // ReFabricPattern3Color0 - var f31 = dict[0x07D45B0F]; // ReFabricPattern3Color1 - var f40 = dict[0x5DB42713]; // ReFabricPattern4Color0 - var f41 = dict[0xE5084076]; // ReFabricPattern4Color1 - var f50 = dict[0xB2764C2D]; // ReFabricPattern5Color0 - var f51 = dict[0x0ACA2B48]; // ReFabricPattern5Color1 - var f60 = dict[0x5941F72E]; // ReFabricPattern6Color0 - var f61 = dict[0xE1FD904B]; // ReFabricPattern6Color1 - var f70 = dict[0xB6839C10]; // ReFabricPattern7Color0 - var f71 = dict[0x0E3FFB75]; // ReFabricPattern7Color1 - - var str = GameInfo.Strings.itemlist; - var bc0 = new[] { b00, b10, b20, b30, b40, b50, b60, b70 }; - var bc1 = new[] { b01, b11, b21, b31, b41, b51, b61, b71 }; - var fc0 = new[] { f00, f10, f20, f30, f40, f50, f60, f70 }; - var fc1 = new[] { f01, f11, f21, f31, f41, f51, f61, f71 }; - - for (int i = 0; i < bcsv.EntryCount; i++) - { - var index = i; - int get(BCSVFieldParam f) - { - var val = bcsv.ReadValue(index, f); - return int.Parse(val); - } - - string getArr(IEnumerable arr) - { - var entries = arr.Select(get).Select(z => z.ToString("00")); - var bytes = string.Join(", ", entries); - return $"new byte[] {{{bytes}}}"; - } - - var vbc0 = getArr(bc0); - var vbc1 = getArr(bc1); - var vfc0 = getArr(fc0); - var vfc1 = getArr(fc1); - - var vfvf = get(fvf) == 1; - var ct = get(bct); - - var vid = get(fid); - //var vct = get(fct); - var vrd = get(rid); - - // (short index, ushort id, sbyte count, byte[] bc0, byte[] bc1, byte[] fc0, byte[] fc1, bool fp0) - yield return $"{{{vrd:0000}, new {nameof(ItemRemakeInfo)}({vrd:0000}, {vid:00000}, {(sbyte)ct,2}, {vbc0}, {vbc1}, {vfc0}, {vfc1}, {(vfvf ? " true": "false")})}}, // {str[vid]}"; - } + // (short index, ushort id, sbyte count, byte[] bc0, byte[] bc1, byte[] fc0, byte[] fc1, bool fp0) + yield return $"{{{vrd:0000}, new({vrd:0000}, {vid:00000}, {(sbyte)ct,2}, {vbc0}, {vbc1}, {vfc0}, {vfc1}, {(vfvf ? " true": "false")})}}, // {str[vid]}"; } } -} +} \ No newline at end of file diff --git a/NHSE.Parsing/GameMSBTDumper.cs b/NHSE.Parsing/GameMSBTDumper.cs index f1dd366..fac6f96 100644 --- a/NHSE.Parsing/GameMSBTDumper.cs +++ b/NHSE.Parsing/GameMSBTDumper.cs @@ -1,217 +1,208 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public static class GameMSBTDumper { - public static class GameMSBTDumper + public static string[] GetItemListResource(string msgPath, string language) { - public static string[] GetItemListResource(string msgPath, string language) + var list = GetItemList(msgPath, language); + var max = list.Max(z => z.Key); + var result = new string?[max + 1]; + + foreach (var item in list) + result[item.Key] = item.Value; + for (int i = 0; i < result.Length; i++) + result[i] ??= string.Empty; + + FinalizeItemList(language, result!); + return result!; + } + + private static void FinalizeItemList(string language, Span result) + { + result[0] = $"({GetNoneName(language)})"; + result[5794] = $"({GetDIYRecipeName(language)})"; + foreach (var internalItem in InternalItemList) + result[internalItem.Key] = internalItem.Value; + } + + public static string[] GetArtList(string msgPath) + { + var file = Path.Combine(msgPath, "Item", "STR_ItemName_01_Art.msbt"); + var pairs = GetLabelList(file).ToArray(); // (itemID, itemName) + + var result = new List(); + foreach (var (Label, Text) in pairs) { - var list = GetItemList(msgPath, language); - var max = list.Max(z => z.Key); - var result = new string?[max + 1]; + var label = Label; + var underscore = label.IndexOf('_'); + var itemIDs = label[(underscore + 1)..]; + ushort itemID = ushort.Parse(itemIDs); - foreach (var item in list) - result[item.Key] = item.Value; - for (int i = 0; i < result.Length; i++) - result[i] ??= string.Empty; - - FinalizeItemList(language, result!); - return result!; + var fake = label.Contains("Fake") ? " (forgery)" : string.Empty; + result.Add($"{itemID:00000}, // {Text}{fake}"); } + result.Sort(); + return result.ToArray(); + } - private static void FinalizeItemList(string language, string[] result) + public static string[] GetVillagerPhraseResource(string msgPath) + { + var file = Path.Combine(msgPath, "Npc", "STR_NNpcPhrase.msbt"); + var list = GetLabelList(file); + var normal = list.Select(z => $"{z.Label}\t{z.Text}").Order(); + return normal.ToArray(); + } + + public static string[] GetVillagerListResource(string msgPath) + { + var file = Path.Combine(msgPath, "Npc", "STR_NNpcName.msbt"); + var list = GetLabelList(file); + var normal = list.Select(z => $"{z.Label}\t{z.Text}").Order(); + + file = Path.Combine(msgPath, "Npc", "STR_SNpcName.msbt"); + list = GetLabelList(file); + var special = list.Select(z => $"{z.Label}\t{z.Text}").Order(); + + return normal.Concat(special).ToArray(); + } + + public static Dictionary GetItemList(string msgPath, string language) + { + var result = new Dictionary(); + AddRegularItems(result, msgPath, language); + AddColoredItems(result, msgPath); + return result; + } + + private static void AddRegularItems(Dictionary result, string msgPath, string language) + { + var pitem = Path.Combine(msgPath, "Item"); + var fitem = Directory.EnumerateFiles(pitem); + var regularItemList = GetLabelList(fitem); // (itemID, itemName) + + var forgery = GetForgerySuffix(language); + foreach (var (label, text) in regularItemList) { - result[0] = $"({GetNoneName(language)})"; - result[5794] = $"({GetDIYRecipeName(language)})"; - foreach (var internalItem in InternalItemList) - result[internalItem.Key] = internalItem.Value; - } + if (label.EndsWith("_pl")) + continue; - public static string[] GetArtList(string msgPath) - { - var file = Path.Combine(msgPath, "Item", "STR_ItemName_01_Art.msbt"); - var pairs = GetLabelList(file).ToArray(); // (itemID, itemName) + var underscore = label.IndexOf('_'); + var itemIDs = label[(underscore + 1)..]; + ushort itemID = ushort.Parse(itemIDs); - var result = new List(); - foreach (var (Label, Text) in pairs) - { - var label = Label; - var underscore = label.IndexOf('_'); - var itemIDs = label.Substring(underscore + 1); - ushort itemID = ushort.Parse(itemIDs); + var itemText = text; + if (label.StartsWith("PictureFake") || label.StartsWith("SculptureFake")) + itemText = $"{itemText} ({forgery})"; - var fake = label.Contains("Fake") ? " (forgery)" : string.Empty; - result.Add($"{itemID:00000}, // {Text}{fake}"); - } - result.Sort(); - return result.ToArray(); - } - - public static string[] GetVillagerPhraseResource(string msgPath) - { - var file = Path.Combine(msgPath, "Npc", "STR_NNpcPhrase.msbt"); - var list = GetLabelList(file); - var normal = list.Select(z => $"{z.Label}\t{z.Text}").OrderBy(z => z); - return normal.ToArray(); - } - - public static string[] GetVillagerListResource(string msgPath) - { - var file = Path.Combine(msgPath, "Npc", "STR_NNpcName.msbt"); - var list = GetLabelList(file); - var normal = list.Select(z => $"{z.Label}\t{z.Text}").OrderBy(z => z); - - file = Path.Combine(msgPath, "Npc", "STR_SNpcName.msbt"); - list = GetLabelList(file); - var special = list.Select(z => $"{z.Label}\t{z.Text}").OrderBy(z => z); - - return normal.Concat(special).ToArray(); - } - - public static Dictionary GetItemList(string msgPath, string language) - { - var result = new Dictionary(); - AddRegularItems(result, msgPath, language); - AddColoredItems(result, msgPath); - return result; - } - - private static void AddRegularItems(IDictionary result, string msgPath, string language) - { - var pitem = Path.Combine(msgPath, "Item"); - var fitem = Directory.EnumerateFiles(pitem); - var regularItemList = GetLabelList(fitem); // (itemID, itemName) - - var forgery = GetForgerySuffix(language); - foreach (var (label, text) in regularItemList) - { - if (label.EndsWith("_pl")) - continue; - - var underscore = label.IndexOf('_'); - var itemIDs = label.Substring(underscore + 1); - ushort itemID = ushort.Parse(itemIDs); - - var itemText = text; - if (label.StartsWith("PictureFake") || label.StartsWith("SculptureFake")) - itemText = $"{itemText} ({forgery})"; - - result.Add(itemID, itemText); - } - } - - private static string GetNoneName(string language) - { - return language switch - { - "de" => "Leer", - "es" => "Ningun", - "fr" => "Aucun", - "it" => "Nessuna", - "ko" => "없음", - "ja" => "無し", - "chs" => "没有", - "cht" => "沒有", - _ => "None", - }; - } - - private static string GetDIYRecipeName(string language) - { - return language switch - { - "de" => "DIY recipe", - "es" => "DIY recipe", - "fr" => "DIY recipe", - "it" => "DIY recipe", - "ko" => "DIY recipe", - "ja" => "DIY recipe", - "chs" => "DIY recipe", - "cht" => "DIY recipe", - _ => "DIY recipe", - }; - } - - private static string GetForgerySuffix(string language) - { - return language switch - { - "de" => "fälschung", - "es" => "falsificación", - "fr" => "falsification", - "it" => "falsificazione", - "ko" => "위조", - "ja" => "偽造", - "chs" => "伪造", - "cht" => "偽造", - _ => "forgery", - }; - } - - private static readonly Dictionary InternalItemList = new() - { - {4200, "k.k. slider's guitar (internal)"}, - }; - - private static void AddColoredItems(IDictionary result, string msgPath) - { - var pgname = Path.Combine(msgPath, "Outfit", "GroupName"); // (baseItemName, groupID) - var pgcolor = Path.Combine(msgPath, "Outfit", "GroupColor"); // (itemID_type_groupID, color) - var fgname = Directory.EnumerateFiles(pgname); - var fgcolor = Directory.EnumerateFiles(pgcolor); - - var coloredItemList = GetLabelList(fgcolor); - var coloredItemBaseNameList = GetLabelList(fgname); - var baseColorItem = coloredItemBaseNameList - .ToDictionary(z => (ushort) short.Parse(z.Label), z => z.Text); - - foreach (var (label, text) in coloredItemList) - { - var (itemID, baseId) = GetUniqueColorItemDefinition(label); - if (!baseColorItem.TryGetValue(baseId, out var baseItemName)) - continue; - - var itemName = $"{baseItemName} ({text})"; - result.Add(itemID, itemName); - } - } - - private static IEnumerable<(string Label, string Text)> GetLabelList(IEnumerable files) - { - foreach (var path in files.Where(z => z.EndsWith("msbt"))) - { - foreach (var valueTuple in GetLabelList(path)) - yield return valueTuple; - } - } - - public static IEnumerable<(string Label, string Text)> GetLabelList(string path) - { - var msbt = new MSBT(File.ReadAllBytes(path)); - foreach (var e in msbt.LBL1.Labels) - yield return GetCleanLabelText(e, msbt.TXT2.Strings); - } - - private static (string Label, string Text) GetCleanLabelText(MSBTLabel lbl, IList txt) - { - var label = lbl.Name; - var index = (int)lbl.Index; - var strObj = txt[index]; - var text = strObj.ToStringNoAtoms(); - return (label, text); - } - - private static (ushort ItemID, ushort BaseID) GetUniqueColorItemDefinition(string line) - { - var split = line.Split('_'); - - var BaseID = ushort.Parse(split[0]); - //Type = split[1]; - var ItemID = ushort.Parse(split[2]); - - return (ItemID, BaseID); + result.Add(itemID, itemText); } } -} + + private static string GetNoneName(string language) => language switch + { + "de" => "Leer", + "es" => "Ningun", + "fr" => "Aucun", + "it" => "Nessuna", + "ko" => "없음", + "ja" => "無し", + "chs" => "没有", + "cht" => "沒有", + _ => "None", + }; + + private static string GetDIYRecipeName(string language) => language switch + { + "de" => "DIY recipe", + "es" => "DIY recipe", + "fr" => "DIY recipe", + "it" => "DIY recipe", + "ko" => "DIY recipe", + "ja" => "DIY recipe", + "chs" => "DIY recipe", + "cht" => "DIY recipe", + _ => "DIY recipe", + }; + + private static string GetForgerySuffix(string language) => language switch + { + "de" => "fälschung", + "es" => "falsificación", + "fr" => "falsification", + "it" => "falsificazione", + "ko" => "위조", + "ja" => "偽造", + "chs" => "伪造", + "cht" => "偽造", + _ => "forgery", + }; + + private static readonly Dictionary InternalItemList = new() + { + {4200, "k.k. slider's guitar (internal)"}, + }; + + private static void AddColoredItems(Dictionary result, string msgPath) + { + var pgname = Path.Combine(msgPath, "Outfit", "GroupName"); // (baseItemName, groupID) + var pgcolor = Path.Combine(msgPath, "Outfit", "GroupColor"); // (itemID_type_groupID, color) + var fgname = Directory.EnumerateFiles(pgname); + var fgcolor = Directory.EnumerateFiles(pgcolor); + + var coloredItemList = GetLabelList(fgcolor); + var coloredItemBaseNameList = GetLabelList(fgname); + var baseColorItem = coloredItemBaseNameList + .ToDictionary(z => (ushort) short.Parse(z.Label), z => z.Text); + + foreach (var (label, text) in coloredItemList) + { + var (itemID, baseId) = GetUniqueColorItemDefinition(label); + if (!baseColorItem.TryGetValue(baseId, out var baseItemName)) + continue; + + var itemName = $"{baseItemName} ({text})"; + result.Add(itemID, itemName); + } + } + + private static IEnumerable<(string Label, string Text)> GetLabelList(IEnumerable files) + { + foreach (var path in files.Where(z => z.EndsWith("msbt"))) + { + foreach (var valueTuple in GetLabelList(path)) + yield return valueTuple; + } + } + + public static IEnumerable<(string Label, string Text)> GetLabelList(string path) + { + var msbt = new MSBT(File.ReadAllBytes(path)); + foreach (var e in msbt.LBL1.Labels) + yield return GetCleanLabelText(e, msbt.TXT2.Strings); + } + + private static (string Label, string Text) GetCleanLabelText(MSBTLabel lbl, List txt) + { + var label = lbl.Name; + var index = (int)lbl.Index; + var strObj = txt[index]; + var text = strObj.ToStringNoAtoms(); + return (label, text); + } + + private static (ushort ItemID, ushort BaseID) GetUniqueColorItemDefinition(string line) + { + var split = line.Split('_'); + + var BaseID = ushort.Parse(split[0]); + //Type = split[1]; + var ItemID = ushort.Parse(split[2]); + + return (ItemID, BaseID); + } +} \ No newline at end of file diff --git a/NHSE.Parsing/GameMSBTDumperNHSE.cs b/NHSE.Parsing/GameMSBTDumperNHSE.cs index 8d31843..4796f8e 100644 --- a/NHSE.Parsing/GameMSBTDumperNHSE.cs +++ b/NHSE.Parsing/GameMSBTDumperNHSE.cs @@ -2,88 +2,87 @@ using System.IO; using System.Linq; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +/// +/// Logic for dumping intermediary assets used by NHSE +/// +public static class GameMSBTDumperNHSE { /// - /// Logic for dumping intermediary assets used by NHSE + /// NHSE language code -> Game Language identifier /// - public static class GameMSBTDumperNHSE + private static readonly IReadOnlyDictionary Languages = new Dictionary { - /// - /// NHSE language code -> Game Language identifier - /// - private static readonly IReadOnlyDictionary Languages = new Dictionary + {"en", "USen"}, + {"jp", "JPja"}, + {"zhs", "CNzh"}, + {"zht", "TWzh"}, + {"de", "EUde"}, + {"fr", "EUfr"}, + {"it", "EUit"}, + {"es", "EUes"}, + {"ko", "KRko"}, + }; + + public static void Dump(string repoPath, string messageStringPath, string unpackedMessageFormat) + { + string corePath = Path.Combine(repoPath, @"NHSE\NHSE.Core\Resources\text\"); + string folder = Path.Combine(messageStringPath, unpackedMessageFormat); + + foreach (var entry in Languages) + DumpLanguageResources(entry, corePath, folder); + } + + private static void DumpLanguageResources(KeyValuePair entry, string corePath, string msbtFolder) + { + var langID = entry.Key; + var langFolderCode = entry.Value; + DumpItem(corePath, langID, msbtFolder, langFolderCode); + DumpVillager(corePath, langID, msbtFolder, langFolderCode); + DumpVillagerPhrase(corePath, langID, msbtFolder, langFolderCode); + DumpRemake(corePath, langID, msbtFolder, langFolderCode); + } + + private static void DumpVillager(string corePath, string langID, string msbtFolder, string langFolderCode) + { + var dest = Path.Combine(corePath, langID, $"text_villager_{langID}.txt"); + var file = string.Format(msbtFolder, langFolderCode); + var villager = GameMSBTDumper.GetVillagerListResource(file); + File.WriteAllLines(dest, villager); + } + + private static void DumpVillagerPhrase(string corePath, string langID, string msbtFolder, string langFolderCode) + { + var dest = Path.Combine(corePath, langID, $"text_phrase_{langID}.txt"); + var file = string.Format(msbtFolder, langFolderCode); + var villager = GameMSBTDumper.GetVillagerPhraseResource(file); + File.WriteAllLines(dest, villager); + } + + private static void DumpItem(string corePath, string langID, string msbtFolder, string langFolderCode) + { + var dest = Path.Combine(corePath, langID, $"text_item_{langID}.txt"); + var file = string.Format(msbtFolder, langFolderCode); + var items = GameMSBTDumper.GetItemListResource(file, langID); + File.WriteAllLines(dest, items); + } + + private static void DumpRemake(string corePath, string langID, string msbtFolder, string langFolderCode) + { + DumpMSBT("body_color", "STR_Remake_BodyColor.msbt"); + DumpMSBT("body_parts", "STR_Remake_BodyParts.msbt"); + DumpMSBT("fabric_color", "STR_Remake_FabricColor.msbt"); + DumpMSBT("fabric_parts", "STR_Remake_FabricParts.msbt"); + void DumpMSBT(string name, string msbt) { - {"en", "USen"}, - {"jp", "JPja"}, - {"zhs", "CNzh"}, - {"zht", "TWzh"}, - {"de", "EUde"}, - {"fr", "EUfr"}, - {"it", "EUit"}, - {"es", "EUes"}, - {"ko", "KRko"}, - }; + var dest = Path.Combine(corePath, langID, $"text_{name}_{langID}.txt"); + var folder = string.Format(msbtFolder, langFolderCode); + var file = Path.Combine(folder, "Remake", msbt); - public static void Dump(string repoPath, string messageStringPath, string unpackedMessageFormat) - { - string corePath = Path.Combine(repoPath, @"NHSE\NHSE.Core\Resources\text\"); - string folder = Path.Combine(messageStringPath, unpackedMessageFormat); - - foreach (var entry in Languages) - DumpLanguageResources(entry, corePath, folder); - } - - private static void DumpLanguageResources(KeyValuePair entry, string corePath, string msbtFolder) - { - var langID = entry.Key; - var langFolderCode = entry.Value; - DumpItem(corePath, langID, msbtFolder, langFolderCode); - DumpVillager(corePath, langID, msbtFolder, langFolderCode); - DumpVillagerPhrase(corePath, langID, msbtFolder, langFolderCode); - DumpRemake(corePath, langID, msbtFolder, langFolderCode); - } - - private static void DumpVillager(string corePath, string langID, string msbtFolder, string langFolderCode) - { - var dest = Path.Combine(corePath, langID, $"text_villager_{langID}.txt"); - var file = string.Format(msbtFolder, langFolderCode); - var villager = GameMSBTDumper.GetVillagerListResource(file); - File.WriteAllLines(dest, villager); - } - - private static void DumpVillagerPhrase(string corePath, string langID, string msbtFolder, string langFolderCode) - { - var dest = Path.Combine(corePath, langID, $"text_phrase_{langID}.txt"); - var file = string.Format(msbtFolder, langFolderCode); - var villager = GameMSBTDumper.GetVillagerPhraseResource(file); - File.WriteAllLines(dest, villager); - } - - private static void DumpItem(string corePath, string langID, string msbtFolder, string langFolderCode) - { - var dest = Path.Combine(corePath, langID, $"text_item_{langID}.txt"); - var file = string.Format(msbtFolder, langFolderCode); - var items = GameMSBTDumper.GetItemListResource(file, langID); - File.WriteAllLines(dest, items); - } - - private static void DumpRemake(string corePath, string langID, string msbtFolder, string langFolderCode) - { - DumpMSBT("body_color", "STR_Remake_BodyColor.msbt"); - DumpMSBT("body_parts", "STR_Remake_BodyParts.msbt"); - DumpMSBT("fabric_color", "STR_Remake_FabricColor.msbt"); - DumpMSBT("fabric_parts", "STR_Remake_FabricParts.msbt"); - void DumpMSBT(string name, string msbt) - { - var dest = Path.Combine(corePath, langID, $"text_{name}_{langID}.txt"); - var folder = string.Format(msbtFolder, langFolderCode); - var file = Path.Combine(folder, "Remake", msbt); - - var lines = GameMSBTDumper.GetLabelList(file); - var result = lines.Select(z => z.Label.Substring(z.Label.IndexOf('_') + 1) + "\t" + z.Text).OrderBy(z => z); - File.WriteAllLines(dest, result); - } + var lines = GameMSBTDumper.GetLabelList(file); + var result = lines.Select(z => z.Label[(z.Label.IndexOf('_') + 1)..] + "\t" + z.Text).Order(); + File.WriteAllLines(dest, result); } } -} +} \ No newline at end of file diff --git a/NHSE.Parsing/GamePBCDumper.cs b/NHSE.Parsing/GamePBCDumper.cs index 07b75bc..e4b49b4 100644 --- a/NHSE.Parsing/GamePBCDumper.cs +++ b/NHSE.Parsing/GamePBCDumper.cs @@ -3,34 +3,31 @@ using System.Linq; using NHSE.Core; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public static class GamePBCDumper { - public static class GamePBCDumper + public static void DumpOutsideAcrePixels(string modelPath, string path) { - public static void DumpOutsideAcrePixels(string modelPath, string path) + var files = Directory.EnumerateFiles(modelPath, "*.pbc", SearchOption.AllDirectories); + + const int acreSize = 32 * 32 * 4; + var maxAcre = Enum.GetValues().Max(); + var result = new byte[acreSize * ((int)maxAcre + 1)]; + + foreach (var f in files) { - var files = Directory.EnumerateFiles(modelPath, "*.pbc", SearchOption.AllDirectories); + var fn = Path.GetFileNameWithoutExtension(f); + if (!Enum.TryParse(fn, out var acre)) + continue; - const int acreSize = 32 * 32 * 4; - var maxAcre = Enum.GetValues(typeof(OutsideAcre)).Cast().Max(); - var result = new byte[acreSize * ((int)maxAcre + 1)]; + var data = File.ReadAllBytes(f); + var pbc = new PBC(data); - foreach (var f in files) - { - var fn = Path.GetFileNameWithoutExtension(f); - if (fn == null) - continue; - if (!Enum.TryParse(fn, out var acre)) - continue; - - var data = File.ReadAllBytes(f); - var pbc = new PBC(data); - - var index = (int)acre; - var offset = acreSize * index; - pbc.Tiles.CopyTo(result, offset); - } - File.WriteAllBytes(path, result); - } + var index = (int)acre; + var offset = acreSize * index; + pbc.Tiles.CopyTo(result, offset); + } + File.WriteAllBytes(path, result); } -} +} \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/BinaryReaderX.cs b/NHSE.Parsing/MSBT/BinaryReaderX.cs index c47c1e9..59745f2 100644 --- a/NHSE.Parsing/MSBT/BinaryReaderX.cs +++ b/NHSE.Parsing/MSBT/BinaryReaderX.cs @@ -1,53 +1,49 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +internal class BinaryReaderX(Stream input, ByteOrder byteOrder = ByteOrder.LittleEndian) : BinaryReader(input) { - internal class BinaryReaderX : BinaryReader + public ByteOrder ByteOrder { get; set; } = byteOrder; + + public override ushort ReadUInt16() { - public ByteOrder ByteOrder { get; set; } + if (ByteOrder == ByteOrder.LittleEndian) + return base.ReadUInt16(); + var buffer = base.ReadBytes(sizeof(ushort)); + if (buffer.Length != sizeof(ushort)) + throw new EndOfStreamException(); + return ReadUInt16BigEndian(buffer); + } - public BinaryReaderX(Stream input, ByteOrder byteOrder = ByteOrder.LittleEndian) - : base(input) - { - ByteOrder = byteOrder; - } + public override uint ReadUInt32() + { + if (ByteOrder == ByteOrder.LittleEndian) + return base.ReadUInt32(); + var buffer = base.ReadBytes(sizeof(uint)); + if (buffer.Length != sizeof(uint)) + throw new EndOfStreamException(); + return ReadUInt32BigEndian(buffer); + } - public override ushort ReadUInt16() - { - if (ByteOrder == ByteOrder.LittleEndian) - return base.ReadUInt16(); - else - return BitConverter.ToUInt16(base.ReadBytes(2).Reverse().ToArray(), 0); - } + public string ReadString(int length) + { + return Encoding.ASCII.GetString(ReadBytes(length)).TrimEnd('\0'); + } - public override uint ReadUInt32() - { - if (ByteOrder == ByteOrder.LittleEndian) - return base.ReadUInt32(); - else - return BitConverter.ToUInt32(base.ReadBytes(4).Reverse().ToArray(), 0); - } + public string PeekString(int length = 4) + { + List bytes = []; + long startOffset = BaseStream.Position; - public string ReadString(int length) - { - return Encoding.ASCII.GetString(ReadBytes(length)).TrimEnd('\0'); - } + for (int i = 0; i < length; i++) + bytes.Add(ReadByte()); - public string PeekString(int length = 4) - { - List bytes = new(); - long startOffset = BaseStream.Position; + BaseStream.Seek(startOffset, SeekOrigin.Begin); - for (int i = 0; i < length; i++) - bytes.Add(ReadByte()); - - BaseStream.Seek(startOffset, SeekOrigin.Begin); - - return Encoding.ASCII.GetString(bytes.ToArray()); - } + return Encoding.ASCII.GetString(bytes.ToArray()); } } \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/ByteOrder.cs b/NHSE.Parsing/MSBT/ByteOrder.cs index 77b051d..93bc457 100644 --- a/NHSE.Parsing/MSBT/ByteOrder.cs +++ b/NHSE.Parsing/MSBT/ByteOrder.cs @@ -1,8 +1,7 @@ -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public enum ByteOrder { - public enum ByteOrder - { - LittleEndian = 0, - BigEndian = 1 - } + LittleEndian = 0, + BigEndian = 1 } \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/LBL1.cs b/NHSE.Parsing/MSBT/LBL1.cs index f97f584..84ffb24 100644 --- a/NHSE.Parsing/MSBT/LBL1.cs +++ b/NHSE.Parsing/MSBT/LBL1.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class LBL1() : MSBTSection(string.Empty, []) { - public class LBL1 : MSBTSection - { - public uint NumberOfGroups; + public uint NumberOfGroups; - public readonly List Groups = new(); - public readonly List Labels = new(); - - public LBL1() : base(string.Empty, Array.Empty()) - { - } - } -} + public readonly List Groups = []; + public readonly List Labels = []; +} \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/MSBT.cs b/NHSE.Parsing/MSBT/MSBT.cs index 7d61007..5053bb3 100644 --- a/NHSE.Parsing/MSBT/MSBT.cs +++ b/NHSE.Parsing/MSBT/MSBT.cs @@ -3,146 +3,145 @@ using System.IO; using System.Text; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class MSBT { - public class MSBT - { - public readonly MSBTHeader Header; - public readonly LBL1 LBL1 = new(); - public readonly TXT2 TXT2 = new(); - public readonly Encoding FileEncoding; - public readonly List SectionOrder; - public bool HasLabels; + public readonly MSBTHeader Header; + public readonly LBL1 LBL1 = new(); + public readonly TXT2 TXT2 = new(); + public readonly Encoding FileEncoding; + public readonly List SectionOrder; + public bool HasLabels; - public MSBT(byte[] rawBytes) - { - using var stream = new MemoryStream(rawBytes); - using var br = new BinaryReaderX(stream); + public MSBT(byte[] rawBytes) + { + using var stream = new MemoryStream(rawBytes, writable: false); + using var br = new BinaryReaderX(stream); - Header = new MSBTHeader(br); - FileEncoding = (Header.EncodingByte == MSBTEncodingByte.UTF8 ? Encoding.UTF8 : Encoding.Unicode); + Header = new MSBTHeader(br); + FileEncoding = (Header.EncodingByte == MSBTEncodingByte.UTF8 ? Encoding.UTF8 : Encoding.Unicode); - SectionOrder = new List(); - for (int i = 0; i < Header.NumberOfSections; i++) + SectionOrder = []; + for (int i = 0; i < Header.NumberOfSections; i++) + { + var peek = br.PeekString(); + switch (peek) { - var peek = br.PeekString(); - switch (peek) + case "LBL1": + ReadLBL1(br); + SectionOrder.Add("LBL1"); + break; + + case "ATR1": + // don't care + br.ReadBytes(sizeof(uint) + sizeof(uint) + sizeof(long) + 1); + while (br.BaseStream.Position % 16 != 0 && br.BaseStream.Position != br.BaseStream.Length) + br.ReadByte(); + SectionOrder.Add("ATR1"); + break; + + case "TXT2": + ReadTXT2(br); + SectionOrder.Add("TXT2"); + break; + } + } + + br.Close(); + } + + private void ReadLBL1(BinaryReaderX br) + { + LBL1.Identifier = br.ReadString(4); + LBL1.SectionSize = br.ReadUInt32(); + LBL1.Padding1 = br.ReadBytes(8); + long startOfLabels = br.BaseStream.Position; + LBL1.NumberOfGroups = br.ReadUInt32(); + + for (int i = 0; i < LBL1.NumberOfGroups; i++) + { + var grp = new MSBTGroup + { + NumberOfLabels = br.ReadUInt32(), + Offset = br.ReadUInt32() + }; + LBL1.Groups.Add(grp); + } + + foreach (var grp in LBL1.Groups) + { + br.BaseStream.Seek(startOfLabels + grp.Offset, SeekOrigin.Begin); + + for (int i = 0; i < grp.NumberOfLabels; i++) + { + var length = Convert.ToUInt32(br.ReadByte()); + var name = br.ReadString((int)length); + var index = br.ReadUInt32(); + var lbl = new MSBTLabel(name) {Index = index, Length = length}; + LBL1.Labels.Add(lbl); + } + } + + if (LBL1.Labels.Count > 0) + HasLabels = true; + + PaddingSeek(br); + } + + private void ReadTXT2(BinaryReaderX br) + { + TXT2.Identifier = br.ReadString(4); + TXT2.SectionSize = br.ReadUInt32(); + TXT2.Padding1 = br.ReadBytes(8); + long startOfStrings = br.BaseStream.Position; + TXT2.NumberOfStrings = br.ReadUInt32(); + + var offsets = new List(); + for (int i = 0; i < TXT2.NumberOfStrings; i++) + offsets.Add(br.ReadUInt32()); + + for (int i = 0; i < TXT2.NumberOfStrings; i++) + { + uint nextOffset = (i + 1 < offsets.Count) ? ((uint)startOfStrings + offsets[i + 1]) : ((uint)startOfStrings + TXT2.SectionSize); + + br.BaseStream.Seek(startOfStrings + offsets[i], SeekOrigin.Begin); + + var result = new List(); + while (br.BaseStream.Position < nextOffset && br.BaseStream.Position < Header.FileSize) + { + if (Header.EncodingByte == MSBTEncodingByte.UTF8) { - case "LBL1": - ReadLBL1(br); - SectionOrder.Add("LBL1"); - break; + result.Add(br.ReadByte()); + } + else + { + byte[] unichar = br.ReadBytes(2); - case "ATR1": - // don't care - br.ReadBytes(sizeof(uint) + sizeof(uint) + sizeof(long) + 1); - while (br.BaseStream.Position % 16 != 0 && br.BaseStream.Position != br.BaseStream.Length) - br.ReadByte(); - SectionOrder.Add("ATR1"); - break; + if (br.ByteOrder == ByteOrder.BigEndian) + Array.Reverse(unichar); - case "TXT2": - ReadTXT2(br); - SectionOrder.Add("TXT2"); - break; + result.AddRange(unichar); } } - - br.Close(); + var str = new MSBTTextString(result.ToArray(), (uint)i); + TXT2.Strings.Add(str); } - private void ReadLBL1(BinaryReaderX br) - { - LBL1.Identifier = br.ReadString(4); - LBL1.SectionSize = br.ReadUInt32(); - LBL1.Padding1 = br.ReadBytes(8); - long startOfLabels = br.BaseStream.Position; - LBL1.NumberOfGroups = br.ReadUInt32(); + // Tie in LBL1 labels + foreach (var lbl in LBL1.Labels) + lbl.String = TXT2.Strings[(int)lbl.Index]; - for (int i = 0; i < LBL1.NumberOfGroups; i++) - { - var grp = new MSBTGroup - { - NumberOfLabels = br.ReadUInt32(), - Offset = br.ReadUInt32() - }; - LBL1.Groups.Add(grp); - } + PaddingSeek(br); + } - foreach (var grp in LBL1.Groups) - { - br.BaseStream.Seek(startOfLabels + grp.Offset, SeekOrigin.Begin); - - for (int i = 0; i < grp.NumberOfLabels; i++) - { - var length = Convert.ToUInt32(br.ReadByte()); - var name = br.ReadString((int)length); - var index = br.ReadUInt32(); - var lbl = new MSBTLabel(name) {Index = index, Length = length}; - LBL1.Labels.Add(lbl); - } - } - - if (LBL1.Labels.Count > 0) - HasLabels = true; - - PaddingSeek(br); - } - - private void ReadTXT2(BinaryReaderX br) - { - TXT2.Identifier = br.ReadString(4); - TXT2.SectionSize = br.ReadUInt32(); - TXT2.Padding1 = br.ReadBytes(8); - long startOfStrings = br.BaseStream.Position; - TXT2.NumberOfStrings = br.ReadUInt32(); - - var offsets = new List(); - for (int i = 0; i < TXT2.NumberOfStrings; i++) - offsets.Add(br.ReadUInt32()); - - for (int i = 0; i < TXT2.NumberOfStrings; i++) - { - uint nextOffset = (i + 1 < offsets.Count) ? ((uint)startOfStrings + offsets[i + 1]) : ((uint)startOfStrings + TXT2.SectionSize); - - br.BaseStream.Seek(startOfStrings + offsets[i], SeekOrigin.Begin); - - var result = new List(); - while (br.BaseStream.Position < nextOffset && br.BaseStream.Position < Header.FileSize) - { - if (Header.EncodingByte == MSBTEncodingByte.UTF8) - { - result.Add(br.ReadByte()); - } - else - { - byte[] unichar = br.ReadBytes(2); - - if (br.ByteOrder == ByteOrder.BigEndian) - Array.Reverse(unichar); - - result.AddRange(unichar); - } - } - var str = new MSBTTextString(result.ToArray(), (uint)i); - TXT2.Strings.Add(str); - } - - // Tie in LBL1 labels - foreach (var lbl in LBL1.Labels) - lbl.String = TXT2.Strings[(int)lbl.Index]; - - PaddingSeek(br); - } - - private static void PaddingSeek(BinaryReader br) - { - long remainder = br.BaseStream.Position % 16; - if (remainder <= 0) - return; - var _ = br.ReadByte(); - br.BaseStream.Seek(-1, SeekOrigin.Current); - br.BaseStream.Seek(16 - remainder, SeekOrigin.Current); - } - } -} + private static void PaddingSeek(BinaryReader br) + { + long remainder = br.BaseStream.Position % 16; + if (remainder <= 0) + return; + _ = br.ReadByte(); + br.BaseStream.Seek(-1, SeekOrigin.Current); + br.BaseStream.Seek(16 - remainder, SeekOrigin.Current); + } +} \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/MSBTEncodingByte.cs b/NHSE.Parsing/MSBT/MSBTEncodingByte.cs index 7ad7259..0185cab 100644 --- a/NHSE.Parsing/MSBT/MSBTEncodingByte.cs +++ b/NHSE.Parsing/MSBT/MSBTEncodingByte.cs @@ -1,8 +1,7 @@ -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public enum MSBTEncodingByte : byte { - public enum MSBTEncodingByte : byte - { - UTF8 = 0x00, - Unicode = 0x01 - } + UTF8 = 0x00, + Unicode = 0x01 } \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/MSBTGroup.cs b/NHSE.Parsing/MSBT/MSBTGroup.cs index 0a0ed08..34353fb 100644 --- a/NHSE.Parsing/MSBT/MSBTGroup.cs +++ b/NHSE.Parsing/MSBT/MSBTGroup.cs @@ -1,8 +1,7 @@ -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class MSBTGroup { - public class MSBTGroup - { - public uint NumberOfLabels; - public uint Offset; - } + public uint NumberOfLabels; + public uint Offset; } \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/MSBTHeader.cs b/NHSE.Parsing/MSBT/MSBTHeader.cs index 94057d7..1eced1c 100644 --- a/NHSE.Parsing/MSBT/MSBTHeader.cs +++ b/NHSE.Parsing/MSBT/MSBTHeader.cs @@ -1,46 +1,45 @@ using System; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class MSBTHeader { - public class MSBTHeader + public readonly string Identifier; // MsgStdBn + public readonly byte[] ByteOrderMark; + public readonly ushort Unknown1; // Always 0x0000 + public readonly MSBTEncodingByte EncodingByte; + public readonly byte Unknown2; // Always 0x03 + public readonly ushort NumberOfSections; + public readonly ushort Unknown3; // Always 0x0000 + public readonly uint FileSize; + public readonly byte[] Unknown4; // Always 0x0000 0000 0000 0000 0000 + + public uint FileSizeOffset; + + internal MSBTHeader(BinaryReaderX br) { - public readonly string Identifier; // MsgStdBn - public readonly byte[] ByteOrderMark; - public readonly ushort Unknown1; // Always 0x0000 - public readonly MSBTEncodingByte EncodingByte; - public readonly byte Unknown2; // Always 0x03 - public readonly ushort NumberOfSections; - public readonly ushort Unknown3; // Always 0x0000 - public readonly uint FileSize; - public readonly byte[] Unknown4; // Always 0x0000 0000 0000 0000 0000 + // Header + Identifier = br.ReadString(8); + if (Identifier != "MsgStdBn") + throw new ArgumentException("The file provided is not a valid MSBT file."); - public uint FileSizeOffset; + // Byte Order + ByteOrderMark = br.ReadBytes(2); + br.ByteOrder = ByteOrderMark[0] > ByteOrderMark[1] ? ByteOrder.LittleEndian : ByteOrder.BigEndian; - internal MSBTHeader(BinaryReaderX br) - { - // Header - Identifier = br.ReadString(8); - if (Identifier != "MsgStdBn") - throw new ArgumentException("The file provided is not a valid MSBT file."); + Unknown1 = br.ReadUInt16(); - // Byte Order - ByteOrderMark = br.ReadBytes(2); - br.ByteOrder = ByteOrderMark[0] > ByteOrderMark[1] ? ByteOrder.LittleEndian : ByteOrder.BigEndian; + // Encoding + EncodingByte = (MSBTEncodingByte)br.ReadByte(); - Unknown1 = br.ReadUInt16(); + Unknown2 = br.ReadByte(); + NumberOfSections = br.ReadUInt16(); + Unknown3 = br.ReadUInt16(); + FileSizeOffset = (uint)br.BaseStream.Position; // Record offset for future use + FileSize = br.ReadUInt32(); + Unknown4 = br.ReadBytes(10); - // Encoding - EncodingByte = (MSBTEncodingByte)br.ReadByte(); - - Unknown2 = br.ReadByte(); - NumberOfSections = br.ReadUInt16(); - Unknown3 = br.ReadUInt16(); - FileSizeOffset = (uint)br.BaseStream.Position; // Record offset for future use - FileSize = br.ReadUInt32(); - Unknown4 = br.ReadBytes(10); - - if (FileSize != br.BaseStream.Length) - throw new ArgumentException("The file provided is not a valid MSBT file."); - } + if (FileSize != br.BaseStream.Length) + throw new ArgumentException("The file provided is not a valid MSBT file."); } } \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/MSBTLabel.cs b/NHSE.Parsing/MSBT/MSBTLabel.cs index 64e679d..5160358 100644 --- a/NHSE.Parsing/MSBT/MSBTLabel.cs +++ b/NHSE.Parsing/MSBT/MSBTLabel.cs @@ -1,21 +1,20 @@ using System.Text; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class MSBTLabel { - public class MSBTLabel + public uint Length; + public readonly string Name; + public MSBTTextString String; + + public MSBTLabel(string name) { - public uint Length; - public readonly string Name; - public MSBTTextString String; - - public MSBTLabel(string name) - { - Name = name; - String = MSBTTextString.Empty; - } - - public uint Index { get; set; } - public override string ToString() => Length > 0 ? Name : (Index + 1).ToString(); - public string ToString(Encoding encoding) => encoding.GetString(String.Value); + Name = name; + String = MSBTTextString.Empty; } + + public uint Index { get; set; } + public override string ToString() => Length > 0 ? Name : (Index + 1).ToString(); + public string ToString(Encoding encoding) => encoding.GetString(String.Value.Span); } \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/MSBTSection.cs b/NHSE.Parsing/MSBT/MSBTSection.cs index 6722b50..8a5fc7a 100644 --- a/NHSE.Parsing/MSBT/MSBTSection.cs +++ b/NHSE.Parsing/MSBT/MSBTSection.cs @@ -1,15 +1,14 @@ -namespace NHSE.Parsing -{ - public class MSBTSection - { - public string Identifier; - public uint SectionSize; // Begins after Unknown1 - public byte[] Padding1; // Always 0x0000 0000 +namespace NHSE.Parsing; - public MSBTSection(string identifier, byte[] padding) - { - Identifier = identifier; - Padding1 = padding; - } +public class MSBTSection +{ + public string Identifier; + public uint SectionSize; // Begins after Unknown1 + public byte[] Padding1; // Always 0x0000 0000 + + public MSBTSection(string identifier, byte[] padding) + { + Identifier = identifier; + Padding1 = padding; } -} +} \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/MSBTTextString.cs b/NHSE.Parsing/MSBT/MSBTTextString.cs index dd0f947..73ce141 100644 --- a/NHSE.Parsing/MSBT/MSBTTextString.cs +++ b/NHSE.Parsing/MSBT/MSBTTextString.cs @@ -1,48 +1,48 @@ using System; using System.Text; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class MSBTTextString { - public class MSBTTextString + public readonly Memory Value; + public readonly uint Index; + + public static readonly MSBTTextString Empty = new(default, 0); + + public MSBTTextString(Memory v, uint i) { - public readonly byte[] Value; - public readonly uint Index; + Value = v; + Index = i; + } - public static readonly MSBTTextString Empty = new(Array.Empty(), 0); + public override string ToString() => (Index + 1).ToString(); - public MSBTTextString(byte[] v, uint i) + public string ToString(Encoding encoding) => encoding.GetString(Value.Span); + + public string ToStringNoAtoms() => GetTextWithoutAtoms(Value.Span); + + public static string GetTextWithoutAtoms(ReadOnlySpan data) + { + var sb = new StringBuilder(data.Length / 2); + for (int i = 0; i < data.Length; i += 2) { - Value = v; - Index = i; - } - - public override string ToString() => (Index + 1).ToString(); - - public string ToString(Encoding encoding) => encoding.GetString(Value); - - public string ToStringNoAtoms() => GetTextWithoutAtoms(Value); - - public static string GetTextWithoutAtoms(byte[] data) - { - var sb = new StringBuilder(); - for (int i = 0; i < data.Length; i += 2) + var c = (char)ReadUInt16LittleEndian(data[i..]); + if (c == 0xE) // atom { - char c = BitConverter.ToChar(data, i); - if (c == 0xE) // atom - { - // skip over atom and the u16,u16 - i += 2 * 3; - var len = BitConverter.ToUInt16(data, i); - i += len; // skip over extra atom data - continue; - } - - if (c == '\0') - break; - sb.Append(c); + // skip over atom and the u16,u16 + i += 2 * 3; + var len = ReadUInt16LittleEndian(data[i..]); + i += len; // skip over extra atom data + continue; } - return sb.ToString(); + if (c == '\0') + break; + sb.Append(c); } + + return sb.ToString(); } -} +} \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/MSBTUtil.cs b/NHSE.Parsing/MSBT/MSBTUtil.cs index a6a8043..6c0b4fa 100644 --- a/NHSE.Parsing/MSBT/MSBTUtil.cs +++ b/NHSE.Parsing/MSBT/MSBTUtil.cs @@ -3,33 +3,32 @@ using System.IO; using System.Linq; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public static class MSBTUtil { - public static class MSBTUtil + public static void DebugDumpLines(this MSBT obj) { - public static void DebugDumpLines(this MSBT obj) + var lines = obj.GetOrderedLines(); + foreach (var line in lines) + Debug.WriteLine(line); + } + + public static IEnumerable GetOrderedLines(string path, int indexBias = 0) => new MSBT(File.ReadAllBytes(path)).GetOrderedLines(indexBias); + + public static IEnumerable GetOrderedLines(this MSBT obj, int indexBias = 0) + { + var sorted = obj.LBL1.Labels + .Where(z => !z.Name.EndsWith("_pl")) + .OrderBy(z => z.Index); + + foreach (var x in sorted) { - var lines = obj.GetOrderedLines(); - foreach (var line in lines) - Debug.WriteLine(line); - } - - public static IEnumerable GetOrderedLines(string path, int indexBias = 0) => new MSBT(File.ReadAllBytes(path)).GetOrderedLines(indexBias); - - public static IEnumerable GetOrderedLines(this MSBT obj, int indexBias = 0) - { - var sorted = obj.LBL1.Labels - .Where(z => !z.Name.EndsWith("_pl")) - .OrderBy(z => z.Index); - - foreach (var x in sorted) - { - var index = x.Index; - var name = x.Name; - var data = obj.TXT2.Strings[(int)index]; - var line = data.ToString(obj.FileEncoding).TrimEnd('\0'); - yield return $"{line} = {index + indexBias}, // {name}"; - } + var index = x.Index; + var name = x.Name; + var data = obj.TXT2.Strings[(int)index]; + var line = data.ToString(obj.FileEncoding).TrimEnd('\0'); + yield return $"{line} = {index + indexBias}, // {name}"; } } -} +} \ No newline at end of file diff --git a/NHSE.Parsing/MSBT/TXT2.cs b/NHSE.Parsing/MSBT/TXT2.cs index ae73b3e..b5c066d 100644 --- a/NHSE.Parsing/MSBT/TXT2.cs +++ b/NHSE.Parsing/MSBT/TXT2.cs @@ -1,16 +1,10 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class TXT2() : MSBTSection(string.Empty, []) { - public class TXT2 : MSBTSection - { - public uint NumberOfStrings; + public uint NumberOfStrings; - public readonly List Strings = new(); - - public TXT2() : base(string.Empty, Array.Empty()) - { - } - } -} + public readonly List Strings = []; +} \ No newline at end of file diff --git a/NHSE.Parsing/NHSE.Parsing.csproj b/NHSE.Parsing/NHSE.Parsing.csproj index b8d1ef1..3268690 100644 --- a/NHSE.Parsing/NHSE.Parsing.csproj +++ b/NHSE.Parsing/NHSE.Parsing.csproj @@ -1,9 +1,5 @@  - - netstandard2.0 - - diff --git a/NHSE.Parsing/PBC/PBC.cs b/NHSE.Parsing/PBC/PBC.cs index 9012771..187d643 100644 --- a/NHSE.Parsing/PBC/PBC.cs +++ b/NHSE.Parsing/PBC/PBC.cs @@ -2,53 +2,54 @@ using System.Diagnostics; using System.Drawing; using NHSE.Core; +using static System.Buffers.Binary.BinaryPrimitives; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +public class PBC { - public class PBC + private const uint MAGIC = 0x00636270; // pbc\0 + + public readonly Memory Raw; + private Span Data => Raw.Span; + + public PBC(Memory data) { - private const uint MAGIC = 0x00636270; // pbc\0 + Raw = data; + Debug.Assert(Magic == MAGIC); - public readonly byte[] Data; - - public PBC(byte[] data) - { - Data = data; - Debug.Assert(Magic == MAGIC); - - Tiles = GetTiles(); - } - - public readonly byte[] Tiles; - - private byte[] GetTiles() - { - int offset = 0x14; - var w = Width; - var h = Height; - byte[] data = new byte[w * h * 4]; - - for (int y = 0; y < h; y++) - { - for (int x = 0; x < w; x++) - { - var ofs = offset + 0x30; - data[(x * 2) + (w * 2 * (y * 2))] = Data[ofs + 0]; - data[(x * 2) + (w * 2 * ((y * 2) + 1))] = Data[ofs + 1]; - data[(x * 2) + (w * 2 * ((y * 2) + 1)) + 1] = Data[ofs + 2]; - data[(x * 2) + (w * 2 * (y * 2)) + 1] = Data[ofs + 3]; - offset += 0x34; - } - } - - return data; - } - - public byte GetTile(int x, int y) => Tiles[(y * Width) + x]; - public Color GetTileColor(int x, int y) => CollisionUtil.Dict[GetTile(x, y)]; - - public uint Magic => BitConverter.ToUInt32(Data, 0x00); - public uint Width => BitConverter.ToUInt32(Data, 0x04); - public uint Height => BitConverter.ToUInt32(Data, 0x08); + Tiles = GetTiles(); } -} + + public readonly byte[] Tiles; + + private byte[] GetTiles() + { + int offset = 0x14; + var w = Width; + var h = Height; + byte[] data = new byte[w * h * 4]; + + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++) + { + var ofs = offset + 0x30; + data[(x * 2) + (w * 2 * (y * 2))] = Data[ofs + 0]; + data[(x * 2) + (w * 2 * ((y * 2) + 1))] = Data[ofs + 1]; + data[(x * 2) + (w * 2 * ((y * 2) + 1)) + 1] = Data[ofs + 2]; + data[(x * 2) + (w * 2 * (y * 2)) + 1] = Data[ofs + 3]; + offset += 0x34; + } + } + + return data; + } + + public byte GetTile(int x, int y) => Tiles[(y * Width) + x]; + public Color GetTileColor(int x, int y) => CollisionUtil.Dict[GetTile(x, y)]; + + public uint Magic => ReadUInt32LittleEndian(Data); + public uint Width => ReadUInt32LittleEndian(Data[0x04..]); + public uint Height => ReadUInt32LittleEndian(Data[0x08..]); +} \ No newline at end of file diff --git a/NHSE.Parsing/ParseConverter.cs b/NHSE.Parsing/ParseConverter.cs index af91913..3b49c26 100644 --- a/NHSE.Parsing/ParseConverter.cs +++ b/NHSE.Parsing/ParseConverter.cs @@ -1,46 +1,45 @@ using System.IO; using System.Linq; -namespace NHSE.Parsing +namespace NHSE.Parsing; + +/// +/// Logic for converting various dumps to resources used by the Core project. +/// +public static class ParseConverter { /// - /// Logic for converting various dumps to resources used by the Core project. + /// Converts {Hex, Name} to an index-able list of strings. /// - public static class ParseConverter + /// Path to Key Value pair listing, with keys being hex numbers (without 0x prefix) + /// File to write the result list to + public static void ConvertItemStrings(string input, string output) { - /// - /// Converts {Hex, Name} to an index-able list of strings. - /// - /// Path to Key Value pair listing, with keys being hex numbers (without 0x prefix) - /// File to write the result list to - public static void ConvertItemStrings(string input, string output) - { - var result = ConvertItemList(input); - File.WriteAllLines(output, result); - } - - private static string[] ConvertItemList(string path) - { - var lines = File.ReadAllLines(path); - var items = lines.Select(z => new ParseItem(z)).ToArray(); - - var max = items.Max(z => z.Index); - var result = new string[max + 1]; - foreach (var item in items) - result[item.Index] = item.Name; - return result; - } + var result = ConvertItemList(input); + File.WriteAllLines(output, result); } - public class ParseItem + private static string[] ConvertItemList(string path) { - public readonly int Index; - public readonly string Name; - public ParseItem(string line) - { - var split = line.Split(new[] { ", " }, 0); - Index = int.Parse(split[0], System.Globalization.NumberStyles.HexNumber); - Name = split[1]; - } + var lines = File.ReadAllLines(path); + var items = lines.Select(z => new ParseItem(z)).ToArray(); + + var max = items.Max(z => z.Index); + var result = new string[max + 1]; + foreach (var item in items) + result[item.Index] = item.Name; + return result; } } + +public class ParseItem +{ + public readonly int Index; + public readonly string Name; + public ParseItem(string line) + { + var split = line.Split(", "); + Index = int.Parse(split[0], System.Globalization.NumberStyles.HexNumber); + Name = split[1]; + } +} \ No newline at end of file diff --git a/NHSE.Sprites/Field/ItemLayerSprite.cs b/NHSE.Sprites/Field/ItemLayerSprite.cs index dbe7fa3..27e90df 100644 --- a/NHSE.Sprites/Field/ItemLayerSprite.cs +++ b/NHSE.Sprites/Field/ItemLayerSprite.cs @@ -1,254 +1,254 @@ -using System.Drawing; +using System; +using System.Drawing; using NHSE.Core; -namespace NHSE.Sprites +namespace NHSE.Sprites; + +public static class ItemLayerSprite { - public static class ItemLayerSprite + public static Bitmap GetBitmapItemLayer(ItemLayer layer) { - public static Bitmap GetBitmapItemLayer(ItemLayer layer) + var items = layer.Tiles; + var height = layer.MaxHeight; + var width = items.Length / height; + + var bmpData = new int[width * height]; + LoadBitmapLayer(items, bmpData, width, height); + + return ImageUtil.GetBitmap(bmpData, width, height); + } + + private static void LoadBitmapLayer(ReadOnlySpan items, Span bmpData, int width, int height) + { + for (int x = 0; x < width; x++) { - var items = layer.Tiles; - var height = layer.MaxHeight; - var width = items.Length / height; - - var bmpData = new int[width * height]; - LoadBitmapLayer(items, bmpData, width, height); - - return ImageUtil.GetBitmap(bmpData, width, height); - } - - private static void LoadBitmapLayer(Item[] items, int[] bmpData, int width, int height) - { - for (int x = 0; x < width; x++) + var ix = x * height; + for (int y = 0; y < height; y++) { - var ix = x * height; - for (int y = 0; y < height; y++) - { - var index = ix + y; - var tile = items[index]; - bmpData[(y * width) + x] = FieldItemColor.GetItemColor(tile).ToArgb(); - } + var index = ix + y; + var tile = items[index]; + bmpData[(y * width) + x] = FieldItemColor.GetItemColor(tile).ToArgb(); } } - - private static void LoadPixelsFromLayer(ItemLayer layer, int x0, int y0, int width, int[] bmpData) - { - var stride = layer.GridWidth; - - for (int y = 0; y < stride; y++) - { - var baseIndex = (y * width); - for (int x = 0; x < stride; x++) - { - var tile = layer.GetTile(x + x0, y + y0); - var color = FieldItemColor.GetItemColor(tile).ToArgb(); - var index = baseIndex + x; - bmpData[index] = color; - } - } - } - - // non-allocation image generator - public static Bitmap GetBitmapItemLayerViewGrid(ItemLayer layer, int x0, int y0, int scale, int[] acre1, int[] acreScale, Bitmap dest, int transparency = -1, int gridlineColor = 0) - { - var w = layer.GridWidth; - var h = layer.GridHeight; - LoadPixelsFromLayer(layer, x0, y0, w, acre1); - w *= scale; - h *= scale; - ImageUtil.ScalePixelImage(acre1, acreScale, w, h, scale); - - if (transparency >> 24 != 0xFF) - ImageUtil.ClampAllTransparencyTo(acreScale, transparency); - - // draw symbols over special items now? - DrawDirectionals(acreScale, layer, w, x0, y0, scale); - - // Slap on a grid - DrawGrid(acreScale, w, h, scale, gridlineColor); - - // Return final data - ImageUtil.SetBitmapData(dest, acreScale); - return dest; - } - - private static void DrawDirectionals(int[] data, ItemLayer layer, int w, int x0, int y0, int scale) - { - for (int x = x0; x < x0 + layer.GridWidth; x++) - { - for (int y = y0; y < y0 + layer.GridHeight; y++) - { - var tile = layer.GetTile(x, y); - if (tile.IsNone) - continue; - if (tile.IsBuried) - DrawX(data, (x - x0) * scale, (y - y0) * scale, scale, w); - else if (tile.IsDropped) - DrawPlus(data, (x - x0) * scale, (y - y0) * scale, scale, w); - else if (tile.IsExtension) - DrawDirectional(data, tile, (x - x0) * scale, (y - y0) * scale, scale, w); - - var id = tile.DisplayItemId; - var kind = ItemInfo.GetItemKind(id); - if (kind.IsFlowerGene(id)) - { - int geneIndex; - if (tile.IsRoot) - { - geneIndex = 0; - } - else - { - geneIndex = (tile.ExtensionY << 1) | tile.ExtensionX; - tile = layer.GetTile(x - tile.ExtensionX, y - tile.ExtensionY); - } - - var genes = ((uint)tile.Genes ^ 0b00_11_00_00); // invert W bits - var geneValue = (genes >> (geneIndex * 2)) & 3; - if (geneValue == 0) - continue; - DrawGene(data, (x - x0) * scale, (y - y0) * scale, scale, w, geneValue, geneIndex); - } - } - } - } - - private static void DrawGene(int[] data, int x0, int y0, int scale, int w, uint geneValue, int geneIndex) - { - var c = ShiftToGeneCoordinate(ref x0, ref y0, scale, geneIndex); - FillSquare(data, x0, y0, scale / 2, w, c, geneValue == 3 ? 1 : 2); - } - - private static void FillSquare(int[] data, int x0, int y0, int scale, int w, int color, int increment) - { - var baseIndex = (y0 * w) + x0; - for (int i = 0; i < scale * scale; i += increment) - { - var x = i % scale; - var y = i / scale; - var index = (y * w) + x; - data[baseIndex + index] = color; - } - } - - private static int ShiftToGeneCoordinate(ref int x0, ref int y0, int scale, int geneIndex) - { - switch (geneIndex) - { - case 0: // bottom right - x0 += scale / 2; - y0 += scale / 2; - return Color.Red.ToArgb(); - case 1: // bottom left - y0 += scale / 2; - return Color.Yellow.ToArgb(); - case 2: // top right - x0 += scale / 2; - return Color.AntiqueWhite.ToArgb(); - default: // top left - return Color.Black.ToArgb(); - } - } - - private static void DrawPlus(int[] data, int x0, int y0, int scale, int w) - { - var x0y0 = (w * y0) + x0; - var s2 = scale / 2; - var ws2 = w * s2; - - var v0 = x0y0 + s2; - var h0 = x0y0 + ws2; - - for (int x = scale / 4; x <= 3 * (scale / 4); x++) - { - var vert = v0 + (w * x); - data[vert] ^= 0x808080; - var hori = h0 + x; - data[hori] ^= 0x808080; - } - } - - private static void DrawX(int[] data, int x0, int y0, int scale, int w) - { - var opposite = scale - 1; - var wo = w * opposite; - - // Starting offsets for each of the slashes - var bBackward = (w * y0) + x0; // Backwards \ - var bForward = bBackward + wo; // Forwards / - - for (int x = 0; x < scale; x++) - { - var wx = w * x; - var backward = bBackward + x + wx; - data[backward] ^= 0x808080; - var forward = bForward + x - wx; - data[forward] ^= 0x808080; - } - } - - private static void DrawDirectional(int[] data, Item tile, int x0, int y0, int scale, int w) - { - var eX = tile.ExtensionX; - var eY = tile.ExtensionY; - if (eX == 0 && eY == 0) - return; - var sum = eX + eY; - var start = scale / (sum + 1); - var startX = eX >= eY ? 0 : start; - var startY = eX <= eY ? 0 : start; - - var baseIndex = (w * y0) + x0; - for (int x = startX, y = startY; x < scale && y < scale; x += eX, y += eY) - { - var index = baseIndex + (w * y) + x; - data[index] ^= 0x808080; - } - } - - public static void DrawGrid(int[] data, int w, int h, int scale, int gridlineColor) - { - // Horizontal Lines - for (int y = scale; y < h; y += scale) - { - var baseIndex = y * w; - for (int x = 0; x < w; x++) - { - var index = baseIndex + x; - data[index] = gridlineColor; - } - } - - // Vertical Lines - for (int y = 0; y < h; y++) - { - var baseIndex = y * w; - for (int x = scale; x < w; x += scale) - { - var index = baseIndex + x; - data[index] = gridlineColor; - } - } - } - - public static Bitmap GetBitmapItemLayer(ItemLayer layer, int x, int y, int[] data, Bitmap dest, int transparency = -1) - { - LoadBitmapLayer(layer.Tiles, data, layer.MaxWidth, layer.MaxHeight); - if (transparency >> 24 != 0xFF) - ImageUtil.ClampAllTransparencyTo(data, transparency); - ImageUtil.SetBitmapData(dest, data); - return DrawViewReticle(dest, layer, x, y); - } - - private static Bitmap DrawViewReticle(Bitmap map, TileGrid g, int x, int y, int scale = 1) - { - using var gfx = Graphics.FromImage(map); - using var pen = new Pen(Color.Red); - - int w = g.GridWidth * scale; - int h = g.GridHeight * scale; - gfx.DrawRectangle(pen, x * scale, y * scale, w, h); - return map; - } } -} + + private static void LoadPixelsFromLayer(ItemLayer layer, int x0, int y0, int width, Span bmpData) + { + var stride = layer.GridWidth; + + for (int y = 0; y < stride; y++) + { + var baseIndex = (y * width); + for (int x = 0; x < stride; x++) + { + var tile = layer.GetTile(x + x0, y + y0); + var color = FieldItemColor.GetItemColor(tile).ToArgb(); + var index = baseIndex + x; + bmpData[index] = color; + } + } + } + + // non-allocation image generator + public static Bitmap GetBitmapItemLayerViewGrid(ItemLayer layer, int x0, int y0, int scale, Span acre1, int[] acreScale, Bitmap dest, int transparency = -1, int gridlineColor = 0) + { + var w = layer.GridWidth; + var h = layer.GridHeight; + LoadPixelsFromLayer(layer, x0, y0, w, acre1); + w *= scale; + h *= scale; + ImageUtil.ScalePixelImage(acre1, acreScale, w, h, scale); + + if (transparency >>> 24 != 0xFF) + ImageUtil.ClampAllTransparencyTo(acreScale, transparency); + + // draw symbols over special items now? + DrawDirectionals(acreScale, layer, w, x0, y0, scale); + + // Slap on a grid + DrawGrid(acreScale, w, h, scale, gridlineColor); + + // Return final data + ImageUtil.SetBitmapData(dest, acreScale); + return dest; + } + + private static void DrawDirectionals(Span data, ItemLayer layer, int w, int x0, int y0, int scale) + { + for (int x = x0; x < x0 + layer.GridWidth; x++) + { + for (int y = y0; y < y0 + layer.GridHeight; y++) + { + var tile = layer.GetTile(x, y); + if (tile.IsNone) + continue; + if (tile.IsBuried) + DrawX(data, (x - x0) * scale, (y - y0) * scale, scale, w); + else if (tile.IsDropped) + DrawPlus(data, (x - x0) * scale, (y - y0) * scale, scale, w); + else if (tile.IsExtension) + DrawDirectional(data, tile, (x - x0) * scale, (y - y0) * scale, scale, w); + + var id = tile.DisplayItemId; + var kind = ItemInfo.GetItemKind(id); + if (kind.IsFlowerGene(id)) + { + int geneIndex; + if (tile.IsRoot) + { + geneIndex = 0; + } + else + { + geneIndex = (tile.ExtensionY << 1) | tile.ExtensionX; + tile = layer.GetTile(x - tile.ExtensionX, y - tile.ExtensionY); + } + + var genes = ((uint)tile.Genes ^ 0b00_11_00_00); // invert W bits + var geneValue = (genes >> (geneIndex * 2)) & 3; + if (geneValue == 0) + continue; + DrawGene(data, (x - x0) * scale, (y - y0) * scale, scale, w, geneValue, geneIndex); + } + } + } + } + + private static void DrawGene(Span data, int x0, int y0, int scale, int w, uint geneValue, int geneIndex) + { + var c = ShiftToGeneCoordinate(ref x0, ref y0, scale, geneIndex); + FillSquare(data, x0, y0, scale / 2, w, c, geneValue == 3 ? 1 : 2); + } + + private static void FillSquare(Span data, int x0, int y0, int scale, int w, int color, int increment) + { + var baseIndex = (y0 * w) + x0; + for (int i = 0; i < scale * scale; i += increment) + { + var x = i % scale; + var y = i / scale; + var index = (y * w) + x; + data[baseIndex + index] = color; + } + } + + private static int ShiftToGeneCoordinate(ref int x0, ref int y0, int scale, int geneIndex) + { + switch (geneIndex) + { + case 0: // bottom right + x0 += scale / 2; + y0 += scale / 2; + return Color.Red.ToArgb(); + case 1: // bottom left + y0 += scale / 2; + return Color.Yellow.ToArgb(); + case 2: // top right + x0 += scale / 2; + return Color.AntiqueWhite.ToArgb(); + default: // top left + return Color.Black.ToArgb(); + } + } + + private static void DrawPlus(Span data, int x0, int y0, int scale, int w) + { + var x0y0 = (w * y0) + x0; + var s2 = scale / 2; + var ws2 = w * s2; + + var v0 = x0y0 + s2; + var h0 = x0y0 + ws2; + + for (int x = scale / 4; x <= 3 * (scale / 4); x++) + { + var vert = v0 + (w * x); + data[vert] ^= 0x808080; + var hori = h0 + x; + data[hori] ^= 0x808080; + } + } + + private static void DrawX(Span data, int x0, int y0, int scale, int w) + { + var opposite = scale - 1; + var wo = w * opposite; + + // Starting offsets for each of the slashes + var bBackward = (w * y0) + x0; // Backwards \ + var bForward = bBackward + wo; // Forwards / + + for (int x = 0; x < scale; x++) + { + var wx = w * x; + var backward = bBackward + x + wx; + data[backward] ^= 0x808080; + var forward = bForward + x - wx; + data[forward] ^= 0x808080; + } + } + + private static void DrawDirectional(Span data, Item tile, int x0, int y0, int scale, int w) + { + var eX = tile.ExtensionX; + var eY = tile.ExtensionY; + if (eX == 0 && eY == 0) + return; + var sum = eX + eY; + var start = scale / (sum + 1); + var startX = eX >= eY ? 0 : start; + var startY = eX <= eY ? 0 : start; + + var baseIndex = (w * y0) + x0; + for (int x = startX, y = startY; x < scale && y < scale; x += eX, y += eY) + { + var index = baseIndex + (w * y) + x; + data[index] ^= 0x808080; + } + } + + public static void DrawGrid(Span data, int w, int h, int scale, int gridlineColor) + { + // Horizontal Lines + for (int y = scale; y < h; y += scale) + { + var baseIndex = y * w; + for (int x = 0; x < w; x++) + { + var index = baseIndex + x; + data[index] = gridlineColor; + } + } + + // Vertical Lines + for (int y = 0; y < h; y++) + { + var baseIndex = y * w; + for (int x = scale; x < w; x += scale) + { + var index = baseIndex + x; + data[index] = gridlineColor; + } + } + } + + public static Bitmap GetBitmapItemLayer(ItemLayer layer, int x, int y, int[] data, Bitmap dest, int transparency = -1) + { + LoadBitmapLayer(layer.Tiles, data, layer.MaxWidth, layer.MaxHeight); + if (transparency >>> 24 != 0xFF) + ImageUtil.ClampAllTransparencyTo(data, transparency); + ImageUtil.SetBitmapData(dest, data); + return DrawViewReticle(dest, layer, x, y); + } + + private static Bitmap DrawViewReticle(Bitmap map, TileGrid g, int x, int y, int scale = 1) + { + using var gfx = Graphics.FromImage(map); + using var pen = new Pen(Color.Red); + + int w = g.GridWidth * scale; + int h = g.GridHeight * scale; + gfx.DrawRectangle(pen, x * scale, y * scale, w, h); + return map; + } +} \ No newline at end of file diff --git a/NHSE.Sprites/Field/MapViewer.cs b/NHSE.Sprites/Field/MapViewer.cs index 142c67d..6d38699 100644 --- a/NHSE.Sprites/Field/MapViewer.cs +++ b/NHSE.Sprites/Field/MapViewer.cs @@ -2,73 +2,72 @@ using System.Drawing; using NHSE.Core; -namespace NHSE.Sprites +namespace NHSE.Sprites; + +public sealed class MapViewer : MapView, IDisposable { - public sealed class MapViewer : MapView, IDisposable + // Cached acre view objects to remove allocation/GC + private readonly int[] PixelsItemAcre1; + private readonly int[] PixelsItemAcreX; + private readonly Bitmap ScaleAcre; + private readonly int[] PixelsItemMap; + private readonly Bitmap MapReticle; + + private readonly int[] PixelsBackgroundAcre1; + private readonly int[] PixelsBackgroundAcreX; + private readonly Bitmap BackgroundAcre; + private readonly int[] PixelsBackgroundMap1; + private readonly int[] PixelsBackgroundMapX; + private readonly Bitmap BackgroundMap; + + public MapViewer(MapManager m, int scale) : base(m, scale) { - // Cached acre view objects to remove allocation/GC - private readonly int[] PixelsItemAcre1; - private readonly int[] PixelsItemAcreX; - private readonly Bitmap ScaleAcre; - private readonly int[] PixelsItemMap; - private readonly Bitmap MapReticle; + var l1 = m.Items.Layer1; + PixelsItemAcre1 = new int[l1.GridWidth * l1.GridHeight]; + PixelsItemAcreX = new int[PixelsItemAcre1.Length * AcreScale * AcreScale]; + ScaleAcre = new Bitmap(l1.GridWidth * AcreScale, l1.GridHeight * AcreScale); - private readonly int[] PixelsBackgroundAcre1; - private readonly int[] PixelsBackgroundAcreX; - private readonly Bitmap BackgroundAcre; - private readonly int[] PixelsBackgroundMap1; - private readonly int[] PixelsBackgroundMapX; - private readonly Bitmap BackgroundMap; + PixelsItemMap = new int[l1.MaxWidth * l1.MaxHeight * MapScale * MapScale]; + MapReticle = new Bitmap(l1.MaxWidth * MapScale, l1.MaxHeight * MapScale); - public MapViewer(MapManager m, int scale) : base(m, scale) - { - var l1 = m.Items.Layer1; - PixelsItemAcre1 = new int[l1.GridWidth * l1.GridHeight]; - PixelsItemAcreX = new int[PixelsItemAcre1.Length * AcreScale * AcreScale]; - ScaleAcre = new Bitmap(l1.GridWidth * AcreScale, l1.GridHeight * AcreScale); + PixelsBackgroundAcre1 = new int[(int)Math.Pow(16, 4)]; + PixelsBackgroundAcreX = new int[PixelsItemAcreX.Length]; + BackgroundAcre = new Bitmap(ScaleAcre.Width, ScaleAcre.Height); - PixelsItemMap = new int[l1.MaxWidth * l1.MaxHeight * MapScale * MapScale]; - MapReticle = new Bitmap(l1.MaxWidth * MapScale, l1.MaxHeight * MapScale); + PixelsBackgroundMap1 = new int[PixelsItemMap.Length / 4]; + PixelsBackgroundMapX = new int[PixelsItemMap.Length]; + BackgroundMap = new Bitmap(MapReticle.Width, MapReticle.Height); + } - PixelsBackgroundAcre1 = new int[(int)Math.Pow(16, 4)]; - PixelsBackgroundAcreX = new int[PixelsItemAcreX.Length]; - BackgroundAcre = new Bitmap(ScaleAcre.Width, ScaleAcre.Height); + public void Dispose() + { + ScaleAcre.Dispose(); + MapReticle.Dispose(); + BackgroundAcre.Dispose(); + BackgroundMap.Dispose(); + } - PixelsBackgroundMap1 = new int[PixelsItemMap.Length / 4]; - PixelsBackgroundMapX = new int[PixelsItemMap.Length]; - BackgroundMap = new Bitmap(MapReticle.Width, MapReticle.Height); - } + public Bitmap GetLayerAcre(int t) => GetLayerAcre(X, Y, t); + public Bitmap GetMapWithReticle(int t) => GetMapWithReticle(X, Y, t, Map.CurrentLayer); - public void Dispose() - { - ScaleAcre.Dispose(); - MapReticle.Dispose(); - BackgroundAcre.Dispose(); - BackgroundMap.Dispose(); - } + public Bitmap GetBackgroundTerrain(int index = -1) + { + return TerrainSprite.GetMapWithBuildings(Map, null, PixelsBackgroundMap1, PixelsBackgroundMapX, BackgroundMap, 2, index); + } - public Bitmap GetLayerAcre(int t) => GetLayerAcre(X, Y, t); - public Bitmap GetMapWithReticle(int t) => GetMapWithReticle(X, Y, t, Map.CurrentLayer); + private Bitmap GetLayerAcre(int topX, int topY, int t) + { + var layer = Map.CurrentLayer; + return ItemLayerSprite.GetBitmapItemLayerViewGrid(layer, topX, topY, AcreScale, PixelsItemAcre1, PixelsItemAcreX, ScaleAcre, t); + } - public Bitmap GetBackgroundTerrain(int index = -1) - { - return TerrainSprite.GetMapWithBuildings(Map, null, PixelsBackgroundMap1, PixelsBackgroundMapX, BackgroundMap, 2, index); - } + public Bitmap GetBackgroundAcre(Font f, byte tbuild, byte tterrain, int index = -1) + { + return TerrainSprite.GetAcre(this, f, PixelsBackgroundAcre1, PixelsBackgroundAcreX, BackgroundAcre, index, tbuild, tterrain); + } - private Bitmap GetLayerAcre(int topX, int topY, int t) - { - var layer = Map.CurrentLayer; - return ItemLayerSprite.GetBitmapItemLayerViewGrid(layer, topX, topY, AcreScale, PixelsItemAcre1, PixelsItemAcreX, ScaleAcre, t); - } - - public Bitmap GetBackgroundAcre(Font f, byte tbuild, byte tterrain, int index = -1) - { - return TerrainSprite.GetAcre(this, f, PixelsBackgroundAcre1, PixelsBackgroundAcreX, BackgroundAcre, index, tbuild, tterrain); - } - - private Bitmap GetMapWithReticle(int topX, int topY, int t, FieldItemLayer layer) - { - return ItemLayerSprite.GetBitmapItemLayer(layer, topX, topY, PixelsItemMap, MapReticle, t); - } + private Bitmap GetMapWithReticle(int topX, int topY, int t, FieldItemLayer layer) + { + return ItemLayerSprite.GetBitmapItemLayer(layer, topX, topY, PixelsItemMap, MapReticle, t); } } \ No newline at end of file diff --git a/NHSE.Sprites/Field/TerrainSprite.cs b/NHSE.Sprites/Field/TerrainSprite.cs index 8487188..077cfd8 100644 --- a/NHSE.Sprites/Field/TerrainSprite.cs +++ b/NHSE.Sprites/Field/TerrainSprite.cs @@ -1,218 +1,218 @@ -using NHSE.Core; +using System; +using NHSE.Core; using System.Collections.Generic; using System.Drawing; -namespace NHSE.Sprites +namespace NHSE.Sprites; + +public static class TerrainSprite { - public static class TerrainSprite + private static readonly Brush Selected = Brushes.Red; + private static readonly Brush Others = Brushes.Yellow; + private static readonly Brush Text = Brushes.White; + private static readonly Brush Tile = Brushes.Black; + private static readonly Brush Plaza = Brushes.RosyBrown; + private static readonly StringFormat BuildingTextFormat = new() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; + + private const int PlazaWidth = 6 * 2; + private const int PlazaHeight = 5 * 2; + + public static void CreateMap(TerrainLayer mgr, Span pixels) { - private static readonly Brush Selected = Brushes.Red; - private static readonly Brush Others = Brushes.Yellow; - private static readonly Brush Text = Brushes.White; - private static readonly Brush Tile = Brushes.Black; - private static readonly Brush Plaza = Brushes.RosyBrown; - private static readonly StringFormat BuildingTextFormat = new() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; - - private const int PlazaWidth = 6 * 2; - private const int PlazaHeight = 5 * 2; - - public static void CreateMap(TerrainLayer mgr, int[] pixels) + int i = 0; + for (int y = 0; y < mgr.MaxHeight; y++) { - int i = 0; - for (int y = 0; y < mgr.MaxHeight; y++) + for (int x = 0; x < mgr.MaxWidth; x++, i++) { - for (int x = 0; x < mgr.MaxWidth; x++, i++) - { - pixels[i] = mgr.GetTileColor(x, y, x, y); - } + pixels[i] = mgr.GetTileColor(x, y, x, y); } } + } - public static Bitmap CreateMap(TerrainLayer mgr, int[] scale1, int[] scaleX, Bitmap map, int scale, int acreIndex = -1) - { - CreateMap(mgr, scale1); - ImageUtil.ScalePixelImage(scale1, scaleX, map.Width, map.Height, scale); - ImageUtil.SetBitmapData(map, scaleX); + public static Bitmap CreateMap(TerrainLayer mgr, Span scale1, int[] scaleX, Bitmap map, int scale, int acreIndex = -1) + { + CreateMap(mgr, scale1); + ImageUtil.ScalePixelImage(scale1, scaleX, map.Width, map.Height, scale); + ImageUtil.SetBitmapData(map, scaleX); - if (acreIndex < 0) - return map; - - var acre = MapGrid.Acres[acreIndex]; - var x = acre.X * mgr.GridWidth; - var y = acre.Y * mgr.GridHeight; - - return DrawReticle(map, mgr, x, y, scale); - } - - private static Bitmap DrawReticle(Bitmap map, TileGrid mgr, int x, int y, int scale) - { - using var gfx = Graphics.FromImage(map); - using var pen = new Pen(Color.Red); - - int w = mgr.GridWidth * scale; - int h = mgr.GridHeight * scale; - gfx.DrawRectangle(pen, x * scale, y * scale, w, h); + if (acreIndex < 0) return map; - } - public static Bitmap GetMapWithBuildings(MapTerrainStructure m, Font? f, int[] scale1, int[] scaleX, Bitmap map, int scale = 4, int index = -1) + var acre = MapGrid.Acres[acreIndex]; + var x = acre.X * mgr.GridWidth; + var y = acre.Y * mgr.GridHeight; + + return DrawReticle(map, mgr, x, y, scale); + } + + private static Bitmap DrawReticle(Bitmap map, TileGrid mgr, int x, int y, int scale) + { + using var gfx = Graphics.FromImage(map); + using var pen = new Pen(Color.Red); + + int w = mgr.GridWidth * scale; + int h = mgr.GridHeight * scale; + gfx.DrawRectangle(pen, x * scale, y * scale, w, h); + return map; + } + + public static Bitmap GetMapWithBuildings(MapTerrainStructure m, Font? f, Span scale1, int[] scaleX, Bitmap map, int scale = 4, int index = -1) + { + CreateMap(m.Terrain, scale1, scaleX, map, scale); + using var gfx = Graphics.FromImage(map); + + gfx.DrawPlaza(m.Terrain, (ushort)m.PlazaX, (ushort)m.PlazaY, scale); + gfx.DrawBuildings(m.Terrain, m.Buildings, f, scale, index); + return map; + } + + private static void DrawPlaza(this Graphics gfx, TerrainLayer g, ushort px, ushort py, int scale) + { + g.GetBuildingCoordinate(px, py, scale, out var x, out var y); + + var width = scale * PlazaWidth; + var height = scale * PlazaHeight; + + gfx.FillRectangle(Plaza, x, y, width, height); + } + + private static void DrawBuildings(this Graphics gfx, TerrainLayer g, IReadOnlyList buildings, Font? f, int scale, int index = -1) + { + for (int i = 0; i < buildings.Count; i++) { - CreateMap(m.Terrain, scale1, scaleX, map, scale); - using var gfx = Graphics.FromImage(map); + var b = buildings[i]; + if (b.BuildingType == 0) + continue; + g.GetBuildingCoordinate(b.X, b.Y, scale, out var x, out var y); - gfx.DrawPlaza(m.Terrain, (ushort)m.PlazaX, (ushort)m.PlazaY, scale); - gfx.DrawBuildings(m.Terrain, m.Buildings, f, scale, index); - return map; + var pen = index == i ? Selected : Others; + DrawBuilding(gfx, f, scale, pen, x, y, b, Text); } + } - private static void DrawPlaza(this Graphics gfx, TerrainLayer g, ushort px, ushort py, int scale) + private static void DrawBuilding(Graphics gfx, Font? f, int scale, Brush pen, int x, int y, Building b, Brush text) + { + gfx.FillRectangle(pen, x - scale, y - scale, scale * 2, scale * 2); + + if (f == null) + return; + + var name = b.BuildingType.ToString(); + gfx.DrawString(name, f, text, new PointF(x, y - (scale * 2)), BuildingTextFormat); + } + + private static void SetAcreTerrainPixels(int x, int y, TerrainLayer t, Span data, Span scaleX, int scale) + { + GetAcre1(x, y, t, data); + ImageUtil.ScalePixelImage(data, scaleX, 16 * scale, 16 * scale, scale / 16); + } + + private static void GetAcre1(int tileTopX, int tileTopY, TerrainLayer t, Span data) + { + int index = 0; + + for (int tileY = 0; tileY < 16; tileY++) { - g.GetBuildingCoordinate(px, py, scale, out var x, out var y); - - var width = scale * PlazaWidth; - var height = scale * PlazaHeight; - - gfx.FillRectangle(Plaza, x, y, width, height); - } - - private static void DrawBuildings(this Graphics gfx, TerrainLayer g, IReadOnlyList buildings, Font? f, int scale, int index = -1) - { - for (int i = 0; i < buildings.Count; i++) + var tileYIx = tileY + tileTopY; + for (int pixelY = 0; pixelY < 16; pixelY++) { - var b = buildings[i]; - if (b.BuildingType == 0) - continue; - g.GetBuildingCoordinate(b.X, b.Y, scale, out var x, out var y); - - var pen = index == i ? Selected : Others; - DrawBuilding(gfx, f, scale, pen, x, y, b, Text); - } - } - - private static void DrawBuilding(Graphics gfx, Font? f, int scale, Brush pen, int x, int y, Building b, Brush text) - { - gfx.FillRectangle(pen, x - scale, y - scale, scale * 2, scale * 2); - - if (f != null) - { - var name = b.BuildingType.ToString(); - gfx.DrawString(name, f, text, new PointF(x, y - (scale * 2)), BuildingTextFormat); - } - } - - private static void SetAcreTerrainPixels(int x, int y, TerrainLayer t, int[] data, int[] scaleX, int scale) - { - GetAcre1(x, y, t, data); - ImageUtil.ScalePixelImage(data, scaleX, 16 * scale, 16 * scale, scale / 16); - } - - private static void GetAcre1(int tileTopX, int tileTopY, TerrainLayer t, int[] data) - { - int index = 0; - - for (int tileY = 0; tileY < 16; tileY++) - { - var tileYIx = tileY + tileTopY; - for (int pixelY = 0; pixelY < 16; pixelY++) + for (int tileX = 0; tileX < 16; tileX++) { - for (int tileX = 0; tileX < 16; tileX++) + var tileXIx = tileX + tileTopX; + for (int pixelX = 0; pixelX < 16; pixelX++) { - var tileXIx = tileX + tileTopX; - for (int pixelX = 0; pixelX < 16; pixelX++) - { - data[index] = t.GetTileColor(tileXIx, tileYIx, pixelX, pixelY); - index++; - } + data[index] = t.GetTileColor(tileXIx, tileYIx, pixelX, pixelY); + index++; } } } } + } - public static Bitmap GetAcre(MapView m, Font f, int[] scale1, int[] scaleX, Bitmap acre, int index, byte tbuild, byte tterrain) + public static Bitmap GetAcre(MapView m, Font f, Span scale1, int[] scaleX, Bitmap acre, int index, byte tbuild, byte tterrain) + { + int mx = m.X / 2; + int my = m.Y / 2; + SetAcreTerrainPixels(mx, my, m.Map.Terrain, scale1, scaleX, m.TerrainScale); + + const int grid1 = unchecked((int)0xFF888888u); + const int grid2 = unchecked((int)0xFF666666u); + ImageUtil.SetBitmapData(acre, scaleX); + + using var gfx = Graphics.FromImage(acre); + + gfx.DrawAcrePlaza(m.Map.Terrain, mx, my, (ushort)m.Map.PlazaX, (ushort)m.Map.PlazaY, m.TerrainScale, tbuild); + + var buildings = m.Map.Buildings; + var t = m.Map.Terrain; + for (var i = 0; i < buildings.Count; i++) { - int mx = m.X / 2; - int my = m.Y / 2; - SetAcreTerrainPixels(mx, my, m.Map.Terrain, scale1, scaleX, m.TerrainScale); + var b = buildings[i]; + t.GetBuildingRelativeCoordinates(mx, my, m.TerrainScale, b.X, b.Y, out var x, out var y); - const int grid1 = unchecked((int)0xFF888888u); - const int grid2 = unchecked((int)0xFF666666u); - ImageUtil.SetBitmapData(acre, scaleX); - - using var gfx = Graphics.FromImage(acre); - - gfx.DrawAcrePlaza(m.Map.Terrain, mx, my, (ushort)m.Map.PlazaX, (ushort)m.Map.PlazaY, m.TerrainScale, tbuild); - - var buildings = m.Map.Buildings; - var t = m.Map.Terrain; - for (var i = 0; i < buildings.Count; i++) - { - var b = buildings[i]; - t.GetBuildingRelativeCoordinates(mx, my, m.TerrainScale, b.X, b.Y, out var x, out var y); - - var pen = index == i ? Selected : Others; - if (tbuild != byte.MaxValue) - { - var orig = ((SolidBrush)pen).Color; - pen = new SolidBrush(Color.FromArgb(tbuild, orig)); - } - - DrawBuilding(gfx, null, m.TerrainScale, pen, x, y, b, Text); - } - - ImageUtil.GetBitmapData(acre, scaleX); - ItemLayerSprite.DrawGrid(scaleX, acre.Width, acre.Height, m.AcreScale, grid1); - ItemLayerSprite.DrawGrid(scaleX, acre.Width, acre.Height, m.TerrainScale, grid2); - ImageUtil.SetBitmapData(acre, scaleX); - - foreach (var b in buildings) - { - t.GetBuildingRelativeCoordinates(mx, my, m.TerrainScale, b.X, b.Y, out var x, out var y); - if (!t.IsWithinGrid(m.TerrainScale, x, y)) - continue; - var name = b.BuildingType.ToString(); - gfx.DrawString(name, f, Text, new PointF(x, y - (m.TerrainScale * 2)), BuildingTextFormat); - } - - if (tterrain != 0) - DrawTerrainTileNames(mx, my, gfx, t, f, m.TerrainScale, tterrain); - - return acre; - } - - private static void DrawTerrainTileNames(int topX, int topY, Graphics gfx, TerrainLayer t, Font f, int scale, byte transparency) - { - var pen = transparency != byte.MaxValue ? new SolidBrush(Color.FromArgb(transparency, Color.Black)) : Tile; - - for (int y = 0; y < 16; y++) - { - var yi = y + topY; - int cy = (y * scale) + (scale / 2); - for (int x = 0; x < 16; x++) - { - var xi = x + topX; - var tile = t.GetTile(xi, yi); - - int cx = (x * scale) + (scale / 2); - var name = TerrainTileColor.GetTileName(tile); - gfx.DrawString(name, f, pen, new PointF(cx, cy), BuildingTextFormat); - } - } - } - - private static void DrawAcrePlaza(this Graphics gfx, TerrainLayer g, int topX, int topY, ushort px, ushort py, int scale, byte transparency) - { - g.GetBuildingRelativeCoordinates(topX, topY, scale, px, py, out var x, out var y); - - var width = scale * PlazaWidth; - var height = scale * PlazaHeight; - - var pen = Plaza; - if (transparency != byte.MaxValue) + var pen = index == i ? Selected : Others; + if (tbuild != byte.MaxValue) { var orig = ((SolidBrush)pen).Color; - pen = new SolidBrush(Color.FromArgb(transparency, orig)); + pen = new SolidBrush(Color.FromArgb(tbuild, orig)); + } + + DrawBuilding(gfx, null, m.TerrainScale, pen, x, y, b, Text); + } + + ImageUtil.GetBitmapData(acre, scaleX); + ItemLayerSprite.DrawGrid(scaleX, acre.Width, acre.Height, m.AcreScale, grid1); + ItemLayerSprite.DrawGrid(scaleX, acre.Width, acre.Height, m.TerrainScale, grid2); + ImageUtil.SetBitmapData(acre, scaleX); + + foreach (var b in buildings) + { + t.GetBuildingRelativeCoordinates(mx, my, m.TerrainScale, b.X, b.Y, out var x, out var y); + if (!t.IsWithinGrid(m.TerrainScale, x, y)) + continue; + var name = b.BuildingType.ToString(); + gfx.DrawString(name, f, Text, new PointF(x, y - (m.TerrainScale * 2)), BuildingTextFormat); + } + + if (tterrain != 0) + DrawTerrainTileNames(mx, my, gfx, t, f, m.TerrainScale, tterrain); + + return acre; + } + + private static void DrawTerrainTileNames(int topX, int topY, Graphics gfx, TerrainLayer t, Font f, int scale, byte transparency) + { + var pen = transparency != byte.MaxValue ? new SolidBrush(Color.FromArgb(transparency, Color.Black)) : Tile; + + for (int y = 0; y < 16; y++) + { + var yi = y + topY; + int cy = (y * scale) + (scale / 2); + for (int x = 0; x < 16; x++) + { + var xi = x + topX; + var tile = t.GetTile(xi, yi); + + int cx = (x * scale) + (scale / 2); + var name = TerrainTileColor.GetTileName(tile); + gfx.DrawString(name, f, pen, new PointF(cx, cy), BuildingTextFormat); } - gfx.FillRectangle(pen, x, y, width, height); } } -} + + private static void DrawAcrePlaza(this Graphics gfx, TerrainLayer g, int topX, int topY, ushort px, ushort py, int scale, byte transparency) + { + g.GetBuildingRelativeCoordinates(topX, topY, scale, px, py, out var x, out var y); + + var width = scale * PlazaWidth; + var height = scale * PlazaHeight; + + var pen = Plaza; + if (transparency != byte.MaxValue) + { + var orig = ((SolidBrush)pen).Color; + pen = new SolidBrush(Color.FromArgb(transparency, orig)); + } + gfx.FillRectangle(pen, x, y, width, height); + } +} \ No newline at end of file diff --git a/NHSE.Sprites/Item/ItemSprite.cs b/NHSE.Sprites/Item/ItemSprite.cs index 626b7bb..519adfa 100644 --- a/NHSE.Sprites/Item/ItemSprite.cs +++ b/NHSE.Sprites/Item/ItemSprite.cs @@ -5,126 +5,125 @@ using NHSE.Core; using NHSE.Sprites.Properties; -namespace NHSE.Sprites +namespace NHSE.Sprites; + +public static class ItemSprite { - public static class ItemSprite + private static string[] ItemNames = []; // currently only used as length check for FieldItem + + // %appdata%/NHSE + public static string PlatformAppDataPath { get; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(NHSE)); + public static string PlatformAppDataImagePath { get; } = Path.Combine(PlatformAppDataPath, "img"); + public static bool SingleSpriteExists => Directory.EnumerateFileSystemEntries(PlatformAppDataImagePath).Any(); + + public static void Initialize(string[] itemNames) { - private static string[] ItemNames = Array.Empty(); // currently only used as length check for FieldItem + ItemNames = itemNames; - // %appdata%/NHSE - public static string PlatformAppDataPath { get; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(NHSE)); - public static string PlatformAppDataImagePath { get; } = Path.Combine(PlatformAppDataPath, "img"); - public static bool SingleSpriteExists => Directory.EnumerateFileSystemEntries(PlatformAppDataImagePath).Any(); + if (!Directory.Exists(PlatformAppDataImagePath)) + Directory.CreateDirectory(PlatformAppDataImagePath); + } - public static void Initialize(string[] itemNames) + public static Bitmap GetItemMarkup(Item item, Font font, int width, int height, Bitmap backing) + { + return CreateFake(item, font, width, height, backing); + } + + public static Image? GetItemSprite(Item item) + { + var id = item.ItemId; + var count = item.Count; + return GetItemSprite(id, count); + } + + public static Image? GetItemSprite(ushort id, ushort count = 0) + { + if (id == Item.NONE) + return null; + + if (!TryGetItemImageSprite(id, out var path, count)) { - ItemNames = itemNames; - - if (!Directory.Exists(PlatformAppDataImagePath)) - Directory.CreateDirectory(PlatformAppDataImagePath); - } - - public static Bitmap GetItemMarkup(Item item, Font font, int width, int height, Bitmap backing) - { - return CreateFake(item, font, width, height, backing); - } - - public static Image? GetItemSprite(Item item) - { - var id = item.ItemId; - var count = item.Count; - return GetItemSprite(id, count); - } - - public static Image? GetItemSprite(ushort id, ushort count = 0) - { - if (id == Item.NONE) - return null; - - if (!TryGetItemImageSprite(id, out var path, count)) - { - if (!TryGetMenuIconSprite(id, out var img)) - return Resources.leaf; - else - return img; - } - - try - { - return Image.FromFile(path); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); + if (!TryGetMenuIconSprite(id, out var img)) return Resources.leaf; - } + else + return img; } - private static bool TryGetMenuIconSprite(ushort id, out Image? img) + try { - id = TryGetFieldItemId(id, ItemNames.Length); - var iconType = ItemInfo.GetMenuIcon(id); - - // the 1 stops the original "leaf" being overwritten - var name = iconType == ItemMenuIconType.Leaf ? $"{iconType}1" : iconType.ToString(); - - img = (Image?)Resources.ResourceManager.GetObject(name); - return img != null; + return Image.FromFile(path); } - - private static bool TryGetItemImageSprite(ushort id, out string path, ushort count = 0) + catch (Exception ex) { - id = TryGetFieldItemId(id, ItemNames.Length); - - var name = $"{id:00000}_{count}"; - if (SpriteFileExists(name, out path)) - return true; - - name = $"{id:00000}_0"; // fallback to no variation - return SpriteFileExists(name, out path); - } - - private static bool SpriteFileExists(string filename, out string path) - { - path = Path.Combine(PlatformAppDataImagePath, filename + ".png"); - return File.Exists(path); - } - - private static ushort TryGetFieldItemId(ushort id, int length) - { - if (id < length) - return id; - if (!FieldItemList.Items.TryGetValue(id, out var definition)) - return id; - - var remap = definition.HeldItemId; - return remap >= length ? id : remap; - } - - private static readonly StringFormat Center = new() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; - - private static Bitmap CreateFake(Item item, Font font, int width, int height, Bitmap bmp) - { - using var gfx = Graphics.FromImage(bmp); - DrawItemAt(gfx, item, font, width, height); - return bmp; - } - - public static void DrawItemAt(Graphics gfx, Item item, Font font, int width, int height) - { - DrawInfo(gfx, font, item, width, height, Brushes.Black); - } - - private static void DrawInfo(Graphics gfx, Font font, Item item, int width, int height, Brush brush) - { - if (item.Count != 0) - gfx.DrawString(item.Count.ToString(), font, brush, 0, 0); - if (item.UseCount != 0) - gfx.DrawString(item.UseCount.ToString(), font, brush, width >> 1, height >> 1, Center); - if (item.SystemParam != 0) - gfx.DrawString(item.SystemParam.ToString(), font, brush, width - 12, 0); - if (item.AdditionalParam != 0) - gfx.DrawString(item.AdditionalParam.ToString(), font, brush, 0, height - 12); + Console.WriteLine(ex.Message); + return Resources.leaf; } } -} + + private static bool TryGetMenuIconSprite(ushort id, out Image? img) + { + id = TryGetFieldItemId(id, ItemNames.Length); + var iconType = ItemInfo.GetMenuIcon(id); + + // the 1 stops the original "leaf" being overwritten + var name = iconType == ItemMenuIconType.Leaf ? $"{iconType}1" : iconType.ToString(); + + img = (Image?)Resources.ResourceManager.GetObject(name); + return img != null; + } + + private static bool TryGetItemImageSprite(ushort id, out string path, ushort count = 0) + { + id = TryGetFieldItemId(id, ItemNames.Length); + + var name = $"{id:00000}_{count}"; + if (SpriteFileExists(name, out path)) + return true; + + name = $"{id:00000}_0"; // fallback to no variation + return SpriteFileExists(name, out path); + } + + private static bool SpriteFileExists(string filename, out string path) + { + path = Path.Combine(PlatformAppDataImagePath, filename + ".png"); + return File.Exists(path); + } + + private static ushort TryGetFieldItemId(ushort id, int length) + { + if (id < length) + return id; + if (!FieldItemList.Items.TryGetValue(id, out var definition)) + return id; + + var remap = definition.HeldItemId; + return remap >= length ? id : remap; + } + + private static readonly StringFormat Center = new() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; + + private static Bitmap CreateFake(Item item, Font font, int width, int height, Bitmap bmp) + { + using var gfx = Graphics.FromImage(bmp); + DrawItemAt(gfx, item, font, width, height); + return bmp; + } + + public static void DrawItemAt(Graphics gfx, Item item, Font font, int width, int height) + { + DrawInfo(gfx, font, item, width, height, Brushes.Black); + } + + private static void DrawInfo(Graphics gfx, Font font, Item item, int width, int height, Brush brush) + { + if (item.Count != 0) + gfx.DrawString(item.Count.ToString(), font, brush, 0, 0); + if (item.UseCount != 0) + gfx.DrawString(item.UseCount.ToString(), font, brush, width >> 1, height >> 1, Center); + if (item.SystemParam != 0) + gfx.DrawString(item.SystemParam.ToString(), font, brush, width - 12, 0); + if (item.AdditionalParam != 0) + gfx.DrawString(item.AdditionalParam.ToString(), font, brush, 0, height - 12); + } +} \ No newline at end of file diff --git a/NHSE.Sprites/NHSE.Sprites.csproj b/NHSE.Sprites/NHSE.Sprites.csproj index 12420b9..94b8aef 100644 --- a/NHSE.Sprites/NHSE.Sprites.csproj +++ b/NHSE.Sprites/NHSE.Sprites.csproj @@ -1,8 +1,8 @@  - net46;net8.0-windows en + $(NoWarn);CA1416 @@ -10,9 +10,9 @@ - - - + + + diff --git a/NHSE.Sprites/Util/ImageUtil.cs b/NHSE.Sprites/Util/ImageUtil.cs index 9a0b633..a4e263f 100644 --- a/NHSE.Sprites/Util/ImageUtil.cs +++ b/NHSE.Sprites/Util/ImageUtil.cs @@ -2,130 +2,129 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using NHSE.Core; -namespace NHSE.Sprites +namespace NHSE.Sprites; + +public static class ImageUtil { - public static class ImageUtil + extension(DesignPattern bg) { - public static Bitmap GetImage(this DesignPattern bg) + public Bitmap GetImage() => GetBitmap(bg.GetBitmap(), DesignPattern.Width, DesignPattern.Height); + + public Bitmap GetPalette() => GetBitmap(bg.GetPaletteBitmap(), DesignPattern.PaletteColorCount, 1, PixelFormat.Format24bppRgb); + } + + extension(DesignPatternPRO bg) + { + public Bitmap GetImage(int sheet) => GetBitmap(bg.GetBitmap(sheet), DesignPatternPRO.Width, DesignPatternPRO.Height); + + public Bitmap GetPalette() => GetBitmap(bg.GetPaletteBitmap(), DesignPatternPRO.PaletteColorCount, 1, PixelFormat.Format24bppRgb); + } + + public static Bitmap GetBitmap(ReadOnlySpan data, int width, int height, PixelFormat format = PixelFormat.Format32bppArgb) + { + var bmp = new Bitmap(width, height, format); + var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, format); + var length = data.Length; + var span = MemoryMarshal.CreateSpan(ref Unsafe.AddByteOffset(ref Unsafe.NullRef(), bmpData.Scan0), length); + data[..length].CopyTo(span); + bmp.UnlockBits(bmpData); + return bmp; + } + + public static Bitmap GetBitmap(int[] data, int width, int height, PixelFormat format = PixelFormat.Format32bppArgb) + { + var bmp = new Bitmap(width, height, format); + SetBitmapData(bmp, data, format); + return bmp; + } + + public static void SetBitmapData(Bitmap bmp, int[] data, PixelFormat format = PixelFormat.Format32bppArgb) + { + var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, format); + var ptr = bmpData.Scan0; + Marshal.Copy(data, 0, ptr, data.Length); + bmp.UnlockBits(bmpData); + } + + public static void GetBitmapData(Bitmap bmp, int[] data, PixelFormat format = PixelFormat.Format32bppArgb) + { + var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, format); + var ptr = bmpData.Scan0; + Marshal.Copy(ptr, data, 0, data.Length); + bmp.UnlockBits(bmpData); + } + + // https://stackoverflow.com/a/24199315 + public static Bitmap ResizeImage(Image image, int width, int height) + { + var destRect = new Rectangle(0, 0, width, height); + var destImage = new Bitmap(width, height); + + destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); + + using var wrapMode = new ImageAttributes(); + wrapMode.SetWrapMode(WrapMode.TileFlipXY); + + using var graphics = Graphics.FromImage(destImage); + graphics.CompositingMode = CompositingMode.SourceCopy; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.NearestNeighbor; + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + + graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode); + + return destImage; + } + + public static int[] ScalePixelImage(ReadOnlySpan data, int scale, int w, int h, out int fW, out int fH) + { + fW = scale * w; + fH = scale * h; + var scaled = new int[fW * fH]; + + ScalePixelImage(data, scaled, fW, fH, scale); + + return scaled; + } + + public static void ScalePixelImage(ReadOnlySpan data, Span scaled, int fW, int fH, int scale) + { + // For each pixel, copy to the X indexes, then block copy the row to the other rows. + int i = 0; + for (int y = 0; y < fH; y += scale) { - return GetBitmap(bg.GetBitmap(), DesignPattern.Width, DesignPattern.Height); - } - - public static Bitmap GetPalette(this DesignPattern bg) - { - return GetBitmap(bg.GetPaletteBitmap(), DesignPattern.PaletteColorCount, 1, PixelFormat.Format24bppRgb); - } - - public static Bitmap GetImage(this DesignPatternPRO bg, int sheet) - { - return GetBitmap(bg.GetBitmap(sheet), DesignPatternPRO.Width, DesignPatternPRO.Height); - } - - public static Bitmap GetPalette(this DesignPatternPRO bg) - { - return GetBitmap(bg.GetPaletteBitmap(), DesignPatternPRO.PaletteColorCount, 1, PixelFormat.Format24bppRgb); - } - - public static Bitmap GetBitmap(byte[] data, int width, int height, PixelFormat format = PixelFormat.Format32bppArgb) - { - var bmp = new Bitmap(width, height, format); - var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, format); - var ptr = bmpData.Scan0; - Marshal.Copy(data, 0, ptr, data.Length); - bmp.UnlockBits(bmpData); - return bmp; - } - - public static Bitmap GetBitmap(int[] data, int width, int height, PixelFormat format = PixelFormat.Format32bppArgb) - { - var bmp = new Bitmap(width, height, format); - SetBitmapData(bmp, data, format); - return bmp; - } - - public static void SetBitmapData(Bitmap bmp, int[] data, PixelFormat format = PixelFormat.Format32bppArgb) - { - var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, format); - var ptr = bmpData.Scan0; - Marshal.Copy(data, 0, ptr, data.Length); - bmp.UnlockBits(bmpData); - } - - public static void GetBitmapData(Bitmap bmp, int[] data, PixelFormat format = PixelFormat.Format32bppArgb) - { - var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, format); - var ptr = bmpData.Scan0; - Marshal.Copy(ptr, data, 0, data.Length); - bmp.UnlockBits(bmpData); - } - - // https://stackoverflow.com/a/24199315 - public static Bitmap ResizeImage(Image image, int width, int height) - { - var destRect = new Rectangle(0, 0, width, height); - var destImage = new Bitmap(width, height); - - destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); - - using var wrapMode = new ImageAttributes(); - wrapMode.SetWrapMode(WrapMode.TileFlipXY); - - using var graphics = Graphics.FromImage(destImage); - graphics.CompositingMode = CompositingMode.SourceCopy; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.NearestNeighbor; - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - - graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode); - - return destImage; - } - - public static int[] ScalePixelImage(int[] data, int scale, int w, int h, out int fW, out int fH) - { - fW = scale * w; - fH = scale * h; - var scaled = new int[fW * fH]; - - ScalePixelImage(data, scaled, fW, fH, scale); - - return scaled; - } - - public static void ScalePixelImage(int[] data, int[] scaled, int fW, int fH, int scale) - { - // For each pixel, copy to the X indexes, then block copy the row to the other rows. - int i = 0; - for (int y = 0; y < fH; y += scale) + // Fill the X pixels + var baseIndex = y * fW; + for (int x = 0; x < fW; x += scale) { - // Fill the X pixels - var baseIndex = y * fW; - for (int x = 0; x < fW; x += scale) - { - var v = data[i]; - var xi = baseIndex + x; - for (int x1 = 0; x1 < scale; x1++) - scaled[xi + x1] = v; - i++; - } + var v = data[i]; + var xi = baseIndex + x; + for (int x1 = 0; x1 < scale; x1++) + scaled[xi + x1] = v; + i++; + } - // Copy entire pixel row down - for (int y1 = 1; y1 < scale; y1++) - Array.Copy(scaled, baseIndex, scaled, baseIndex + (y1 * fW), fW); + // Copy entire pixel row down + for (int y1 = 1; y1 < scale; y1++) + { + var src = scaled.Slice(baseIndex, fW); + var dest = scaled.Slice(baseIndex + (y1 * fW), fW); + src.CopyTo(dest); } } - - /// - /// Sets a bitwise and of the requested transparency; this is assuming the pixel value is 0xFF_xx_xx_xx. Single operation laziness! - /// - public static void ClampAllTransparencyTo(int[] data, int trans) - { - for (int i = 0; i < data.Length; i++) - data[i] &= trans; - } } -} + + /// + /// Sets a bitwise and of the requested transparency; this is assuming the pixel value is 0xFF_xx_xx_xx. Single operation laziness! + /// + public static void ClampAllTransparencyTo(Span data, int trans) + { + for (int i = 0; i < data.Length; i++) + data[i] &= trans; + } +} \ No newline at end of file diff --git a/NHSE.Sprites/VillagerSprite.cs b/NHSE.Sprites/VillagerSprite.cs index 1f4b625..3c5ce80 100644 --- a/NHSE.Sprites/VillagerSprite.cs +++ b/NHSE.Sprites/VillagerSprite.cs @@ -2,31 +2,30 @@ using NHSE.Core; using NHSE.Sprites.Properties; -namespace NHSE.Sprites +namespace NHSE.Sprites; + +/// +/// Provides sprites for Villagers. +/// +public static class VillagerSprite { /// - /// Provides sprites for Villagers. + /// Gets the Villager's 128x128 sprite based on the input parameters. /// - public static class VillagerSprite + /// Species of Villager + /// Variant of Villager + public static Image? GetVillagerSprite(VillagerSpecies species, int variant) { - /// - /// Gets the Villager's 128x128 sprite based on the input parameters. - /// - /// Species of Villager - /// Variant of Villager - public static Image? GetVillagerSprite(VillagerSpecies species, int variant) - { - var asset = VillagerUtil.GetInternalVillagerName(species, variant); - return GetVillagerSprite(asset); - } - - /// - /// Gets the sprite for the Villager based on its internal name. - /// - /// Internal name of the villager (3char, 2digit) - public static Image? GetVillagerSprite(string asset) - { - return (Image?)Resources.ResourceManager.GetObject(asset); - } + var asset = VillagerUtil.GetInternalVillagerName(species, variant); + return GetVillagerSprite(asset); } -} + + /// + /// Gets the sprite for the Villager based on its internal name. + /// + /// Internal name of the villager (3char, 2digit) + public static Image? GetVillagerSprite(string asset) + { + return (Image?)Resources.ResourceManager.GetObject(asset); + } +} \ No newline at end of file diff --git a/NHSE.Tests/BuildingTests.cs b/NHSE.Tests/BuildingTests.cs index f177ae5..7dd11fc 100644 --- a/NHSE.Tests/BuildingTests.cs +++ b/NHSE.Tests/BuildingTests.cs @@ -3,28 +3,27 @@ using NHSE.Core; using Xunit; -namespace NHSE.Tests +namespace NHSE.Tests; + +public class BuildingTests { - public class BuildingTests + [Fact] + public void BuildingMarshal() { - [Fact] - public void BuildingMarshal() - { - var building = new Building(); - var bytes = building.ToBytesClass(); - bytes.Length.Should().Be(Building.SIZE); - } - - [Fact] - public void BuildingClear() - { - var item = new Building {BuildingType = BuildingType.PlayerHouse1, X=5, Y=7}; - var bytes = item.ToBytesClass(); - bytes.Any(z => z != 0).Should().BeTrue(); - - item.Clear(); - bytes = item.ToBytesClass(); - bytes.Any(z => z != 0).Should().BeFalse(); - } + var building = new Building(); + var bytes = building.ToBytesClass(); + bytes.Length.Should().Be(Building.SIZE); } -} + + [Fact] + public void BuildingClear() + { + var item = new Building {BuildingType = BuildingType.PlayerHouse1, X=5, Y=7}; + var bytes = item.ToBytesClass(); + bytes.Any(z => z != 0).Should().BeTrue(); + + item.Clear(); + bytes = item.ToBytesClass(); + bytes.Any(z => z != 0).Should().BeFalse(); + } +} \ No newline at end of file diff --git a/NHSE.Tests/DumpTests.cs b/NHSE.Tests/DumpTests.cs index b9825db..8d56834 100644 --- a/NHSE.Tests/DumpTests.cs +++ b/NHSE.Tests/DumpTests.cs @@ -1,26 +1,35 @@ -using NHSE.Parsing; +using System.IO; +using NHSE.Parsing; using Xunit; -namespace NHSE.Tests +namespace NHSE.Tests; + +public static class DumpTests { - public static class DumpTests + private const string RepoPath = @"C:\Users\kapho\source\repos"; + private const string PatchDumpPath = @"E:\acnh\" + PatchFolderName; + private const string PatchFolderName = "v20"; + private const string MessageDumpFormat = @"Message\String_{0}"; + + [Fact] + public static void DumpBCSV() { - private const string RepoPath = @"C:\Users\Kurt\Documents\GitHub"; - private const string PatchDumpPath = @"D:\Kurt\Desktop\ac\" + PatchFolderName; - private const string PatchFolderName = "v20"; - private const string MessageDumpFormat = @"Message\String_{0}"; + const string folder = PatchDumpPath + @"\bcsv"; + if (!Directory.Exists(folder)) // skip this test if not properly configured for this test + return; - [Fact] - public static void DumpBCSV() - { - const string folder = PatchDumpPath + @"\bcsv"; - GameBCSVDumper.UpdateDumps(folder, folder, true); - } - - [Fact] - public static void DumpMSBT() - { - GameMSBTDumperNHSE.Dump(RepoPath, PatchDumpPath, MessageDumpFormat); - } + GameBCSVDumper.UpdateDumps(folder, folder, true); } -} + + [Fact] + public static void DumpMSBT() + { + const string folder = RepoPath; + if (!Directory.Exists(folder)) // skip this test if not properly configured for this test + return; + const string dump = PatchDumpPath; + if (!Directory.Exists(dump)) // skip this test if not properly configured for this test + return; + GameMSBTDumperNHSE.Dump(folder, dump, MessageDumpFormat); + } +} \ No newline at end of file diff --git a/NHSE.Tests/EncryptedIntTests.cs b/NHSE.Tests/EncryptedIntTests.cs index c4b413d..2cb74fa 100644 --- a/NHSE.Tests/EncryptedIntTests.cs +++ b/NHSE.Tests/EncryptedIntTests.cs @@ -1,21 +1,21 @@ -using FluentAssertions; +using System; +using FluentAssertions; using NHSE.Core; using Xunit; -namespace NHSE.Tests -{ - public class EncryptedIntTests - { - [Fact] - public void TestParse() - { - const int expect = 31_280; - byte[] data = {0x8A, 0xC4, 0xE3, 0xCF, 0x37, 0xD5, 0x1A, 0xD3}; - var val = EncryptedInt32.ReadVerify(data, 0); - val.Value.Should().Be(expect); +namespace NHSE.Tests; - var encode = EncryptedInt32.Encrypt(expect, val.Shift, val.Adjust); - val.OriginalEncrypted.Should().Be(encode); - } +public class EncryptedIntTests +{ + [Fact] + public void TestParse() + { + const int expect = 31_280; + ReadOnlySpan data = [0x8A, 0xC4, 0xE3, 0xCF, 0x37, 0xD5, 0x1A, 0xD3]; + var val = EncryptedInt32.ReadVerify(data, 0); + val.Value.Should().Be(expect); + + var encode = EncryptedInt32.Encrypt(expect, val.Shift, val.Adjust); + val.OriginalEncrypted.Should().Be(encode); } -} +} \ No newline at end of file diff --git a/NHSE.Tests/EnumHashTests.cs b/NHSE.Tests/EnumHashTests.cs index 0bb1589..c5fc527 100644 --- a/NHSE.Tests/EnumHashTests.cs +++ b/NHSE.Tests/EnumHashTests.cs @@ -2,18 +2,17 @@ using NHSE.Parsing; using Xunit; -namespace NHSE.Tests +namespace NHSE.Tests; + +public class EnumHashTests { - public class EnumHashTests + [Theory] + [InlineData("Base", 0x6086515F)] + [InlineData("River", 0x3422482F)] + [InlineData("RoadStone", 0x13011867)] + public void ChecksumMatches(string str, uint val) { - [Theory] - [InlineData("Base", 0x6086515F)] - [InlineData("River", 0x3422482F)] - [InlineData("RoadStone", 0x13011867)] - public void ChecksumMatches(string str, uint val) - { - var computed = CRC32.Compute(str); - computed.Should().Be(val); - } + var computed = CRC32.Compute(str); + computed.Should().Be(val); } -} +} \ No newline at end of file diff --git a/NHSE.Tests/FancyMarshalTests.cs b/NHSE.Tests/FancyMarshalTests.cs index 1ab7937..68b84d9 100644 --- a/NHSE.Tests/FancyMarshalTests.cs +++ b/NHSE.Tests/FancyMarshalTests.cs @@ -2,47 +2,46 @@ using NHSE.Core; using Xunit; -namespace NHSE.Tests +namespace NHSE.Tests; + +public class FancyMarshalTests { - public class FancyMarshalTests + [Fact] public void MarshalGSaveBulletinBoard() => MarshalBytesTestS(GSaveBulletinBoard.SIZE); + [Fact] public void MarshalBulletinBoard() => MarshalBytesTestS(BulletinBoardStock.SIZE); + [Fact] public void MarshalGSaveBBS() => MarshalBytesTestS(GSaveBBS.SIZE); + [Fact] public void MarshalGSaveDate() => MarshalBytesTestS(GSaveDate.SIZE); + [Fact] public void MarshalGSaveDateMD() => MarshalBytesTestS(GSaveDateMD.SIZE); + [Fact] public void MarshalGSavePlayerId() => MarshalBytesTestS(GSavePlayerId.SIZE); + [Fact] public void MarshalGSaveLandId() => MarshalBytesTestS(GSaveLandId.SIZE); + [Fact] public void MarshalGSavePlayerBaseId() => MarshalBytesTestS(GSavePlayerBaseId.SIZE); + [Fact] public void MarshalHandwriting() => MarshalBytesTestS(Handwriting.SIZE); + + [Fact] public void MarshalGSaveRoomFloorWall() => MarshalBytesTestS(GSaveRoomFloorWall.SIZE); + [Fact] public void MarshalGSaveAudioInfo() => MarshalBytesTestS(GSaveAudioInfo.SIZE); + + [Fact] public void MarshalGSaveManpu() => MarshalBytesTestS(GSavePlayerManpu.SIZE); + [Fact] public void MarshalGSavePlayerHandleName() => MarshalBytesTestS(GSavePlayerHandleName.SIZE); + + [Fact] public void MarshalGSaveFg() => MarshalBytesTest(GSaveFg.SIZE); + [Fact] public void MarshalGSaveVisitorNpc() => MarshalBytesTest(GSaveVisitorNpc.SIZE); + + [Fact] public void MarshalAchievementList() => MarshalBytesTestS(AchievementList.SIZE); + + private static void MarshalBytesTestS(int size) where T : struct { - [Fact] public void MarshalGSaveBulletinBoard() => MarshalBytesTestS(GSaveBulletinBoard.SIZE); - [Fact] public void MarshalBulletinBoard() => MarshalBytesTestS(BulletinBoardStock.SIZE); - [Fact] public void MarshalGSaveBBS() => MarshalBytesTestS(GSaveBBS.SIZE); - [Fact] public void MarshalGSaveDate() => MarshalBytesTestS(GSaveDate.SIZE); - [Fact] public void MarshalGSaveDateMD() => MarshalBytesTestS(GSaveDateMD.SIZE); - [Fact] public void MarshalGSavePlayerId() => MarshalBytesTestS(GSavePlayerId.SIZE); - [Fact] public void MarshalGSaveLandId() => MarshalBytesTestS(GSaveLandId.SIZE); - [Fact] public void MarshalGSavePlayerBaseId() => MarshalBytesTestS(GSavePlayerBaseId.SIZE); - [Fact] public void MarshalHandwriting() => MarshalBytesTestS(Handwriting.SIZE); + var bytes = new byte[size]; + var obj = bytes.ToStructure(); - [Fact] public void MarshalGSaveRoomFloorWall() => MarshalBytesTestS(GSaveRoomFloorWall.SIZE); - [Fact] public void MarshalGSaveAudioInfo() => MarshalBytesTestS(GSaveAudioInfo.SIZE); - - [Fact] public void MarshalGSaveManpu() => MarshalBytesTestS(GSavePlayerManpu.SIZE); - [Fact] public void MarshalGSavePlayerHandleName() => MarshalBytesTestS(GSavePlayerHandleName.SIZE); - - [Fact] public void MarshalGSaveFg() => MarshalBytesTest(GSaveFg.SIZE); - [Fact] public void MarshalGSaveVisitorNpc() => MarshalBytesTest(GSaveVisitorNpc.SIZE); - - [Fact] public void MarshalAchievementList() => MarshalBytesTestS(AchievementList.SIZE); - - private static void MarshalBytesTestS(int size) where T : struct - { - var bytes = new byte[size]; - var obj = bytes.ToStructure(); - - var decomputed = obj.ToBytes(); - decomputed.Length.Should().Be(size); - } - - private static void MarshalBytesTest(int size) where T : class - { - var bytes = new byte[size]; - var obj = bytes.ToClass(); - - var decomputed = obj.ToBytesClass(); - decomputed.Length.Should().Be(size); - } + var decomputed = obj.ToBytes(); + decomputed.Length.Should().Be(size); } -} + + private static void MarshalBytesTest(int size) where T : class + { + var bytes = new byte[size]; + var obj = bytes.ToClass(); + + var decomputed = obj.ToBytesClass(); + decomputed.Length.Should().Be(size); + } +} \ No newline at end of file diff --git a/NHSE.Tests/InjectionTests.cs b/NHSE.Tests/InjectionTests.cs index b1bc439..9f8d867 100644 --- a/NHSE.Tests/InjectionTests.cs +++ b/NHSE.Tests/InjectionTests.cs @@ -2,16 +2,15 @@ using NHSE.Core; using Xunit; -namespace NHSE.Tests +namespace NHSE.Tests; + +public static class InjectionTests { - public static class InjectionTests + [Fact] + public static void VerifyItemBinary() { - [Fact] - public static void VerifyItemBinary() - { - var data = Properties.Resources.itempacket; - bool result = PlayerItemSet.ValidateItemBinary(data); - result.Should().BeTrue(); - } + var data = Properties.Resources.itempacket; + bool result = PlayerItemSet.ValidateItemBinary(data); + result.Should().BeTrue(); } -} +} \ No newline at end of file diff --git a/NHSE.Tests/ItemParsingTests.cs b/NHSE.Tests/ItemParsingTests.cs index 6e3fa3c..e6c64b2 100644 --- a/NHSE.Tests/ItemParsingTests.cs +++ b/NHSE.Tests/ItemParsingTests.cs @@ -3,54 +3,53 @@ using NHSE.Core; using Xunit; -namespace NHSE.Tests +namespace NHSE.Tests; + +public static class ItemParsingTests { - public static class ItemParsingTests + [Theory] + [InlineData("diner sofa", 0x102D)] + [InlineData("? block", 0x35FD)] + [InlineData("block", 0x35FE)] + [InlineData("dal apron", 0x2F5E)] + public static void ParseItem(string name, ushort id) { - [Theory] - [InlineData("diner sofa", 0x102D)] - [InlineData("? block", 0x35FD)] - [InlineData("block", 0x35FE)] - [InlineData("dal apron", 0x2F5E)] - public static void ParseItem(string name, ushort id) + // single { - // single - { - // by name - var parse = ItemParser.GetItem(name); - parse.ItemId.Should().Be(id); - } - - // many - { - var cfg = new ConfigWrapFake(); - var parse = ItemParser.GetItemsFromUserInput(name, cfg); - parse.Count.Should().Be(1); - parse.ToList()[0].ItemId.Should().Be(id); - - var hex = ItemParser.GetItemsFromUserInput(id.ToString("X8"), cfg); - hex.Count.Should().Be(1); - hex.ToList()[0].ItemId.Should().Be(id); - } - } - - [Theory] - [InlineData("royal Crown", 0x14BB)] - [InlineData("royal crown (No Variations)", 0x14BB)] - [InlineData("bug aloha shirt ", 0x223C)] - [InlineData("quaint painting", 0xA)] - [InlineData("(none)", Item.NONE)] - public static void ParseAssociatedItem(string nameNoParenthesis, ushort id) - { - var parse = ItemParser.GetItem(nameNoParenthesis); + // by name + var parse = ItemParser.GetItem(name); parse.ItemId.Should().Be(id); } - private class ConfigWrapFake : IConfigItem + // many { - public bool WrapAllItems { get; } = true; - public ItemWrappingPaper WrappingPaper { get; } = ItemWrappingPaper.Black; - public bool SkipDropCheck { get; } = false; + var cfg = new ConfigWrapFake(); + var parse = ItemParser.GetItemsFromUserInput(name, cfg); + parse.Count.Should().Be(1); + parse.ToList()[0].ItemId.Should().Be(id); + + var hex = ItemParser.GetItemsFromUserInput(id.ToString("X8"), cfg); + hex.Count.Should().Be(1); + hex.ToList()[0].ItemId.Should().Be(id); } } -} + + [Theory] + [InlineData("royal Crown", 0x14BB)] + [InlineData("royal crown (No Variations)", 0x14BB)] + [InlineData("bug aloha shirt ", 0x223C)] + [InlineData("quaint painting", 0xA)] + [InlineData("(none)", Item.NONE)] + public static void ParseAssociatedItem(string nameNoParenthesis, ushort id) + { + var parse = ItemParser.GetItem(nameNoParenthesis); + parse.ItemId.Should().Be(id); + } + + private class ConfigWrapFake : IConfigItem + { + public bool WrapAllItems { get; } = true; + public ItemWrappingPaper WrappingPaper { get; } = ItemWrappingPaper.Black; + public bool SkipDropCheck { get; } = false; + } +} \ No newline at end of file diff --git a/NHSE.Tests/MSBTTests.cs b/NHSE.Tests/MSBTTests.cs index 7f008cb..8bb24ed 100644 --- a/NHSE.Tests/MSBTTests.cs +++ b/NHSE.Tests/MSBTTests.cs @@ -3,31 +3,30 @@ using NHSE.Tests.Properties; using Xunit; -namespace NHSE.Tests +namespace NHSE.Tests; + +public static class MSBTTests { - public static class MSBTTests + [Fact] + public static void TestTownDefaultNames() { - [Fact] - public static void TestTownDefaultNames() - { - var data = Resources.STR_TownName; - var obj = new MSBT(data); - obj.SectionOrder.Count.Should().Be(3); - obj.TXT2.Strings.Count.Should().BeGreaterThan(0); + var data = Resources.STR_TownName; + var obj = new MSBT(data); + obj.SectionOrder.Count.Should().Be(3); + obj.TXT2.Strings.Count.Should().BeGreaterThan(0); - var str = obj.TXT2.Strings[8].ToString(obj.FileEncoding).TrimEnd('\0'); - str.Should().Be("Awesome Beach"); - obj.DebugDumpLines(); - } - - [Fact] - public static void TestTurnip() - { - var data = Resources.STR_ItemName_41_Turnip; - var obj = new MSBT(data); - obj.SectionOrder.Count.Should().Be(3); - obj.TXT2.Strings.Count.Should().BeGreaterThan(0); - obj.DebugDumpLines(); - } + var str = obj.TXT2.Strings[8].ToString(obj.FileEncoding).TrimEnd('\0'); + str.Should().Be("Awesome Beach"); + obj.DebugDumpLines(); } -} + + [Fact] + public static void TestTurnip() + { + var data = Resources.STR_ItemName_41_Turnip; + var obj = new MSBT(data); + obj.SectionOrder.Count.Should().Be(3); + obj.TXT2.Strings.Count.Should().BeGreaterThan(0); + obj.DebugDumpLines(); + } +} \ No newline at end of file diff --git a/NHSE.Tests/MarshalTests.cs b/NHSE.Tests/MarshalTests.cs index 0df2f46..87a2e5d 100644 --- a/NHSE.Tests/MarshalTests.cs +++ b/NHSE.Tests/MarshalTests.cs @@ -2,44 +2,43 @@ using NHSE.Core; using Xunit; -namespace NHSE.Tests +namespace NHSE.Tests; + +public class MarshalTests { - public class MarshalTests + [Fact] public void MarshalItem() => MarshalTest(Item.SIZE); + [Fact] public void MarshalVillagerItem() => MarshalTest(VillagerItem.SIZE); + [Fact] public void MarshalTerrainTile() => MarshalTest(TerrainTile.SIZE); + [Fact] public void MarshalTurnip() => MarshalTest(TurnipStonk.SIZE); + [Fact] public void MarshalBuilding() => MarshalTest(Building.SIZE); + + [Fact] public void MarshalVillagerHouseItem() => MarshalTestS(VillagerHouseItem.SIZE); + [Fact] public void MarshalGSaveItemName() => MarshalTestS(GSaveItemName.SIZE); + + [Fact] public void MarshalHouse1() => MarshalTestS(s_f9acc222.SIZE); + [Fact] public void MarshalHouse2() => MarshalTestS(s_e74059db.SIZE); + [Fact] public void MarshalHouse3() => MarshalTestS(s_a7a72585.SIZE); + [Fact] public void MarshalHouse4() => MarshalTestS(GSaveRoomFloorWall.SIZE); + [Fact] public void MarshalHouse5() => MarshalTestS(s_e13a81f4.SIZE); + [Fact] public void MarshalHouse6() => MarshalTestS(GSaveAudioRegister.SIZE); + + private static void MarshalTest(int size) where T : class, new() { - [Fact] public void MarshalItem() => MarshalTest(Item.SIZE); - [Fact] public void MarshalVillagerItem() => MarshalTest(VillagerItem.SIZE); - [Fact] public void MarshalTerrainTile() => MarshalTest(TerrainTile.SIZE); - [Fact] public void MarshalTurnip() => MarshalTest(TurnipStonk.SIZE); - [Fact] public void MarshalBuilding() => MarshalTest(Building.SIZE); + var obj = new T(); + var bytes = obj.ToBytesClass(); + bytes.Length.Should().Be(size); - [Fact] public void MarshalVillagerHouseItem() => MarshalTestS(VillagerHouseItem.SIZE); - [Fact] public void MarshalGSaveItemName() => MarshalTestS(GSaveItemName.SIZE); - - [Fact] public void MarshalHouse1() => MarshalTestS(s_f9acc222.SIZE); - [Fact] public void MarshalHouse2() => MarshalTestS(s_e74059db.SIZE); - [Fact] public void MarshalHouse3() => MarshalTestS(s_a7a72585.SIZE); - [Fact] public void MarshalHouse4() => MarshalTestS(GSaveRoomFloorWall.SIZE); - [Fact] public void MarshalHouse5() => MarshalTestS(s_e13a81f4.SIZE); - [Fact] public void MarshalHouse6() => MarshalTestS(GSaveAudioRegister.SIZE); - - private static void MarshalTest(int size) where T : class, new() - { - var obj = new T(); - var bytes = obj.ToBytesClass(); - bytes.Length.Should().Be(size); - - var recomputed = bytes.ToClass(); - recomputed.Should().NotBeNull(); - } - - private static void MarshalTestS(int size) where T : struct - { - var obj = new T(); - var bytes = obj.ToBytes(); - bytes.Length.Should().Be(size); - - var recomputed = bytes.ToStructure(); - recomputed.Should().NotBeNull(); - } + var recomputed = bytes.ToClass(); + recomputed.Should().NotBeNull(); } -} + + private static void MarshalTestS(int size) where T : struct + { + var obj = new T(); + var bytes = obj.ToBytes(); + bytes.Length.Should().Be(size); + + var recomputed = bytes.ToStructure(); + recomputed.Should().NotBeNull(); + } +} \ No newline at end of file diff --git a/NHSE.Tests/NHSE.Tests.csproj b/NHSE.Tests/NHSE.Tests.csproj index 8164338..a4dd9dc 100644 --- a/NHSE.Tests/NHSE.Tests.csproj +++ b/NHSE.Tests/NHSE.Tests.csproj @@ -1,15 +1,14 @@  - net8.0 false - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/NHSE.Villagers/NHSE.Villagers.csproj b/NHSE.Villagers/NHSE.Villagers.csproj index f9edf8e..fb92633 100644 --- a/NHSE.Villagers/NHSE.Villagers.csproj +++ b/NHSE.Villagers/NHSE.Villagers.csproj @@ -1,7 +1,6 @@  - net46;net8.0-windows en @@ -24,9 +23,9 @@ - - - + + + diff --git a/NHSE.Villagers/VillagerData.cs b/NHSE.Villagers/VillagerData.cs index 32abe26..cc8007e 100644 --- a/NHSE.Villagers/VillagerData.cs +++ b/NHSE.Villagers/VillagerData.cs @@ -1,14 +1,15 @@ -namespace NHSE.Villagers -{ - public class VillagerData - { - public readonly byte[] Villager; - public readonly byte[] House; +using System; - public VillagerData(byte[] villager, byte[] house) - { - Villager = villager; - House = house; - } +namespace NHSE.Villagers; + +public class VillagerData +{ + public readonly Memory Villager; + public readonly Memory House; + + public VillagerData(Memory villager, Memory house) + { + Villager = villager; + House = house; } -} +} \ No newline at end of file diff --git a/NHSE.Villagers/VillagerInfo.cs b/NHSE.Villagers/VillagerInfo.cs index ce06e63..efb7746 100644 --- a/NHSE.Villagers/VillagerInfo.cs +++ b/NHSE.Villagers/VillagerInfo.cs @@ -1,16 +1,15 @@ using NHSE.Core; -namespace NHSE.Villagers -{ - public class VillagerInfo - { - public readonly Villager2 Villager; - public readonly IVillagerHouse House; +namespace NHSE.Villagers; - public VillagerInfo(Villager2 villager, IVillagerHouse house) - { - Villager = villager; - House = house; - } +public class VillagerInfo +{ + public readonly Villager2 Villager; + public readonly IVillagerHouse House; + + public VillagerInfo(Villager2 villager, IVillagerHouse house) + { + Villager = villager; + House = house; } -} +} \ No newline at end of file diff --git a/NHSE.Villagers/VillagerResources.cs b/NHSE.Villagers/VillagerResources.cs index fd65044..81d8018 100644 --- a/NHSE.Villagers/VillagerResources.cs +++ b/NHSE.Villagers/VillagerResources.cs @@ -3,41 +3,38 @@ using NHSE.Core; using static NHSE.Villagers.Properties.Resources; -namespace NHSE.Villagers +namespace NHSE.Villagers; + +public static class VillagerResources { - public static class VillagerResources + private static string GetResourceNameVillager(string villagerName) => $"{villagerName}V"; + private static string GetResourceNameHouse(string villagerName) => $"{villagerName}H"; + + /// + /// Checks if the villager name is in the database. + /// + /// Internal villager name. + /// True if exists in database + public static bool IsVillagerDataKnown(string villagerName) => ResourceManager.GetObject(GetResourceNameVillager(villagerName)) != null; + + /// + /// Gets the raw Villager data and house data for the . + /// + /// Internal villager name. + public static VillagerData GetVillager(string villagerName) { - private static string GetResourceNameVillager(string villagerName) => $"{villagerName}V"; - private static string GetResourceNameHouse(string villagerName) => $"{villagerName}H"; + var nv = GetResourceNameVillager(villagerName); + var nh = GetResourceNameHouse(villagerName); - /// - /// Checks if the villager name is in the database. - /// - /// Internal villager name. - /// True if exists in database - public static bool IsVillagerDataKnown(string villagerName) => ResourceManager.GetObject(GetResourceNameVillager(villagerName)) != null; + if (ResourceManager.GetObject(nv) is not byte[] bv) + throw new ArgumentException($"Villager data not found for {villagerName} ({nv})", nameof(villagerName)); - /// - /// Gets the raw Villager data and house data for the . - /// - /// Internal villager name. - public static VillagerData GetVillager(string villagerName) - { - var nv = GetResourceNameVillager(villagerName); - var nh = GetResourceNameHouse(villagerName); + if (ResourceManager.GetObject(nh) is not byte[] bh) + throw new ArgumentException($"House data not found for {villagerName} ({nh})", nameof(villagerName)); - var bv = (byte[]?)ResourceManager.GetObject(nv); - if (bv == null) - throw new ArgumentException($"Villager data not found for {villagerName} ({nv})", nameof(villagerName)); + Debug.Assert(bv.Length == Villager2.SIZE); + Debug.Assert(bh.Length == VillagerHouse2.SIZE); - var bh = (byte[]?)ResourceManager.GetObject(nh); - if (bh == null) - throw new ArgumentException($"House data not found for {villagerName} ({nh})", nameof(villagerName)); - - Debug.Assert(bv.Length == Villager2.SIZE); - Debug.Assert(bh.Length == VillagerHouse2.SIZE); - - return new VillagerData(bv, bh); - } + return new VillagerData(bv, bh); } -} +} \ No newline at end of file diff --git a/NHSE.Villagers/VillagerSwap.cs b/NHSE.Villagers/VillagerSwap.cs index 28f2463..9489965 100644 --- a/NHSE.Villagers/VillagerSwap.cs +++ b/NHSE.Villagers/VillagerSwap.cs @@ -1,33 +1,32 @@ using NHSE.Core; -namespace NHSE.Villagers +namespace NHSE.Villagers; + +public static class VillagerSwap { - public static class VillagerSwap + public static VillagerData GetReplacementVillager(VillagerInfo exist, string newVillager, bool prepMoveOut = false) { - public static VillagerData GetReplacementVillager(VillagerInfo exist, string newVillager, bool prepMoveOut = false) - { - var replace = VillagerResources.GetVillager(newVillager); - return AdaptVillager(exist, replace, prepMoveOut); - } - - private static VillagerData AdaptVillager(VillagerInfo exist, VillagerData replace, bool prepMoveOut = false) - { - var ov = exist.Villager; - var oh = exist.House; - var nv = new Villager2(replace.Villager); - _ = new VillagerHouse1(replace.House) {NPC1 = oh.NPC1, NPC2 = oh.NPC2, BuildPlayer = oh.BuildPlayer}; - - // Copy Memories - var om = nv.GetMemory(0); - var nm = ov.GetMemory(0); - nm.PlayerId = om.PlayerId; - nv.SetMemory(nm, 0); - - if (!prepMoveOut) - return replace; - - nv.MovingOut = true; - return replace; - } + var replace = VillagerResources.GetVillager(newVillager); + return AdaptVillager(exist, replace, prepMoveOut); } -} + + private static VillagerData AdaptVillager(VillagerInfo exist, VillagerData replace, bool prepMoveOut = false) + { + var ov = exist.Villager; + var oh = exist.House; + var nv = new Villager2(replace.Villager.ToArray()); + _ = new VillagerHouse1(replace.House.ToArray()) {NPC1 = oh.NPC1, NPC2 = oh.NPC2, BuildPlayer = oh.BuildPlayer}; + + // Copy Memories + var om = nv.GetMemory(0); + var nm = ov.GetMemory(0); + nm.PlayerId = om.PlayerId; + nv.SetMemory(nm, 0); + + if (!prepMoveOut) + return replace; + + nv.MovingOut = true; + return replace; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Controls/AchievementRow.cs b/NHSE.WinForms/Controls/AchievementRow.cs index d8961bd..bb6b17a 100644 --- a/NHSE.WinForms/Controls/AchievementRow.cs +++ b/NHSE.WinForms/Controls/AchievementRow.cs @@ -3,62 +3,61 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms -{ - public partial class AchievementRow : UserControl - { - public AchievementRow() - { - InitializeComponent(); - CAL_Date.MinDate = DateTime.MinValue; - } +namespace NHSE.WinForms; - public void LoadRow(AchievementList list, in int index, in int row) +public partial class AchievementRow : UserControl +{ + public AchievementRow() + { + InitializeComponent(); + CAL_Date.MinDate = DateTime.MinValue; + } + + public void LoadRow(AchievementList list, in int index, in int row) + { + if (!LifeSupportAchievement.List.TryGetValue(index, out var detail)) { - if (!LifeSupportAchievement.List.TryGetValue(index, out var detail)) + L_Threshold.Text = "N/A"; + } + else + { + if (row >= detail.AchievementCount) { - L_Threshold.Text = "N/A"; + L_Threshold.Text = string.Empty; } else { - if (row >= detail.AchievementCount) - { - L_Threshold.Text = string.Empty; - } - else - { - var threshold = detail.GetThresholdValue(row); - L_Threshold.Text = threshold <= 0 ? "N/A" : threshold.ToString(); - } + var threshold = detail.GetThresholdValue(row); + L_Threshold.Text = threshold <= 0 ? "N/A" : threshold.ToString(); } - - var date = list.Date[index][row]; - if (date < CAL_Date.MinDate) - date = CAL_Date.MinDate; - CAL_Date.Value = date; - - CHK_Read.Checked = list.Read[index][row]; } - public void SaveRow(AchievementList list, in int index, in int row) - { - list.Date[index][row] = CAL_Date.Value; - list.Read[index][row] = CHK_Read.Checked; - } + var date = list.Date[index][row]; + if (date < CAL_Date.MinDate) + date = CAL_Date.MinDate; + CAL_Date.Value = date; - public void ChangeCount(in int index, in int row, in uint count) - { - if (!LifeSupportAchievement.List.TryGetValue(index, out var detail)) - return; - - bool satisfied = detail.GetIsSatisfied(row, count); - L_Threshold.ForeColor = satisfied ? Color.Red : CHK_Read.ForeColor; - } - - private void CAL_Date_MouseDown(object sender, MouseEventArgs e) - { - if ((ModifierKeys & Keys.Alt) != 0 && e.Button == MouseButtons.Left) - CAL_Date.Value = CAL_Date.MinDate; - } + CHK_Read.Checked = list.Read[index][row]; } -} + + public void SaveRow(AchievementList list, in int index, in int row) + { + list.Date[index][row] = CAL_Date.Value; + list.Read[index][row] = CHK_Read.Checked; + } + + public void ChangeCount(in int index, in int row, in uint count) + { + if (!LifeSupportAchievement.List.TryGetValue(index, out var detail)) + return; + + bool satisfied = detail.GetIsSatisfied(row, count); + L_Threshold.ForeColor = satisfied ? Color.Red : CHK_Read.ForeColor; + } + + private void CAL_Date_MouseDown(object sender, MouseEventArgs e) + { + if ((ModifierKeys & Keys.Alt) != 0 && e.Button == MouseButtons.Left) + CAL_Date.Value = CAL_Date.MinDate; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Controls/ItemEditor.cs b/NHSE.WinForms/Controls/ItemEditor.cs index 4eed170..74d7d7e 100644 --- a/NHSE.WinForms/Controls/ItemEditor.cs +++ b/NHSE.WinForms/Controls/ItemEditor.cs @@ -6,406 +6,405 @@ using NHSE.Core; using NHSE.Sprites; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class ItemEditor : UserControl { - public partial class ItemEditor : UserControl + private readonly List Recipes = GameInfo.Strings.CreateItemDataSource(RecipeList.Recipes, false); + private readonly List Fossils = GameInfo.Strings.CreateItemDataSource(GameLists.Fossils, false); + private readonly CheckBox[] Watered; + + private bool Loading = true; + private bool CanExtend; + + public ItemEditor() { - private readonly List Recipes = GameInfo.Strings.CreateItemDataSource(RecipeList.Recipes, false); - private readonly List Fossils = GameInfo.Strings.CreateItemDataSource(GameLists.Fossils, false); - private readonly CheckBox[] Watered; + InitializeComponent(); - private bool Loading = true; - private bool CanExtend; + CB_WrapColor.Items.AddRange(Enum.GetNames()); + CB_WrapType.Items.AddRange(Enum.GetNames()); - public ItemEditor() + Watered = + [ + CHK_WV0, CHK_WV1, + CHK_WV2, CHK_WV3, + CHK_WV4, CHK_WV5, + CHK_WV6, CHK_WV7, + CHK_WV8, CHK_WV9 + ]; + } + + private IReadOnlyList AllItems = []; + + public void Initialize(IReadOnlyList items, bool canExtend = false) + { + CHK_IsExtension.Visible = CanExtend = canExtend; + + CB_ItemID.DisplayMember = nameof(ComboItem.Text); + CB_ItemID.ValueMember = nameof(ComboItem.Value); + CB_ItemID.DataSource = items; + + CB_Recipe.DisplayMember = nameof(ComboItem.Text); + CB_Recipe.ValueMember = nameof(ComboItem.Value); + CB_Recipe.DataSource = Recipes; + + CB_Fossil.DisplayMember = nameof(ComboItem.Text); + CB_Fossil.ValueMember = nameof(ComboItem.Value); + CB_Fossil.DataSource = Fossils; + + LoadItem(Item.NO_ITEM); + + AllItems = items; + } + + public Item LoadItem(Item item) + { + Loading = true; + var id = item.ItemId; + if (CanExtend && id == Item.EXTENSION) + return LoadExtensionItem(item); + + CHK_IsExtension.Checked = false; + CB_ItemID.SelectedValue = (int)id; + var kind = ItemInfo.GetItemKind(id); + + if (kind.IsFlowerGene(id)) { - InitializeComponent(); - - CB_WrapColor.Items.AddRange(Enum.GetNames(typeof(ItemWrappingPaper))); - CB_WrapType.Items.AddRange(Enum.GetNames(typeof(ItemWrapping))); - - Watered = new[] - { - CHK_WV0, CHK_WV1, - CHK_WV2, CHK_WV3, - CHK_WV4, CHK_WV5, - CHK_WV6, CHK_WV7, - CHK_WV8, CHK_WV9, - }; + LoadGenes(item.Genes); + CHK_Gold.Checked = item.IsWateredGold; + CHK_IsWatered.Checked = item.IsWatered; + NUD_WaterDays.Value = item.DaysWatered; + for (int i = 0; i < Watered.Length; i++) + Watered[i].Checked = item.GetIsWateredByVisitor(i); + } + else + { + NUD_Count.Value = item.Count; + NUD_Uses.Value = item.UseCount; + NUD_Flag0.Value = item.SystemParam; } - private IReadOnlyList AllItems = Array.Empty(); - - public void Initialize(IReadOnlyList items, bool canExtend = false) + LoadItemTypeValues(kind, id); + if (kind == ItemKind.Kind_MessageBottle || id >= 60_000) { - CHK_IsExtension.Visible = CanExtend = canExtend; - - CB_ItemID.DisplayMember = nameof(ComboItem.Text); - CB_ItemID.ValueMember = nameof(ComboItem.Value); - CB_ItemID.DataSource = items; - - CB_Recipe.DisplayMember = nameof(ComboItem.Text); - CB_Recipe.ValueMember = nameof(ComboItem.Value); - CB_Recipe.DataSource = Recipes; - - CB_Fossil.DisplayMember = nameof(ComboItem.Text); - CB_Fossil.ValueMember = nameof(ComboItem.Value); - CB_Fossil.DataSource = Fossils; - - LoadItem(Item.NO_ITEM); - - AllItems = items; + NUD_Flag1.Value = item.AdditionalParam; + } + else + { + CHK_Wrapped.Checked = item.WrappingType != 0; + CB_WrapType.SelectedIndex = (int)item.WrappingType; + CB_WrapColor.SelectedIndex = (int)item.WrappingPaper; + CHK_WrapShowName.Checked = item.WrappingShowItem; + CHK_Wrap80.Checked = item.Wrapping80; } - public Item LoadItem(Item item) + Loading = false; + return item; + } + + private Item LoadExtensionItem(Item item) + { + CB_ItemID.SelectedValue = (int) item.ExtensionItemId; + CHK_IsExtension.Checked = true; + NUD_ExtensionX.Value = item.ExtensionX; + NUD_ExtensionY.Value = item.ExtensionY; + return item; + } + + public Item SetItem(Item item) + { + if (CHK_IsExtension.Checked) + return SetExtensionItem(item); + + var id = (ushort)WinFormsUtil.GetIndex(CB_ItemID); + var kind = ItemInfo.GetItemKind(id); + + item.ItemId = id; + if (kind.IsFlowerGene(id)) { - Loading = true; - var id = item.ItemId; - if (CanExtend && id == Item.EXTENSION) - return LoadExtensionItem(item); + item.Genes = SaveGenes(); + item.DaysWatered = (int) NUD_WaterDays.Value; + item.IsWateredGold = CHK_Gold.Checked; + item.IsWatered = CHK_IsWatered.Checked; + for (int i = 0; i < Watered.Length; i++) + item.SetIsWateredByVisitor(i, Watered[i].Checked); - CHK_IsExtension.Checked = false; - CB_ItemID.SelectedValue = (int)id; - var kind = ItemInfo.GetItemKind(id); + item.SystemParam = 0; + item.AdditionalParam = 0; + } + else + { + item.Count = (ushort)NUD_Count.Value; + item.UseCount = (ushort)NUD_Uses.Value; + item.SystemParam = (byte)NUD_Flag0.Value; + } - if (kind.IsFlowerGene(id)) + if (kind == ItemKind.Kind_MessageBottle || id >= 60_000) + { + item.AdditionalParam = (byte)NUD_Flag1.Value; + } + else + { + if (!CHK_Wrapped.Checked) { - LoadGenes(item.Genes); - CHK_Gold.Checked = item.IsWateredGold; - CHK_IsWatered.Checked = item.IsWatered; - NUD_WaterDays.Value = item.DaysWatered; - for (int i = 0; i < Watered.Length; i++) - Watered[i].Checked = item.GetIsWateredByVisitor(i); + item.SetWrapping(0, 0); } else { - NUD_Count.Value = item.Count; - NUD_Uses.Value = item.UseCount; - NUD_Flag0.Value = item.SystemParam; + var type = (ItemWrapping)CB_WrapType.SelectedIndex; + var color = (ItemWrappingPaper)CB_WrapColor.SelectedIndex; + var show = CHK_WrapShowName.Checked; + var flag = CHK_Wrap80.Checked; + item.SetWrapping(type, color, show, flag); } + } + return item; + } - LoadItemTypeValues(kind, id); - if (kind == ItemKind.Kind_MessageBottle || id >= 60_000) + private Item SetExtensionItem(Item item) + { + var id = (ushort)WinFormsUtil.GetIndex(CB_ItemID); + item.ItemId = Item.EXTENSION; + item.ExtensionItemId = id; + item.ExtensionX = (byte) NUD_ExtensionX.Value; + item.ExtensionY = (byte) NUD_ExtensionY.Value; + return item; + } + + private void CB_ItemID_SelectedValueChanged(object sender, EventArgs e) + { + var itemID = (ushort)WinFormsUtil.GetIndex(CB_ItemID); + var itemCount = (ushort)NUD_Count.Value; + ChangeItem(itemID, itemCount); + var kind = ItemInfo.GetItemKind(itemID); + + ToggleEditorVisibility(kind, itemID); + if (!Loading) + LoadItemTypeValues(kind, itemID); + + var remake = ItemRemakeUtil.GetRemakeIndex(itemID); + if (remake < 0) + { + var closeItems = GameInfo.Strings.GetAssociatedItems(itemID, out var bse); + if (closeItems.Count > 1) // ignore if we are the only parenthesised item { - NUD_Flag1.Value = item.AdditionalParam; + L_RemakeBody.Text = $"{bse.Trim()}:\n" + closeItems.ToStringList(false); + L_RemakeBody.Visible = true; } else { - CHK_Wrapped.Checked = item.WrappingType != 0; - CB_WrapType.SelectedIndex = (int)item.WrappingType; - CB_WrapColor.SelectedIndex = (int)item.WrappingPaper; - CHK_WrapShowName.Checked = item.WrappingShowItem; - CHK_Wrap80.Checked = item.Wrapping80; - } - - Loading = false; - return item; - } - - private Item LoadExtensionItem(Item item) - { - CB_ItemID.SelectedValue = (int) item.ExtensionItemId; - CHK_IsExtension.Checked = true; - NUD_ExtensionX.Value = item.ExtensionX; - NUD_ExtensionY.Value = item.ExtensionY; - return item; - } - - public Item SetItem(Item item) - { - if (CHK_IsExtension.Checked) - return SetExtensionItem(item); - - var id = (ushort)WinFormsUtil.GetIndex(CB_ItemID); - var kind = ItemInfo.GetItemKind(id); - - item.ItemId = id; - if (kind.IsFlowerGene(id)) - { - item.Genes = SaveGenes(); - item.DaysWatered = (int) NUD_WaterDays.Value; - item.IsWateredGold = CHK_Gold.Checked; - item.IsWatered = CHK_IsWatered.Checked; - for (int i = 0; i < Watered.Length; i++) - item.SetIsWateredByVisitor(i, Watered[i].Checked); - - item.SystemParam = 0; - item.AdditionalParam = 0; - } - else - { - item.Count = (ushort)NUD_Count.Value; - item.UseCount = (ushort)NUD_Uses.Value; - item.SystemParam = (byte)NUD_Flag0.Value; - } - - if (kind == ItemKind.Kind_MessageBottle || id >= 60_000) - { - item.AdditionalParam = (byte)NUD_Flag1.Value; - } - else - { - if (!CHK_Wrapped.Checked) - { - item.SetWrapping(0, 0); - } - else - { - var type = (ItemWrapping)CB_WrapType.SelectedIndex; - var color = (ItemWrappingPaper)CB_WrapColor.SelectedIndex; - var show = CHK_WrapShowName.Checked; - var flag = CHK_Wrap80.Checked; - item.SetWrapping(type, color, show, flag); - } - } - return item; - } - - private Item SetExtensionItem(Item item) - { - var id = (ushort)WinFormsUtil.GetIndex(CB_ItemID); - item.ItemId = Item.EXTENSION; - item.ExtensionItemId = id; - item.ExtensionX = (byte) NUD_ExtensionX.Value; - item.ExtensionY = (byte) NUD_ExtensionY.Value; - return item; - } - - private void CB_ItemID_SelectedValueChanged(object sender, EventArgs e) - { - var itemID = (ushort)WinFormsUtil.GetIndex(CB_ItemID); - var itemCount = (ushort)NUD_Count.Value; - ChangeItem(itemID, itemCount); - var kind = ItemInfo.GetItemKind(itemID); - - ToggleEditorVisibility(kind, itemID); - if (!Loading) - LoadItemTypeValues(kind, itemID); - - var remake = ItemRemakeUtil.GetRemakeIndex(itemID); - if (remake < 0) - { - var closeItems = GameInfo.Strings.GetAssociatedItems(itemID, out var bse); - if (closeItems.Count > 1) // ignore if we are the only parenthesised item - { - L_RemakeBody.Text = $"{bse.Trim()}:\n" + closeItems.ToStringList(false); - L_RemakeBody.Visible = true; - } - else - { - L_RemakeBody.Visible = false; - L_RemakeFabric.Visible = false; - } - } - else - { - var info = ItemRemakeInfoData.List[remake]; - var body = info.GetBodySummary(GameInfo.Strings); - L_RemakeBody.Text = body; - L_RemakeBody.Visible = body.Length != 0; - - var fabric = info.GetFabricSummary(GameInfo.Strings); - L_RemakeFabric.Text = fabric; - L_RemakeFabric.Visible = fabric.Length != 0; + L_RemakeBody.Visible = false; + L_RemakeFabric.Visible = false; } } - - private void LoadItemTypeValues(ItemKind k, ushort index) + else { - if (k == ItemKind.Kind_MessageBottle || index >= 60_000) - { - CHK_Wrapped.Checked = false; + var info = ItemRemakeInfoData.List[remake]; + var body = info.GetBodySummary(GameInfo.Strings); + L_RemakeBody.Text = body; + L_RemakeBody.Visible = body.Length != 0; + + var fabric = info.GetFabricSummary(GameInfo.Strings); + L_RemakeFabric.Text = fabric; + L_RemakeFabric.Visible = fabric.Length != 0; + } + } + + private void LoadItemTypeValues(ItemKind k, ushort index) + { + if (k == ItemKind.Kind_MessageBottle || index >= 60_000) + { + CHK_Wrapped.Checked = false; + CHK_Wrapped.Visible = CHK_Wrapped.Checked = false; + FLP_Flag1.Visible = true; + return; + } + + switch (k) + { + case ItemKind.Kind_FossilUnknown: + CB_Fossil.SelectedValue = (int) NUD_Count.Value; + break; + + case ItemKind.Kind_DIYRecipe: + CB_Recipe.SelectedValue = (int)NUD_Count.Value; + break; + + case ItemKind.Kind_MessageBottle: + CB_Recipe.SelectedValue = (int) NUD_Count.Value; CHK_Wrapped.Visible = CHK_Wrapped.Checked = false; FLP_Flag1.Visible = true; return; - } - - switch (k) - { - case ItemKind.Kind_FossilUnknown: - CB_Fossil.SelectedValue = (int) NUD_Count.Value; - break; - - case ItemKind.Kind_DIYRecipe: - CB_Recipe.SelectedValue = (int)NUD_Count.Value; - break; - - case ItemKind.Kind_MessageBottle: - CB_Recipe.SelectedValue = (int) NUD_Count.Value; - CHK_Wrapped.Visible = CHK_Wrapped.Checked = false; - FLP_Flag1.Visible = true; - return; - } - - CHK_Wrapped.Visible = true; - FLP_Flag1.Visible = false; } - private void ToggleEditorVisibility(ItemKind k, ushort id) + CHK_Wrapped.Visible = true; + FLP_Flag1.Visible = false; + } + + private void ToggleEditorVisibility(ItemKind k, ushort id) + { + if (k.IsFlowerGene(id)) { - if (k.IsFlowerGene(id)) - { + CB_Recipe.Visible = false; + FLP_Uses.Visible = FLP_Count.Visible = false; + FLP_Flower.Visible = true; + return; + } + + switch (k) + { + case ItemKind.Kind_FossilUnknown: + CB_Fossil.Visible = true; + CB_Recipe.Visible = false; FLP_Uses.Visible = FLP_Count.Visible = false; - FLP_Flower.Visible = true; - return; - } + FLP_Flower.Visible = false; + break; - switch (k) - { - case ItemKind.Kind_FossilUnknown: - CB_Fossil.Visible = true; + case ItemKind.Kind_DIYRecipe: + CB_Recipe.Visible = true; - CB_Recipe.Visible = false; - FLP_Uses.Visible = FLP_Count.Visible = false; - FLP_Flower.Visible = false; - break; + CB_Fossil.Visible = false; + FLP_Uses.Visible = FLP_Count.Visible = false; + FLP_Flower.Visible = false; + break; - case ItemKind.Kind_DIYRecipe: - CB_Recipe.Visible = true; + case ItemKind.Kind_MessageBottle: + CB_Recipe.Visible = true; - CB_Fossil.Visible = false; - FLP_Uses.Visible = FLP_Count.Visible = false; - FLP_Flower.Visible = false; - break; + CB_Fossil.Visible = false; + FLP_Uses.Visible = true; + FLP_Count.Visible = false; + FLP_Flower.Visible = false; + break; - case ItemKind.Kind_MessageBottle: - CB_Recipe.Visible = true; - - CB_Fossil.Visible = false; - FLP_Uses.Visible = true; - FLP_Count.Visible = false; - FLP_Flower.Visible = false; - break; - - default: - CB_Fossil.Visible = false; - CB_Recipe.Visible = false; - FLP_Uses.Visible = FLP_Count.Visible = true; - FLP_Flower.Visible = false; - break; - } - } - - private void L_Count_DoubleClick(object sender, EventArgs e) - { - Item currentItem = SetItem(new Item()); - var result = ItemInfo.TryGetMaxStackCount(currentItem, out var max); - if (!result) - return; - currentItem.Count = (ushort)(max - 1); - LoadItem(currentItem); - } - - private void CB_CountAlias_SelectedValueChanged(object sender,EventArgs e) - { - var val = WinFormsUtil.GetIndex((ComboBox)sender); - NUD_Count.Value = Math.Max(0, Math.Min(NUD_Count.Maximum, val)); - } - - private void LoadGenes(FlowerGene genes) - { - CHK_R1.Checked = (genes & FlowerGene.R1) != 0; - CHK_R2.Checked = (genes & FlowerGene.R2) != 0; - CHK_Y1.Checked = (genes & FlowerGene.Y1) != 0; - CHK_Y2.Checked = (genes & FlowerGene.Y2) != 0; - CHK_W1.Checked = (genes & FlowerGene.w1) == 0; // inverted; both bits on = no gene (not white) - CHK_W2.Checked = (genes & FlowerGene.w2) == 0; // inverted; both bits on = no gene (not white) - CHK_S1.Checked = (genes & FlowerGene.S1) != 0; - CHK_S2.Checked = (genes & FlowerGene.S2) != 0; - } - - private FlowerGene SaveGenes() - { - var val = FlowerGene.None; - if (CHK_R1.Checked) val |= FlowerGene.R1; - if (CHK_R2.Checked) val |= FlowerGene.R2; - if (CHK_Y1.Checked) val |= FlowerGene.Y1; - if (CHK_Y2.Checked) val |= FlowerGene.Y2; - if (!CHK_W1.Checked) val |= FlowerGene.w1; // inverted; both bits on = no gene (not white) - if (!CHK_W2.Checked) val |= FlowerGene.w2; // inverted; both bits on = no gene (not white) - if (CHK_S1.Checked) val |= FlowerGene.S1; - if (CHK_S2.Checked) val |= FlowerGene.S2; - return val; - } - - private void L_WaterDays_Click(object sender, EventArgs e) - { - bool value = (ModifierKeys & Keys.Alt) == 0; - CHK_Gold.Checked = value; - CHK_IsWatered.Checked = value; - NUD_WaterDays.Value = value ? 31 : 0; - foreach (var v in Watered) - v.Checked = value; - } - - private void CB_KeyDown(object sender, KeyEventArgs e) => WinFormsUtil.RemoveDropCB(sender, e); - - private void CHK_IsExtension_CheckedChanged(object sender, EventArgs e) - { - if (CHK_IsExtension.Checked) - { - FLP_Item.Visible = false; - FLP_Extension.Visible = true; - } - else - { - FLP_Item.Visible = true; - FLP_Extension.Visible = false; - } - } - - private void ChangeItem(ushort item, ushort count) - { - var pb = PB_Item; - pb.BackColor = ItemColor.GetItemColor(item); - pb.BackgroundImage = ItemSprite.GetItemSprite(item, count); - } - - private void CHK_Wrapped_CheckedChanged(object sender, EventArgs e) - { - FLP_Wrapped.Visible = CHK_Wrapped.Checked; - if (CHK_Wrapped.Checked && CB_WrapType.SelectedIndex == 0) - CB_WrapType.SelectedIndex = (int)ItemWrapping.WrappingPaper; - } - - private void CB_WrapType_SelectedIndexChanged(object sender, EventArgs e) => CB_WrapColor.Visible = (ItemWrapping)CB_WrapType.SelectedIndex == ItemWrapping.WrappingPaper; - - private void CB_ItemID_TextChanged(object sender, EventArgs e) - { - var entered = CB_ItemID.Text; - var itemNames = AllItems.Where(z => z.Text.Contains(entered)).Take(10).Select(z => z.Text); - var caption = string.Join(Environment.NewLine, itemNames); - TT_Search.SetToolTip(CB_ItemID, caption); - } - - private void NUD_Count_ValueChanged(object sender, EventArgs e) - { - var itemID = (ushort)WinFormsUtil.GetIndex(CB_ItemID); - var itemCount = (ushort)NUD_Count.Value; - ChangeItem(itemID, itemCount); - } - - private void PB_Item_Click(object sender, EventArgs e) - { - // Import if requested - if (ModifierKeys == Keys.Shift && Clipboard.ContainsText()) - { - var text = Clipboard.GetText(); - if (!ulong.TryParse(text, NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out var val)) - return; - var import = BitConverter.GetBytes(val).ToClass(); - LoadItem(import); - System.Media.SystemSounds.Asterisk.Play(); - return; - } - - // Otherwise, export - var item = SetItem(new Item()); - var data = item.ToBytesClass(); - var u64 = BitConverter.ToUInt64(data, 0); - Clipboard.SetText($"{u64:X16}"); - System.Media.SystemSounds.Asterisk.Play(); + default: + CB_Fossil.Visible = false; + CB_Recipe.Visible = false; + FLP_Uses.Visible = FLP_Count.Visible = true; + FLP_Flower.Visible = false; + break; } } -} + + private void L_Count_DoubleClick(object sender, EventArgs e) + { + Item currentItem = SetItem(new Item()); + var result = ItemInfo.TryGetMaxStackCount(currentItem, out var max); + if (!result) + return; + currentItem.Count = (ushort)(max - 1); + LoadItem(currentItem); + } + + private void CB_CountAlias_SelectedValueChanged(object sender,EventArgs e) + { + var val = WinFormsUtil.GetIndex((ComboBox)sender); + NUD_Count.Value = Math.Max(0, Math.Min(NUD_Count.Maximum, val)); + } + + private void LoadGenes(FlowerGene genes) + { + CHK_R1.Checked = (genes & FlowerGene.R1) != 0; + CHK_R2.Checked = (genes & FlowerGene.R2) != 0; + CHK_Y1.Checked = (genes & FlowerGene.Y1) != 0; + CHK_Y2.Checked = (genes & FlowerGene.Y2) != 0; + CHK_W1.Checked = (genes & FlowerGene.w1) == 0; // inverted; both bits on = no gene (not white) + CHK_W2.Checked = (genes & FlowerGene.w2) == 0; // inverted; both bits on = no gene (not white) + CHK_S1.Checked = (genes & FlowerGene.S1) != 0; + CHK_S2.Checked = (genes & FlowerGene.S2) != 0; + } + + private FlowerGene SaveGenes() + { + var val = FlowerGene.None; + if (CHK_R1.Checked) val |= FlowerGene.R1; + if (CHK_R2.Checked) val |= FlowerGene.R2; + if (CHK_Y1.Checked) val |= FlowerGene.Y1; + if (CHK_Y2.Checked) val |= FlowerGene.Y2; + if (!CHK_W1.Checked) val |= FlowerGene.w1; // inverted; both bits on = no gene (not white) + if (!CHK_W2.Checked) val |= FlowerGene.w2; // inverted; both bits on = no gene (not white) + if (CHK_S1.Checked) val |= FlowerGene.S1; + if (CHK_S2.Checked) val |= FlowerGene.S2; + return val; + } + + private void L_WaterDays_Click(object sender, EventArgs e) + { + bool value = (ModifierKeys & Keys.Alt) == 0; + CHK_Gold.Checked = value; + CHK_IsWatered.Checked = value; + NUD_WaterDays.Value = value ? 31 : 0; + foreach (var v in Watered) + v.Checked = value; + } + + private void CB_KeyDown(object sender, KeyEventArgs e) => WinFormsUtil.RemoveDropCB(sender, e); + + private void CHK_IsExtension_CheckedChanged(object sender, EventArgs e) + { + if (CHK_IsExtension.Checked) + { + FLP_Item.Visible = false; + FLP_Extension.Visible = true; + } + else + { + FLP_Item.Visible = true; + FLP_Extension.Visible = false; + } + } + + private void ChangeItem(ushort item, ushort count) + { + var pb = PB_Item; + pb.BackColor = ItemColor.GetItemColor(item); + pb.BackgroundImage = ItemSprite.GetItemSprite(item, count); + } + + private void CHK_Wrapped_CheckedChanged(object sender, EventArgs e) + { + FLP_Wrapped.Visible = CHK_Wrapped.Checked; + if (CHK_Wrapped.Checked && CB_WrapType.SelectedIndex == 0) + CB_WrapType.SelectedIndex = (int)ItemWrapping.WrappingPaper; + } + + private void CB_WrapType_SelectedIndexChanged(object sender, EventArgs e) => CB_WrapColor.Visible = (ItemWrapping)CB_WrapType.SelectedIndex == ItemWrapping.WrappingPaper; + + private void CB_ItemID_TextChanged(object sender, EventArgs e) + { + var entered = CB_ItemID.Text; + var itemNames = AllItems.Where(z => z.Text.Contains(entered)).Take(10).Select(z => z.Text); + var caption = string.Join(Environment.NewLine, itemNames); + TT_Search.SetToolTip(CB_ItemID, caption); + } + + private void NUD_Count_ValueChanged(object sender, EventArgs e) + { + var itemID = (ushort)WinFormsUtil.GetIndex(CB_ItemID); + var itemCount = (ushort)NUD_Count.Value; + ChangeItem(itemID, itemCount); + } + + private void PB_Item_Click(object sender, EventArgs e) + { + // Import if requested + if (ModifierKeys == Keys.Shift && Clipboard.ContainsText()) + { + var text = Clipboard.GetText(); + if (!ulong.TryParse(text, NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out var val)) + return; + var import = new Item(val); + LoadItem(import); + System.Media.SystemSounds.Asterisk.Play(); + return; + } + + // Otherwise, export + var item = SetItem(new Item()); + var data = item.ToBytesClass(); + var u64 = System.Buffers.Binary.BinaryPrimitives.ReadUInt64LittleEndian(data); + Clipboard.SetText($"{u64:X16}"); + System.Media.SystemSounds.Asterisk.Play(); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Controls/ItemGrid.cs b/NHSE.WinForms/Controls/ItemGrid.cs index bcf786d..92efaac 100644 --- a/NHSE.WinForms/Controls/ItemGrid.cs +++ b/NHSE.WinForms/Controls/ItemGrid.cs @@ -4,75 +4,74 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class ItemGrid : UserControl { - public partial class ItemGrid : UserControl + public ItemGrid() { - public ItemGrid() - { - InitializeComponent(); - } - - public readonly List Entries = new(); - public int Slots { get; private set; } - - private int sizeW = 32; - private int sizeH = 32; - - public void InitializeGrid(int width, int height, IGridItem info) - { - sizeW = info.Width; - sizeH = info.Height; - Generate(width, height); - Slots = width * height; - } - - private const int padEdge = 0; // edges - private const int border = 1; // between - - private void Generate(int width, int height) - { - SuspendLayout(); - Controls.Clear(); - Entries.Clear(); - - int colWidth = sizeW; - int rowHeight = sizeH; - - for (int row = 0; row < height; row++) - { - var y = padEdge + (row * (rowHeight + border)); - for (int column = 0; column < width; column++) - { - var x = padEdge + (column * (colWidth + border)); - var pb = GetControl(sizeW, sizeH); - pb.SuspendLayout(); - Controls.Add(pb); - pb.Location = new Point(x, y); - Entries.Add(pb); - } - } - - Width = (2 * padEdge) + border + (width * (colWidth + border)) + 2; - Height = (2 * padEdge) + border + (height * (rowHeight + border)) + 2; - Debug.WriteLine($"{Name} -- Width: {Width}, Height: {Height}"); - ResumeLayout(); - } - - public static PictureBox GetControl(int width, int height) - { - return new InterpolatingPictureBox - { - AutoSize = false, - SizeMode = PictureBoxSizeMode.Zoom, - BackgroundImageLayout = ImageLayout.Zoom, - BackColor = Color.Transparent, - Width = width + (2 * 1), - Height = height + (2 * 1), - Padding = Padding.Empty, - Margin = Padding.Empty, - BorderStyle = BorderStyle.FixedSingle, - }; - } + InitializeComponent(); } -} + + public readonly List Entries = []; + public int Slots { get; private set; } + + private int sizeW = 32; + private int sizeH = 32; + + public void InitializeGrid(int width, int height, IGridItem info) + { + sizeW = info.Width; + sizeH = info.Height; + Generate(width, height); + Slots = width * height; + } + + private const int padEdge = 0; // edges + private const int border = 1; // between + + private void Generate(int width, int height) + { + SuspendLayout(); + Controls.Clear(); + Entries.Clear(); + + int colWidth = sizeW; + int rowHeight = sizeH; + + for (int row = 0; row < height; row++) + { + var y = padEdge + (row * (rowHeight + border)); + for (int column = 0; column < width; column++) + { + var x = padEdge + (column * (colWidth + border)); + var pb = GetControl(sizeW, sizeH); + pb.SuspendLayout(); + Controls.Add(pb); + pb.Location = new Point(x, y); + Entries.Add(pb); + } + } + + Width = (2 * padEdge) + border + (width * (colWidth + border)) + 2; + Height = (2 * padEdge) + border + (height * (rowHeight + border)) + 2; + Debug.WriteLine($"{Name} -- Width: {Width}, Height: {Height}"); + ResumeLayout(); + } + + public static PictureBox GetControl(int width, int height) + { + return new InterpolatingPictureBox + { + AutoSize = false, + SizeMode = PictureBoxSizeMode.Zoom, + BackgroundImageLayout = ImageLayout.Zoom, + BackColor = Color.Transparent, + Width = width + (2 * 1), + Height = height + (2 * 1), + Padding = Padding.Empty, + Margin = Padding.Empty, + BorderStyle = BorderStyle.FixedSingle, + }; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Controls/ItemGridEditor.cs b/NHSE.WinForms/Controls/ItemGridEditor.cs index 061ca54..7d16d20 100644 --- a/NHSE.WinForms/Controls/ItemGridEditor.cs +++ b/NHSE.WinForms/Controls/ItemGridEditor.cs @@ -1,313 +1,312 @@ -using System; +using NHSE.Core; +using NHSE.Sprites; +using System; using System.Collections.Generic; +using System.ComponentModel; using System.Drawing; using System.Linq; using System.Windows.Forms; -using NHSE.Core; -using NHSE.Sprites; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class ItemGridEditor : UserControl { - public partial class ItemGridEditor : UserControl + private static readonly GridSize Sprites = new(); + private readonly ItemEditor Editor; + private readonly IReadOnlyList Items; + + private List SlotPictureBoxes = []; + private int Count => Items.Count; + private int Page; + private int ItemsPerPage; + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Action? ItemChanged { private get; set; } + + private void ItemUpdated() => ItemChanged?.Invoke(); + + public ItemGridEditor(ItemEditor editor, IReadOnlyList items) { - private static readonly GridSize Sprites = new(); - private readonly ItemEditor Editor; - private readonly IReadOnlyList Items; + Editor = editor; + Items = items; + InitializeComponent(); - private IList SlotPictureBoxes = Array.Empty(); - private int Count => Items.Count; - private int Page; - private int ItemsPerPage; - public Action? ItemChanged { private get; set; } - private void ItemUpdated() => ItemChanged?.Invoke(); - - public ItemGridEditor(ItemEditor editor, IReadOnlyList items) - { - Editor = editor; - Items = items; - InitializeComponent(); - - L_ItemName.Text = string.Empty; - } - - public void InitializeGrid(int width, int height, int itemWidth, int itemHeight) - { - Sprites.Width = itemWidth; - Sprites.Height = itemHeight; - ItemsPerPage = width * height; - ItemGrid.InitializeGrid(width, height, Sprites); - InitializeSlots(); - } - - private void InitializeSlots() - { - SlotPictureBoxes = ItemGrid.Entries; - foreach (var pb in SlotPictureBoxes) - { - pb.MouseEnter += Slot_MouseEnter; - pb.MouseLeave += Slot_MouseLeave; - pb.MouseClick += Slot_MouseClick; - pb.MouseWheel += Slot_MouseWheel; - pb.ContextMenuStrip = CM_Hand; - } - ChangePage(); - } - - private void Slot_MouseWheel(object? sender, MouseEventArgs e) - { - var delta = e.Delta < 0 ? 1 : -1; // scrolling down increases page # - var newpage = Math.Min(PageCount - 1, Math.Max(0, Page + delta)); - if (newpage == Page) - return; - Page = newpage; - ChangePage(); - } - - public void Slot_MouseEnter(object? sender, EventArgs e) - { - if (sender is not PictureBox pb) - return; - var index = SlotPictureBoxes.IndexOf(pb); - var item = GetItem(index); - - var text = GetItemText(item); - HoverTip.SetToolTip(pb, text); - L_ItemName.Text = text; - } - - public void Slot_MouseLeave(object? sender, EventArgs e) - { - if (sender is not PictureBox) - return; - L_ItemName.Text = string.Empty; - HoverTip.RemoveAll(); - } - - public static string GetItemText(Item item) => GameInfo.Strings.GetItemName(item); - - public void Slot_MouseClick(object? sender, MouseEventArgs e) - { - if (sender == null) - return; - switch (ModifierKeys) - { - case Keys.Control | Keys.Alt: ClickClone(sender, e); break; - case Keys.Control: ClickView(sender, e); break; - case Keys.Shift: ClickSet(sender, e); break; - case Keys.Alt: ClickDelete(sender, e); break; - default: - return; - } - // restart hovering since the mouse event isn't fired - Slot_MouseEnter(sender, e); - } - - public Item LoadItem(int index) => Editor.LoadItem(GetItem(index)); - public Item SetItem(int index) => Editor.SetItem(GetItem(index)); - - private Item GetItem(int index) - { - index += Page * ItemsPerPage; - return Items[index]; - } - - private void ClickView(object sender, EventArgs e) - { - var pb = WinFormsUtil.GetUnderlyingControl(sender); - if (pb == null) - return; - var index = SlotPictureBoxes.IndexOf(pb); - LoadItem(index); - } - - private void ClickSet(object sender, EventArgs e) - { - var pb = WinFormsUtil.GetUnderlyingControl(sender); - if (pb == null) - return; - var index = SlotPictureBoxes.IndexOf(pb); - var item = SetItem(index); - SetItemSprite(item, pb); - ItemUpdated(); - } - - private void ClickDelete(object sender, EventArgs e) - { - var pb = WinFormsUtil.GetUnderlyingControl(sender); - if (pb == null) - return; - var index = SlotPictureBoxes.IndexOf(pb); - var item = GetItem(index); - item.Delete(); - SetItemSprite(item, pb); - ItemUpdated(); - } - - private void ClickClone(object sender, EventArgs e) - { - var pb = WinFormsUtil.GetUnderlyingControl(sender); - if (pb == null) - return; - var index = SlotPictureBoxes.IndexOf(pb); - var item = GetItem(index); - for (int i = 0; i < SlotPictureBoxes.Count; i++) - { - if (i == index) - continue; - var dest = GetItem(i); - dest.CopyFrom(item); - SetItemSprite(item, SlotPictureBoxes[i]); - ItemUpdated(); - } - System.Media.SystemSounds.Asterisk.Play(); - } - - private void SetItemSprite(Item item, PictureBox pb) - { - var dw = Sprites.Width; - var dh = Sprites.Height; - var font = L_ItemName.Font; - pb.BackColor = ItemColor.GetItemColor(item); - pb.BackgroundImage = ItemSprite.GetItemSprite(item); - var backing = new Bitmap(dw, dh); - pb.Image = ItemSprite.GetItemMarkup(item, font, dw, dh, backing); - } - - private static int GetPageJump() - { - return ModifierKeys switch - { - Keys.Control => 10, - Keys.Alt => 25, - Keys.Shift => 1000, - _ => 1 - }; - } - - private void B_Up_Click(object sender, EventArgs e) - { - if (Page == 0) - return; - Page = Math.Max(0, Page - GetPageJump()); - ChangePage(); - } - - private void B_Down_Click(object sender, EventArgs e) - { - if (ItemsPerPage * (Page + 1) == Count) - return; - Page = Math.Min(PageCount - 1, Page + GetPageJump()); - ChangePage(); - } - - private int PageCount => Count / ItemsPerPage; - - private void ChangePage() - { - bool hasPages = Count > ItemsPerPage; - B_Up.Visible = hasPages && Page > 0; - B_Down.Visible = hasPages && Page < PageCount; - L_Page.Visible = hasPages; - - L_Page.Text = $"{Page + 1}/{Count / ItemsPerPage}"; - LoadItems(); - } - - public void LoadItems() - { - for (int i = 0; i < SlotPictureBoxes.Count; i++) - { - var item = GetItem(i); - SetItemSprite(item, SlotPictureBoxes[i]); - } - ItemUpdated(); - } - - private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); - private void B_Clear_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Remove, B_Clear); - - private void ClearItemIf(Func criteria) - { - bool all = ModifierKeys == Keys.Shift; - int start = 0, end = Items.Count - 1; - if (!all) - { - start = ItemsPerPage * Page; - end = start + ItemsPerPage; - } - for (int i = start; i < end; i++) - { - var item = Items[i]; - if (criteria(item)) - item.Delete(); - } - LoadItems(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Sort_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Sort, B_Sort); - private void B_SortAlpha_Click(object sender, EventArgs e) - { - var sortedItems = Items.Where(item => item.ItemId != Item.NONE) - .OrderBy(item => GetItemText(item).ToLower()); - var sortedItemsCopy = new List(); // to prevent object reference issues - - foreach(var item in sortedItems) - { - var itemCopy = new Item(); - itemCopy.CopyFrom(item); - sortedItemsCopy.Add(itemCopy); - } - - SetEditorItems(sortedItemsCopy); - } - - private void B_SortType_Click(object sender, EventArgs e) - { - var sortedItems = Items.Where(item => item.ItemId != Item.NONE) - .OrderBy(ItemInfo.GetItemKind) - .ThenBy(item => GetItemText(item).ToLower()); - var sortedItemsCopy = new List(); // to prevent object reference issues - - foreach (var item in sortedItems) - { - var itemCopy = new Item(); - itemCopy.CopyFrom(item); - sortedItemsCopy.Add(itemCopy); - } - - SetEditorItems(sortedItemsCopy); - } - - private void SetEditorItems(IReadOnlyList items) - { - if (items.Count > Items.Count) - return; - - for (int i = 0; i < Items.Count; i++) - { - var src = i < items.Count ? items[i] : Item.NO_ITEM; - GetItem(i).CopyFrom(src); - ItemUpdated(); - } - - LoadItems(); - Editor.LoadItem(Item.NO_ITEM); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ClearAll_Click(object sender, EventArgs e) => ClearItemIf(_ => true); - private void B_ClearClothing_Click(object sender, EventArgs e) => ClearItemIf(z => ItemInfo.GetItemKind(z).IsClothing()); - private void B_ClearCrafting_Click(object sender, EventArgs e) => ClearItemIf(z => ItemInfo.GetItemKind(z).IsCrafting()); - private void B_ClearFurniture_Click(object sender, EventArgs e) => ClearItemIf(z => ItemInfo.GetItemKind(z).IsFurniture()); - private void B_ClearBugs_Click(object sender, EventArgs e) => ClearItemIf(z => GameLists.Bugs.Contains(z.ItemId)); - private void B_ClearFish_Click(object sender, EventArgs e) => ClearItemIf(z => GameLists.Fish.Contains(z.ItemId)); - private void B_ClearDive_Click(object sender, EventArgs e) => ClearItemIf(z => GameLists.Dive.Contains(z.ItemId)); - - private class GridSize : IGridItem - { - public int Width { get; set; } = 64; - public int Height { get; set; } = 64; - } + L_ItemName.Text = string.Empty; } -} + + public void InitializeGrid(int width, int height, int itemWidth, int itemHeight) + { + Sprites.Width = itemWidth; + Sprites.Height = itemHeight; + ItemsPerPage = width * height; + ItemGrid.InitializeGrid(width, height, Sprites); + InitializeSlots(); + } + + private void InitializeSlots() + { + SlotPictureBoxes = ItemGrid.Entries; + foreach (var pb in SlotPictureBoxes) + { + pb.MouseEnter += Slot_MouseEnter; + pb.MouseLeave += Slot_MouseLeave; + pb.MouseClick += Slot_MouseClick; + pb.MouseWheel += Slot_MouseWheel; + pb.ContextMenuStrip = CM_Hand; + } + ChangePage(); + } + + private void Slot_MouseWheel(object? sender, MouseEventArgs e) + { + var delta = e.Delta < 0 ? 1 : -1; // scrolling down increases page # + var newpage = Math.Min(PageCount - 1, Math.Max(0, Page + delta)); + if (newpage == Page) + return; + Page = newpage; + ChangePage(); + } + + public void Slot_MouseEnter(object? sender, EventArgs e) + { + if (sender is not PictureBox pb) + return; + var index = SlotPictureBoxes.IndexOf(pb); + var item = GetItem(index); + + var text = GetItemText(item); + HoverTip.SetToolTip(pb, text); + L_ItemName.Text = text; + } + + public void Slot_MouseLeave(object? sender, EventArgs e) + { + if (sender is not PictureBox) + return; + L_ItemName.Text = string.Empty; + HoverTip.RemoveAll(); + } + + public static string GetItemText(Item item) => GameInfo.Strings.GetItemName(item); + + public void Slot_MouseClick(object? sender, MouseEventArgs e) + { + if (sender == null) + return; + switch (ModifierKeys) + { + case Keys.Control | Keys.Alt: ClickClone(sender, e); break; + case Keys.Control: ClickView(sender, e); break; + case Keys.Shift: ClickSet(sender, e); break; + case Keys.Alt: ClickDelete(sender, e); break; + default: + return; + } + // restart hovering since the mouse event isn't fired + Slot_MouseEnter(sender, e); + } + + public Item LoadItem(int index) => Editor.LoadItem(GetItem(index)); + public Item SetItem(int index) => Editor.SetItem(GetItem(index)); + + private Item GetItem(int index) + { + index += Page * ItemsPerPage; + return Items[index]; + } + + private void ClickView(object sender, EventArgs e) + { + if (!WinFormsUtil.TryGetUnderlying(sender, out var pb)) + return; + var index = SlotPictureBoxes.IndexOf(pb); + LoadItem(index); + } + + private void ClickSet(object sender, EventArgs e) + { + if (!WinFormsUtil.TryGetUnderlying(sender, out var pb)) + return; + var index = SlotPictureBoxes.IndexOf(pb); + var item = SetItem(index); + SetItemSprite(item, pb); + ItemUpdated(); + } + + private void ClickDelete(object sender, EventArgs e) + { + if (!WinFormsUtil.TryGetUnderlying(sender, out var pb)) + return; + var index = SlotPictureBoxes.IndexOf(pb); + var item = GetItem(index); + item.Delete(); + SetItemSprite(item, pb); + ItemUpdated(); + } + + private void ClickClone(object sender, EventArgs e) + { + if (!WinFormsUtil.TryGetUnderlying(sender, out var pb)) + return; + var index = SlotPictureBoxes.IndexOf(pb); + var item = GetItem(index); + for (int i = 0; i < SlotPictureBoxes.Count; i++) + { + if (i == index) + continue; + var dest = GetItem(i); + dest.CopyFrom(item); + SetItemSprite(item, SlotPictureBoxes[i]); + ItemUpdated(); + } + System.Media.SystemSounds.Asterisk.Play(); + } + + private void SetItemSprite(Item item, PictureBox pb) + { + var dw = Sprites.Width; + var dh = Sprites.Height; + var font = L_ItemName.Font; + pb.BackColor = ItemColor.GetItemColor(item); + pb.BackgroundImage = ItemSprite.GetItemSprite(item); + var backing = new Bitmap(dw, dh); + pb.Image = ItemSprite.GetItemMarkup(item, font, dw, dh, backing); + } + + private static int GetPageJump() + { + return ModifierKeys switch + { + Keys.Control => 10, + Keys.Alt => 25, + Keys.Shift => 1000, + _ => 1 + }; + } + + private void B_Up_Click(object sender, EventArgs e) + { + if (Page == 0) + return; + Page = Math.Max(0, Page - GetPageJump()); + ChangePage(); + } + + private void B_Down_Click(object sender, EventArgs e) + { + if (ItemsPerPage * (Page + 1) == Count) + return; + Page = Math.Min(PageCount - 1, Page + GetPageJump()); + ChangePage(); + } + + private int PageCount => Count / ItemsPerPage; + + private void ChangePage() + { + bool hasPages = Count > ItemsPerPage; + B_Up.Visible = hasPages && Page > 0; + B_Down.Visible = hasPages && Page < PageCount; + L_Page.Visible = hasPages; + + L_Page.Text = $"{Page + 1}/{Count / ItemsPerPage}"; + LoadItems(); + } + + public void LoadItems() + { + for (int i = 0; i < SlotPictureBoxes.Count; i++) + { + var item = GetItem(i); + SetItemSprite(item, SlotPictureBoxes[i]); + } + ItemUpdated(); + } + + private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); + private void B_Clear_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Remove, B_Clear); + + private void ClearItemIf(Func criteria) + { + bool all = ModifierKeys == Keys.Shift; + int start = 0, end = Items.Count - 1; + if (!all) + { + start = ItemsPerPage * Page; + end = start + ItemsPerPage; + } + for (int i = start; i < end; i++) + { + var item = Items[i]; + if (criteria(item)) + item.Delete(); + } + LoadItems(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Sort_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Sort, B_Sort); + private void B_SortAlpha_Click(object sender, EventArgs e) + { + var sortedItems = Items.Where(item => item.ItemId != Item.NONE) + .OrderBy(item => GetItemText(item).ToLower()); + var sortedItemsCopy = new List(); // to prevent object reference issues + + foreach(var item in sortedItems) + { + var itemCopy = new Item(); + itemCopy.CopyFrom(item); + sortedItemsCopy.Add(itemCopy); + } + + SetEditorItems(sortedItemsCopy); + } + + private void B_SortType_Click(object sender, EventArgs e) + { + var sortedItems = Items.Where(item => item.ItemId != Item.NONE) + .OrderBy(ItemInfo.GetItemKind) + .ThenBy(item => GetItemText(item).ToLower()); + var sortedItemsCopy = new List(); // to prevent object reference issues + + foreach (var item in sortedItems) + { + var itemCopy = new Item(); + itemCopy.CopyFrom(item); + sortedItemsCopy.Add(itemCopy); + } + + SetEditorItems(sortedItemsCopy); + } + + private void SetEditorItems(List items) + { + if (items.Count > Items.Count) + return; + + for (int i = 0; i < Items.Count; i++) + { + var src = i < items.Count ? items[i] : Item.NO_ITEM; + GetItem(i).CopyFrom(src); + ItemUpdated(); + } + + LoadItems(); + Editor.LoadItem(Item.NO_ITEM); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ClearAll_Click(object sender, EventArgs e) => ClearItemIf(_ => true); + private void B_ClearClothing_Click(object sender, EventArgs e) => ClearItemIf(z => ItemInfo.GetItemKind(z).IsClothing); + private void B_ClearCrafting_Click(object sender, EventArgs e) => ClearItemIf(z => ItemInfo.GetItemKind(z).IsCrafting); + private void B_ClearFurniture_Click(object sender, EventArgs e) => ClearItemIf(z => ItemInfo.GetItemKind(z).IsFurniture); + private void B_ClearBugs_Click(object sender, EventArgs e) => ClearItemIf(z => GameLists.Bugs.Contains(z.ItemId)); + private void B_ClearFish_Click(object sender, EventArgs e) => ClearItemIf(z => GameLists.Fish.Contains(z.ItemId)); + private void B_ClearDive_Click(object sender, EventArgs e) => ClearItemIf(z => GameLists.Dive.Contains(z.ItemId)); + + private class GridSize : IGridItem + { + public int Width { get; set; } = 64; + public int Height { get; set; } = 64; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Controls/RestrictedItemSelect.cs b/NHSE.WinForms/Controls/RestrictedItemSelect.cs index cb0d8f7..dfa6edc 100644 --- a/NHSE.WinForms/Controls/RestrictedItemSelect.cs +++ b/NHSE.WinForms/Controls/RestrictedItemSelect.cs @@ -1,54 +1,55 @@ -using System; +using NHSE.Core; +using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Windows.Forms; -using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class RestrictedItemSelect : UserControl { - public partial class RestrictedItemSelect : UserControl + private IList DataSource = []; + + public RestrictedItemSelect() => InitializeComponent(); + + public void Initialize(IList items, bool canType = false) { - private IList DataSource = Array.Empty(); + CB_ItemID.DisplayMember = nameof(ComboItem.Text); + CB_ItemID.ValueMember = nameof(ComboItem.Value); + CB_ItemID.DataSource = DataSource = items; - public RestrictedItemSelect() => InitializeComponent(); + if (!canType) + CB_ItemID.DropDownStyle = ComboBoxStyle.DropDownList; + } - public void Initialize(IList items, bool canType = false) + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public ushort Value + { + get => CHK_CustomItem.Checked ? (ushort) NUD_CustomItem.Value : (ushort) WinFormsUtil.GetIndex(CB_ItemID); + set { - CB_ItemID.DisplayMember = nameof(ComboItem.Text); - CB_ItemID.ValueMember = nameof(ComboItem.Value); - CB_ItemID.DataSource = DataSource = items; - - if (!canType) - CB_ItemID.DropDownStyle = ComboBoxStyle.DropDownList; - } - - public ushort Value - { - get => CHK_CustomItem.Checked ? (ushort) NUD_CustomItem.Value : (ushort) WinFormsUtil.GetIndex(CB_ItemID); - set + if (DataSource.Any(z => z.Value == value)) { - if (DataSource.Any(z => z.Value == value)) - { - CHK_CustomItem.Checked = false; - CB_ItemID.SelectedValue = (int)value; - } - else - { - CHK_CustomItem.Checked = true; - NUD_CustomItem.Value = value; - } + CHK_CustomItem.Checked = false; + CB_ItemID.SelectedValue = (int)value; + } + else + { + CHK_CustomItem.Checked = true; + NUD_CustomItem.Value = value; } } - - private void CHK_Custom_CheckedChanged(object sender, EventArgs e) - { - CB_ItemID.Enabled = !CHK_CustomItem.Checked; - NUD_CustomItem.Enabled = CHK_CustomItem.Checked; - } - - private void CB_ItemID_SelectedValueChanged(object sender, EventArgs e) - { - NUD_CustomItem.Value = WinFormsUtil.GetIndex(CB_ItemID); - } } -} + + private void CHK_Custom_CheckedChanged(object sender, EventArgs e) + { + CB_ItemID.Enabled = !CHK_CustomItem.Checked; + NUD_CustomItem.Enabled = CHK_CustomItem.Checked; + } + + private void CB_ItemID_SelectedValueChanged(object sender, EventArgs e) + { + NUD_CustomItem.Value = WinFormsUtil.GetIndex(CB_ItemID); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Controls/VillagerEditor.cs b/NHSE.WinForms/Controls/VillagerEditor.cs index d348946..b3586c7 100644 --- a/NHSE.WinForms/Controls/VillagerEditor.cs +++ b/NHSE.WinForms/Controls/VillagerEditor.cs @@ -6,320 +6,314 @@ using NHSE.Sprites; using NHSE.Villagers; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class VillagerEditor : UserControl { - public partial class VillagerEditor : UserControl + public IVillager[] Villagers; + public IVillagerOrigin Origin; + private readonly HorizonSave SAV; + private int VillagerIndex = -1; + private bool Loading; + + public VillagerEditor(IVillager[] villagers, IVillagerOrigin origin, HorizonSave sav, bool hasHouses) { - public IVillager[] Villagers; - public IVillagerOrigin Origin; - private readonly HorizonSave SAV; - private int VillagerIndex = -1; - private bool Loading; + InitializeComponent(); + Villagers = villagers; + Origin = origin; + SAV = sav; + LoadVillagers(); - public VillagerEditor(IVillager[] villagers, IVillagerOrigin origin, HorizonSave sav, bool hasHouses) - { - InitializeComponent(); - Villagers = villagers; - Origin = origin; - SAV = sav; - LoadVillagers(); - - B_EditHouses.Visible = hasHouses; - } - - public void Save() => SaveVillager(VillagerIndex); - - private void LoadVillagers() - { - CB_Personality.Items.Clear(); - var personalities = Enum.GetNames(typeof(VillagerPersonality)); - foreach (var p in personalities) - CB_Personality.Items.Add(p); - - VillagerIndex = -1; - LoadVillager(0); - } - - private void LoadVillager(object sender, EventArgs e) => LoadVillager((int)NUD_Villager.Value); - - private void LoadVillager(int index) - { - if (VillagerIndex >= 0) - SaveVillager(VillagerIndex); - - if (index < 0) - return; - - LoadVillager(Villagers[index]); - VillagerIndex = index; - } - - private void LoadVillager(IVillager v) - { - Loading = true; - NUD_Species.Value = v.Species; - NUD_Variant.Value = v.Variant; - CB_Personality.SelectedIndex = (int)v.Personality; - TB_Catchphrase.Text = v.CatchPhrase; - CHK_VillagerMovingOut.Checked = v.MovingOut; - Loading = false; - } - - private void SaveVillager(int index) - { - var v = Villagers[index]; - - v.Species = (byte)NUD_Species.Value; - v.Variant = (byte)NUD_Variant.Value; - v.Personality = (VillagerPersonality)CB_Personality.SelectedIndex; - v.CatchPhrase = TB_Catchphrase.Text; - v.MovingOut = CHK_VillagerMovingOut.Checked; - } - - private void CHK_VillagerMovingOut_CheckedChanged(object sender, EventArgs e) - { - if (Loading) - return; - - if (!CHK_VillagerMovingOut.Checked) - return; - - WinFormsUtil.Alert(MessageStrings.MsgMoveOut, MessageStrings.MsgMoveOutSuggest); - } - - private void B_DumpVillager_Click(object sender, EventArgs e) - { - if (ModifierKeys == Keys.Shift) - { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() != DialogResult.OK) - return; - - var dir = Path.GetDirectoryName(fbd.SelectedPath); - if (dir == null || !Directory.Exists(dir)) - return; - Villagers.Dump(fbd.SelectedPath); - return; - } - - var name = L_ExternalName.Text; - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Villager (*.nhv)|*.nhv|" + - "New Horizons Villager (*.nhv2)|*.nhv2|" + - "All files (*.*)|*.*", - FileName = $"{name}.{Villagers[VillagerIndex].Extension}", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - SaveVillager(VillagerIndex); - var v = Villagers[VillagerIndex]; - File.WriteAllBytes(sfd.FileName, v.Write()); - } - - private void B_LoadVillager_Click(object sender, EventArgs e) - { - var name = L_ExternalName.Text; - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Villager (*.nhv)|*.nhv|" + - "New Horizons Villager (*.nhv2)|*.nhv2|" + - "All files (*.*)|*.*", - FileName = $"{name}.{Villagers[VillagerIndex].Extension}", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return; - - var path = ofd.FileName; - var expectLength = SAV.Main.Offsets.VillagerSize; - var fi = new FileInfo(path); - if (!VillagerConverter.IsCompatible((int)fi.Length, expectLength)) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); - return; - } - - var data = File.ReadAllBytes(ofd.FileName); - data = VillagerConverter.GetCompatible(data, expectLength); - if (data.Length != expectLength) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); - return; - } - - var v = SAV.Main.Offsets.ReadVillager(data); - var player0 = Origin; - if (!v.IsOriginatedFrom(player0)) - { - string msg = string.Format(MessageStrings.MsgDataDidNotOriginateFromHost_0, player0.PlayerName); - var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, msg, MessageStrings.MsgAskUpdateValues); - if (result == DialogResult.Cancel) - return; - if (result == DialogResult.Yes) - v.ChangeOrigins(player0, v.Write()); - } - - LoadVillager(Villagers[VillagerIndex] = v); - } - - private void B_EditWear_Click(object sender, EventArgs e) - { - var v = Villagers[VillagerIndex]; - var items = v.WearStockList; - using var editor = new PlayerItemEditor(items, 8, 3); - if (editor.ShowDialog() == DialogResult.OK) - v.WearStockList = items; - } - - private void B_EditFurniture_Click(object sender, EventArgs e) - { - var v = Villagers[VillagerIndex]; - var items = v.FtrStockList; - using var editor = new PlayerItemEditor(items, 8, 4); - if (editor.ShowDialog() == DialogResult.OK) - v.FtrStockList = items; - } - - private void B_EditVillagerFlags_Click(object sender, EventArgs e) - { - var v = Villagers[VillagerIndex]; - var flags = v.GetEventFlagsSave(); - using var editor = new VillagerFlagEditor(flags); - if (editor.ShowDialog() == DialogResult.OK) - v.SetEventFlagsSave(flags); - } - - private string GetCurrentVillagerInternalName() => VillagerUtil.GetInternalVillagerName((VillagerSpecies)NUD_Species.Value, (int)NUD_Variant.Value); - private void ChangeVillager(object sender, EventArgs e) => ChangeVillager(); - private void ChangeVillager() - { - var name = GetCurrentVillagerInternalName(); - L_InternalName.Text = name; - L_ExternalName.Text = GameInfo.Strings.GetVillager(name); - PB_Villager.Image = VillagerSprite.GetVillagerSprite(name); - } - - private void B_EditHouse_Click(object sender, EventArgs e) - { - SaveVillager(VillagerIndex); - var villagers = SAV.Main.GetVillagers(); - var houses = SAV.Main.GetVillagerHouses(); - using var editor = new VillagerHouseEditor(houses, villagers, SAV.Main, VillagerIndex); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.SetVillagerHouses(houses); - } - - private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new System.Drawing.Point(0, n.Height))); - private void B_EditVillager_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_EditVillager, B_EditVillager); - - private void B_EditVillagerRoom_Click(object sender, EventArgs e) - { - var v = Villagers[VillagerIndex]; - using var editor = new SaveRoomFloorWallEditor(v.Room); - if (editor.ShowDialog() == DialogResult.OK) - v.Room = editor.Entity; - } - - private void B_EditVillagerDesign_Click(object sender, EventArgs e) - { - var playerID = SAV.Players[0].Personal.GetPlayerIdentity(); // fetch ID for overwrite ownership - var townID = SAV.Players[0].Personal.GetTownIdentity(); // fetch ID for overwrite ownership - var v = Villagers[VillagerIndex]; - var tmp = new[] {v.Design}; - using var editor = new PatternEditorPRO(tmp); - playerID.CopyTo(tmp[0].Data, 0x54); // overwrite playerID bytes - townID.CopyTo(tmp[0].Data, 0x38); // overwrite townID bytes - if (editor.ShowDialog() == DialogResult.OK) - v.Design = tmp[0]; - } - - private void B_EditVillagerPlayerMemories_Click(object sender, EventArgs e) - { - if (ModifierKeys == Keys.Shift) - { - var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgVillagerFriendshipMax); - if (prompt != DialogResult.Yes) - return; - foreach (var villager in Villagers) - villager.SetFriendshipAll(); - System.Media.SystemSounds.Asterisk.Play(); - return; - } - - var v = Villagers[VillagerIndex]; - using var editor = new VillagerMemoryEditor(v); - if (editor.ShowDialog() == DialogResult.OK) - { } // editor saves our changes - } - - private void B_EditDIYTimer_Click(object sender, EventArgs e) - { - var v = Villagers[VillagerIndex]; - using var editor = new VillagerDIYTimerEditor(v); - if (editor.ShowDialog() == DialogResult.OK) - { } // editor saves our changes - } - - private void B_MoveOutAllVillagers_Click(object sender, EventArgs e) - { - if (Loading) - return; - - var prompt = WinFormsUtil.Prompt(MessageBoxButtons.OKCancel, MessageStrings.MsgMoveOutAll); - if (prompt != DialogResult.OK) - return; - - foreach (var villager in Villagers) - villager.MovingOut = true; - CHK_VillagerMovingOut.Checked = true; - - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_SetPhraseOriginal_Click(object sender, EventArgs e) - { - var internalName = GetCurrentVillagerInternalName(); - TB_Catchphrase.Text = GameInfo.Strings.GetVillagerDefaultPhrase(internalName); - } - - private void B_ReplaceVillager_Click(object sender, EventArgs e) - { - if (!Clipboard.ContainsText()) - { - WinFormsUtil.Error(MessageStrings.MsgVillagerReplaceNoText); - return; - } - - var internalName = Clipboard.GetText(); - if (!VillagerResources.IsVillagerDataKnown(internalName)) - { - internalName = GameInfo.Strings.VillagerMap.FirstOrDefault(z => string.Equals(z.Value, internalName, StringComparison.InvariantCultureIgnoreCase)).Key; - if (internalName == default) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgVillagerReplaceUnknownName, internalName)); - return; - } - } - - var index = VillagerIndex; - var villager = Villagers[index]; - if (villager is not Villager2 v2) - { - WinFormsUtil.Error(MessageStrings.MsgVillagerReplaceOutdatedSaveFormat); - return; - } - - var houses = SAV.Main.GetVillagerHouses(); - var houseIndex = Array.FindIndex(houses, z => z.NPC1 == index); - var exist = new VillagerInfo(v2, houses[houseIndex]); - var replace = VillagerSwap.GetReplacementVillager(exist, internalName); - - var nh = new VillagerHouse1(replace.House); - SAV.Main.SetVillagerHouse(nh, houseIndex); - var nv = new Villager2(replace.Villager); - LoadVillager(Villagers[index] = nv); - System.Media.SystemSounds.Asterisk.Play(); - } + B_EditHouses.Visible = hasHouses; } -} + + public void Save() => SaveVillager(VillagerIndex); + + private void LoadVillagers() + { + CB_Personality.Items.Clear(); + var personalities = Enum.GetNames(); + CB_Personality.Items.AddRange(personalities); + + VillagerIndex = -1; + LoadVillager(0); + } + + private void LoadVillager(object sender, EventArgs e) => LoadVillager((int)NUD_Villager.Value); + + private void LoadVillager(int index) + { + if (VillagerIndex >= 0) + SaveVillager(VillagerIndex); + + if (index < 0) + return; + + LoadVillager(Villagers[index]); + VillagerIndex = index; + } + + private void LoadVillager(IVillager v) + { + Loading = true; + NUD_Species.Value = v.Species; + NUD_Variant.Value = v.Variant; + CB_Personality.SelectedIndex = (int)v.Personality; + TB_Catchphrase.Text = v.CatchPhrase; + CHK_VillagerMovingOut.Checked = v.MovingOut; + Loading = false; + } + + private void SaveVillager(int index) + { + var v = Villagers[index]; + + v.Species = (byte)NUD_Species.Value; + v.Variant = (byte)NUD_Variant.Value; + v.Personality = (VillagerPersonality)CB_Personality.SelectedIndex; + v.CatchPhrase = TB_Catchphrase.Text; + v.MovingOut = CHK_VillagerMovingOut.Checked; + } + + private void CHK_VillagerMovingOut_CheckedChanged(object sender, EventArgs e) + { + if (Loading) + return; + + if (!CHK_VillagerMovingOut.Checked) + return; + + WinFormsUtil.Alert(MessageStrings.MsgMoveOut, MessageStrings.MsgMoveOutSuggest); + } + + private void B_DumpVillager_Click(object sender, EventArgs e) + { + if (ModifierKeys == Keys.Shift) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() != DialogResult.OK) + return; + + var dir = Path.GetDirectoryName(fbd.SelectedPath); + if (dir == null || !Directory.Exists(dir)) + return; + Villagers.Dump(fbd.SelectedPath); + return; + } + + var name = L_ExternalName.Text; + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Villager (*.nhv)|*.nhv|" + + "New Horizons Villager (*.nhv2)|*.nhv2|" + + "All files (*.*)|*.*"; + sfd.FileName = $"{name}.{Villagers[VillagerIndex].Extension}"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + SaveVillager(VillagerIndex); + var v = Villagers[VillagerIndex]; + File.WriteAllBytes(sfd.FileName, v.Write()); + } + + private void B_LoadVillager_Click(object sender, EventArgs e) + { + var name = L_ExternalName.Text; + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Villager (*.nhv)|*.nhv|" + + "New Horizons Villager (*.nhv2)|*.nhv2|" + + "All files (*.*)|*.*"; + ofd.FileName = $"{name}.{Villagers[VillagerIndex].Extension}"; + if (ofd.ShowDialog() != DialogResult.OK) + return; + + var path = ofd.FileName; + var expectLength = SAV.Main.Offsets.VillagerSize; + var fi = new FileInfo(path); + if (!VillagerConverter.IsCompatible((int)fi.Length, expectLength)) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); + return; + } + + var data = File.ReadAllBytes(ofd.FileName); + data = VillagerConverter.GetCompatible(data, expectLength); + if (data.Length != expectLength) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); + return; + } + + var v = SAV.Main.Offsets.ReadVillager(data); + var player0 = Origin; + if (!v.IsOriginatedFrom(player0)) + { + string msg = string.Format(MessageStrings.MsgDataDidNotOriginateFromHost_0, player0.PlayerName); + var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, msg, MessageStrings.MsgAskUpdateValues); + if (result == DialogResult.Cancel) + return; + if (result == DialogResult.Yes) + v.ChangeOrigins(player0, v.Write()); + } + + LoadVillager(Villagers[VillagerIndex] = v); + } + + private void B_EditWear_Click(object sender, EventArgs e) + { + var v = Villagers[VillagerIndex]; + var items = v.WearStockList; + using var editor = new PlayerItemEditor(items, 8, 3); + if (editor.ShowDialog() == DialogResult.OK) + v.WearStockList = items; + } + + private void B_EditFurniture_Click(object sender, EventArgs e) + { + var v = Villagers[VillagerIndex]; + var items = v.FtrStockList; + using var editor = new PlayerItemEditor(items, 8, 4); + if (editor.ShowDialog() == DialogResult.OK) + v.FtrStockList = items; + } + + private void B_EditVillagerFlags_Click(object sender, EventArgs e) + { + var v = Villagers[VillagerIndex]; + var flags = v.GetEventFlagsSave(); + using var editor = new VillagerFlagEditor(flags); + if (editor.ShowDialog() == DialogResult.OK) + v.SetEventFlagsSave(flags); + } + + private string GetCurrentVillagerInternalName() => VillagerUtil.GetInternalVillagerName((VillagerSpecies)NUD_Species.Value, (int)NUD_Variant.Value); + private void ChangeVillager(object sender, EventArgs e) => ChangeVillager(); + private void ChangeVillager() + { + var name = GetCurrentVillagerInternalName(); + L_InternalName.Text = name; + L_ExternalName.Text = GameInfo.Strings.GetVillager(name); + PB_Villager.Image = VillagerSprite.GetVillagerSprite(name); + } + + private void B_EditHouse_Click(object sender, EventArgs e) + { + SaveVillager(VillagerIndex); + var villagers = SAV.Main.GetVillagers(); + var houses = SAV.Main.GetVillagerHouses(); + using var editor = new VillagerHouseEditor(houses, villagers, SAV.Main, VillagerIndex); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.SetVillagerHouses(houses); + } + + private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new System.Drawing.Point(0, n.Height))); + private void B_EditVillager_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_EditVillager, B_EditVillager); + + private void B_EditVillagerRoom_Click(object sender, EventArgs e) + { + var v = Villagers[VillagerIndex]; + using var editor = new SaveRoomFloorWallEditor(v.Room); + if (editor.ShowDialog() == DialogResult.OK) + v.Room = editor.Entity; + } + + private void B_EditVillagerDesign_Click(object sender, EventArgs e) + { + var playerID = SAV.Players[0].Personal.GetPlayerIdentity(); // fetch ID for overwrite ownership + var townID = SAV.Players[0].Personal.GetTownIdentity(); // fetch ID for overwrite ownership + var v = Villagers[VillagerIndex]; + DesignPatternPRO[] tmp = [v.Design]; + using var editor = new PatternEditorPRO(tmp); + playerID.CopyTo(tmp[0].Data[0x54..]); // overwrite playerID bytes + townID.CopyTo(tmp[0].Data[0x38..]); // overwrite townID bytes + if (editor.ShowDialog() == DialogResult.OK) + v.Design = tmp[0]; + } + + private void B_EditVillagerPlayerMemories_Click(object sender, EventArgs e) + { + if (ModifierKeys == Keys.Shift) + { + var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgVillagerFriendshipMax); + if (prompt != DialogResult.Yes) + return; + foreach (var villager in Villagers) + villager.SetFriendshipAll(); + System.Media.SystemSounds.Asterisk.Play(); + return; + } + + var v = Villagers[VillagerIndex]; + using var editor = new VillagerMemoryEditor(v); + if (editor.ShowDialog() == DialogResult.OK) + { } // editor saves our changes + } + + private void B_EditDIYTimer_Click(object sender, EventArgs e) + { + var v = Villagers[VillagerIndex]; + using var editor = new VillagerDIYTimerEditor(v); + if (editor.ShowDialog() == DialogResult.OK) + { } // editor saves our changes + } + + private void B_MoveOutAllVillagers_Click(object sender, EventArgs e) + { + if (Loading) + return; + + var prompt = WinFormsUtil.Prompt(MessageBoxButtons.OKCancel, MessageStrings.MsgMoveOutAll); + if (prompt != DialogResult.OK) + return; + + foreach (var villager in Villagers) + villager.MovingOut = true; + CHK_VillagerMovingOut.Checked = true; + + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_SetPhraseOriginal_Click(object sender, EventArgs e) + { + var internalName = GetCurrentVillagerInternalName(); + TB_Catchphrase.Text = GameInfo.Strings.GetVillagerDefaultPhrase(internalName); + } + + private void B_ReplaceVillager_Click(object sender, EventArgs e) + { + if (!Clipboard.ContainsText()) + { + WinFormsUtil.Error(MessageStrings.MsgVillagerReplaceNoText); + return; + } + + var internalName = Clipboard.GetText(); + if (!VillagerResources.IsVillagerDataKnown(internalName)) + { + internalName = GameInfo.Strings.VillagerMap.FirstOrDefault(z => string.Equals(z.Value, internalName, StringComparison.InvariantCultureIgnoreCase)).Key; + if (internalName is null) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgVillagerReplaceUnknownName, internalName)); + return; + } + } + + var index = VillagerIndex; + var villager = Villagers[index]; + if (villager is not Villager2 v2) + { + WinFormsUtil.Error(MessageStrings.MsgVillagerReplaceOutdatedSaveFormat); + return; + } + + var houses = SAV.Main.GetVillagerHouses(); + var houseIndex = Array.FindIndex(houses, z => z.NPC1 == index); + var exist = new VillagerInfo(v2, houses[houseIndex]); + var replace = VillagerSwap.GetReplacementVillager(exist, internalName); + + var nh = new VillagerHouse1(replace.House); + SAV.Main.SetVillagerHouse(nh, houseIndex); + var nv = new Villager2(replace.Villager); + LoadVillager(Villagers[index] = nv); + System.Media.SystemSounds.Asterisk.Play(); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Editor.cs b/NHSE.WinForms/Editor.cs index ebaa707..716a53e 100644 --- a/NHSE.WinForms/Editor.cs +++ b/NHSE.WinForms/Editor.cs @@ -10,520 +10,513 @@ using NHSE.Sprites; using NHSE.WinForms.Properties; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public sealed partial class Editor : Form { - public sealed partial class Editor : Form + private readonly HorizonSave SAV; + private readonly VillagerEditor Villagers; + + public Editor(HorizonSave file) { - private readonly HorizonSave SAV; - private readonly VillagerEditor Villagers; + InitializeComponent(); - public Editor(HorizonSave file) - { - InitializeComponent(); + SAV = file; - SAV = file; + LoadPlayers(); + Villagers = LoadVillagers(); - LoadPlayers(); - Villagers = LoadVillagers(); + LoadMain(); - LoadMain(); + var lang = Settings.Default.Language; + var index = GameLanguage.GetLanguageIndex(lang); + Menu_Language.SelectedIndex = index; // triggers translation + // this.TranslateInterface(GameInfo.CurrentLanguage); - var lang = Settings.Default.Language; - var index = GameLanguage.GetLanguageIndex(lang); - Menu_Language.SelectedIndex = index; // triggers translation - // this.TranslateInterface(GameInfo.CurrentLanguage); - - Text = SAV.GetSaveTitle("NHSE"); - } - - private void Menu_Settings_Click(object sender, EventArgs e) - { - using var editor = new SettingsEditor(); - editor.ShowDialog(); - } - - private void Menu_Language_SelectedIndexChanged(object sender, EventArgs e) - { - Menu_Options.DropDown.Close(); - if ((uint)Menu_Language.SelectedIndex >= GameLanguage.LanguageCount) - return; - var lang = GameInfo.SetLanguage2Char(Menu_Language.SelectedIndex); - - this.TranslateInterface(lang); - var settings = Settings.Default; - settings.Language = lang; - settings.Save(); - - Task.Run(() => - { - ItemSprite.Initialize(GameInfo.GetStrings("en").itemlist); - TranslationUtil.SetLocalization(typeof(MessageStrings), lang); - TranslationUtil.SetLocalization(GameInfo.Strings.InternalNameTranslation, lang); - }); - } - - private void Menu_Save_Click(object sender, EventArgs e) - { - SaveAll(); - try - { - SAV.Save((uint) DateTime.Now.Ticks); - } - catch (Exception ex) - { - WinFormsUtil.Error(MessageStrings.MsgSaveDataExportFail, ex.Message); - return; - } - WinFormsUtil.Alert(MessageStrings.MsgSaveDataExportSuccess); - } - - private void Menu_DumpDecrypted_Click(object sender, EventArgs e) - { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() != DialogResult.OK) - return; - SAV.Dump(fbd.SelectedPath); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void Menu_LoadDecrypted_Click(object sender, EventArgs e) - { - using var ofd = new OpenFileDialog - { - Title = "Open main.dat ...", - Filter = "New Horizons Save File (main.dat)|main.dat", - FileName = "main.dat", - }; - - if (ofd.ShowDialog() == DialogResult.OK) - LoadDecryptedFromPath(ofd.FileName); - } - - private void LoadDecryptedFromPath(string main) - { - var dir = Path.GetDirectoryName(main); - if (dir is null || !Directory.Exists(dir)) - { - WinFormsUtil.Alert(MessageStrings.MsgImportDirectoryDoesNotExist); - return; - } - - SAV.Load(dir); - ReloadAll(); // reload all fields - System.Media.SystemSounds.Asterisk.Play(); - } - - private void Menu_VerifyHashes_Click(object sender, EventArgs e) - { - var result = SAV.GetInvalidHashes().ToArray(); - if (result.Length == 0) - { - WinFormsUtil.Alert(MessageStrings.MsgSaveDataHashesValid); - return; - } - - if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgAskExportResultToClipboard) != DialogResult.Yes) - return; - - var lines = result.Select(z => z.ToString()); - Clipboard.SetText(string.Join(Environment.NewLine, lines)); - } - - private void Menu_RAMEdit_Click(object sender, EventArgs e) - { - var exist = WinFormsUtil.FirstFormOfType(); - if (exist != null) - { - exist.Show(); - return; - } - - var sysbot = new SysBotRAMEdit(InjectionType.Generic); - sysbot.Show(); - } - - private void Menu_ItemImages_Click(object sender, EventArgs e) - { - var exist = WinFormsUtil.FirstFormOfType(); - if (exist != null) - { - exist.Show(); - return; - } - - var imgfetcher = new ImageFetcher(); - imgfetcher.Show(); - } - - private void ReloadAll() - { - Villagers.Villagers = SAV.Main.GetVillagers(); - Villagers.Origin = SAV.Players[0].Personal; - LoadPlayers(); - } - - private VillagerEditor LoadVillagers() - { - var p0 = SAV.Players[0].Personal; - var villagers = SAV.Main.GetVillagers(); - var v = new VillagerEditor(villagers, p0, SAV, true) {Dock = DockStyle.Fill}; - Tab_Villagers.Controls.Add(v); - return v; - } - - private void SaveAll() - { - SavePlayer(PlayerIndex); - Villagers.Save(); - SAV.Main.SetVillagers(Villagers.Villagers); - SaveMain(); - } - - private void LoadMain() - { - var m = SAV.Main; - var names = Enum.GetNames(typeof(Hemisphere)); - foreach (var n in names) - CB_Hemisphere.Items.Add(n); - CB_Hemisphere.SelectedIndex = (int)m.Hemisphere; - - names = Enum.GetNames(typeof(AirportColor)); - foreach (var n in names) - CB_AirportColor.Items.Add(n); - CB_AirportColor.SelectedIndex = (int)m.AirportThemeColor; - NUD_WeatherSeed.Value = m.WeatherSeed; - } - - private void SaveMain() - { - var m = SAV.Main; - m.Hemisphere = (Hemisphere)CB_Hemisphere.SelectedIndex; - m.AirportThemeColor = (AirportColor)CB_AirportColor.SelectedIndex; - m.WeatherSeed = (uint)NUD_WeatherSeed.Value; - } - - #region Player Editing - private void LoadPlayers() - { - if (SAV.Players.Length == 0) - throw new Exception("No players found in the loaded directory."); - - CB_Players.Items.Clear(); - var playerList = SAV.Players.Select(z => z.DirectoryName); - foreach (var p in playerList) - CB_Players.Items.Add(p); - - PlayerIndex = -1; - CB_Players.SelectedIndex = 0; - } - - private int PlayerIndex = -1; - private void LoadPlayer(object sender, EventArgs e) => LoadPlayer(CB_Players.SelectedIndex); - - private void B_EditPlayerItems_Click(object sender, EventArgs e) - { - var player = SAV.Players[PlayerIndex]; - { - var pers = player.Personal; - var bag = pers.Bag; - var pocket = pers.Pocket; - var items = pocket.Concat(bag).ToArray(); - using var editor = new PlayerItemEditor(items, 10, 4, sysbot: true); - if (editor.ShowDialog() != DialogResult.OK) - return; - - pers.Pocket = items.Take(pocket.Count).ToArray(); - pers.Bag = items.Skip(pocket.Count).Take(bag.Count).ToArray(); - } - } - - private void B_Storage_Click(object sender, EventArgs e) - { - var player = SAV.Players[PlayerIndex]; - var pers = player.Personal; - var p1 = pers.ItemChest; - using var editor = new PlayerItemEditor(p1, 10, 5); - if (editor.ShowDialog() == DialogResult.OK) - pers.ItemChest = p1; - } - - private void B_RecycleBin_Click(object sender, EventArgs e) - { - var items = SAV.Main.RecycleBin; - using var editor = new PlayerItemEditor(items, 10, 4); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.RecycleBin = items; - } - - private void B_EditPlayerRecipes_Click(object sender, EventArgs e) - { - var player = SAV.Players[PlayerIndex]; - using var editor = new RecipeListEditor(player); - editor.ShowDialog(); - } - - private void B_EditPlayerReceivedItems_Click(object sender, EventArgs e) - { - var player = SAV.Players[PlayerIndex]; - using var editor = new ItemReceivedEditor(player); - editor.ShowDialog(); - } - - private void B_EditPlayerReactions_Click(object sender, EventArgs e) - { - var player = SAV.Players[PlayerIndex]; - using var editor = new ReactionEditor(player.Personal); - editor.ShowDialog(); - } - - private void B_EditPlayerMisc_Click(object sender, EventArgs e) - { - var player = SAV.Players[PlayerIndex]; - using var editor = new MiscPlayerEditor(player); - editor.ShowDialog(); - } - - private void LoadPlayer(int index) - { - if (PlayerIndex >= 0) - SavePlayer(PlayerIndex); - - if (index < 0) - return; - - var player = SAV.Players[index]; - - var pers = player.Personal; - TB_Name.Text = pers.PlayerName; - TB_TownName.Text = pers.TownName; - NUD_BankBells.Value = Math.Min(int.MaxValue, pers.Bank.Value); - NUD_NookMiles.Value = Math.Min(int.MaxValue, pers.NookMiles.Value); - NUD_TotalNookMiles.Value = Math.Min(int.MaxValue, pers.TotalNookMiles.Value); - NUD_Wallet.Value = Math.Min(int.MaxValue, pers.Wallet.Value); - - // swapped on purpose -- first count is the first two rows of items - NUD_PocketCount1.Value = Math.Min(int.MaxValue, pers.PocketCount); - NUD_PocketCount2.Value = Math.Min(int.MaxValue, pers.BagCount); - NUD_StorageCount.Value = Math.Min(int.MaxValue, pers.ItemChestCount); - - if (player.WhereAreN is not null) - { - NUD_Poki.Value = Math.Min(int.MaxValue, player.WhereAreN.Poki.Value); - } - else - { - L_Poki.Visible = NUD_Poki.Visible = false; - } - - try - { - var photo = pers.GetPhotoData(); - PB_Player.Image = new Bitmap(new MemoryStream(photo)); - } - catch (Exception e) - { - Console.WriteLine(e); - } - - PlayerIndex = index; - } - - private void SavePlayer(int index) - { - if (index < 0) - return; - - var player = SAV.Players[index]; - var pers = player.Personal; - - if (pers.PlayerName != TB_Name.Text) - { - var orig = pers.GetPlayerIdentity(); - pers.PlayerName = TB_Name.Text; - var updated = pers.GetPlayerIdentity(); - SAV.ChangeIdentity(orig, updated); - } - if (pers.TownName != TB_TownName.Text) - { - var orig = pers.GetTownIdentity(); - pers.TownName = TB_TownName.Text; - var updated = pers.GetTownIdentity(); - SAV.ChangeIdentity(orig, updated); - } - - var bank = pers.Bank; - bank.Value = (uint)NUD_BankBells.Value; - pers.Bank = bank; - - var nook = pers.NookMiles; - nook.Value = (uint)NUD_NookMiles.Value; - pers.NookMiles = nook; - - var tnook = pers.TotalNookMiles; - tnook.Value = (uint)NUD_TotalNookMiles.Value; - pers.TotalNookMiles = tnook; - - var wallet = pers.Wallet; - wallet.Value = (uint)NUD_Wallet.Value; - pers.Wallet = wallet; - - // swapped on purpose -- first count is the first two rows of items - pers.PocketCount = (uint)NUD_PocketCount1.Value; - pers.BagCount = (uint)NUD_PocketCount2.Value; - - pers.ItemChestCount = (uint)NUD_StorageCount.Value; - - if (player.WhereAreN is { } x) - { - var poki = x.Poki; - poki.Value = (uint)NUD_Poki.Value; - x.Poki = poki; - } - } - - private void B_EditAchievements_Click(object sender, EventArgs e) - { - var pers = SAV.Players[PlayerIndex].Personal; - using var editor = new AchievementEditor(pers); - editor.ShowDialog(); - } - - private void B_EditPlayerFlags_Click(object sender, EventArgs e) - { - var pers = SAV.Players[PlayerIndex].Personal; - var flags = pers.GetEventFlagsPlayer(); - using var editor = new FlagEditor(flags); - if (editor.ShowDialog() == DialogResult.OK) - pers.SetEventFlagsPlayer(flags); - } - - #endregion - - private void Menu_SavePNG_Click(object sender, EventArgs e) - { - var pb = WinFormsUtil.GetUnderlyingControl(sender); - if (pb?.Image == null) - { - WinFormsUtil.Alert(MessageStrings.MsgNoPictureLoaded); - return; - } - - string name = SAV.Players[PlayerIndex].Personal.PlayerName; - var bmp = pb.Image; - using var sfd = new SaveFileDialog - { - Filter = "png file (*.png)|*.png|All files (*.*)|*.*", - FileName = $"{name}.png", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - bmp.Save(sfd.FileName, ImageFormat.Png); - } - - private void B_EditTurnipExchange_Click(object sender, EventArgs e) - { - var turnips = SAV.Main.Turnips; - using var editor = new SingleObjectEditor(turnips, PropertySort.Categorized, false); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.Turnips = turnips; - } - - private void B_EditFieldItems_Click(object sender, EventArgs e) - { - using var editor = new FieldItemEditor(SAV.Main); - editor.ShowDialog(); - } - - private void B_EditLandFlags_Click(object sender, EventArgs e) - { - var flags = SAV.Main.GetEventFlagLand(); - using var editor = new LandFlagEditor(flags); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.SetEventFlagLand(flags); - } - - private void B_EditPatterns_Click(object sender, EventArgs e) - { - var playerID = SAV.Players[0].Personal.GetPlayerIdentity(); // fetch ID for overwrite ownership - var townID = SAV.Players[0].Personal.GetTownIdentity(); // fetch ID for overwrite ownership - var patterns = SAV.Main.GetDesigns(); - using var editor = new PatternEditor(patterns); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.SetDesigns(patterns, playerID, townID); - } - - private void B_EditPRODesigns_Click(object sender, EventArgs e) - { - var playerID = SAV.Players[0].Personal.GetPlayerIdentity(); // fetch ID for overwrite ownership - var townID = SAV.Players[0].Personal.GetTownIdentity(); // fetch ID for overwrite ownership - var patterns = SAV.Main.GetDesignsPRO(); - using var editor = new PatternEditorPRO(patterns); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.SetDesignsPRO(patterns, playerID, townID); - } - - private void B_EditPatternFlag_Click(object sender, EventArgs e) - { - var patterns = new[] {SAV.Main.FlagMyDesign}; - using var editor = new PatternEditor(patterns); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.FlagMyDesign = patterns[0]; - } - - private void B_EditDesignsTailor_Click(object sender, EventArgs e) - { - var patterns = SAV.Main.GetDesignsTailor(); - using var editor = new PatternEditorPRO(patterns); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.SetDesignsTailor(patterns); - } - - private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); - private void B_EditPlayer_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_EditPlayer, B_EditPlayer); - private void B_EditMap_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_EditMap, B_EditMap); - - private void B_EditPlayerHouses_Click(object sender, EventArgs e) - { - var houses = SAV.Main.GetPlayerHouses(); - using var editor = new PlayerHouseEditor(houses, SAV.Players, SAV.Main, PlayerIndex); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.SetPlayerHouses(houses); - } - - private void B_EditBulletin_Click(object sender, EventArgs e) - { - var boxed = SAV.Main.Bulletin; - using var editor = new SingleObjectEditor(boxed, PropertySort.NoSort, false); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.Bulletin = boxed; - } - - private void B_EditFieldGoods_Click(object sender, EventArgs e) - { - var boxed = SAV.Main.SaveFg; - using var editor = new SingleObjectEditor(boxed, PropertySort.NoSort, false); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.SaveFg = boxed; - } - - private void B_EditMuseum_Click_Click(object sender, EventArgs e) - { - var museum = SAV.Main.Museum; - using var editor = new MuseumEditor(museum); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.Museum = museum; - } - - private void B_EditVisitors_Click(object sender, EventArgs e) - { - var boxed = SAV.Main.Visitor; - using var editor = new SingleObjectEditor(boxed, PropertySort.NoSort, false); - if (editor.ShowDialog() == DialogResult.OK) - SAV.Main.Visitor = boxed; - } - - private void NUD_PocketCount_ValueChanged(object sender, EventArgs e) => ((NumericUpDown) sender).BackColor = (uint) ((NumericUpDown) sender).Value > 20 ? Color.Red : NUD_BankBells.BackColor; - private void NUD_Wallet_ValueChanged(object sender, EventArgs e) => NUD_Wallet.BackColor = (ulong) NUD_Wallet.Value > 99_999 ? Color.Red : NUD_BankBells.BackColor; + Text = SAV.GetSaveTitle("NHSE"); } -} + + private void Menu_Settings_Click(object sender, EventArgs e) + { + using var editor = new SettingsEditor(); + editor.ShowDialog(); + } + + private void Menu_Language_SelectedIndexChanged(object sender, EventArgs e) + { + Menu_Options.DropDown.Close(); + if ((uint)Menu_Language.SelectedIndex >= GameLanguage.LanguageCount) + return; + var lang = GameInfo.SetLanguage2Char(Menu_Language.SelectedIndex); + + this.TranslateInterface(lang); + var settings = Settings.Default; + settings.Language = lang; + settings.Save(); + + Task.Run(() => + { + ItemSprite.Initialize(GameInfo.GetStrings("en").itemlist); + TranslationUtil.SetLocalization(typeof(MessageStrings), lang); + TranslationUtil.SetLocalization(GameInfo.Strings.InternalNameTranslation, lang); + }); + } + + private void Menu_Save_Click(object sender, EventArgs e) + { + SaveAll(); + try + { + SAV.Save((uint) DateTime.Now.Ticks); + } + catch (Exception ex) + { + WinFormsUtil.Error(MessageStrings.MsgSaveDataExportFail, ex.Message); + return; + } + WinFormsUtil.Alert(MessageStrings.MsgSaveDataExportSuccess); + } + + private void Menu_DumpDecrypted_Click(object sender, EventArgs e) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() != DialogResult.OK) + return; + SAV.Dump(fbd.SelectedPath); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void Menu_LoadDecrypted_Click(object sender, EventArgs e) + { + using var ofd = new OpenFileDialog(); + ofd.Title = "Open main.dat ..."; + ofd.Filter = "New Horizons Save File (main.dat)|main.dat"; + ofd.FileName = "main.dat"; + + if (ofd.ShowDialog() == DialogResult.OK) + LoadDecryptedFromPath(ofd.FileName); + } + + private void LoadDecryptedFromPath(string main) + { + var dir = Path.GetDirectoryName(main); + if (dir is null || !Directory.Exists(dir)) + { + WinFormsUtil.Alert(MessageStrings.MsgImportDirectoryDoesNotExist); + return; + } + + SAV.Load(dir); + ReloadAll(); // reload all fields + System.Media.SystemSounds.Asterisk.Play(); + } + + private void Menu_VerifyHashes_Click(object sender, EventArgs e) + { + var result = SAV.GetInvalidHashes().ToArray(); + if (result.Length == 0) + { + WinFormsUtil.Alert(MessageStrings.MsgSaveDataHashesValid); + return; + } + + if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgAskExportResultToClipboard) != DialogResult.Yes) + return; + + var lines = result.Select(z => z.ToString()); + Clipboard.SetText(string.Join(Environment.NewLine, lines)); + } + + private void Menu_RAMEdit_Click(object sender, EventArgs e) + { + var exist = WinFormsUtil.FirstFormOfType(); + if (exist != null) + { + exist.Show(); + return; + } + + var sysbot = new SysBotRAMEdit(InjectionType.Generic); + sysbot.Show(); + } + + private void Menu_ItemImages_Click(object sender, EventArgs e) + { + var exist = WinFormsUtil.FirstFormOfType(); + if (exist != null) + { + exist.Show(); + return; + } + + var imgfetcher = new ImageFetcher(); + imgfetcher.Show(); + } + + private void ReloadAll() + { + Villagers.Villagers = SAV.Main.GetVillagers(); + Villagers.Origin = SAV.Players[0].Personal; + LoadPlayers(); + } + + private VillagerEditor LoadVillagers() + { + var p0 = SAV.Players[0].Personal; + var villagers = SAV.Main.GetVillagers(); + var v = new VillagerEditor(villagers, p0, SAV, true) {Dock = DockStyle.Fill}; + Tab_Villagers.Controls.Add(v); + return v; + } + + private void SaveAll() + { + SavePlayer(PlayerIndex); + Villagers.Save(); + SAV.Main.SetVillagers(Villagers.Villagers); + SaveMain(); + } + + private void LoadMain() + { + var m = SAV.Main; + var names = Enum.GetNames(); + CB_Hemisphere.Items.AddRange(names); + CB_Hemisphere.SelectedIndex = (int)m.Hemisphere; + + names = Enum.GetNames(); + CB_AirportColor.Items.AddRange(names); + CB_AirportColor.SelectedIndex = (int)m.AirportThemeColor; + NUD_WeatherSeed.Value = m.WeatherSeed; + } + + private void SaveMain() + { + var m = SAV.Main; + m.Hemisphere = (Hemisphere)CB_Hemisphere.SelectedIndex; + m.AirportThemeColor = (AirportColor)CB_AirportColor.SelectedIndex; + m.WeatherSeed = (uint)NUD_WeatherSeed.Value; + } + + #region Player Editing + private void LoadPlayers() + { + if (SAV.Players.Length == 0) + throw new Exception("No players found in the loaded directory."); + + CB_Players.Items.Clear(); + var playerList = SAV.Players.Select(z => z.DirectoryName); + foreach (var p in playerList) + CB_Players.Items.Add(p); + + PlayerIndex = -1; + CB_Players.SelectedIndex = 0; + } + + private int PlayerIndex = -1; + private void LoadPlayer(object sender, EventArgs e) => LoadPlayer(CB_Players.SelectedIndex); + + private void B_EditPlayerItems_Click(object sender, EventArgs e) + { + var player = SAV.Players[PlayerIndex]; + { + var pers = player.Personal; + var bag = pers.Bag; + var pocket = pers.Pocket; + var items = pocket.Concat(bag).ToArray(); + using var editor = new PlayerItemEditor(items, 10, 4, sysbot: true); + if (editor.ShowDialog() != DialogResult.OK) + return; + + pers.Pocket = items.AsSpan(0, pocket.Count).ToArray(); + pers.Bag = items.AsSpan(pocket.Count, bag.Count).ToArray(); + } + } + + private void B_Storage_Click(object sender, EventArgs e) + { + var player = SAV.Players[PlayerIndex]; + var pers = player.Personal; + var p1 = pers.ItemChest; + using var editor = new PlayerItemEditor(p1, 10, 5); + if (editor.ShowDialog() == DialogResult.OK) + pers.ItemChest = p1; + } + + private void B_RecycleBin_Click(object sender, EventArgs e) + { + var items = SAV.Main.RecycleBin; + using var editor = new PlayerItemEditor(items, 10, 4); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.RecycleBin = items; + } + + private void B_EditPlayerRecipes_Click(object sender, EventArgs e) + { + var player = SAV.Players[PlayerIndex]; + using var editor = new RecipeListEditor(player); + editor.ShowDialog(); + } + + private void B_EditPlayerReceivedItems_Click(object sender, EventArgs e) + { + var player = SAV.Players[PlayerIndex]; + using var editor = new ItemReceivedEditor(player); + editor.ShowDialog(); + } + + private void B_EditPlayerReactions_Click(object sender, EventArgs e) + { + var player = SAV.Players[PlayerIndex]; + using var editor = new ReactionEditor(player.Personal); + editor.ShowDialog(); + } + + private void B_EditPlayerMisc_Click(object sender, EventArgs e) + { + var player = SAV.Players[PlayerIndex]; + using var editor = new MiscPlayerEditor(player); + editor.ShowDialog(); + } + + private void LoadPlayer(int index) + { + if (PlayerIndex >= 0) + SavePlayer(PlayerIndex); + + if (index < 0) + return; + + var player = SAV.Players[index]; + + var pers = player.Personal; + TB_Name.Text = pers.PlayerName; + TB_TownName.Text = pers.TownName; + NUD_BankBells.Value = Math.Min(int.MaxValue, pers.Bank.Value); + NUD_NookMiles.Value = Math.Min(int.MaxValue, pers.NookMiles.Value); + NUD_TotalNookMiles.Value = Math.Min(int.MaxValue, pers.TotalNookMiles.Value); + NUD_Wallet.Value = Math.Min(int.MaxValue, pers.Wallet.Value); + + // swapped on purpose -- first count is the first two rows of items + NUD_PocketCount1.Value = Math.Min(int.MaxValue, pers.PocketCount); + NUD_PocketCount2.Value = Math.Min(int.MaxValue, pers.BagCount); + NUD_StorageCount.Value = Math.Min(int.MaxValue, pers.ItemChestCount); + + if (player.WhereAreN is not null) + { + NUD_Poki.Value = Math.Min(int.MaxValue, player.WhereAreN.Poki.Value); + } + else + { + L_Poki.Visible = NUD_Poki.Visible = false; + } + + try + { + var photo = pers.GetPhotoData(); + PB_Player.Image = new Bitmap(new MemoryStream(photo)); + } + catch (Exception e) + { + Console.WriteLine(e); + } + + PlayerIndex = index; + } + + private void SavePlayer(int index) + { + if (index < 0) + return; + + var player = SAV.Players[index]; + var pers = player.Personal; + + if (pers.PlayerName != TB_Name.Text) + { + var orig = pers.GetPlayerIdentity(); + pers.PlayerName = TB_Name.Text; + var updated = pers.GetPlayerIdentity(); + SAV.ChangeIdentity(orig, updated); + } + if (pers.TownName != TB_TownName.Text) + { + var orig = pers.GetTownIdentity(); + pers.TownName = TB_TownName.Text; + var updated = pers.GetTownIdentity(); + SAV.ChangeIdentity(orig, updated); + } + + var bank = pers.Bank; + bank.Value = (uint)NUD_BankBells.Value; + pers.Bank = bank; + + var nook = pers.NookMiles; + nook.Value = (uint)NUD_NookMiles.Value; + pers.NookMiles = nook; + + var tnook = pers.TotalNookMiles; + tnook.Value = (uint)NUD_TotalNookMiles.Value; + pers.TotalNookMiles = tnook; + + var wallet = pers.Wallet; + wallet.Value = (uint)NUD_Wallet.Value; + pers.Wallet = wallet; + + // swapped on purpose -- first count is the first two rows of items + pers.PocketCount = (uint)NUD_PocketCount1.Value; + pers.BagCount = (uint)NUD_PocketCount2.Value; + + pers.ItemChestCount = (uint)NUD_StorageCount.Value; + + if (player.WhereAreN is { } x) + { + var poki = x.Poki; + poki.Value = (uint)NUD_Poki.Value; + x.Poki = poki; + } + } + + private void B_EditAchievements_Click(object sender, EventArgs e) + { + var pers = SAV.Players[PlayerIndex].Personal; + using var editor = new AchievementEditor(pers); + editor.ShowDialog(); + } + + private void B_EditPlayerFlags_Click(object sender, EventArgs e) + { + var pers = SAV.Players[PlayerIndex].Personal; + var flags = pers.GetEventFlagsPlayer(); + using var editor = new FlagEditor(flags); + if (editor.ShowDialog() == DialogResult.OK) + pers.SetEventFlagsPlayer(flags); + } + + #endregion + + private void Menu_SavePNG_Click(object sender, EventArgs e) + { + if (!WinFormsUtil.TryGetUnderlying(sender, out var pb) || pb.Image is null) + { + WinFormsUtil.Alert(MessageStrings.MsgNoPictureLoaded); + return; + } + + string name = SAV.Players[PlayerIndex].Personal.PlayerName; + var bmp = pb.Image; + using var sfd = new SaveFileDialog(); + sfd.Filter = "png file (*.png)|*.png|All files (*.*)|*.*"; + sfd.FileName = $"{name}.png"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + bmp.Save(sfd.FileName, ImageFormat.Png); + } + + private void B_EditTurnipExchange_Click(object sender, EventArgs e) + { + var turnips = SAV.Main.Turnips; + using var editor = new SingleObjectEditor(turnips, PropertySort.Categorized, false); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.Turnips = turnips; + } + + private void B_EditFieldItems_Click(object sender, EventArgs e) + { + using var editor = new FieldItemEditor(SAV.Main); + editor.ShowDialog(); + } + + private void B_EditLandFlags_Click(object sender, EventArgs e) + { + var flags = SAV.Main.EventFlagLand; + var edit = flags.ToArray(); + using var editor = new LandFlagEditor(edit); + if (editor.ShowDialog() == DialogResult.OK) + edit.CopyTo(flags); + } + + private void B_EditPatterns_Click(object sender, EventArgs e) + { + var playerID = SAV.Players[0].Personal.GetPlayerIdentity(); // fetch ID for overwrite ownership + var townID = SAV.Players[0].Personal.GetTownIdentity(); // fetch ID for overwrite ownership + var patterns = SAV.Main.GetDesigns(); + using var editor = new PatternEditor(patterns); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.SetDesigns(patterns, playerID, townID); + } + + private void B_EditPRODesigns_Click(object sender, EventArgs e) + { + var playerID = SAV.Players[0].Personal.GetPlayerIdentity(); // fetch ID for overwrite ownership + var townID = SAV.Players[0].Personal.GetTownIdentity(); // fetch ID for overwrite ownership + var patterns = SAV.Main.GetDesignsPRO(); + using var editor = new PatternEditorPRO(patterns); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.SetDesignsPRO(patterns, playerID, townID); + } + + private void B_EditPatternFlag_Click(object sender, EventArgs e) + { + var patterns = new[] {SAV.Main.FlagMyDesign}; + using var editor = new PatternEditor(patterns); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.FlagMyDesign = patterns[0]; + } + + private void B_EditDesignsTailor_Click(object sender, EventArgs e) + { + var patterns = SAV.Main.GetDesignsTailor(); + using var editor = new PatternEditorPRO(patterns); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.SetDesignsTailor(patterns); + } + + private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); + private void B_EditPlayer_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_EditPlayer, B_EditPlayer); + private void B_EditMap_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_EditMap, B_EditMap); + + private void B_EditPlayerHouses_Click(object sender, EventArgs e) + { + var houses = SAV.Main.GetPlayerHouses(); + using var editor = new PlayerHouseEditor(houses, SAV.Players, SAV.Main, PlayerIndex); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.SetPlayerHouses(houses); + } + + private void B_EditBulletin_Click(object sender, EventArgs e) + { + var boxed = SAV.Main.Bulletin; + using var editor = new SingleObjectEditor(boxed, PropertySort.NoSort, false); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.Bulletin = boxed; + } + + private void B_EditFieldGoods_Click(object sender, EventArgs e) + { + var boxed = SAV.Main.SaveFg; + using var editor = new SingleObjectEditor(boxed, PropertySort.NoSort, false); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.SaveFg = boxed; + } + + private void B_EditMuseum_Click_Click(object sender, EventArgs e) + { + var museum = SAV.Main.Museum; + using var editor = new MuseumEditor(museum); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.Museum = museum; + } + + private void B_EditVisitors_Click(object sender, EventArgs e) + { + var boxed = SAV.Main.Visitor; + using var editor = new SingleObjectEditor(boxed, PropertySort.NoSort, false); + if (editor.ShowDialog() == DialogResult.OK) + SAV.Main.Visitor = boxed; + } + + private void NUD_PocketCount_ValueChanged(object sender, EventArgs e) => ((NumericUpDown) sender).BackColor = (uint) ((NumericUpDown) sender).Value > 20 ? Color.Red : NUD_BankBells.BackColor; + private void NUD_Wallet_ValueChanged(object sender, EventArgs e) => NUD_Wallet.BackColor = (ulong) NUD_Wallet.Value > 99_999 ? Color.Red : NUD_BankBells.BackColor; +} \ No newline at end of file diff --git a/NHSE.WinForms/FodyWeavers.xml b/NHSE.WinForms/FodyWeavers.xml deleted file mode 100644 index a5dcf04..0000000 --- a/NHSE.WinForms/FodyWeavers.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/NHSE.WinForms/FodyWeavers.xsd b/NHSE.WinForms/FodyWeavers.xsd deleted file mode 100644 index 44a5374..0000000 --- a/NHSE.WinForms/FodyWeavers.xsd +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks - - - - - A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. - - - - - A list of unmanaged 32 bit assembly names to include, delimited with line breaks. - - - - - A list of unmanaged 64 bit assembly names to include, delimited with line breaks. - - - - - The order of preloaded assemblies, delimited with line breaks. - - - - - - This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. - - - - - Controls if .pdbs for reference assemblies are also embedded. - - - - - Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. - - - - - As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. - - - - - Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. - - - - - Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. - - - - - A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | - - - - - A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. - - - - - A list of unmanaged 32 bit assembly names to include, delimited with |. - - - - - A list of unmanaged 64 bit assembly names to include, delimited with |. - - - - - The order of preloaded assemblies, delimited with |. - - - - - - - - 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. - - - - - A comma-separated list of error codes that can be safely ignored in assembly verification. - - - - - 'false' to turn off automatic generation of the XML Schema file. - - - - - \ No newline at end of file diff --git a/NHSE.WinForms/Main.cs b/NHSE.WinForms/Main.cs index 088f354..5606788 100644 --- a/NHSE.WinForms/Main.cs +++ b/NHSE.WinForms/Main.cs @@ -6,196 +6,196 @@ using NHSE.Sprites; using NHSE.WinForms.Properties; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +/// +/// Simple launcher for opening a save file. +/// +public partial class Main : Form { - /// - /// Simple launcher for opening a save file. - /// - public partial class Main : Form + public const string BackupFolderName = "bak"; + public const string ItemFolderName = "items"; + public static readonly string WorkingDirectory = Application.StartupPath; + public static readonly string BackupPath = Path.Combine(WorkingDirectory, BackupFolderName); + public static readonly string ItemPath = Path.Combine(WorkingDirectory, ItemFolderName); + + public Main() { - public const string BackupFolderName = "bak"; - public const string ItemFolderName = "items"; - public static readonly string WorkingDirectory = Application.StartupPath; - public static readonly string BackupPath = Path.Combine(WorkingDirectory, BackupFolderName); - public static readonly string ItemPath = Path.Combine(WorkingDirectory, ItemFolderName); + InitializeComponent(); - public Main() + // Flash to front + BringToFront(); + WindowState = FormWindowState.Minimized; + Show(); + WindowState = FormWindowState.Normal; + + var args = Environment.GetCommandLineArgs().AsSpan(); + foreach (var arg in args) { - InitializeComponent(); - - // Flash to front - BringToFront(); - WindowState = FormWindowState.Minimized; - Show(); - WindowState = FormWindowState.Normal; - - var args = Environment.GetCommandLineArgs(); - for (int i = 1; i < args.Length; i++) - Open(args[i]); + if (Directory.Exists(arg)) + Open(arg); } + } - private static void Open(HorizonSave file) + private static void Open(HorizonSave file) + { + bool sized = file.ValidateSizes(); + if (!sized) { - bool sized = file.ValidateSizes(); - if (!sized) - { - var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgSaveDataSizeMismatch, MessageStrings.MsgAskContinue); - if (prompt != DialogResult.Yes) - return; - } - - new Editor(file).Show(); - } - - private void Main_DragEnter(object sender, DragEventArgs e) - { - if (e.AllowedEffect == (DragDropEffects.Copy | DragDropEffects.Link)) // external file - e.Effect = DragDropEffects.Copy; - else if (e.Data != null) // within - e.Effect = DragDropEffects.Move; - } - - private void Main_DragDrop(object sender, DragEventArgs e) - { - var files = (string[]?)e.Data?.GetData(DataFormats.FileDrop); - if (files == null || files.Length == 0) + var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgSaveDataSizeMismatch, MessageStrings.MsgAskContinue); + if (prompt != DialogResult.Yes) return; - Open(files[0]); + } + + new Editor(file).Show(); + } + + private void Main_DragEnter(object sender, DragEventArgs e) + { + if (e.AllowedEffect == (DragDropEffects.Copy | DragDropEffects.Link)) // external file e.Effect = DragDropEffects.Copy; + else if (e.Data != null) // within + e.Effect = DragDropEffects.Move; + } + + private void Main_DragDrop(object sender, DragEventArgs e) + { + var files = (string[]?)e.Data?.GetData(DataFormats.FileDrop); + if (files == null || files.Length == 0) + return; + Open(files[0]); + e.Effect = DragDropEffects.Copy; + } + + private void Menu_Open(object sender, EventArgs e) + { + if ((ModifierKeys & Keys.Control) != 0) + { + // Detect save file from SD cards? + } + else if ((ModifierKeys & Keys.Shift) != 0) + { + var path = Settings.Default.LastFilePath; + if (Directory.Exists(path)) + { + Open(path); + return; + } } - private void Menu_Open(object sender, EventArgs e) - { - if ((ModifierKeys & Keys.Control) != 0) - { - // Detect save file from SD cards? - } - else if ((ModifierKeys & Keys.Shift) != 0) - { - var path = Settings.Default.LastFilePath; - if (Directory.Exists(path)) - { - Open(path); - return; - } - } + using var ofd = new OpenFileDialog(); + ofd.Title = "Open main.dat ..."; + ofd.Filter = "New Horizons Save File (main.dat)|main.dat"; + ofd.FileName = "main.dat"; + if (ofd.ShowDialog() == DialogResult.OK) + Open(ofd.FileName); + } - using var ofd = new OpenFileDialog - { - Title = "Open main.dat ...", - Filter = "New Horizons Save File (main.dat)|main.dat", - FileName = "main.dat", - }; - if (ofd.ShowDialog() == DialogResult.OK) - Open(ofd.FileName); - } - - private static void Open(string path) - { - #if !DEBUG + private static void Open(string path) + { +#if !DEBUG try - #endif - { - OpenFileOrPath(path); - } - #if !DEBUG +#endif + { + OpenFileOrPath(path); + } +#if !DEBUG catch (Exception ex) { WinFormsUtil.Error(ex.Message); } - #endif - } - - private static void OpenFileOrPath(string path) - { - if (Directory.Exists(path)) - { - OpenSaveFile(path); - return; - } - - var dir = Path.GetDirectoryName(path); - if (dir is null || !Directory.Exists(dir)) // ya never know - { - WinFormsUtil.Error(MessageStrings.MsgSaveDataImportFail, MessageStrings.MsgSaveDataImportSuggest); - return; - } - - OpenSaveFile(dir); - } - - private static void OpenSaveFile(string path) - { - var file = new HorizonSave(path); - Open(file); - - var settings = Settings.Default; - settings.LastFilePath = path; - - if (!settings.BackupPrompted) - { - settings.BackupPrompted = true; - var line1 = string.Format(MessageStrings.MsgBackupCreateLocation, BackupFolderName); - var line2 = MessageStrings.MsgBackupCreateQuestion; - var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, line1, line2); - settings.AutomaticBackup = prompt == DialogResult.Yes; - } - - if (settings.AutomaticBackup) - BackupSaveFile(file, path, BackupPath); - - settings.Save(); - } - - private static void BackupSaveFile(HorizonSave file, string path, string bak) - { - Directory.CreateDirectory(bak); - var dest = Path.Combine(bak, file.GetBackupFolderTitle()); - if (!Directory.Exists(dest)) - FileUtil.CopyFolder(path, dest); - } - - private void Main_KeyDown(object sender, KeyEventArgs e) - { - if (ModifierKeys != Keys.Control) - { -#if DEBUG - if (ModifierKeys == (Keys.Control | Keys.Alt) && e.KeyCode == Keys.D) - DevUtil.UpdateAll(); #endif - return; - } + } - switch (e.KeyCode) + private static void OpenFileOrPath(string path) + { + if (Directory.Exists(path)) + { + OpenSaveFile(path); + return; + } + + var dir = Path.GetDirectoryName(path); + if (dir is null || !Directory.Exists(dir)) // ya never know + { + WinFormsUtil.Error(MessageStrings.MsgSaveDataImportFail, MessageStrings.MsgSaveDataImportSuggest); + return; + } + + OpenSaveFile(dir); + } + + private static void OpenSaveFile(string path) + { + var file = new HorizonSave(path); + Open(file); + + var settings = Settings.Default; + settings.LastFilePath = path; + + if (!settings.BackupPrompted) + { + settings.BackupPrompted = true; + var line1 = string.Format(MessageStrings.MsgBackupCreateLocation, BackupFolderName); + var line2 = MessageStrings.MsgBackupCreateQuestion; + var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, line1, line2); + settings.AutomaticBackup = prompt == DialogResult.Yes; + } + + if (settings.AutomaticBackup) + BackupSaveFile(file, path, BackupPath); + + settings.Save(); + } + + private static void BackupSaveFile(HorizonSave file, string path, string bak) + { + Directory.CreateDirectory(bak); + var dest = Path.Combine(bak, file.GetBackupFolderTitle()); + if (!Directory.Exists(dest)) + FileUtil.CopyFolder(path, dest); + } + + private void Main_KeyDown(object sender, KeyEventArgs e) + { + if (ModifierKeys != Keys.Control) + { +#if DEBUG + if (ModifierKeys == (Keys.Control | Keys.Alt) && e.KeyCode == Keys.D) + DevUtil.UpdateAll(); +#endif + return; + } + + switch (e.KeyCode) + { + case Keys.O: { - case Keys.O: - { - Menu_Open(sender, e); - break; - } - case Keys.I: - { - ItemSprite.Initialize(GameInfo.GetStrings("en").itemlist); - var items = new Item[40]; - for (int i = 0; i < items.Length; i++) - items[i] = new Item(Item.NONE); - using var editor = new PlayerItemEditor(items, 10, 4, true); - editor.ShowDialog(); - break; - } - case Keys.H: - { - using var editor = new SysBotRAMEdit(InjectionType.Generic); - editor.ShowDialog(); - break; - } - case Keys.P: - { - using var editor = new SettingsEditor(); - editor.ShowDialog(); - break; - } + Menu_Open(sender, e); + break; + } + case Keys.I: + { + ItemSprite.Initialize(GameInfo.GetStrings("en").itemlist); + var items = new Item[40]; + for (int i = 0; i < items.Length; i++) + items[i] = new Item(Item.NONE); + using var editor = new PlayerItemEditor(items, 10, 4, true); + editor.ShowDialog(); + break; + } + case Keys.H: + { + using var editor = new SysBotRAMEdit(InjectionType.Generic); + editor.ShowDialog(); + break; + } + case Keys.P: + { + using var editor = new SettingsEditor(); + editor.ShowDialog(); + break; } } } -} +} \ No newline at end of file diff --git a/NHSE.WinForms/NHSE.WinForms.csproj b/NHSE.WinForms/NHSE.WinForms.csproj index 169dc48..963dbb4 100644 --- a/NHSE.WinForms/NHSE.WinForms.csproj +++ b/NHSE.WinForms/NHSE.WinForms.csproj @@ -1,13 +1,16 @@ - + WinExe - net46;net8.0-windows + net10.0-windows true + true + SystemAware + true Animal Crossing - New Horizons Save Editor NHSE.WinForms.Program icon.ico - AnyCPU;x86 + AnyCPU @@ -18,15 +21,6 @@ - - UserControl - - - ItemEditor.cs - - - Form - True True @@ -37,80 +31,6 @@ True Settings.settings - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - - Form - - - Form - - - PropertyEditor.cs - - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - Form - - - - - diff --git a/NHSE.WinForms/Program.cs b/NHSE.WinForms/Program.cs index f0f0bfb..dc1ab03 100644 --- a/NHSE.WinForms/Program.cs +++ b/NHSE.WinForms/Program.cs @@ -1,22 +1,26 @@ -using System; +using System; using System.Windows.Forms; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +internal static class Program { - internal static class Program + /// + /// The main entry point for the application. + /// + [STAThread] + private static void Main() { - /// - /// The main entry point for the application. - /// - [STAThread] - private static void Main() + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + var args = Environment.GetCommandLineArgs(); + if (args.Length > 1) { -#if NETCOREAPP - Application.SetHighDpiMode(HighDpiMode.SystemAware); -#endif - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new Main()); + if (args.Contains("-dark")) + Application.SetColorMode(SystemColorMode.Dark); } + + Application.Run(new Main()); } -} +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/BuildingHelp.cs b/NHSE.WinForms/Subforms/Map/BuildingHelp.cs index 7f0f65b..30faa70 100644 --- a/NHSE.WinForms/Subforms/Map/BuildingHelp.cs +++ b/NHSE.WinForms/Subforms/Map/BuildingHelp.cs @@ -3,30 +3,28 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class BuildingHelp : Form { - public partial class BuildingHelp : Form + private static readonly IReadOnlyDictionary HelpDictionary = StructureUtil.GetStructureHelpList(); + + public BuildingHelp() { - private static readonly IReadOnlyDictionary HelpDictionary = StructureUtil.GetStructureHelpList(); + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - public BuildingHelp() - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - - foreach (var entry in HelpDictionary) - CB_StructureType.Items.Add(entry.Key); - CB_StructureType.SelectedIndex = 0; - } - - private void CB_StructureType_SelectedIndexChanged(object sender, EventArgs e) - { - var name = CB_StructureType.Text; - var values = HelpDictionary[name]; - CB_StructureValues.Items.Clear(); - foreach (var item in values) - CB_StructureValues.Items.Add(item); - CB_StructureValues.SelectedIndex = 0; - } + foreach (var entry in HelpDictionary) + CB_StructureType.Items.Add(entry.Key); + CB_StructureType.SelectedIndex = 0; } -} + + private void CB_StructureType_SelectedIndexChanged(object sender, EventArgs e) + { + var name = CB_StructureType.Text; + var values = HelpDictionary[name]; + CB_StructureValues.Items.Clear(); + CB_StructureValues.Items.AddRange(values); + CB_StructureValues.SelectedIndex = 0; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/BulkSpawn.cs b/NHSE.WinForms/Subforms/Map/BulkSpawn.cs index d44b4bb..abc146e 100644 --- a/NHSE.WinForms/Subforms/Map/BulkSpawn.cs +++ b/NHSE.WinForms/Subforms/Map/BulkSpawn.cs @@ -5,193 +5,190 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class BulkSpawn : Form { - public partial class BulkSpawn : Form + private readonly IItemLayerEditor Editor; + private string NHIFilePath = ""; + + public BulkSpawn(IItemLayerEditor editor, int x = 0, int y = 0) { - private readonly IItemLayerEditor Editor; - private string NHIFilePath = ""; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - public BulkSpawn(IItemLayerEditor editor, int x = 0, int y = 0) + Editor = editor; + + CB_SpawnType.Items.AddRange(Enum.GetNames()); + CB_SpawnArrange.Items.AddRange(Enum.GetNames()); + + CB_SpawnType.SelectedIndex = 0; + CB_SpawnArrange.SelectedIndex = 0; + NUD_SpawnX.Value = x; + NUD_SpawnY.Value = y; + } + + private void B_Apply_Click(object sender, EventArgs e) + { + var type = (SpawnType)CB_SpawnType.SelectedIndex; + var arrange = (SpawnArrangement)CB_SpawnArrange.SelectedIndex; + var x = (int)NUD_SpawnX.Value; + var y = (int)NUD_SpawnY.Value; + var count = (int)NUD_SpawnCount.Value; + + IReadOnlyList items; + int sizeX; + int sizeY; + if (type is SpawnType.SequentialDIY or SpawnType.AlphabeticalDIY) { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); + var min = (ushort)NUD_DIYStart.Value; + var max = (ushort)NUD_DIYStop.Value; + var diy = RecipeList.Recipes + .Where(z => z.Key is not (RecipeList.BridgeConstructionKit or RecipeList.CampsiteConstructionKit) && min <= z.Key && z.Key <= max) + .Select(z => z.Key) + .Select(z => new Item(Item.DIYRecipe) {FreeParam = z}); - Editor = editor; + if (type == SpawnType.AlphabeticalDIY) + diy = diy.OrderBy(z => GameInfo.Strings.GetItemName(z)); - CB_SpawnType.Items.AddRange(Enum.GetNames(typeof(SpawnType))); - CB_SpawnArrange.Items.AddRange(Enum.GetNames(typeof(SpawnArrangement))); - - CB_SpawnType.SelectedIndex = 0; - CB_SpawnArrange.SelectedIndex = 0; - NUD_SpawnX.Value = x; - NUD_SpawnY.Value = y; + items = Enumerable.Repeat(diy, count).SelectMany(z => z).ToArray(); + sizeX = sizeY = 2; } - - private void B_Apply_Click(object sender, EventArgs e) + else if (type == SpawnType.ItemsFromNHI) { - var type = (SpawnType)CB_SpawnType.SelectedIndex; - var arrange = (SpawnArrangement)CB_SpawnArrange.SelectedIndex; - var x = (int)NUD_SpawnX.Value; - var y = (int)NUD_SpawnY.Value; - var count = (int)NUD_SpawnCount.Value; - - IReadOnlyList items; - int sizeX; - int sizeY; - if (type is SpawnType.SequentialDIY or SpawnType.AlphabeticalDIY) + if (string.IsNullOrEmpty(NHIFilePath) || !File.Exists(NHIFilePath)) { - var min = (ushort)NUD_DIYStart.Value; - var max = (ushort)NUD_DIYStop.Value; - var diy = RecipeList.Recipes - .Where(z => z.Key is not RecipeList.BridgeConstructionKit or RecipeList.CampsiteConstructionKit && min <= z.Key && z.Key <= max) - .Select(z => z.Key) - .Select(z => new Item(Item.DIYRecipe) {FreeParam = z}); - - if (type == SpawnType.AlphabeticalDIY) - diy = diy.OrderBy(x => GameInfo.Strings.GetItemName(x)); - - items = Enumerable.Repeat(diy, count).SelectMany(z => z).ToArray(); - sizeX = sizeY = 2; - } - else if (type == SpawnType.ItemsFromNHI) - { - if (string.IsNullOrEmpty(NHIFilePath) || !File.Exists(NHIFilePath)) - { - WinFormsUtil.Alert(MessageStrings.MsgFieldItemNoNHI); - return; - } - - // read non-empty slots into item array - var data = File.ReadAllBytes(this.NHIFilePath); - var array = data.GetArray(Item.SIZE).Where(item => !item.IsNone); - items = Enumerable.Repeat(array, count).SelectMany(z => z).ToArray(); - - // set flag0 = 0x20 for each item to ensure it gets dropped - // this also forces a 2x2 item size - foreach (Item item in items) - item.SystemParam = 0x20; - - sizeX = sizeY = 2; - } - else - { - var item = Editor.ItemProvider.SetItem(new Item()); - items = Enumerable.Repeat(item, count).ToArray(); - var size = ItemInfo.GetItemSize(item); - sizeX = size.GetWidth(); - sizeY = size.GetHeight(); - } - - if (sizeX % 2 == 1) - sizeX++; - if (sizeY % 2 == 1) - sizeY++; - - var ctr = SpawnItems(Editor.SpawnLayer, items, x, y, arrange, sizeX, sizeY, true); - if (ctr == 0) - { - WinFormsUtil.Alert(MessageStrings.MsgFieldItemModifyNone); + WinFormsUtil.Alert(MessageStrings.MsgFieldItemNoNHI); return; } - Editor.ReloadItems(); - WinFormsUtil.Alert(string.Format(MessageStrings.MsgFieldItemModifyCount, count)); + + // read non-empty slots into item array + var data = File.ReadAllBytes(NHIFilePath); + var array = data.GetArray(Item.SIZE).Where(item => !item.IsNone); + items = Enumerable.Repeat(array, count).SelectMany(z => z).ToArray(); + + // set flag0 = 0x20 for each item to ensure it gets dropped + // this also forces a 2x2 item size + foreach (var item in items) + item.SystemParam = 0x20; + + sizeX = sizeY = 2; + } + else + { + var item = Editor.ItemProvider.SetItem(new Item()); + items = Enumerable.Repeat(item, count).ToArray(); + var size = ItemInfo.GetItemSize(item); + sizeX = size.Width; + sizeY = size.Height; } - private static int SpawnItems(ItemLayer layer, IReadOnlyList items, int x, int y, SpawnArrangement arrange, int sizeX, int sizeY, bool noOverwrite) + if (sizeX % 2 == 1) + sizeX++; + if (sizeY % 2 == 1) + sizeY++; + + var ctr = SpawnItems(Editor.SpawnLayer, items, x, y, arrange, sizeX, sizeY, true); + if (ctr == 0) { - // every {setting} tiles, we jump down to the next available row of tiles. - int x0 = x; - var newline = arrange switch + WinFormsUtil.Alert(MessageStrings.MsgFieldItemModifyNone); + return; + } + Editor.ReloadItems(); + WinFormsUtil.Alert(string.Format(MessageStrings.MsgFieldItemModifyCount, count)); + } + + private static int SpawnItems(ItemLayer layer, IReadOnlyList items, int x, int y, SpawnArrangement arrange, int sizeX, int sizeY, bool noOverwrite) + { + // every {setting} tiles, we jump down to the next available row of tiles. + int x0 = x; + var newline = arrange switch + { + SpawnArrangement.Square => (int)Math.Sqrt(items.Count * sizeX * sizeY), + SpawnArrangement.Vertical => 1 * sizeY, + _ => items.Count * sizeX // Horizontal + }; + + int ctr = 0; + for (var i = 0; i < items.Count; i++) + { + var item = items[i]; + var permission = layer.IsOccupied(item, x, y); + switch (permission) { - SpawnArrangement.Square => (int)Math.Sqrt(items.Count * sizeX * sizeY), - SpawnArrangement.Vertical => 1 * sizeY, - _ => items.Count * sizeX // Horizontal - }; + case PlacedItemPermission.OutOfBounds when y >= layer.MaxHeight: + return ctr; + case PlacedItemPermission.OutOfBounds: + case PlacedItemPermission.Collision when noOverwrite: + i--; + break; - int ctr = 0; - for (var i = 0; i < items.Count; i++) - { - var item = items[i]; - var permission = layer.IsOccupied(item, x, y); - switch (permission) - { - case PlacedItemPermission.OutOfBounds when y >= layer.MaxHeight: - return ctr; - case PlacedItemPermission.OutOfBounds: - case PlacedItemPermission.Collision when noOverwrite: - i--; - break; + default: + var exist = layer.GetTile(x, y); + layer.DeleteExtensionTiles(exist, x, y); - default: - var exist = layer.GetTile(x, y); - layer.DeleteExtensionTiles(exist, x, y); - - // Set new placed data - layer.SetExtensionTiles(item, x, y); - exist.CopyFrom(item); - ctr++; - break; - } - - x += sizeX; - if (x - x0 >= newline) - { - y += sizeY; - x = x0; - } + // Set new placed data + layer.SetExtensionTiles(item, x, y); + exist.CopyFrom(item); + ctr++; + break; } - return ctr; - } - - private void CB_SpawnType_SelectedIndexChanged(object sender, EventArgs e) - { - var index = (SpawnType)CB_SpawnType.SelectedIndex; - L_DIYStart.Visible = L_DIYStop.Visible = NUD_DIYStart.Visible = NUD_DIYStop.Visible = index is SpawnType.SequentialDIY or SpawnType.AlphabeticalDIY; - L_NHI.Visible = L_NHIFileName.Visible = index == SpawnType.ItemsFromNHI; - NUD_SpawnCount.Value = index switch + x += sizeX; + if (x - x0 >= newline) { - SpawnType.SequentialDIY => 1, - SpawnType.AlphabeticalDIY => 1, - SpawnType.ItemsFromNHI => 1, - _ => 8, - }; - - if (index == SpawnType.ItemsFromNHI) - { - L_NHIFileName_Click(sender, e); + y += sizeY; + x = x0; } } - private void L_NHIFileName_Click(object sender, EventArgs e) + return ctr; + } + + private void CB_SpawnType_SelectedIndexChanged(object sender, EventArgs e) + { + var index = (SpawnType)CB_SpawnType.SelectedIndex; + L_DIYStart.Visible = L_DIYStop.Visible = NUD_DIYStart.Visible = NUD_DIYStop.Visible = index is SpawnType.SequentialDIY or SpawnType.AlphabeticalDIY; + L_NHI.Visible = L_NHIFileName.Visible = index == SpawnType.ItemsFromNHI; + NUD_SpawnCount.Value = index switch { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Inventory (*.nhi)|*.nhi|All files (*.*)|*.*", - FileName = "items.nhi", - }; + SpawnType.SequentialDIY => 1, + SpawnType.AlphabeticalDIY => 1, + SpawnType.ItemsFromNHI => 1, + _ => 8, + }; - if (ofd.ShowDialog() != DialogResult.OK) - return; - - L_NHIFileName.Text = ofd.SafeFileName; - this.NHIFilePath = ofd.FileName; - } - - private enum SpawnType + if (index == SpawnType.ItemsFromNHI) { - ItemFromEditor, - SequentialDIY, - AlphabeticalDIY, - ItemsFromNHI, - } - - private enum SpawnArrangement - { - Square, - Horizontal, - Vertical, + L_NHIFileName_Click(sender, e); } } -} + + private void L_NHIFileName_Click(object sender, EventArgs e) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Inventory (*.nhi)|*.nhi|All files (*.*)|*.*"; + ofd.FileName = "items.nhi"; + + if (ofd.ShowDialog() != DialogResult.OK) + return; + + L_NHIFileName.Text = ofd.SafeFileName; + this.NHIFilePath = ofd.FileName; + } + + private enum SpawnType + { + ItemFromEditor, + SequentialDIY, + AlphabeticalDIY, + ItemsFromNHI, + } + + private enum SpawnArrangement + { + Square, + Horizontal, + Vertical, + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/FieldItemEditor.cs b/NHSE.WinForms/Subforms/Map/FieldItemEditor.cs index cec9dd4..814f354 100644 --- a/NHSE.WinForms/Subforms/Map/FieldItemEditor.cs +++ b/NHSE.WinForms/Subforms/Map/FieldItemEditor.cs @@ -9,1134 +9,1125 @@ using NHSE.Sprites; using NHSE.WinForms.Subforms.Map; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public sealed partial class FieldItemEditor : Form, IItemLayerEditor { - public sealed partial class FieldItemEditor : Form, IItemLayerEditor + private readonly MainSave SAV; + + private readonly MapManager Map; + private readonly MapViewer View; + + private bool Loading; + private int SelectedBuildingIndex; + + private int HoverX; + private int HoverY; + private int DragX = -1; + private int DragY = -1; + private bool Dragging; + + public ItemEditor ItemProvider => ItemEdit; + public ItemLayer SpawnLayer => Map.CurrentLayer; + + private TerrainBrushEditor? tbeForm; + + public FieldItemEditor(MainSave sav) { - private readonly MainSave SAV; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - private readonly MapManager Map; - private readonly MapViewer View; + var scale = (PB_Acre.Width - 2) / 32; + SAV = sav; + Map = new MapManager(sav); + View = new MapViewer(Map, scale); - private bool Loading; - private int SelectedBuildingIndex; + Loading = true; - private int HoverX; - private int HoverY; - private int DragX = -1; - private int DragY = -1; - private bool Dragging; + LoadComboBoxes(); + LoadBuildings(sav); + ReloadMapBackground(); + LoadEditors(); + LB_Items.SelectedIndex = 0; + CB_Acre.SelectedIndex = 0; + CB_MapAcre.SelectedIndex = 0; + Loading = false; + LoadItemGridAcre(); + } - public ItemEditor ItemProvider => ItemEdit; - public ItemLayer SpawnLayer => Map.CurrentLayer; + private void LoadComboBoxes() + { + foreach (var acre in MapGrid.Acres) + CB_Acre.Items.Add(acre.Name); - private TerrainBrushEditor? tbeForm; + var exterior = AcreCoordinate.GetGridWithExterior(9, 8); + foreach (var acre in exterior) + CB_MapAcre.Items.Add(acre.Name); - public FieldItemEditor(MainSave sav) + CB_MapAcreSelect.DisplayMember = nameof(ComboItem.Text); + CB_MapAcreSelect.ValueMember = nameof(ComboItem.Value); + CB_MapAcreSelect.DataSource = ComboItemUtil.GetArray(typeof(OutsideAcre)); + + NUD_MapAcreTemplateOutside.Value = SAV.OutsideFieldTemplateUniqueId; + NUD_MapAcreTemplateField.Value = SAV.MainFieldParamUniqueID; + } + + private void LoadBuildings(MainSave sav) + { + NUD_PlazaX.Value = sav.EventPlazaLeftUpX; + NUD_PlazaY.Value = sav.EventPlazaLeftUpZ; + + foreach (var obj in Map.Buildings) + LB_Items.Items.Add(obj.ToString()); + } + + private void LoadEditors() + { + var data = GameInfo.Strings.ItemDataSource.ToList(); + var field = FieldItemList.Items.Select(z => z.Value).ToList(); + data.Add(field, GameInfo.Strings.InternalNameTranslation); + ItemEdit.Initialize(data, true); + PG_TerrainTile.SelectedObject = new TerrainTile(); + } + + private int AcreIndex => CB_Acre.SelectedIndex; + + private void ChangeAcre(object sender, EventArgs e) + { + ChangeViewToAcre(AcreIndex); + CB_MapAcre.Text = CB_Acre.Text; + } + + private void ChangeViewToAcre(int acre) + { + View.SetViewToAcre(acre); + LoadItemGridAcre(); + } + + private void LoadItemGridAcre() + { + ReloadItems(); + ReloadAcreBackground(); + UpdateArrowVisibility(); + } + + private int GetItemTransparency() => ((int)(0xFF * TR_Transparency.Value / 100d) << 24) | 0x00FF_FFFF; + + private void ReloadMapBackground() + { + PB_Map.BackgroundImage = View.GetBackgroundTerrain(SelectedBuildingIndex); + PB_Map.Invalidate(); // background image reassigning to same img doesn't redraw; force it + } + + private void ReloadAcreBackground() + { + var tbuild = (byte)TR_BuildingTransparency.Value; + var tterrain = (byte)TR_Terrain.Value; + PB_Acre.BackgroundImage = View.GetBackgroundAcre(L_Coordinates.Font, tbuild, tterrain, SelectedBuildingIndex); + PB_Acre.Invalidate(); // background image reassigning to same img doesn't redraw; force it + } + + private void ReloadMapItemGrid() => PB_Map.Image = View.GetMapWithReticle(GetItemTransparency()); + + private void ReloadAcreItemGrid() => PB_Acre.Image = View.GetLayerAcre(GetItemTransparency()); + + public void ReloadItems() + { + ReloadAcreItemGrid(); + ReloadMapItemGrid(); + } + + private void ReloadBuildingsTerrain() + { + ReloadAcreBackground(); + ReloadMapBackground(); + } + + private void UpdateArrowVisibility() + { + B_Up.Enabled = View.CanUp; + B_Down.Enabled = View.CanDown; + B_Left.Enabled = View.CanLeft; + B_Right.Enabled = View.CanRight; + } + + private void PB_Acre_MouseClick(object sender, MouseEventArgs e) + { + if (Dragging) { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - - var scale = (PB_Acre.Width - 2) / 32; - SAV = sav; - Map = new MapManager(sav); - View = new MapViewer(Map, scale); - - Loading = true; - - LoadComboBoxes(); - LoadBuildings(sav); - ReloadMapBackground(); - LoadEditors(); - LB_Items.SelectedIndex = 0; - CB_Acre.SelectedIndex = 0; - CB_MapAcre.SelectedIndex = 0; - Loading = false; - LoadItemGridAcre(); + ResetDrag(); + return; } - private void LoadComboBoxes() + if (RB_Item.Checked) + OmniTile(e); + else if (RB_Terrain.Checked) + OmniTileTerrain(e); + } + + private void ResetDrag() + { + DragX = -1; + DragY = -1; + Dragging = false; + } + + private void OmniTile(MouseEventArgs e) + { + var tile = GetTile(Map.CurrentLayer, e, out var x, out var y); + OmniTile(tile, x, y); + } + + private void OmniTileTerrain(MouseEventArgs e) + { + SetHoveredItem(e); + var x = View.X + HoverX; + var y = View.Y + HoverY; + var tile = Map.Terrain.GetTile(x / 2, y / 2); + if (tbeForm?.IsBrushSelected != true) { - foreach (var acre in MapGrid.Acres) - CB_Acre.Items.Add(acre.Name); - - var exterior = AcreCoordinate.GetGridWithExterior(9, 8); - foreach (var acre in exterior) - CB_MapAcre.Items.Add(acre.Name); - - CB_MapAcreSelect.DisplayMember = nameof(ComboItem.Text); - CB_MapAcreSelect.ValueMember = nameof(ComboItem.Value); - CB_MapAcreSelect.DataSource = ComboItemUtil.GetArray(typeof(OutsideAcre)); - - NUD_MapAcreTemplateOutside.Value = SAV.OutsideFieldTemplateUniqueId; - NUD_MapAcreTemplateField.Value = SAV.MainFieldParamUniqueID; + OmniTileTerrain(tile); + return; } - private void LoadBuildings(MainSave sav) + if (tbeForm.Slider_thickness.Value <= 1) { - NUD_PlazaX.Value = sav.EventPlazaLeftUpX; - NUD_PlazaY.Value = sav.EventPlazaLeftUpZ; - - foreach (var obj in Map.Buildings) - LB_Items.Items.Add(obj.ToString()); + SetTile(tile); + return; } - private void LoadEditors() + List selectedTiles = []; + int radius = tbeForm.Slider_thickness.Value; + int threshold = (radius * radius) / 2; + for (int i = -radius; i < radius; i++) { - var data = GameInfo.Strings.ItemDataSource.ToList(); - var field = FieldItemList.Items.Select(z => z.Value).ToList(); - data.Add(field, GameInfo.Strings.InternalNameTranslation); - ItemEdit.Initialize(data, true); - PG_TerrainTile.SelectedObject = new TerrainTile(); - } - - private int AcreIndex => CB_Acre.SelectedIndex; - - private void ChangeAcre(object sender, EventArgs e) - { - ChangeViewToAcre(AcreIndex); - CB_MapAcre.Text = CB_Acre.Text; - } - - private void ChangeViewToAcre(int acre) - { - View.SetViewToAcre(acre); - LoadItemGridAcre(); - } - - private void LoadItemGridAcre() - { - ReloadItems(); - ReloadAcreBackground(); - UpdateArrowVisibility(); - } - - private int GetItemTransparency() => ((int)(0xFF * TR_Transparency.Value / 100d) << 24) | 0x00FF_FFFF; - - private void ReloadMapBackground() - { - PB_Map.BackgroundImage = View.GetBackgroundTerrain(SelectedBuildingIndex); - PB_Map.Invalidate(); // background image reassigning to same img doesn't redraw; force it - } - - private void ReloadAcreBackground() - { - var tbuild = (byte)TR_BuildingTransparency.Value; - var tterrain = (byte)TR_Terrain.Value; - PB_Acre.BackgroundImage = View.GetBackgroundAcre(L_Coordinates.Font, tbuild, tterrain, SelectedBuildingIndex); - PB_Acre.Invalidate(); // background image reassigning to same img doesn't redraw; force it - } - - private void ReloadMapItemGrid() => PB_Map.Image = View.GetMapWithReticle(GetItemTransparency()); - - private void ReloadAcreItemGrid() => PB_Acre.Image = View.GetLayerAcre(GetItemTransparency()); - - public void ReloadItems() - { - ReloadAcreItemGrid(); - ReloadMapItemGrid(); - } - - private void ReloadBuildingsTerrain() - { - ReloadAcreBackground(); - ReloadMapBackground(); - } - - private void UpdateArrowVisibility() - { - B_Up.Enabled = View.CanUp; - B_Down.Enabled = View.CanDown; - B_Left.Enabled = View.CanLeft; - B_Right.Enabled = View.CanRight; - } - - private void PB_Acre_MouseClick(object sender, MouseEventArgs e) - { - if (Dragging) + for (int j = -radius; j < radius; j++) { - ResetDrag(); - return; + if ((i * i) + (j * j) < threshold) + selectedTiles.Add(Map.Terrain.GetTile((x / 2) + i, (y / 2) + j)); } - - if (RB_Item.Checked) - OmniTile(e); - else if (RB_Terrain.Checked) - OmniTileTerrain(e); } - private void ResetDrag() - { - DragX = -1; - DragY = -1; - Dragging = false; - } + SetTiles(selectedTiles); + } - private void OmniTile(MouseEventArgs e) + private void OmniTile(Item tile, int x, int y) + { + switch (ModifierKeys) { - var tile = GetTile(Map.CurrentLayer, e, out var x, out var y); - OmniTile(tile, x, y); - } - - private void OmniTileTerrain(MouseEventArgs e) - { - SetHoveredItem(e); - var x = View.X + HoverX; - var y = View.Y + HoverY; - var tile = Map.Terrain.GetTile(x / 2, y / 2); - if (tbeForm?.brushSelected != true) - { - OmniTileTerrain(tile); + default: + ViewTile(tile, x, y); return; - } - if (tbeForm.Slider_thickness.Value <= 1) - { + case Keys.Alt | Keys.Control: + case Keys.Alt | Keys.Control | Keys.Shift: + ReplaceTile(tile, x, y); + return; + + case Keys.Shift: + SetTile(tile, x, y); + return; + + case Keys.Alt: + DeleteTile(tile, x, y); + return; + } + } + + private void OmniTileTerrain(TerrainTile tile) + { + switch (ModifierKeys) + { + default: + ViewTile(tile); + return; + + case Keys.Shift | Keys.Control: + RotateTile(tile); + return; + + case Keys.Shift: SetTile(tile); return; - } - List selectedTiles = new(); - int radius = tbeForm.Slider_thickness.Value; - int threshold = (radius * radius) / 2; - for (int i = -radius; i < radius; i++) - { - for (int j = -radius; j < radius; j++) - { - if ((i * i) + (j * j) < threshold) - selectedTiles.Add(Map.Terrain.GetTile((x / 2) + i, (y / 2) + j)); - } - } - - SetTiles(selectedTiles); - } - - private void OmniTile(Item tile, int x, int y) - { - switch (ModifierKeys) - { - default: - ViewTile(tile, x, y); - return; - - case Keys.Alt | Keys.Control: - case Keys.Alt | Keys.Control | Keys.Shift: - ReplaceTile(tile, x, y); - return; - - case Keys.Shift: - SetTile(tile, x, y); - return; - - case Keys.Alt: - DeleteTile(tile, x, y); - return; - } - } - - private void OmniTileTerrain(TerrainTile tile) - { - switch (ModifierKeys) - { - default: - ViewTile(tile); - return; - - case Keys.Shift | Keys.Control: - RotateTile(tile); - return; - - case Keys.Shift: - SetTile(tile); - return; - - case Keys.Alt: - DeleteTile(tile); - return; - } - } - - private Item GetTile(FieldItemLayer layer, MouseEventArgs e, out int x, out int y) - { - SetHoveredItem(e); - return layer.GetTile(x = View.X + HoverX, y = View.Y + HoverY); - } - - private void SetHoveredItem(MouseEventArgs e) - { - GetAcreCoordinates(e, out HoverX, out HoverY); - - // Mouse event may fire with a slightly too large x/y; clamp just in case. - HoverX &= 0x1F; - HoverY &= 0x1F; - } - - private void GetAcreCoordinates(MouseEventArgs e, out int x, out int y) - { - x = e.X / View.AcreScale; - y = e.Y / View.AcreScale; - } - - private void PB_Acre_MouseDown(object sender, MouseEventArgs e) => ResetDrag(); - - private void PB_Acre_MouseMove(object sender, MouseEventArgs e) - { - var l = Map.CurrentLayer; - if (e.Button == MouseButtons.Left && CHK_MoveOnDrag.Checked) - { - MoveDrag(e); + case Keys.Alt: + DeleteTile(tile); return; - } - if (e.Button == MouseButtons.Left && tbeForm?.brushSelected == true) - { - OmniTileTerrain(e); - } + } + } - var oldTile = l.GetTile(View.X + HoverX, View.Y + HoverY); - var tile = GetTile(l, e, out var x, out var y); - if (ReferenceEquals(tile, oldTile)) - return; - var str = GameInfo.Strings; - var name = str.GetItemName(tile); - bool active = Map.Items.GetIsActive(NUD_Layer.Value == 0, x, y); - if (active) - name = $"{name} [Active]"; - TT_Hover.SetToolTip(PB_Acre, name); - SetCoordinateText(x, y); + private Item GetTile(FieldItemLayer layer, MouseEventArgs e, out int x, out int y) + { + SetHoveredItem(e); + return layer.GetTile(x = View.X + HoverX, y = View.Y + HoverY); + } + + private void SetHoveredItem(MouseEventArgs e) + { + GetAcreCoordinates(e, out HoverX, out HoverY); + + // Mouse event may fire with a slightly too large x/y; clamp just in case. + HoverX &= 0x1F; + HoverY &= 0x1F; + } + + private void GetAcreCoordinates(MouseEventArgs e, out int x, out int y) + { + x = e.X / View.AcreScale; + y = e.Y / View.AcreScale; + } + + private void PB_Acre_MouseDown(object sender, MouseEventArgs e) => ResetDrag(); + + private void PB_Acre_MouseMove(object sender, MouseEventArgs e) + { + var l = Map.CurrentLayer; + if (e.Button == MouseButtons.Left && CHK_MoveOnDrag.Checked) + { + MoveDrag(e); + return; + } + if (e.Button == MouseButtons.Left && tbeForm?.IsBrushSelected == true) + { + OmniTileTerrain(e); } - private void MoveDrag(MouseEventArgs e) + var oldTile = l.GetTile(View.X + HoverX, View.Y + HoverY); + var tile = GetTile(l, e, out var x, out var y); + if (ReferenceEquals(tile, oldTile)) + return; + var str = GameInfo.Strings; + var name = str.GetItemName(tile); + bool active = Map.Items.GetIsActive(NUD_Layer.Value == 0, x, y); + if (active) + name = $"{name} [Active]"; + TT_Hover.SetToolTip(PB_Acre, name); + SetCoordinateText(x, y); + } + + private void MoveDrag(MouseEventArgs e) + { + GetAcreCoordinates(e, out var nhX, out var nhY); + + if (DragX == -1) { - GetAcreCoordinates(e, out var nhX, out var nhY); - - if (DragX == -1) - { - DragX = nhX; - DragY = nhY; - return; - } - - var dX = DragX - nhX; - var dY = DragY - nhY; - - if (ModifierKeys == Keys.Control) - { - dX *= 2; - dY *= 2; - } - - if ((dX & 1) == 1) - dX ^= 1; - if ((dY & 1) == 1) - dY ^= 1; - - var aX = Math.Abs(dX); - var aY = Math.Abs(dY); - if (aX < 2 && aY < 2) - return; - DragX = nhX; DragY = nhY; - if (!View.SetViewTo(View.X + dX, View.Y + dY)) - return; - - Dragging = true; - LoadItemGridAcre(); + return; } - private void ViewTile(Item tile, int x, int y) + var dX = DragX - nhX; + var dY = DragY - nhY; + + if (ModifierKeys == Keys.Control) { - if (CHK_RedirectExtensionLoad.Checked && tile.IsExtension) - { - var l = Map.CurrentLayer; - var rx = Math.Max(0, Math.Min(l.MaxWidth - 1, x - tile.ExtensionX)); - var ry = Math.Max(0, Math.Min(l.MaxHeight - 1, y - tile.ExtensionY)); - var redir = l.GetTile(rx, ry); - if (redir.IsRoot && redir.ItemId == tile.ExtensionItemId) - tile = redir; - } - - ViewTile(tile); + dX *= 2; + dY *= 2; } - private void ViewTile(Item tile) - { - ItemEdit.LoadItem(tile); - TC_Editor.SelectedTab = Tab_Item; - } + if ((dX & 1) == 1) + dX ^= 1; + if ((dY & 1) == 1) + dY ^= 1; - private void ViewTile(TerrainTile tile) - { - var pgt = (TerrainTile)PG_TerrainTile.SelectedObject; - pgt.CopyFrom(tile); - PG_TerrainTile.SelectedObject = pgt; - TC_Editor.SelectedTab = Tab_Terrain; - } + var aX = Math.Abs(dX); + var aY = Math.Abs(dY); + if (aX < 2 && aY < 2) + return; - private void SetTile(Item tile, int x, int y) + DragX = nhX; + DragY = nhY; + if (!View.SetViewTo(View.X + dX, View.Y + dY)) + return; + + Dragging = true; + LoadItemGridAcre(); + } + + private void ViewTile(Item tile, int x, int y) + { + if (CHK_RedirectExtensionLoad.Checked && tile.IsExtension) { var l = Map.CurrentLayer; - var pgt = new Item(); - ItemEdit.SetItem(pgt); - - if (pgt.IsFieldItem && CHK_FieldItemSnap.Checked) - { - // coordinates must be even (not odd-half) - x &= 0xFFFE; - y &= 0xFFFE; - tile = l.GetTile(x, y); - } - - var permission = l.IsOccupied(pgt, x, y); - switch (permission) - { - case PlacedItemPermission.OutOfBounds: - case PlacedItemPermission.Collision when CHK_NoOverwrite.Checked: - System.Media.SystemSounds.Asterisk.Play(); - return; - } - - // Clean up original placed data - if (tile.IsRoot && CHK_AutoExtension.Checked) - l.DeleteExtensionTiles(tile, x, y); - - // Set new placed data - if (pgt.IsRoot && CHK_AutoExtension.Checked) - l.SetExtensionTiles(pgt, x, y); - tile.CopyFrom(pgt); - - ReloadItems(); + var rx = Math.Max(0, Math.Min(l.MaxWidth - 1, x - tile.ExtensionX)); + var ry = Math.Max(0, Math.Min(l.MaxHeight - 1, y - tile.ExtensionY)); + var redir = l.GetTile(rx, ry); + if (redir.IsRoot && redir.ItemId == tile.ExtensionItemId) + tile = redir; } - private void ReplaceTile(Item tile, int x, int y) + ViewTile(tile); + } + + private void ViewTile(Item tile) + { + ItemEdit.LoadItem(tile); + TC_Editor.SelectedTab = Tab_Item; + } + + private void ViewTile(TerrainTile tile) + { + var pgt = (TerrainTile)PG_TerrainTile.SelectedObject!; + pgt.CopyFrom(tile); + PG_TerrainTile.SelectedObject = pgt; + TC_Editor.SelectedTab = Tab_Terrain; + } + + private void SetTile(Item tile, int x, int y) + { + var l = Map.CurrentLayer; + var pgt = new Item(); + ItemEdit.SetItem(pgt); + + if (pgt.IsFieldItem && CHK_FieldItemSnap.Checked) { - var l = Map.CurrentLayer; - var pgt = new Item(); - ItemEdit.SetItem(pgt); - - if (pgt.IsFieldItem && CHK_FieldItemSnap.Checked) - { - // coordinates must be even (not odd-half) - x &= 0xFFFE; - y &= 0xFFFE; - tile = l.GetTile(x, y); - } - - var permission = l.IsOccupied(pgt, x, y); - switch (permission) - { - case PlacedItemPermission.OutOfBounds: - System.Media.SystemSounds.Asterisk.Play(); - return; - } - - bool wholeMap = (ModifierKeys & Keys.Shift) != 0; - var copy = new Item(tile.RawValue); - var count = View.ReplaceFieldItems(copy, pgt, wholeMap); - if (count == 0) - { - WinFormsUtil.Alert(MessageStrings.MsgFieldItemModifyNone); - return; - } - LoadItemGridAcre(); - WinFormsUtil.Alert(string.Format(MessageStrings.MsgFieldItemModifyCount, count)); + // coordinates must be even (not odd-half) + x &= 0xFFFE; + y &= 0xFFFE; + tile = l.GetTile(x, y); } - private void RotateTile(TerrainTile tile) + var permission = l.IsOccupied(pgt, x, y); + switch (permission) { - bool rotated = tile.Rotate(); - if (!rotated) - { + case PlacedItemPermission.OutOfBounds: + case PlacedItemPermission.Collision when CHK_NoOverwrite.Checked: System.Media.SystemSounds.Asterisk.Play(); return; - } - ReloadBuildingsTerrain(); } - private void SetTile(TerrainTile tile) - { - var pgt = (TerrainTile)PG_TerrainTile.SelectedObject; - if (tbeForm?.randomizeVariation == true) - { - switch (pgt.UnitModel) - { - case TerrainUnitModel.Cliff5B: - case TerrainUnitModel.River5B: - Random rand = new(); - pgt.Variation = (ushort)rand.Next(4); - break; - } - } + // Clean up original placed data + if (tile.IsRoot && CHK_AutoExtension.Checked) + l.DeleteExtensionTiles(tile, x, y); + // Set new placed data + if (pgt.IsRoot && CHK_AutoExtension.Checked) + l.SetExtensionTiles(pgt, x, y); + tile.CopyFrom(pgt); + + ReloadItems(); + } + + private void ReplaceTile(Item tile, int x, int y) + { + var l = Map.CurrentLayer; + var pgt = new Item(); + ItemEdit.SetItem(pgt); + + if (pgt.IsFieldItem && CHK_FieldItemSnap.Checked) + { + // coordinates must be even (not odd-half) + x &= 0xFFFE; + y &= 0xFFFE; + tile = l.GetTile(x, y); + } + + var permission = l.IsOccupied(pgt, x, y); + switch (permission) + { + case PlacedItemPermission.OutOfBounds: + System.Media.SystemSounds.Asterisk.Play(); + return; + } + + bool wholeMap = (ModifierKeys & Keys.Shift) != 0; + var copy = new Item(tile.RawValue); + var count = View.ReplaceFieldItems(copy, pgt, wholeMap); + if (count == 0) + { + WinFormsUtil.Alert(MessageStrings.MsgFieldItemModifyNone); + return; + } + LoadItemGridAcre(); + WinFormsUtil.Alert(string.Format(MessageStrings.MsgFieldItemModifyCount, count)); + } + + private void RotateTile(TerrainTile tile) + { + bool rotated = tile.Rotate(); + if (!rotated) + { + System.Media.SystemSounds.Asterisk.Play(); + return; + } + ReloadBuildingsTerrain(); + } + + private void SetTile(TerrainTile tile) + { + var pgt = (TerrainTile)PG_TerrainTile.SelectedObject!; + if (tbeForm?.RandomizeVariation == true) + { + switch (pgt.UnitModel) + { + case TerrainUnitModel.Cliff5B: + case TerrainUnitModel.River5B: + Random rand = new(); + pgt.Variation = (ushort)rand.Next(4); + break; + } + } + + tile.CopyFrom(pgt); + + ReloadBuildingsTerrain(); + } + + private void SetTiles(IEnumerable tiles) + { + var pgt = (TerrainTile)PG_TerrainTile.SelectedObject!; + foreach (TerrainTile tile in tiles) + { tile.CopyFrom(pgt); - - ReloadBuildingsTerrain(); } - private void SetTiles(IEnumerable tiles) + ReloadBuildingsTerrain(); + } + + private void DeleteTile(Item tile, int x, int y) + { + if (CHK_AutoExtension.Checked) { - var pgt = (TerrainTile)PG_TerrainTile.SelectedObject; - foreach (TerrainTile tile in tiles) + if (!tile.IsRoot) { - tile.CopyFrom(pgt); + x -= tile.ExtensionX; + y -= tile.ExtensionY; + tile = Map.CurrentLayer.GetTile(x, y); } - - ReloadBuildingsTerrain(); + Map.CurrentLayer.DeleteExtensionTiles(tile, x, y); } - private void DeleteTile(Item tile, int x, int y) + tile.Delete(); + ReloadItems(); + } + + private void DeleteTile(TerrainTile tile) + { + tile.Clear(); + ReloadBuildingsTerrain(); + } + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + var unsupported = Map.Items.GetUnsupportedTiles(); + if (unsupported.Count != 0) { - if (CHK_AutoExtension.Checked) + var err = MessageStrings.MsgFieldItemUnsupportedLayer2Tile; + var ask = MessageStrings.MsgAskContinue; + var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, err, ask); + if (prompt != DialogResult.Yes) + return; + } + + Map.Items.Save(); + SAV.SetTerrainTiles(Map.Terrain.Tiles); + + SAV.SetAcreBytes(Map.Terrain.BaseAcres); + SAV.OutsideFieldTemplateUniqueId = (ushort)NUD_MapAcreTemplateOutside.Value; + SAV.MainFieldParamUniqueID = (ushort)NUD_MapAcreTemplateField.Value; + + SAV.Buildings = Map.Buildings; + SAV.EventPlazaLeftUpX = Map.PlazaX; + SAV.EventPlazaLeftUpZ = Map.PlazaY; + Close(); + } + + private void Menu_View_Click(object sender, EventArgs e) + { + var x = View.X + HoverX; + var y = View.Y + HoverY; + + if (RB_Item.Checked) + { + var tile = Map.CurrentLayer.GetTile(x, y); + ViewTile(tile, x, y); + } + else if (RB_Terrain.Checked) + { + var tile = Map.Terrain.GetTile(x / 2, y / 2); + ViewTile(tile); + } + } + + private void Menu_Set_Click(object sender, EventArgs e) + { + var x = View.X + HoverX; + var y = View.Y + HoverY; + + if (RB_Item.Checked) + { + var tile = Map.CurrentLayer.GetTile(x, y); + SetTile(tile, x, y); + } + else if (RB_Terrain.Checked) + { + var tile = Map.Terrain.GetTile(x / 2, y / 2); + SetTile(tile); + } + } + + private void Menu_Reset_Click(object sender, EventArgs e) + { + var x = View.X + HoverX; + var y = View.Y + HoverY; + + if (RB_Item.Checked) + { + var tile = Map.CurrentLayer.GetTile(x, y); + DeleteTile(tile, x, y); + } + else if (RB_Terrain.Checked) + { + var tile = Map.Terrain.GetTile(x / 2, y / 2); + DeleteTile(tile); + } + } + + private bool hasActivate = true; + + private void CM_Click_Opening(object sender, System.ComponentModel.CancelEventArgs e) + { + if (!RB_Item.Checked) + { + if (hasActivate) + CM_Click.Items.Remove(Menu_Activate); + hasActivate = false; + return; + } + + var isBase = NUD_Layer.Value == 0; + var x = View.X + HoverX; + var y = View.Y + HoverY; + Menu_Activate.Text = Map.Items.GetIsActive(isBase, x, y) ? "Inactivate" : "Activate"; + CM_Click.Items.Add(Menu_Activate); + hasActivate = true; + } + + private void Menu_Activate_Click(object sender, EventArgs e) + { + var x = View.X + HoverX; + var y = View.Y + HoverY; + var isBase = NUD_Layer.Value == 0; + Map.Items.SetIsActive(isBase, x, y, !Map.Items.GetIsActive(isBase, x, y)); + } + + private void B_Up_Click(object sender, EventArgs e) + { + if (ModifierKeys == Keys.Shift) + CB_Acre.SelectedIndex = Math.Max(0, CB_Acre.SelectedIndex - MapGrid.AcreWidth); + else if (View.ArrowUp()) + LoadItemGridAcre(); + } + + private void B_Left_Click(object sender, EventArgs e) + { + if (ModifierKeys == Keys.Shift) + CB_Acre.SelectedIndex = Math.Max(0, CB_Acre.SelectedIndex - 1); + else if (View.ArrowLeft()) + LoadItemGridAcre(); + } + + private void B_Right_Click(object sender, EventArgs e) + { + if (ModifierKeys == Keys.Shift) + CB_Acre.SelectedIndex = Math.Min(CB_Acre.SelectedIndex + 1, CB_Acre.Items.Count - 1); + else if (View.ArrowRight()) + LoadItemGridAcre(); + } + + private void B_Down_Click(object sender, EventArgs e) + { + if (ModifierKeys == Keys.Shift) + CB_Acre.SelectedIndex = Math.Min(CB_Acre.SelectedIndex + MapGrid.AcreWidth, CB_Acre.Items.Count - 1); + else if (View.ArrowDown()) + LoadItemGridAcre(); + } + + private void B_DumpAcre_Click(object sender, EventArgs e) => MapDumpHelper.DumpLayerAcreSingle(Map.CurrentLayer, AcreIndex, CB_Acre.Text, (int)NUD_Layer.Value); + + private void B_DumpAllAcres_Click(object sender, EventArgs e) => MapDumpHelper.DumpLayerAcreAll(Map.CurrentLayer); + + private void B_ImportAcre_Click(object sender, EventArgs e) + { + var layer = Map.CurrentLayer; + if (!MapDumpHelper.ImportToLayerAcreSingle(layer, AcreIndex, CB_Acre.Text, (int)NUD_Layer.Value)) + return; + ChangeViewToAcre(AcreIndex); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ImportAllAcres_Click(object sender, EventArgs e) + { + if (!MapDumpHelper.ImportToLayerAcreAll(Map.CurrentLayer)) + return; + ChangeViewToAcre(AcreIndex); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpBuildings_Click(object sender, EventArgs e) => MapDumpHelper.DumpBuildings(Map.Buildings); + + private void B_ImportBuildings_Click(object sender, EventArgs e) + { + if (!MapDumpHelper.ImportBuildings(Map.Buildings)) + return; + + for (int i = 0; i < Map.Buildings.Count; i++) + LB_Items.Items[i] = Map.Buildings[i].ToString(); + LB_Items.SelectedIndex = 0; + System.Media.SystemSounds.Asterisk.Play(); + ReloadBuildingsTerrain(); + } + + private void B_DumpTerrainAcre_Click(object sender, EventArgs e) => MapDumpHelper.DumpTerrainAcre(Map.Terrain, AcreIndex, CB_Acre.Text); + + private void B_DumpTerrainAll_Click(object sender, EventArgs e) => MapDumpHelper.DumpTerrainAll(Map.Terrain); + + private void B_ImportTerrainAcre_Click(object sender, EventArgs e) + { + if (!MapDumpHelper.ImportTerrainAcre(Map.Terrain, AcreIndex, CB_Acre.Text)) + return; + ChangeViewToAcre(AcreIndex); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ImportTerrainAll_Click(object sender, EventArgs e) + { + if (!MapDumpHelper.ImportTerrainAll(Map.Terrain)) + return; + ChangeViewToAcre(AcreIndex); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void Menu_SavePNG_Click(object sender, EventArgs e) + { + if (!WinFormsUtil.TryGetUnderlying(sender, out var pb) || pb.Image is null) + { + WinFormsUtil.Alert(MessageStrings.MsgNoPictureLoaded); + return; + } + + CM_Picture.Close(ToolStripDropDownCloseReason.CloseCalled); + + const string name = "map"; + using var sfd = new SaveFileDialog(); + sfd.Filter = "png file (*.png)|*.png|All files (*.*)|*.*"; + sfd.FileName = $"{name}.png"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + if (!Menu_SavePNGTerrain.Checked) + { + PB_Map.Image!.Save(sfd.FileName, ImageFormat.Png); + } + else if (!Menu_SavePNGItems.Checked) + { + PB_Map.BackgroundImage!.Save(sfd.FileName, ImageFormat.Png); + } + else + { + var img = (Bitmap)PB_Map.BackgroundImage!.Clone(); + using var gfx = Graphics.FromImage(img); + gfx.DrawImage(PB_Map.Image!, new Point(0, 0)); + img.Save(sfd.FileName, ImageFormat.Png); + } + } + + private void CM_Picture_Closing(object sender, ToolStripDropDownClosingEventArgs e) + { + if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked && sender != Menu_SavePNG) + e.Cancel = true; + } + + private void PB_Map_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button != MouseButtons.Left) + return; + ClickMapAt(e, true); + } + + private void ClickMapAt(MouseEventArgs e, bool skipLagCheck) + { + var layer = Map.Items.Layer1; + int mX = e.X; + int mY = e.Y; + bool centerReticle = CHK_SnapToAcre.Checked; + View.GetViewAnchorCoordinates(mX, mY, out var x, out var y, centerReticle); + x &= 0xFFFE; + y &= 0xFFFE; + + var acre = layer.GetAcre(x, y); + bool sameAcre = AcreIndex == acre; + if (!skipLagCheck) + { + if (CHK_SnapToAcre.Checked) { - if (!tile.IsRoot) - { - x -= tile.ExtensionX; - y -= tile.ExtensionY; - tile = Map.CurrentLayer.GetTile(x, y); - } - Map.CurrentLayer.DeleteExtensionTiles(tile, x, y); - } - - tile.Delete(); - ReloadItems(); - } - - private void DeleteTile(TerrainTile tile) - { - tile.Clear(); - ReloadBuildingsTerrain(); - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - var unsupported = Map.Items.GetUnsupportedTiles(); - if (unsupported.Count != 0) - { - var err = MessageStrings.MsgFieldItemUnsupportedLayer2Tile; - var ask = MessageStrings.MsgAskContinue; - var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, err, ask); - if (prompt != DialogResult.Yes) + if (sameAcre) return; } - - Map.Items.Save(); - SAV.SetTerrainTiles(Map.Terrain.Tiles); - - SAV.SetAcreBytes(Map.Terrain.BaseAcres); - SAV.OutsideFieldTemplateUniqueId = (ushort)NUD_MapAcreTemplateOutside.Value; - SAV.MainFieldParamUniqueID = (ushort)NUD_MapAcreTemplateField.Value; - - SAV.Buildings = Map.Buildings; - SAV.EventPlazaLeftUpX = Map.PlazaX; - SAV.EventPlazaLeftUpZ = Map.PlazaY; - Close(); - } - - private void Menu_View_Click(object sender, EventArgs e) - { - var x = View.X + HoverX; - var y = View.Y + HoverY; - - if (RB_Item.Checked) - { - var tile = Map.CurrentLayer.GetTile(x, y); - ViewTile(tile, x, y); - } - else if (RB_Terrain.Checked) - { - var tile = Map.Terrain.GetTile(x / 2, y / 2); - ViewTile(tile); - } - } - - private void Menu_Set_Click(object sender, EventArgs e) - { - var x = View.X + HoverX; - var y = View.Y + HoverY; - - if (RB_Item.Checked) - { - var tile = Map.CurrentLayer.GetTile(x, y); - SetTile(tile, x, y); - } - else if (RB_Terrain.Checked) - { - var tile = Map.Terrain.GetTile(x / 2, y / 2); - SetTile(tile); - } - } - - private void Menu_Reset_Click(object sender, EventArgs e) - { - var x = View.X + HoverX; - var y = View.Y + HoverY; - - if (RB_Item.Checked) - { - var tile = Map.CurrentLayer.GetTile(x, y); - DeleteTile(tile, x, y); - } - else if (RB_Terrain.Checked) - { - var tile = Map.Terrain.GetTile(x / 2, y / 2); - DeleteTile(tile); - } - } - - private bool hasActivate = true; - - private void CM_Click_Opening(object sender, System.ComponentModel.CancelEventArgs e) - { - if (!RB_Item.Checked) - { - if (hasActivate) - CM_Click.Items.Remove(Menu_Activate); - hasActivate = false; - return; - } - - var isBase = NUD_Layer.Value == 0; - var x = View.X + HoverX; - var y = View.Y + HoverY; - Menu_Activate.Text = Map.Items.GetIsActive(isBase, x, y) ? "Inactivate" : "Activate"; - CM_Click.Items.Add(Menu_Activate); - hasActivate = true; - } - - private void Menu_Activate_Click(object sender, EventArgs e) - { - var x = View.X + HoverX; - var y = View.Y + HoverY; - var isBase = NUD_Layer.Value == 0; - Map.Items.SetIsActive(isBase, x, y, !Map.Items.GetIsActive(isBase, x, y)); - } - - private void B_Up_Click(object sender, EventArgs e) - { - if (ModifierKeys == Keys.Shift) - CB_Acre.SelectedIndex = Math.Max(0, CB_Acre.SelectedIndex - MapGrid.AcreWidth); - else if (View.ArrowUp()) - LoadItemGridAcre(); - } - - private void B_Left_Click(object sender, EventArgs e) - { - if (ModifierKeys == Keys.Shift) - CB_Acre.SelectedIndex = Math.Max(0, CB_Acre.SelectedIndex - 1); - else if (View.ArrowLeft()) - LoadItemGridAcre(); - } - - private void B_Right_Click(object sender, EventArgs e) - { - if (ModifierKeys == Keys.Shift) - CB_Acre.SelectedIndex = Math.Min(CB_Acre.SelectedIndex + 1, CB_Acre.Items.Count - 1); - else if (View.ArrowRight()) - LoadItemGridAcre(); - } - - private void B_Down_Click(object sender, EventArgs e) - { - if (ModifierKeys == Keys.Shift) - CB_Acre.SelectedIndex = Math.Min(CB_Acre.SelectedIndex + MapGrid.AcreWidth, CB_Acre.Items.Count - 1); - else if (View.ArrowDown()) - LoadItemGridAcre(); - } - - private void B_DumpAcre_Click(object sender, EventArgs e) => MapDumpHelper.DumpLayerAcreSingle(Map.CurrentLayer, AcreIndex, CB_Acre.Text, (int)NUD_Layer.Value); - - private void B_DumpAllAcres_Click(object sender, EventArgs e) => MapDumpHelper.DumpLayerAcreAll(Map.CurrentLayer); - - private void B_ImportAcre_Click(object sender, EventArgs e) - { - var layer = Map.CurrentLayer; - if (!MapDumpHelper.ImportToLayerAcreSingle(layer, AcreIndex, CB_Acre.Text, (int)NUD_Layer.Value)) - return; - ChangeViewToAcre(AcreIndex); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ImportAllAcres_Click(object sender, EventArgs e) - { - if (!MapDumpHelper.ImportToLayerAcreAll(Map.CurrentLayer)) - return; - ChangeViewToAcre(AcreIndex); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_DumpBuildings_Click(object sender, EventArgs e) => MapDumpHelper.DumpBuildings(Map.Buildings); - - private void B_ImportBuildings_Click(object sender, EventArgs e) - { - if (!MapDumpHelper.ImportBuildings(Map.Buildings)) - return; - - for (int i = 0; i < Map.Buildings.Count; i++) - LB_Items.Items[i] = Map.Buildings[i].ToString(); - LB_Items.SelectedIndex = 0; - System.Media.SystemSounds.Asterisk.Play(); - ReloadBuildingsTerrain(); - } - - private void B_DumpTerrainAcre_Click(object sender, EventArgs e) => MapDumpHelper.DumpTerrainAcre(Map.Terrain, AcreIndex, CB_Acre.Text); - - private void B_DumpTerrainAll_Click(object sender, EventArgs e) => MapDumpHelper.DumpTerrainAll(Map.Terrain); - - private void B_ImportTerrainAcre_Click(object sender, EventArgs e) - { - if (!MapDumpHelper.ImportTerrainAcre(Map.Terrain, AcreIndex, CB_Acre.Text)) - return; - ChangeViewToAcre(AcreIndex); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ImportTerrainAll_Click(object sender, EventArgs e) - { - if (!MapDumpHelper.ImportTerrainAll(Map.Terrain)) - return; - ChangeViewToAcre(AcreIndex); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void Menu_SavePNG_Click(object sender, EventArgs e) - { - var pb = WinFormsUtil.GetUnderlyingControl(sender); - if (pb?.Image == null) - { - WinFormsUtil.Alert(MessageStrings.MsgNoPictureLoaded); - return; - } - - CM_Picture.Close(ToolStripDropDownCloseReason.CloseCalled); - - const string name = "map"; - using var sfd = new SaveFileDialog - { - Filter = "png file (*.png)|*.png|All files (*.*)|*.*", - FileName = $"{name}.png", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - if (!Menu_SavePNGTerrain.Checked) - { - PB_Map.Image.Save(sfd.FileName, ImageFormat.Png); - } - else if (!Menu_SavePNGItems.Checked) - { - PB_Map.BackgroundImage!.Save(sfd.FileName, ImageFormat.Png); - } else { - var img = (Bitmap)PB_Map.BackgroundImage!.Clone(); - using var gfx = Graphics.FromImage(img); - gfx.DrawImage(PB_Map.Image, new Point(0, 0)); - img.Save(sfd.FileName, ImageFormat.Png); + const int delta = 0; // disabled = 0 + var dx = Math.Abs(View.X - x); + var dy = Math.Abs(View.Y - y); + if (dx <= delta && dy <= delta && !sameAcre) + return; } } - private void CM_Picture_Closing(object sender, ToolStripDropDownClosingEventArgs e) + if (!CHK_SnapToAcre.Checked) { - if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked && sender != Menu_SavePNG) - e.Cancel = true; + if (View.SetViewTo(x, y)) + LoadItemGridAcre(); + return; } - private void PB_Map_MouseDown(object sender, MouseEventArgs e) - { - if (e.Button != MouseButtons.Left) - return; - ClickMapAt(e, true); - } - - private void ClickMapAt(MouseEventArgs e, bool skipLagCheck) - { - var layer = Map.Items.Layer1; - int mX = e.X; - int mY = e.Y; - bool centerReticle = CHK_SnapToAcre.Checked; - View.GetViewAnchorCoordinates(mX, mY, out var x, out var y, centerReticle); - x &= 0xFFFE; - y &= 0xFFFE; - - var acre = layer.GetAcre(x, y); - bool sameAcre = AcreIndex == acre; - if (!skipLagCheck) - { - if (CHK_SnapToAcre.Checked) - { - if (sameAcre) - return; - } - else - { - const int delta = 0; // disabled = 0 - var dx = Math.Abs(View.X - x); - var dy = Math.Abs(View.Y - y); - if (dx <= delta && dy <= delta && !sameAcre) - return; - } - } - - if (!CHK_SnapToAcre.Checked) - { - if (View.SetViewTo(x, y)) - LoadItemGridAcre(); - return; - } - - if (!sameAcre) - CB_Acre.SelectedIndex = acre; - } - - private void PB_Map_MouseMove(object sender, MouseEventArgs e) - { - if (e.Button == MouseButtons.Left) - { - ClickMapAt(e, false); - } - else if (e.Button == MouseButtons.None) - { - View.GetCursorCoordinates(e.X, e.Y, out var x, out var y); - SetCoordinateText(x, y); - } - } - - private void SetCoordinateText(int x, int y) => L_Coordinates.Text = $"({x:000},{y:000}) = (0x{x:X2},0x{y:X2})"; - - private void NUD_Layer_ValueChanged(object sender, EventArgs e) - { - Map.MapLayer = (int)NUD_Layer.Value - 1; - LoadItemGridAcre(); - } - - private void Remove(ToolStripItem sender, Func removal) - { - bool wholeMap = (ModifierKeys & Keys.Shift) != 0; - - string q = string.Format(MessageStrings.MsgFieldItemRemoveAsk, sender.Text); - var question = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, q); - if (question != DialogResult.Yes) - return; - - int count = View.ModifyFieldItems(removal, wholeMap); - - if (count == 0) - { - WinFormsUtil.Alert(MessageStrings.MsgFieldItemRemoveNone); - return; - } - LoadItemGridAcre(); - WinFormsUtil.Alert(string.Format(MessageStrings.MsgFieldItemRemoveCount, count)); - } - - private void Modify(ToolStripItem sender, Func action) - { - bool wholeMap = (ModifierKeys & Keys.Shift) != 0; - - string q = string.Format(MessageStrings.MsgFieldItemModifyAsk, sender.Text); - var question = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, q); - if (question != DialogResult.Yes) - return; - - int count = View.ModifyFieldItems(action, wholeMap); - - if (count == 0) - { - WinFormsUtil.Alert(MessageStrings.MsgFieldItemModifyNone); - return; - } - LoadItemGridAcre(); - WinFormsUtil.Alert(string.Format(MessageStrings.MsgFieldItemModifyCount, count)); - } - - private void B_RemoveEditor_Click(object sender, EventArgs e) => Remove(B_RemoveEditor, (min, max, x, y) - => Map.CurrentLayer.RemoveAllLike(min, max, x, y, ItemEdit.SetItem(new Item()))); - - private void B_RemoveAllWeeds_Click(object sender, EventArgs e) => Remove(B_RemoveAllWeeds, Map.CurrentLayer.RemoveAllWeeds); - - private void B_RemoveAllTrees_Click(object sender, EventArgs e) => Remove(B_RemoveAllTrees, Map.CurrentLayer.RemoveAllTrees); - - private void B_FillHoles_Click(object sender, EventArgs e) => Remove(B_FillHoles, Map.CurrentLayer.RemoveAllHoles); - - private void B_RemovePlants_Click(object sender, EventArgs e) => Remove(B_RemovePlants, Map.CurrentLayer.RemoveAllPlants); - - private void B_RemoveFences_Click(object sender, EventArgs e) => Remove(B_RemoveFences, Map.CurrentLayer.RemoveAllFences); - - private void B_RemoveObjects_Click(object sender, EventArgs e) => Remove(B_RemoveObjects, Map.CurrentLayer.RemoveAllObjects); - - private void B_RemoveAll_Click(object sender, EventArgs e) => Remove(B_RemoveAll, Map.CurrentLayer.RemoveAll); - - private void B_RemovePlacedItems_Click(object sender, EventArgs e) => Remove(B_RemovePlacedItems, Map.CurrentLayer.RemoveAllPlacedItems); - - private void B_RemoveShells_Click(object sender, EventArgs e) => Remove(B_RemoveShells, Map.CurrentLayer.RemoveAllShells); - - private void B_RemoveBranches_Click(object sender, EventArgs e) => Remove(B_RemoveBranches, Map.CurrentLayer.RemoveAllBranches); - - private void B_RemoveFlowers_Click(object sender, EventArgs e) => Remove(B_RemoveFlowers, Map.CurrentLayer.RemoveAllFlowers); - - private void B_RemoveBushes_Click(object sender, EventArgs e) => Remove(B_RemoveBushes, Map.CurrentLayer.RemoveAllBushes); - - private void B_WaterFlowers_Click(object sender, EventArgs e) => Modify(B_WaterFlowers, (xmin, ymin, width, height) - => Map.CurrentLayer.WaterAllFlowers(xmin, ymin, width, height, (ModifierKeys & Keys.Control) != 0)); - - private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); - - private void B_RemoveItemDropDown_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Remove, B_RemoveItemDropDown); - - private void B_DumpLoadField_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLField, B_DumpLoadField); - - private void B_DumpLoadTerrain_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLTerrain, B_DumpLoadTerrain); - - private void B_DumpLoadBuildings_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLBuilding, B_DumpLoadBuildings); - - private void B_ModifyAllTerrain_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Terrain, B_ModifyAllTerrain); - - private void B_DumpLoadAcres_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLMapAcres, B_DumpLoadAcres); - - private void TR_Transparency_Scroll(object sender, EventArgs e) => ReloadItems(); - - private void TR_BuildingTransparency_Scroll(object sender, EventArgs e) => ReloadBuildingsTerrain(); - - private void TR_Terrain_Scroll(object sender, EventArgs e) => ReloadBuildingsTerrain(); - - #region Buildings - - private void B_Help_Click(object sender, EventArgs e) - { - using var form = new BuildingHelp(); - form.ShowDialog(); - } - - private void NUD_PlazaX_ValueChanged(object sender, EventArgs e) - { - if (Loading) - return; - Map.PlazaX = (uint)NUD_PlazaX.Value; - ReloadBuildingsTerrain(); - } - - private void NUD_PlazaY_ValueChanged(object sender, EventArgs e) - { - if (Loading) - return; - Map.PlazaY = (uint)NUD_PlazaY.Value; - ReloadBuildingsTerrain(); - } - - private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Items.SelectedIndex < 0) - return; - LoadIndex(LB_Items.SelectedIndex); - - // View location snap has changed the view. Reload everything - LoadItemGridAcre(); - ReloadMapBackground(); - } - - private void LoadIndex(int index) - { - Loading = true; - SelectedBuildingIndex = index; - var b = Map.Buildings[index]; - NUD_BuildingType.Value = (int)b.BuildingType; - NUD_X.Value = b.X; - NUD_Y.Value = b.Y; - NUD_Angle.Value = b.Angle; - NUD_Bit.Value = b.Bit; - NUD_Type.Value = b.Type; - NUD_TypeArg.Value = b.TypeArg; - NUD_UniqueID.Value = b.UniqueID; - Loading = false; - - // -32 for relative offset on map (buildings can be placed on the exterior ocean acres) - // -16 to put it in the center of the view - const int shift = 48; - var x = (b.X - shift) & 0xFFFE; - var y = (b.Y - shift) & 0xFFFE; - View.SetViewTo(x, y); - } - - private void NUD_BuildingType_ValueChanged(object sender, EventArgs e) - { - if (Loading || sender is not NumericUpDown n) - return; - - var b = Map.Buildings[SelectedBuildingIndex]; - if (sender == NUD_BuildingType) - b.BuildingType = (BuildingType)n.Value; - else if (sender == NUD_X) - b.X = (ushort)n.Value; - else if (sender == NUD_Y) - b.Y = (ushort)n.Value; - else if (sender == NUD_Angle) - b.Angle = (byte)n.Value; - else if (sender == NUD_Bit) - b.Bit = (sbyte)n.Value; - else if (sender == NUD_Type) - b.Type = (ushort)n.Value; - else if (sender == NUD_TypeArg) - b.TypeArg = (byte)n.Value; - else if (sender == NUD_UniqueID) - b.UniqueID = (ushort)n.Value; - - LB_Items.Items[SelectedBuildingIndex] = Map.Buildings[SelectedBuildingIndex].ToString(); - ReloadBuildingsTerrain(); - } - - #endregion Buildings - - #region Acres - - private void CB_MapAcre_SelectedIndexChanged(object sender, EventArgs e) - { - var acre = Map.Terrain.BaseAcres[CB_MapAcre.SelectedIndex * 2]; - CB_MapAcreSelect.SelectedValue = (int)acre; - - // Jump view if available - if (CB_Acre.Items.OfType().Any(z => z == CB_MapAcre.Text)) - CB_Acre.Text = CB_MapAcre.Text; - } - - private void CB_MapAcreSelect_SelectedValueChanged(object sender, EventArgs e) - { - if (Loading) - return; - - var index = CB_MapAcre.SelectedIndex; - var value = WinFormsUtil.GetIndex(CB_MapAcreSelect); - - var oldValue = Map.Terrain.BaseAcres[index * 2]; - if (value == oldValue) - return; - byte[] ValueBytes = BitConverter.GetBytes(value); - var a = index * 2; - Map.Terrain.BaseAcres[a] = ValueBytes[0]; - Map.Terrain.BaseAcres[a + 1] = ValueBytes[1]; - ReloadBuildingsTerrain(); - } - - private void B_DumpMapAcres_Click(object sender, EventArgs e) - { - if (!MapDumpHelper.DumpMapAcresAll(Map.Terrain.BaseAcres)) - return; - ReloadBuildingsTerrain(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ImportMapAcres_Click(object sender, EventArgs e) - { - if (!MapDumpHelper.ImportMapAcresAll(Map.Terrain.BaseAcres)) - return; - ReloadBuildingsTerrain(); - System.Media.SystemSounds.Asterisk.Play(); - } - - #endregion Acres - - private void B_ZeroElevation_Click(object sender, EventArgs e) - { - if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetElevation0)) - return; - foreach (var t in Map.Terrain.Tiles) - t.Elevation = 0; - ReloadBuildingsTerrain(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_SetAllTerrain_Click(object sender, EventArgs e) - { - if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetAll)) - return; - - var pgt = (TerrainTile)PG_TerrainTile.SelectedObject; - bool interiorOnly = DialogResult.Yes == WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetAllSkipExterior); - Map.Terrain.SetAll(pgt, interiorOnly); - - ReloadBuildingsTerrain(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_SetAllRoadTiles_Click(object sender, EventArgs e) - { - if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetAll)) - return; - - var pgt = (TerrainTile)PG_TerrainTile.SelectedObject; - bool interiorOnly = DialogResult.Yes == WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetAllSkipExterior); - Map.Terrain.SetAllRoad(pgt, interiorOnly); - - ReloadBuildingsTerrain(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ClearPlacedDesigns_Click(object sender, EventArgs e) - { - MapManager.ClearDesignTiles(SAV); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ExportPlacedDesigns_Click(object sender, EventArgs e) - { - using var sfd = new SaveFileDialog - { - Filter = "nhmd file (*.nhmd)|*.nhmd", - FileName = "Island MyDesignMap.nhmd", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - string path = sfd.FileName; - var tiles = MapManager.ExportDesignTiles(SAV); - File.WriteAllBytes(path, tiles); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ImportPlacedDesigns_Click(object sender, EventArgs e) - { - using var ofd = new OpenFileDialog - { - Filter = "nhmd file (*.nhmd)|*.nhmd", - FileName = "Island MyDesignMap.nhmd", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return; - - string path = ofd.FileName; - var tiles = File.ReadAllBytes(path); - MapManager.ImportDesignTiles(SAV, tiles); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void Menu_Spawn_Click(object sender, EventArgs e) => new BulkSpawn(this, View.X, View.Y).ShowDialog(); - - private void Menu_Bulk_Click(object sender, EventArgs e) - { - var editor = new BatchEditor(SpawnLayer.Tiles, ItemEdit.SetItem(new Item())); - editor.ShowDialog(); - SpawnLayer.ClearDanglingExtensions(0, 0, SpawnLayer.MaxWidth, SpawnLayer.MaxHeight); - LoadItemGridAcre(); - } - - private void B_TerrainBrush_Click(object sender, EventArgs e) - { - tbeForm = new TerrainBrushEditor(PG_TerrainTile, this); - tbeForm.Show(); - } - - private void FieldItemEditor_FormClosed(object sender, FormClosedEventArgs e) - { - tbeForm?.Close(); - } + if (!sameAcre) + CB_Acre.SelectedIndex = acre; } - public interface IItemLayerEditor + private void PB_Map_MouseMove(object sender, MouseEventArgs e) { - void ReloadItems(); - - ItemEditor ItemProvider { get; } - ItemLayer SpawnLayer { get; } + if (e.Button == MouseButtons.Left) + { + ClickMapAt(e, false); + } + else if (e.Button == MouseButtons.None) + { + View.GetCursorCoordinates(e.X, e.Y, out var x, out var y); + SetCoordinateText(x, y); + } } + + private void SetCoordinateText(int x, int y) => L_Coordinates.Text = $"({x:000},{y:000}) = (0x{x:X2},0x{y:X2})"; + + private void NUD_Layer_ValueChanged(object sender, EventArgs e) + { + Map.MapLayer = (int)NUD_Layer.Value - 1; + LoadItemGridAcre(); + } + + private void Remove(ToolStripItem sender, Func removal) + { + bool wholeMap = (ModifierKeys & Keys.Shift) != 0; + + string q = string.Format(MessageStrings.MsgFieldItemRemoveAsk, sender.Text); + var question = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, q); + if (question != DialogResult.Yes) + return; + + int count = View.ModifyFieldItems(removal, wholeMap); + + if (count == 0) + { + WinFormsUtil.Alert(MessageStrings.MsgFieldItemRemoveNone); + return; + } + LoadItemGridAcre(); + WinFormsUtil.Alert(string.Format(MessageStrings.MsgFieldItemRemoveCount, count)); + } + + private void Modify(ToolStripItem sender, Func action) + { + bool wholeMap = (ModifierKeys & Keys.Shift) != 0; + + string q = string.Format(MessageStrings.MsgFieldItemModifyAsk, sender.Text); + var question = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, q); + if (question != DialogResult.Yes) + return; + + int count = View.ModifyFieldItems(action, wholeMap); + + if (count == 0) + { + WinFormsUtil.Alert(MessageStrings.MsgFieldItemModifyNone); + return; + } + LoadItemGridAcre(); + WinFormsUtil.Alert(string.Format(MessageStrings.MsgFieldItemModifyCount, count)); + } + + private void B_RemoveEditor_Click(object sender, EventArgs e) => Remove(B_RemoveEditor, (min, max, x, y) + => Map.CurrentLayer.RemoveAllLike(min, max, x, y, ItemEdit.SetItem(new Item()))); + + private void B_RemoveAllWeeds_Click(object sender, EventArgs e) => Remove(B_RemoveAllWeeds, Map.CurrentLayer.RemoveAllWeeds); + + private void B_RemoveAllTrees_Click(object sender, EventArgs e) => Remove(B_RemoveAllTrees, Map.CurrentLayer.RemoveAllTrees); + + private void B_FillHoles_Click(object sender, EventArgs e) => Remove(B_FillHoles, Map.CurrentLayer.RemoveAllHoles); + + private void B_RemovePlants_Click(object sender, EventArgs e) => Remove(B_RemovePlants, Map.CurrentLayer.RemoveAllPlants); + + private void B_RemoveFences_Click(object sender, EventArgs e) => Remove(B_RemoveFences, Map.CurrentLayer.RemoveAllFences); + + private void B_RemoveObjects_Click(object sender, EventArgs e) => Remove(B_RemoveObjects, Map.CurrentLayer.RemoveAllObjects); + + private void B_RemoveAll_Click(object sender, EventArgs e) => Remove(B_RemoveAll, Map.CurrentLayer.RemoveAll); + + private void B_RemovePlacedItems_Click(object sender, EventArgs e) => Remove(B_RemovePlacedItems, Map.CurrentLayer.RemoveAllPlacedItems); + + private void B_RemoveShells_Click(object sender, EventArgs e) => Remove(B_RemoveShells, Map.CurrentLayer.RemoveAllShells); + + private void B_RemoveBranches_Click(object sender, EventArgs e) => Remove(B_RemoveBranches, Map.CurrentLayer.RemoveAllBranches); + + private void B_RemoveFlowers_Click(object sender, EventArgs e) => Remove(B_RemoveFlowers, Map.CurrentLayer.RemoveAllFlowers); + + private void B_RemoveBushes_Click(object sender, EventArgs e) => Remove(B_RemoveBushes, Map.CurrentLayer.RemoveAllBushes); + + private void B_WaterFlowers_Click(object sender, EventArgs e) => Modify(B_WaterFlowers, (xmin, ymin, width, height) + => Map.CurrentLayer.WaterAllFlowers(xmin, ymin, width, height, (ModifierKeys & Keys.Control) != 0)); + + private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); + + private void B_RemoveItemDropDown_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Remove, B_RemoveItemDropDown); + + private void B_DumpLoadField_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLField, B_DumpLoadField); + + private void B_DumpLoadTerrain_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLTerrain, B_DumpLoadTerrain); + + private void B_DumpLoadBuildings_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLBuilding, B_DumpLoadBuildings); + + private void B_ModifyAllTerrain_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Terrain, B_ModifyAllTerrain); + + private void B_DumpLoadAcres_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLMapAcres, B_DumpLoadAcres); + + private void TR_Transparency_Scroll(object sender, EventArgs e) => ReloadItems(); + + private void TR_BuildingTransparency_Scroll(object sender, EventArgs e) => ReloadBuildingsTerrain(); + + private void TR_Terrain_Scroll(object sender, EventArgs e) => ReloadBuildingsTerrain(); + + #region Buildings + + private void B_Help_Click(object sender, EventArgs e) + { + using var form = new BuildingHelp(); + form.ShowDialog(); + } + + private void NUD_PlazaX_ValueChanged(object sender, EventArgs e) + { + if (Loading) + return; + Map.PlazaX = (uint)NUD_PlazaX.Value; + ReloadBuildingsTerrain(); + } + + private void NUD_PlazaY_ValueChanged(object sender, EventArgs e) + { + if (Loading) + return; + Map.PlazaY = (uint)NUD_PlazaY.Value; + ReloadBuildingsTerrain(); + } + + private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Items.SelectedIndex < 0) + return; + LoadIndex(LB_Items.SelectedIndex); + + // View location snap has changed the view. Reload everything + LoadItemGridAcre(); + ReloadMapBackground(); + } + + private void LoadIndex(int index) + { + Loading = true; + SelectedBuildingIndex = index; + var b = Map.Buildings[index]; + NUD_BuildingType.Value = (int)b.BuildingType; + NUD_X.Value = b.X; + NUD_Y.Value = b.Y; + NUD_Angle.Value = b.Angle; + NUD_Bit.Value = b.Bit; + NUD_Type.Value = b.Type; + NUD_TypeArg.Value = b.TypeArg; + NUD_UniqueID.Value = b.UniqueID; + Loading = false; + + // -32 for relative offset on map (buildings can be placed on the exterior ocean acres) + // -16 to put it in the center of the view + const int shift = 48; + var x = (b.X - shift) & 0xFFFE; + var y = (b.Y - shift) & 0xFFFE; + View.SetViewTo(x, y); + } + + private void NUD_BuildingType_ValueChanged(object sender, EventArgs e) + { + if (Loading || sender is not NumericUpDown n) + return; + + var b = Map.Buildings[SelectedBuildingIndex]; + if (sender == NUD_BuildingType) + b.BuildingType = (BuildingType)n.Value; + else if (sender == NUD_X) + b.X = (ushort)n.Value; + else if (sender == NUD_Y) + b.Y = (ushort)n.Value; + else if (sender == NUD_Angle) + b.Angle = (byte)n.Value; + else if (sender == NUD_Bit) + b.Bit = (sbyte)n.Value; + else if (sender == NUD_Type) + b.Type = (ushort)n.Value; + else if (sender == NUD_TypeArg) + b.TypeArg = (byte)n.Value; + else if (sender == NUD_UniqueID) + b.UniqueID = (ushort)n.Value; + + LB_Items.Items[SelectedBuildingIndex] = Map.Buildings[SelectedBuildingIndex].ToString(); + ReloadBuildingsTerrain(); + } + + #endregion Buildings + + #region Acres + + private void CB_MapAcre_SelectedIndexChanged(object sender, EventArgs e) + { + var acre = Map.Terrain.BaseAcres[CB_MapAcre.SelectedIndex * 2]; + CB_MapAcreSelect.SelectedValue = (int)acre; + + // Jump view if available + if (CB_Acre.Items.OfType().Any(z => z == CB_MapAcre.Text)) + CB_Acre.Text = CB_MapAcre.Text; + } + + private void CB_MapAcreSelect_SelectedValueChanged(object sender, EventArgs e) + { + if (Loading) + return; + + var index = CB_MapAcre.SelectedIndex; + var value = WinFormsUtil.GetIndex(CB_MapAcreSelect); + + var span = Map.Terrain.BaseAcres.AsSpan(index * 2, 2); + var oldValue = span[0]; + if (value == oldValue) + return; + + System.Buffers.Binary.BinaryPrimitives.WriteUInt16LittleEndian(span, (ushort)value); + ReloadBuildingsTerrain(); + } + + private void B_DumpMapAcres_Click(object sender, EventArgs e) + { + if (!MapDumpHelper.DumpMapAcresAll(Map.Terrain.BaseAcres)) + return; + ReloadBuildingsTerrain(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ImportMapAcres_Click(object sender, EventArgs e) + { + if (!MapDumpHelper.ImportMapAcresAll(Map.Terrain.BaseAcres)) + return; + ReloadBuildingsTerrain(); + System.Media.SystemSounds.Asterisk.Play(); + } + + #endregion Acres + + private void B_ZeroElevation_Click(object sender, EventArgs e) + { + if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetElevation0)) + return; + foreach (var t in Map.Terrain.Tiles) + t.Elevation = 0; + ReloadBuildingsTerrain(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_SetAllTerrain_Click(object sender, EventArgs e) + { + if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetAll)) + return; + + var pgt = (TerrainTile)PG_TerrainTile.SelectedObject!; + bool interiorOnly = DialogResult.Yes == WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetAllSkipExterior); + Map.Terrain.SetAll(pgt, interiorOnly); + + ReloadBuildingsTerrain(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_SetAllRoadTiles_Click(object sender, EventArgs e) + { + if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetAll)) + return; + + var pgt = (TerrainTile)PG_TerrainTile.SelectedObject!; + bool interiorOnly = DialogResult.Yes == WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgTerrainSetAllSkipExterior); + Map.Terrain.SetAllRoad(pgt, interiorOnly); + + ReloadBuildingsTerrain(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ClearPlacedDesigns_Click(object sender, EventArgs e) + { + MapManager.ClearDesignTiles(SAV); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ExportPlacedDesigns_Click(object sender, EventArgs e) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "nhmd file (*.nhmd)|*.nhmd"; + sfd.FileName = "Island MyDesignMap.nhmd"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + string path = sfd.FileName; + var tiles = MapManager.ExportDesignTiles(SAV); + File.WriteAllBytes(path, tiles); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ImportPlacedDesigns_Click(object sender, EventArgs e) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "nhmd file (*.nhmd)|*.nhmd"; + ofd.FileName = "Island MyDesignMap.nhmd"; + if (ofd.ShowDialog() != DialogResult.OK) + return; + + string path = ofd.FileName; + var tiles = File.ReadAllBytes(path); + MapManager.ImportDesignTiles(SAV, tiles); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void Menu_Spawn_Click(object sender, EventArgs e) => new BulkSpawn(this, View.X, View.Y).ShowDialog(); + + private void Menu_Bulk_Click(object sender, EventArgs e) + { + var editor = new BatchEditor(SpawnLayer.Tiles, ItemEdit.SetItem(new Item())); + editor.ShowDialog(); + SpawnLayer.ClearDanglingExtensions(0, 0, SpawnLayer.MaxWidth, SpawnLayer.MaxHeight); + LoadItemGridAcre(); + } + + private void B_TerrainBrush_Click(object sender, EventArgs e) + { + tbeForm = new TerrainBrushEditor(PG_TerrainTile, this); + tbeForm.Show(); + } + + private void FieldItemEditor_FormClosed(object sender, FormClosedEventArgs e) + { + tbeForm?.Close(); + } +} + +public interface IItemLayerEditor +{ + void ReloadItems(); + + ItemEditor ItemProvider { get; } + ItemLayer SpawnLayer { get; } } \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/LandFlagEditor.cs b/NHSE.WinForms/Subforms/Map/LandFlagEditor.cs index 2e89e88..c0cce33 100644 --- a/NHSE.WinForms/Subforms/Map/LandFlagEditor.cs +++ b/NHSE.WinForms/Subforms/Map/LandFlagEditor.cs @@ -1,66 +1,65 @@ using System; +using System.Runtime.InteropServices; using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class LandFlagEditor : Form { - public partial class LandFlagEditor : Form + private readonly short[] Counts; + + public LandFlagEditor(short[] counts) { - private readonly short[] Counts; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - public LandFlagEditor(short[] counts) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - - Counts = counts; - var str = GameInfo.Strings.InternalNameTranslation; - for (ushort i = 0; i < counts.Length; i++) - LB_Counts.Items.Add(EventFlagLand.GetName(i, counts[i], str)); - DialogResult = DialogResult.Cancel; - LB_Counts.SelectedIndex = 0; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - private int Index; - - private void NUD_Count_ValueChanged(object sender, EventArgs e) - { - if (Index < 0) - return; - - Counts[Index] = (short) NUD_Count.Value; - LB_Counts.Items[Index] = EventFlagLand.GetName((ushort)Index, Counts[Index], GameInfo.Strings.InternalNameTranslation); - } - - private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Counts.SelectedIndex < 0) - return; - - NUD_Count.Value = Counts[Index = LB_Counts.SelectedIndex]; - } - - private void B_Dump_Click(object sender, EventArgs e) - { - byte[] data = new byte[Counts.Length * 2]; - Buffer.BlockCopy(Counts, 0, data, 0, data.Length); - MiscDumpHelper.DumpFlags(data, nameof(EventFlagLand)); - } - - private void B_Load_Click(object sender, EventArgs e) - { - var data = MiscDumpHelper.LoadFlags(Counts.Length * 2, nameof(EventFlagLand)); - if (data.Length != 0) - Buffer.BlockCopy(data, 0, Counts, 0, data.Length); - LB_Counts.SelectedIndex = LB_Counts.SelectedIndex; - } + Counts = counts; + var str = GameInfo.Strings.InternalNameTranslation; + for (ushort i = 0; i < counts.Length; i++) + LB_Counts.Items.Add(EventFlagLand.GetName(i, counts[i], str)); + DialogResult = DialogResult.Cancel; + LB_Counts.SelectedIndex = 0; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private int Index; + + private void NUD_Count_ValueChanged(object sender, EventArgs e) + { + if (Index < 0) + return; + + Counts[Index] = (short) NUD_Count.Value; + LB_Counts.Items[Index] = EventFlagLand.GetName((ushort)Index, Counts[Index], GameInfo.Strings.InternalNameTranslation); + } + + private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Counts.SelectedIndex < 0) + return; + + NUD_Count.Value = Counts[Index = LB_Counts.SelectedIndex]; + } + + private void B_Dump_Click(object sender, EventArgs e) + { + var data = MemoryMarshal.Cast(Counts); + MiscDumpHelper.DumpFlags(data, nameof(EventFlagLand)); + } + + private void B_Load_Click(object sender, EventArgs e) + { + var data = MiscDumpHelper.LoadFlags(Counts.Length * 2, nameof(EventFlagLand)); + if (data.Length != 0) + Buffer.BlockCopy(data, 0, Counts, 0, data.Length); + LB_Counts.SelectedIndex = LB_Counts.SelectedIndex; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/MapDumpHelper.cs b/NHSE.WinForms/Subforms/Map/MapDumpHelper.cs index 82f851e..ba10465 100644 --- a/NHSE.WinForms/Subforms/Map/MapDumpHelper.cs +++ b/NHSE.WinForms/Subforms/Map/MapDumpHelper.cs @@ -1,252 +1,228 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public static class MapDumpHelper { - public static class MapDumpHelper + public static bool ImportToLayerAcreSingle(FieldItemLayer layer, int acreIndex, string acre, int layerIndex) { - public static bool ImportToLayerAcreSingle(FieldItemLayer layer, int acreIndex, string acre, int layerIndex) + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Field Item Layer (*.nhl)|*.nhl|All files (*.*)|*.*"; + ofd.FileName = $"{acre}-{layerIndex}.nhl"; + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var path = ofd.FileName; + var fi = new FileInfo(path); + + int expect = layer.GridTileCount * Item.SIZE; + if (fi.Length != expect) { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Field Item Layer (*.nhl)|*.nhl|All files (*.*)|*.*", - FileName = $"{acre}-{layerIndex}.nhl", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var path = ofd.FileName; - var fi = new FileInfo(path); - - int expect = layer.GridTileCount * Item.SIZE; - if (fi.Length != expect) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); - return false; - } - - var data = File.ReadAllBytes(path); - layer.ImportAcre(acreIndex, data); - return true; + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); + return false; } - public static bool ImportToLayerAcreAll(FieldItemLayer layer) - { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Field Item Layer (*.nhl)|*.nhl|All files (*.*)|*.*", - FileName = "acres.nhl", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var path = ofd.FileName; - var fi = new FileInfo(path); - - int expect = layer.MaxTileCount * Item.SIZE; - if (fi.Length != expect) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); - return false; - } - - var data = File.ReadAllBytes(path); - layer.ImportAll(data); - return true; - } - - public static void DumpLayerAcreSingle(FieldItemLayer layer, int acreIndex, string acre, int layerIndex) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Field Item Layer (*.nhl)|*.nhl|All files (*.*)|*.*", - FileName = $"{acre}-{layerIndex}.nhl", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var path = sfd.FileName; - var data = layer.DumpAcre(acreIndex); - File.WriteAllBytes(path, data); - } - - public static void DumpLayerAcreAll(FieldItemLayer layer) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Field Item Layer (*.nhl)|*.nhl|All files (*.*)|*.*", - FileName = "acres.nhl", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var path = sfd.FileName; - var data = layer.DumpAll(); - File.WriteAllBytes(path, data); - } - - public static bool ImportTerrainAcre(TerrainLayer m, int acreIndex, string acre) - { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Terrain (*.nht)|*.nht|All files (*.*)|*.*", - FileName = $"{acre}.nht", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var path = ofd.FileName; - var fi = new FileInfo(path); - - int expect = m.GridTileCount * TerrainTile.SIZE; - if (fi.Length != expect) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); - return false; - } - - var data = File.ReadAllBytes(path); - m.ImportAcre(acreIndex, data); - return true; - } - - public static bool ImportTerrainAll(TerrainLayer m) - { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Terrain (*.nht)|*.nht|All files (*.*)|*.*", - FileName = "terrainAcres.nht", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var path = ofd.FileName; - var fi = new FileInfo(path); - - int expect = m.MaxTileCount * TerrainTile.SIZE; - if (fi.Length != expect) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); - return false; - } - - var data = File.ReadAllBytes(path); - m.ImportAll(data); - return true; - } - - public static void DumpTerrainAcre(TerrainLayer m, int acreIndex, string acre) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Terrain (*.nht)|*.nht|All files (*.*)|*.*", - FileName = $"{acre}.nht", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var path = sfd.FileName; - var data = m.DumpAcre(acreIndex); - File.WriteAllBytes(path, data); - } - - public static void DumpTerrainAll(TerrainLayer m) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Terrain (*.nht)|*.nht|All files (*.*)|*.*", - FileName = "terrainAcres.nht", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var path = sfd.FileName; - var data = m.DumpAll(); - File.WriteAllBytes(path, data); - } - - public static void DumpBuildings(IReadOnlyList buildings) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Building List (*.nhb)|*.nhb|All files (*.*)|*.*", - FileName = "buildings.nhb", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var path = sfd.FileName; - byte[] data = Building.SetArray(buildings); - File.WriteAllBytes(path, data); - } - - public static bool ImportBuildings(IReadOnlyList buildings) - { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Building List (*.nhb)|*.nhb|All files (*.*)|*.*", - FileName = "buildings.nhb", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var path = ofd.FileName; - var fi = new FileInfo(path); - - const int expect = Building.SIZE * MainSaveOffsets.BuildingCount; // 46 - const int oldSize = Building.SIZE * 40; - if (fi.Length != expect && fi.Length != oldSize) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); - return false; - } - - var data = File.ReadAllBytes(path); - var arr = Building.GetArray(data); - for (int i = 0; i < arr.Length; i++) - buildings[i].CopyFrom(arr[i]); - return true; - } - - public static bool DumpMapAcresAll(byte[] data) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Acres (*.nha)|*.nha|All files (*.*)|*.*", - FileName = "acres.nha", - }; - - if (sfd.ShowDialog() != DialogResult.OK) - return false; - - File.WriteAllBytes(sfd.FileName, data); - return true; - } - - public static bool ImportMapAcresAll(byte[] data) - { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Acres (*.nha)|*.nha|All files (*.*)|*.*", - FileName = "acres.nha", - }; - - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var path = ofd.FileName; - var original = data; - var modified = File.ReadAllBytes(path); - if (original.Length != modified.Length) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, modified.Length, original.Length), path); - return false; - } - - modified.CopyTo(data, 0); - return true; - } + var data = File.ReadAllBytes(path); + layer.ImportAcre(acreIndex, data); + return true; } -} + + public static bool ImportToLayerAcreAll(FieldItemLayer layer) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Field Item Layer (*.nhl)|*.nhl|All files (*.*)|*.*"; + ofd.FileName = "acres.nhl"; + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var path = ofd.FileName; + var fi = new FileInfo(path); + + int expect = layer.MaxTileCount * Item.SIZE; + if (fi.Length != expect) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); + return false; + } + + var data = File.ReadAllBytes(path); + layer.ImportAll(data); + return true; + } + + public static void DumpLayerAcreSingle(FieldItemLayer layer, int acreIndex, string acre, int layerIndex) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Field Item Layer (*.nhl)|*.nhl|All files (*.*)|*.*"; + sfd.FileName = $"{acre}-{layerIndex}.nhl"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var path = sfd.FileName; + var data = layer.DumpAcre(acreIndex); + File.WriteAllBytes(path, data); + } + + public static void DumpLayerAcreAll(FieldItemLayer layer) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Field Item Layer (*.nhl)|*.nhl|All files (*.*)|*.*"; + sfd.FileName = "acres.nhl"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var path = sfd.FileName; + var data = layer.DumpAll(); + File.WriteAllBytes(path, data); + } + + public static bool ImportTerrainAcre(TerrainLayer m, int acreIndex, string acre) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Terrain (*.nht)|*.nht|All files (*.*)|*.*"; + ofd.FileName = $"{acre}.nht"; + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var path = ofd.FileName; + var fi = new FileInfo(path); + + int expect = m.GridTileCount * TerrainTile.SIZE; + if (fi.Length != expect) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); + return false; + } + + var data = File.ReadAllBytes(path); + m.ImportAcre(acreIndex, data); + return true; + } + + public static bool ImportTerrainAll(TerrainLayer m) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Terrain (*.nht)|*.nht|All files (*.*)|*.*"; + ofd.FileName = "terrainAcres.nht"; + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var path = ofd.FileName; + var fi = new FileInfo(path); + + int expect = m.MaxTileCount * TerrainTile.SIZE; + if (fi.Length != expect) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); + return false; + } + + var data = File.ReadAllBytes(path); + m.ImportAll(data); + return true; + } + + public static void DumpTerrainAcre(TerrainLayer m, int acreIndex, string acre) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Terrain (*.nht)|*.nht|All files (*.*)|*.*"; + sfd.FileName = $"{acre}.nht"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var path = sfd.FileName; + var data = m.DumpAcre(acreIndex); + File.WriteAllBytes(path, data); + } + + public static void DumpTerrainAll(TerrainLayer m) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Terrain (*.nht)|*.nht|All files (*.*)|*.*"; + sfd.FileName = "terrainAcres.nht"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var path = sfd.FileName; + var data = m.DumpAll(); + File.WriteAllBytes(path, data); + } + + public static void DumpBuildings(IReadOnlyList buildings) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Building List (*.nhb)|*.nhb|All files (*.*)|*.*"; + sfd.FileName = "buildings.nhb"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var path = sfd.FileName; + byte[] data = Building.SetArray(buildings); + File.WriteAllBytes(path, data); + } + + public static bool ImportBuildings(IReadOnlyList buildings) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Building List (*.nhb)|*.nhb|All files (*.*)|*.*"; + ofd.FileName = "buildings.nhb"; + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var path = ofd.FileName; + var fi = new FileInfo(path); + + const int expect = Building.SIZE * MainSaveOffsets.BuildingCount; // 46 + const int oldSize = Building.SIZE * 40; + if (fi.Length != expect && fi.Length != oldSize) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expect)); + return false; + } + + var data = File.ReadAllBytes(path); + var arr = Building.GetArray(data); + for (int i = 0; i < arr.Length; i++) + buildings[i].CopyFrom(arr[i]); + return true; + } + + public static bool DumpMapAcresAll(ReadOnlySpan data) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Acres (*.nha)|*.nha|All files (*.*)|*.*"; + sfd.FileName = "acres.nha"; + + if (sfd.ShowDialog() != DialogResult.OK) + return false; + + File.WriteAllBytes(sfd.FileName, data); + return true; + } + + public static bool ImportMapAcresAll(Span data) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Acres (*.nha)|*.nha|All files (*.*)|*.*"; + ofd.FileName = "acres.nha"; + + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var path = ofd.FileName; + var original = data; + var modified = File.ReadAllBytes(path); + if (original.Length != modified.Length) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, modified.Length, original.Length), path); + return false; + } + + modified.CopyTo(data); + return true; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/MiscDumpHelper.cs b/NHSE.WinForms/Subforms/Map/MiscDumpHelper.cs index cc7b1b9..15ebdba 100644 --- a/NHSE.WinForms/Subforms/Map/MiscDumpHelper.cs +++ b/NHSE.WinForms/Subforms/Map/MiscDumpHelper.cs @@ -1,261 +1,241 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public static class MiscDumpHelper { - public static class MiscDumpHelper + public static void DumpVillagerMemoryPlayer(IVillager v, GSaveMemory memory) { - public static void DumpVillagerMemoryPlayer(IVillager v, GSaveMemory memory) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Villager Player Memory (*.nhvpm)|*.nhvpm|All files (*.*)|*.*", - FileName = $"{v.InternalName}.nhvpm", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Villager Player Memory (*.nhvpm)|*.nhvpm|All files (*.*)|*.*"; + sfd.FileName = $"{v.InternalName}.nhvpm"; + if (sfd.ShowDialog() != DialogResult.OK) + return; - var data = memory.Data; - File.WriteAllBytes(sfd.FileName, data); - } - - public static bool LoadVillagerMemoryPlayer(IVillager v, GSaveMemory[] memories, int index) - { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Villager Player Memory (*.nhvpm)|*.nhvpm|All files (*.*)|*.*", - FileName = $"{v.InternalName}.nhvpm", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var file = ofd.FileName; - var fi = new FileInfo(file); - const int expectLength = GSaveMemory.SIZE; - if (fi.Length != expectLength) - { - WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength)); - return false; - } - - var data = File.ReadAllBytes(file); - var memory = new GSaveMemory(data); - var old = memories[index]; - - if (!memory.IsOriginatedFrom(old)) - { - string msg = string.Format(MessageStrings.MsgDataDidNotOriginateFromHost_0, old.PlayerName); - var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, msg, MessageStrings.MsgAskUpdateValues); - if (result == DialogResult.Cancel) - return false; - if (result == DialogResult.Yes) - memory.ChangeOrigins(old, memory.Data); - } - - memories[index] = memory; - return true; - } - - public static void DumpMuseum(Museum museum) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Museum (*.nhm)|*.nhm|All files (*.*)|*.*", - FileName = "museum.nhm", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var data = museum.Data; - File.WriteAllBytes(sfd.FileName, data); - } - - public static bool LoadMuseum(Museum museum) - { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Museum (*.nhm)|*.nhm|All files (*.*)|*.*", - FileName = "museum.nhm", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var file = ofd.FileName; - var fi = new FileInfo(file); - const int expectLength = Museum.SIZE; - if (fi.Length != expectLength) - { - WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength)); - return false; - } - - var data = File.ReadAllBytes(file); - data.CopyTo(museum.Data); - return true; - } - - public static void DumpHouse(IReadOnlyList players, IReadOnlyList houses, int index, bool dumpAll) - { - if (dumpAll) - DumpAllPlayerHouses(houses, players); - else - DumpPlayerHouse(players, houses, index); - } - - private static void DumpPlayerHouse(IReadOnlyList players, IReadOnlyList houses, int index) - { - var house = houses[index]; - var name = PlayerHouseEditor.GetHouseSummary(players, house, index); - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Player House (*.nhph)|*.nhph|" + - "New Horizons Player House (*.nhph2)|*.nhph2|" + - "All files (*.*)|*.*", - FileName = $"{name}.{house.Extension}", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var data = house.Write(); - File.WriteAllBytes(sfd.FileName, data); - } - - private static void DumpAllPlayerHouses(IReadOnlyList houses, IReadOnlyList players) - { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() != DialogResult.OK) - return; - - var dir = Path.GetDirectoryName(fbd.SelectedPath); - if (dir == null || !Directory.Exists(dir)) - return; - houses.DumpPlayerHouses(players, fbd.SelectedPath); - } - - public static bool LoadHouse(MainSaveOffsets offsets, IReadOnlyList players, IPlayerHouse[] houses, int index) - { - var h = houses[index]; - var name = PlayerHouseEditor.GetHouseSummary(players, houses[index], index); - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Player House (*.nhph)|*.nhph|" + - "New Horizons Player House (*.nhph2)|*.nhph2|" + - "All files (*.*)|*.*", - FileName = $"{name}.{h.Extension}", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var path = ofd.FileName; - var expectLength = offsets.PlayerHouseSize; - var fi = new FileInfo(path); - if (!PlayerHouseConverter.IsCompatible((int)fi.Length, expectLength)) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); - return false; - } - - var data = File.ReadAllBytes(ofd.FileName); - data = PlayerHouseConverter.GetCompatible(data, expectLength); - if (data.Length != expectLength) - { - WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); - return false; - } - - h = offsets.ReadPlayerHouse(data); - var current = houses[index]; - h.NPC1 = current.NPC1; - houses[index] = h; - return true; - } - - public static void DumpRoom(IPlayerRoom room, int index) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Player House Room (*.nhpr)|*.nhpr|" + - "New Horizons Player House Room (*.nhpr2)|*.nhpr2|" + - "All files (*.*)|*.*", - FileName = $"Room {index + 1}.{room.Extension}", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var data = room.Write(); - File.WriteAllBytes(sfd.FileName, data); - } - - public static bool LoadRoom(MainSaveOffsets offsets, ref IPlayerRoom room, int index) - { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Player House Room (*.nhpr)|*.nhpr|" + - "New Horizons Player House Room (*.nhpr2)|*.nhpr2|" + - "All files (*.*)|*.*", - FileName = $"Room {index + 1}.{room.Extension}", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return false; - - var path = ofd.FileName; - var expectLength = offsets.PlayerRoomSize; - var fi = new FileInfo(path); - if (!PlayerRoomConverter.IsCompatible((int)fi.Length, expectLength)) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); - return false; - } - - var data = File.ReadAllBytes(ofd.FileName); - data = PlayerRoomConverter.GetCompatible(data, offsets.PlayerRoomSize); - if (data.Length != expectLength) - { - WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); - return false; - } - - room = offsets.ReadPlayerRoom(data); - return true; - } - - public static void DumpFlags(byte[] data, string name) - { - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Flag List (*.nhfl)|*.nhfl|All files (*.*)|*.*", - FileName = $"{name}.nhfl", - }; - if (sfd.ShowDialog() == DialogResult.OK) - File.WriteAllBytes(sfd.FileName, data); - } - public static void DumpFlagsToClipboard(string data) - { - Clipboard.SetData(DataFormats.Text, data); - } - - public static byte[] LoadFlags(int size, string name) - { - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Flag List (*.nhfl)|*.nhfl|All files (*.*)|*.*", - FileName = $"{name}.nhfl", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return System.Array.Empty(); - - var file = ofd.FileName; - var fi = new FileInfo(file); - int expectLength = size; - if (fi.Length != expectLength) - { - WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength)); - return System.Array.Empty(); - } - - return File.ReadAllBytes(file); - } + var data = memory.Data; + File.WriteAllBytes(sfd.FileName, data); } -} + + public static bool LoadVillagerMemoryPlayer(IVillager v, GSaveMemory[] memories, int index) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Villager Player Memory (*.nhvpm)|*.nhvpm|All files (*.*)|*.*"; + ofd.FileName = $"{v.InternalName}.nhvpm"; + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var file = ofd.FileName; + var fi = new FileInfo(file); + const int expectLength = GSaveMemory.SIZE; + if (fi.Length != expectLength) + { + WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength)); + return false; + } + + var data = File.ReadAllBytes(file); + var memory = new GSaveMemory(data); + var old = memories[index]; + + if (!memory.IsOriginatedFrom(old)) + { + string msg = string.Format(MessageStrings.MsgDataDidNotOriginateFromHost_0, old.PlayerName); + var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, msg, MessageStrings.MsgAskUpdateValues); + if (result == DialogResult.Cancel) + return false; + if (result == DialogResult.Yes) + memory.ChangeOrigins(old, memory.Data); + } + + memories[index] = memory; + return true; + } + + public static void DumpMuseum(Museum museum) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Museum (*.nhm)|*.nhm|All files (*.*)|*.*"; + sfd.FileName = "museum.nhm"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var data = museum.Data; + File.WriteAllBytes(sfd.FileName, data); + } + + public static bool LoadMuseum(Museum museum) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Museum (*.nhm)|*.nhm|All files (*.*)|*.*"; + ofd.FileName = "museum.nhm"; + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var file = ofd.FileName; + var fi = new FileInfo(file); + const int expectLength = Museum.SIZE; + if (fi.Length != expectLength) + { + WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength)); + return false; + } + + var data = File.ReadAllBytes(file); + data.AsSpan().CopyTo(museum.Data); + return true; + } + + public static void DumpHouse(IReadOnlyList players, IReadOnlyList houses, int index, bool dumpAll) + { + if (dumpAll) + DumpAllPlayerHouses(houses, players); + else + DumpPlayerHouse(players, houses, index); + } + + private static void DumpPlayerHouse(IReadOnlyList players, IReadOnlyList houses, int index) + { + var house = houses[index]; + var name = PlayerHouseEditor.GetHouseSummary(players, house, index); + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Player House (*.nhph)|*.nhph|" + + "New Horizons Player House (*.nhph2)|*.nhph2|" + + "All files (*.*)|*.*"; + sfd.FileName = $"{name}.{house.Extension}"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var data = house.Write(); + File.WriteAllBytes(sfd.FileName, data); + } + + private static void DumpAllPlayerHouses(IReadOnlyList houses, IReadOnlyList players) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() != DialogResult.OK) + return; + + var dir = Path.GetDirectoryName(fbd.SelectedPath); + if (dir == null || !Directory.Exists(dir)) + return; + houses.DumpPlayerHouses(players, fbd.SelectedPath); + } + + public static bool LoadHouse(MainSaveOffsets offsets, IReadOnlyList players, IPlayerHouse[] houses, int index) + { + var h = houses[index]; + var name = PlayerHouseEditor.GetHouseSummary(players, houses[index], index); + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Player House (*.nhph)|*.nhph|" + + "New Horizons Player House (*.nhph2)|*.nhph2|" + + "All files (*.*)|*.*"; + ofd.FileName = $"{name}.{h.Extension}"; + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var path = ofd.FileName; + var expectLength = offsets.PlayerHouseSize; + var fi = new FileInfo(path); + if (!PlayerHouseConverter.IsCompatible((int)fi.Length, expectLength)) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); + return false; + } + + var data = File.ReadAllBytes(ofd.FileName); + data = PlayerHouseConverter.GetCompatible(data, expectLength); + if (data.Length != expectLength) + { + WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); + return false; + } + + h = offsets.ReadPlayerHouse(data); + var current = houses[index]; + h.NPC1 = current.NPC1; + houses[index] = h; + return true; + } + + public static void DumpRoom(IPlayerRoom room, int index) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Player House Room (*.nhpr)|*.nhpr|" + + "New Horizons Player House Room (*.nhpr2)|*.nhpr2|" + + "All files (*.*)|*.*"; + sfd.FileName = $"Room {index + 1}.{room.Extension}"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var data = room.Write(); + File.WriteAllBytes(sfd.FileName, data); + } + + public static bool LoadRoom(MainSaveOffsets offsets, ref IPlayerRoom room, int index) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Player House Room (*.nhpr)|*.nhpr|" + + "New Horizons Player House Room (*.nhpr2)|*.nhpr2|" + + "All files (*.*)|*.*"; + ofd.FileName = $"Room {index + 1}.{room.Extension}"; + if (ofd.ShowDialog() != DialogResult.OK) + return false; + + var path = ofd.FileName; + var expectLength = offsets.PlayerRoomSize; + var fi = new FileInfo(path); + if (!PlayerRoomConverter.IsCompatible((int)fi.Length, expectLength)) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); + return false; + } + + var data = File.ReadAllBytes(ofd.FileName); + data = PlayerRoomConverter.GetCompatible(data, offsets.PlayerRoomSize); + if (data.Length != expectLength) + { + WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); + return false; + } + + room = offsets.ReadPlayerRoom(data); + return true; + } + + public static void DumpFlags(ReadOnlySpan data, string name) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Flag List (*.nhfl)|*.nhfl|All files (*.*)|*.*"; + sfd.FileName = $"{name}.nhfl"; + if (sfd.ShowDialog() == DialogResult.OK) + File.WriteAllBytes(sfd.FileName, data); + } + public static void DumpFlagsToClipboard(string data) + { + Clipboard.SetData(DataFormats.Text, data); + } + + public static byte[] LoadFlags(int size, string name) + { + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Flag List (*.nhfl)|*.nhfl|All files (*.*)|*.*"; + ofd.FileName = $"{name}.nhfl"; + if (ofd.ShowDialog() != DialogResult.OK) + return []; + + var file = ofd.FileName; + var fi = new FileInfo(file); + int expectLength = size; + if (fi.Length != expectLength) + { + WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength)); + return []; + } + + return File.ReadAllBytes(file); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/MuseumEditor.cs b/NHSE.WinForms/Subforms/Map/MuseumEditor.cs index 5e01496..3f1feaf 100644 --- a/NHSE.WinForms/Subforms/Map/MuseumEditor.cs +++ b/NHSE.WinForms/Subforms/Map/MuseumEditor.cs @@ -2,123 +2,122 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class MuseumEditor : Form { - public partial class MuseumEditor : Form + private readonly Core.MuseumEditor Editor; + private int Index = -1; + + public MuseumEditor(Museum museum) { - private readonly Core.MuseumEditor Editor; - private int Index = -1; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - public MuseumEditor(Museum museum) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); + Editor = new Core.MuseumEditor(museum); + CAL_Date.MinDate = DateTime.MinValue; - Editor = new Core.MuseumEditor(museum); - CAL_Date.MinDate = DateTime.MinValue; + var str = GameInfo.Strings; + ItemEdit.Initialize(str.ItemDataSource); + for (int i = 0; i < Editor.Dates.Length; i++) + LB_Donations.Items.Add(Editor.GetDonationText(str, i)); - var str = GameInfo.Strings; - ItemEdit.Initialize(str.ItemDataSource); - for (int i = 0; i < Editor.Dates.Length; i++) - LB_Donations.Items.Add(Editor.GetDonationText(str, i)); - - DialogResult = DialogResult.Cancel; - LB_Donations.SelectedIndex = 0; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Editor.Save(); - Close(); - } - - private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Donations.SelectedIndex < 0 || Changing) - return; - - SaveIndex(Index); - Index = LB_Donations.SelectedIndex; - LoadIndex(Index); - } - - private void LoadIndex(in int index) - { - if (index < 0) - return; - - var date = (DateTime)Editor.Dates[index]; - if (date < CAL_Date.MinDate) - date = CAL_Date.MinDate; - CAL_Date.Value = date; - NUD_Player.Value = Editor.Players[index]; - ItemEdit.LoadItem(Editor.Items[index]); - } - - private void SaveIndex(in int index) - { - if (index < 0) - return; - - var date = CAL_Date.Value; - if (date == CAL_Date.MinDate) - date = DateTime.MinValue; - Editor.Dates[index] = date; - Editor.Players[index] = (byte)NUD_Player.Value; - ItemEdit.SetItem(Editor.Items[index]); - - SetNameForIndex(index); - } - - private bool Changing; - - private void SetNameForIndex(in int index) - { - Changing = true; - LB_Donations.Items[index] = Editor.GetDonationText(GameInfo.Strings, index); - Changing = false; - } - - private void B_Dump_Click(object sender, EventArgs e) - { - Editor.Save(); - MiscDumpHelper.DumpMuseum(Editor.Museum); - } - - private void B_Load_Click(object sender, EventArgs e) - { - if (!MiscDumpHelper.LoadMuseum(Editor.Museum)) - return; - - // data imported, mark as saved and close - DialogResult = DialogResult.OK; - Close(); - } - - private void B_GiveAll_Click(object sender, EventArgs e) - { - SaveIndex(Index); - Editor.GiveAll(GameInfo.GetStrings("en").itemlist, 1000); - Editor.Save(); - System.Media.SystemSounds.Asterisk.Play(); - DialogResult = DialogResult.OK; - Close(); - } - - private void B_SortDate_Click(object sender, EventArgs e) - { - SaveIndex(Index); - Editor.SortAll(); - Editor.Save(); - System.Media.SystemSounds.Asterisk.Play(); - DialogResult = DialogResult.OK; - Close(); - } - - private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new System.Drawing.Point(0, n.Height))); - private void B_Tools_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Tools, B_Tools); + DialogResult = DialogResult.Cancel; + LB_Donations.SelectedIndex = 0; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Editor.Save(); + Close(); + } + + private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Donations.SelectedIndex < 0 || Changing) + return; + + SaveIndex(Index); + Index = LB_Donations.SelectedIndex; + LoadIndex(Index); + } + + private void LoadIndex(in int index) + { + if (index < 0) + return; + + var date = (DateTime)Editor.Dates[index]; + if (date < CAL_Date.MinDate) + date = CAL_Date.MinDate; + CAL_Date.Value = date; + NUD_Player.Value = Editor.Players[index]; + ItemEdit.LoadItem(Editor.Items[index]); + } + + private void SaveIndex(in int index) + { + if (index < 0) + return; + + var date = CAL_Date.Value; + if (date == CAL_Date.MinDate) + date = DateTime.MinValue; + Editor.Dates[index] = date; + Editor.Players[index] = (byte)NUD_Player.Value; + ItemEdit.SetItem(Editor.Items[index]); + + SetNameForIndex(index); + } + + private bool Changing; + + private void SetNameForIndex(in int index) + { + Changing = true; + LB_Donations.Items[index] = Editor.GetDonationText(GameInfo.Strings, index); + Changing = false; + } + + private void B_Dump_Click(object sender, EventArgs e) + { + Editor.Save(); + MiscDumpHelper.DumpMuseum(Editor.Museum); + } + + private void B_Load_Click(object sender, EventArgs e) + { + if (!MiscDumpHelper.LoadMuseum(Editor.Museum)) + return; + + // data imported, mark as saved and close + DialogResult = DialogResult.OK; + Close(); + } + + private void B_GiveAll_Click(object sender, EventArgs e) + { + SaveIndex(Index); + Editor.GiveAll(GameInfo.GetStrings("en").itemlist, 1000); + Editor.Save(); + System.Media.SystemSounds.Asterisk.Play(); + DialogResult = DialogResult.OK; + Close(); + } + + private void B_SortDate_Click(object sender, EventArgs e) + { + SaveIndex(Index); + Editor.SortAll(); + Editor.Save(); + System.Media.SystemSounds.Asterisk.Play(); + DialogResult = DialogResult.OK; + Close(); + } + + private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new System.Drawing.Point(0, n.Height))); + private void B_Tools_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Tools, B_Tools); +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/PatternEditor.cs b/NHSE.WinForms/Subforms/Map/PatternEditor.cs index 2ff1279..527d8c0 100644 --- a/NHSE.WinForms/Subforms/Map/PatternEditor.cs +++ b/NHSE.WinForms/Subforms/Map/PatternEditor.cs @@ -6,182 +6,174 @@ using NHSE.Core; using NHSE.Sprites; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class PatternEditor : Form { - public partial class PatternEditor : Form + private readonly DesignPattern[] Patterns; + + private int Index; + private const int scale = 8; + + public PatternEditor(DesignPattern[] patterns) { - private readonly DesignPattern[] Patterns; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + Patterns = patterns; + DialogResult = DialogResult.Cancel; - private int Index; - private const int scale = 8; + foreach (var p in patterns) + LB_Items.Items.Add(GetPatternSummary(p)); - public PatternEditor(DesignPattern[] patterns) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - Patterns = patterns; - DialogResult = DialogResult.Cancel; - - foreach (var p in patterns) - LB_Items.Items.Add(GetPatternSummary(p)); - - LB_Items.SelectedIndex = 0; - SetCM_DLDesign(); - } - - private void SetCM_DLDesign() - { - var arr = LB_Items.Items.Count == 0 - ? new ToolStripItem[] { B_DumpDesign, B_LoadDesign } - : new ToolStripItem[] { B_DumpDesign, B_DumpDesignAll, B_LoadDesign, B_LoadDesignAll }; - CM_DLDesign.Items.AddRange(arr); - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Items.SelectedIndex < 0) - return; - LoadPattern(Patterns[Index = LB_Items.SelectedIndex]); - } - - private static string GetPatternSummary(DesignPattern p) => p.DesignName; - private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); - private void B_DumpLoadDesign_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLDesign, B_DumpLoadDesign); - - private void B_DumpDesign_Click(object sender, EventArgs e) - { - if (sender == B_DumpDesignAll) - { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() != DialogResult.OK) - return; - - var dir = Path.GetDirectoryName(fbd.SelectedPath); - if (dir == null || !Directory.Exists(dir)) - return; - bool indexed = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgAskExportResultsWithFileIndex) == DialogResult.Yes; - Patterns.Dump(fbd.SelectedPath, indexed); - return; - } - - var original = Patterns[Index]; - var name = original.DesignName; - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Design Pattern (*.nhd)|*.nhd|All files (*.*)|*.*", - FileName = $"{name}.nhd", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var d = original; - File.WriteAllBytes(sfd.FileName, d.Data); - } - - private void B_LoadDesign_Click(object sender, EventArgs e) - { - if (sender == B_LoadDesignAll) - { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() != DialogResult.OK) - return; - - var dir = Path.GetDirectoryName(fbd.SelectedPath); - if (dir == null || !Directory.Exists(dir)) - return; - var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, MessageStrings.MsgAskUpdateValues); - Patterns.Load(fbd.SelectedPath, result == DialogResult.Yes); - LoadPattern(Patterns[Index]); - RepopulateList(Index); - return; - } - - var original = Patterns[Index]; - var name = original.DesignName; - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Design Pattern (*.nhd)|*.nhd|All files (*.*)|*.*", - FileName = $"{name}.nhd", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return; - - var file = ofd.FileName; - var expectLength = original.Data.Length; - var fi = new FileInfo(file); - if (fi.Length != expectLength) - { - var msg = string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength); - WinFormsUtil.Error(MessageStrings.MsgCanceling, msg); - return; - } - - var data = File.ReadAllBytes(ofd.FileName); - var d = new DesignPattern(data); - var player0 = original; - if (!d.IsOriginatedFrom(player0)) - { - var notHost = string.Format(MessageStrings.MsgDataDidNotOriginateFromHost_0, player0.PlayerName); - var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, notHost, MessageStrings.MsgAskUpdateValues); - if (result == DialogResult.Cancel) - return; - if (result == DialogResult.Yes) - d.ChangeOrigins(player0, d.Data); - } - - Patterns[Index] = d; - LoadPattern(d); - RepopulateList(Index); - } - - private void RepopulateList(int index) - { - LB_Items.Items.Clear(); - foreach (var p in Patterns) - LB_Items.Items.Add(GetPatternSummary(p)); - LB_Items.SelectedIndex = index; - } - - private void LoadPattern(DesignPattern designPattern) - { - PB_Pattern.Image = ImageUtil.ResizeImage(designPattern.GetImage(), DesignPattern.Width * scale, DesignPattern.Height * scale); - PB_Palette.Image = ImageUtil.ResizeImage(designPattern.GetPalette(), 150, 10); - L_PatternName.Text = designPattern.DesignName + Environment.NewLine + - designPattern.TownName + Environment.NewLine + - designPattern.PlayerName; - } - - private void PB_Pattern_MouseEnter(object sender, EventArgs e) => PB_Pattern.BackColor = Color.GreenYellow; - private void PB_Pattern_MouseLeave(object sender, EventArgs e) => PB_Pattern.BackColor = Color.Transparent; - - private void Menu_SavePNG_Click(object sender, EventArgs e) - { - var pb = WinFormsUtil.GetUnderlyingControl(sender); - if (pb?.Image == null) - { - WinFormsUtil.Alert(MessageStrings.MsgNoPictureLoaded); - return; - } - - var name = Patterns[Index].DesignName; - using var sfd = new SaveFileDialog - { - Filter = "png file (*.png)|*.png|All files (*.*)|*.*", - FileName = $"{name}.png", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var bmp = pb.Image; - bmp.Save(sfd.FileName, ImageFormat.Png); - } + LB_Items.SelectedIndex = 0; + SetCM_DLDesign(); } -} + + private void SetCM_DLDesign() + { + var arr = LB_Items.Items.Count == 0 + ? new ToolStripItem[] { B_DumpDesign, B_LoadDesign } + : new ToolStripItem[] { B_DumpDesign, B_DumpDesignAll, B_LoadDesign, B_LoadDesignAll }; + CM_DLDesign.Items.AddRange(arr); + } + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Items.SelectedIndex < 0) + return; + LoadPattern(Patterns[Index = LB_Items.SelectedIndex]); + } + + private static string GetPatternSummary(DesignPattern p) => p.DesignName; + private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); + private void B_DumpLoadDesign_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLDesign, B_DumpLoadDesign); + + private void B_DumpDesign_Click(object sender, EventArgs e) + { + if (sender == B_DumpDesignAll) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() != DialogResult.OK) + return; + + var dir = Path.GetDirectoryName(fbd.SelectedPath); + if (dir == null || !Directory.Exists(dir)) + return; + bool indexed = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgAskExportResultsWithFileIndex) == DialogResult.Yes; + Patterns.Dump(fbd.SelectedPath, indexed); + return; + } + + var original = Patterns[Index]; + var name = original.DesignName; + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Design Pattern (*.nhd)|*.nhd|All files (*.*)|*.*"; + sfd.FileName = $"{name}.nhd"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var d = original; + File.WriteAllBytes(sfd.FileName, d.Data); + } + + private void B_LoadDesign_Click(object sender, EventArgs e) + { + if (sender == B_LoadDesignAll) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() != DialogResult.OK) + return; + + var dir = Path.GetDirectoryName(fbd.SelectedPath); + if (dir == null || !Directory.Exists(dir)) + return; + var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, MessageStrings.MsgAskUpdateValues); + Patterns.Load(fbd.SelectedPath, result == DialogResult.Yes); + LoadPattern(Patterns[Index]); + RepopulateList(Index); + return; + } + + var original = Patterns[Index]; + var name = original.DesignName; + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Design Pattern (*.nhd)|*.nhd|All files (*.*)|*.*"; + ofd.FileName = $"{name}.nhd"; + if (ofd.ShowDialog() != DialogResult.OK) + return; + + var file = ofd.FileName; + var expectLength = original.Data.Length; + var fi = new FileInfo(file); + if (fi.Length != expectLength) + { + var msg = string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength); + WinFormsUtil.Error(MessageStrings.MsgCanceling, msg); + return; + } + + var data = File.ReadAllBytes(ofd.FileName); + var d = new DesignPattern(data); + var player0 = original; + if (!d.IsOriginatedFrom(player0)) + { + var notHost = string.Format(MessageStrings.MsgDataDidNotOriginateFromHost_0, player0.PlayerName); + var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, notHost, MessageStrings.MsgAskUpdateValues); + if (result == DialogResult.Cancel) + return; + if (result == DialogResult.Yes) + d.ChangeOrigins(player0, d.Data); + } + + Patterns[Index] = d; + LoadPattern(d); + RepopulateList(Index); + } + + private void RepopulateList(int index) + { + LB_Items.Items.Clear(); + foreach (var p in Patterns) + LB_Items.Items.Add(GetPatternSummary(p)); + LB_Items.SelectedIndex = index; + } + + private void LoadPattern(DesignPattern designPattern) + { + PB_Pattern.Image = ImageUtil.ResizeImage(designPattern.GetImage(), DesignPattern.Width * scale, DesignPattern.Height * scale); + PB_Palette.Image = ImageUtil.ResizeImage(designPattern.GetPalette(), 150, 10); + L_PatternName.Text = designPattern.DesignName + Environment.NewLine + + designPattern.TownName + Environment.NewLine + + designPattern.PlayerName; + } + + private void PB_Pattern_MouseEnter(object sender, EventArgs e) => PB_Pattern.BackColor = Color.GreenYellow; + private void PB_Pattern_MouseLeave(object sender, EventArgs e) => PB_Pattern.BackColor = Color.Transparent; + + private void Menu_SavePNG_Click(object sender, EventArgs e) + { + if (!WinFormsUtil.TryGetUnderlying(sender, out var pb) || pb.Image is null) + { + WinFormsUtil.Alert(MessageStrings.MsgNoPictureLoaded); + return; + } + + var name = Patterns[Index].DesignName; + using var sfd = new SaveFileDialog(); + sfd.Filter = "png file (*.png)|*.png|All files (*.*)|*.*"; + sfd.FileName = $"{name}.png"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var bmp = pb.Image; + bmp.Save(sfd.FileName, ImageFormat.Png); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/PatternEditorPRO.cs b/NHSE.WinForms/Subforms/Map/PatternEditorPRO.cs index 77e22a4..47edadd 100644 --- a/NHSE.WinForms/Subforms/Map/PatternEditorPRO.cs +++ b/NHSE.WinForms/Subforms/Map/PatternEditorPRO.cs @@ -6,187 +6,179 @@ using NHSE.Core; using NHSE.Sprites; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class PatternEditorPRO : Form { - public partial class PatternEditorPRO : Form + private readonly DesignPatternPRO[] Patterns; + + private int Index; + private const int scale = 4; + + public PatternEditorPRO(DesignPatternPRO[] patterns) { - private readonly DesignPatternPRO[] Patterns; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + Patterns = patterns; + DialogResult = DialogResult.Cancel; - private int Index; - private const int scale = 4; + foreach (var p in patterns) + LB_Items.Items.Add(GetPatternSummary(p)); - public PatternEditorPRO(DesignPatternPRO[] patterns) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - Patterns = patterns; - DialogResult = DialogResult.Cancel; - - foreach (var p in patterns) - LB_Items.Items.Add(GetPatternSummary(p)); - - LB_Items.SelectedIndex = 0; - SetCM_DLDesign(); - } - - private void SetCM_DLDesign() - { - var arr = LB_Items.Items.Count == 0 - ? new ToolStripItem[] { B_DumpDesign, B_LoadDesign } - : new ToolStripItem[] { B_DumpDesign, B_DumpDesignAll, B_LoadDesign, B_LoadDesignAll }; - CM_DLDesign.Items.AddRange(arr); - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Items.SelectedIndex < 0) - return; - LoadPattern(Patterns[Index = LB_Items.SelectedIndex]); - } - - private static string GetPatternSummary(DesignPatternPRO p) => p.DesignName; - private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); - private void B_DumpLoadDesign_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLDesign, B_DumpLoadDesign); - private void B_DumpDesign_Click(object sender, EventArgs e) - { - if (sender == B_DumpDesignAll) - { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() != DialogResult.OK) - return; - - var dir = Path.GetDirectoryName(fbd.SelectedPath); - if (dir == null || !Directory.Exists(dir)) - return; - bool indexed = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgAskExportResultsWithFileIndex) == DialogResult.Yes; - Patterns.Dump(fbd.SelectedPath, indexed); - return; - } - - var original = Patterns[Index]; - var name = original.DesignName; - using var sfd = new SaveFileDialog - { - Filter = "New Horizons PRO Design (*.nhpd)|*.nhpd|All files (*.*)|*.*", - FileName = $"{name}.nhpd", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var d = original; - File.WriteAllBytes(sfd.FileName, d.Data); - } - - private void B_LoadDesign_Click(object sender, EventArgs e) - { - if (sender == B_LoadDesignAll) - { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() != DialogResult.OK) - return; - - var dir = Path.GetDirectoryName(fbd.SelectedPath); - if (dir == null || !Directory.Exists(dir)) - return; - var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, MessageStrings.MsgAskUpdateValues); - Patterns.Load(fbd.SelectedPath, result == DialogResult.Yes); - LoadPattern(Patterns[Index]); - RepopulateList(Index); - return; - } - - var original = Patterns[Index]; - var name = original.DesignName; - using var ofd = new OpenFileDialog - { - Filter = "New Horizons PRO Design (*.nhpd)|*.nhpd|All files (*.*)|*.*", - FileName = $"{name}.nhpd", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return; - - var file = ofd.FileName; - var expectLength = original.Data.Length; - var fi = new FileInfo(file); - if (fi.Length != expectLength) - { - var msg = string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength); - WinFormsUtil.Error(MessageStrings.MsgCanceling, msg); - return; - } - - var data = File.ReadAllBytes(ofd.FileName); - var d = new DesignPatternPRO(data); - var player0 = original; - if (!d.IsOriginatedFrom(player0)) - { - var notHost = string.Format(MessageStrings.MsgDataDidNotOriginateFromHost_0, player0.PlayerName); - var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, notHost, MessageStrings.MsgAskUpdateValues); - if (result == DialogResult.Cancel) - return; - if (result == DialogResult.Yes) - d.ChangeOrigins(player0, d.Data); - } - - Patterns[Index] = d; - LoadPattern(d); - RepopulateList(Index); - } - - private void RepopulateList(int index) - { - LB_Items.Items.Clear(); - foreach (var p in Patterns) - LB_Items.Items.Add(GetPatternSummary(p)); - LB_Items.SelectedIndex = index; - } - - private void LoadPattern(DesignPatternPRO dp) - { - const int w = DesignPatternPRO.Width * scale; - const int h = DesignPatternPRO.Height * scale; - PB_Sheet0.Image = ImageUtil.ResizeImage(dp.GetImage(0), w, h); - PB_Sheet1.Image = ImageUtil.ResizeImage(dp.GetImage(1), w, h); - PB_Sheet2.Image = ImageUtil.ResizeImage(dp.GetImage(2), w, h); - PB_Sheet3.Image = ImageUtil.ResizeImage(dp.GetImage(3), w, h); - - PB_Palette.Image = ImageUtil.ResizeImage(dp.GetPalette(), 150, 10); - L_PatternName.Text = dp.DesignName + Environment.NewLine + - dp.TownName + Environment.NewLine + - dp.PlayerName; - } - - private void PB_Pattern_MouseEnter(object sender, EventArgs e) => PB_Sheet0.BackColor = Color.GreenYellow; - private void PB_Pattern_MouseLeave(object sender, EventArgs e) => PB_Sheet0.BackColor = Color.Transparent; - - private void Menu_SavePNG_Click(object sender, EventArgs e) - { - var pb = WinFormsUtil.GetUnderlyingControl(sender); - if (pb?.Image == null) - { - WinFormsUtil.Alert(MessageStrings.MsgNoPictureLoaded); - return; - } - - var name = Patterns[Index].DesignName; - using var sfd = new SaveFileDialog - { - Filter = "png file (*.png)|*.png|All files (*.*)|*.*", - FileName = $"{name}.png", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var bmp = pb.Image; - bmp.Save(sfd.FileName, ImageFormat.Png); - } + LB_Items.SelectedIndex = 0; + SetCM_DLDesign(); } -} + + private void SetCM_DLDesign() + { + var arr = LB_Items.Items.Count == 0 + ? new ToolStripItem[] { B_DumpDesign, B_LoadDesign } + : new ToolStripItem[] { B_DumpDesign, B_DumpDesignAll, B_LoadDesign, B_LoadDesignAll }; + CM_DLDesign.Items.AddRange(arr); + } + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Items.SelectedIndex < 0) + return; + LoadPattern(Patterns[Index = LB_Items.SelectedIndex]); + } + + private static string GetPatternSummary(DesignPatternPRO p) => p.DesignName; + private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new Point(0, n.Height))); + private void B_DumpLoadDesign_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_DLDesign, B_DumpLoadDesign); + private void B_DumpDesign_Click(object sender, EventArgs e) + { + if (sender == B_DumpDesignAll) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() != DialogResult.OK) + return; + + var dir = Path.GetDirectoryName(fbd.SelectedPath); + if (dir == null || !Directory.Exists(dir)) + return; + bool indexed = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgAskExportResultsWithFileIndex) == DialogResult.Yes; + Patterns.Dump(fbd.SelectedPath, indexed); + return; + } + + var original = Patterns[Index]; + var name = original.DesignName; + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons PRO Design (*.nhpd)|*.nhpd|All files (*.*)|*.*"; + sfd.FileName = $"{name}.nhpd"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var d = original; + File.WriteAllBytes(sfd.FileName, d.Data); + } + + private void B_LoadDesign_Click(object sender, EventArgs e) + { + if (sender == B_LoadDesignAll) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() != DialogResult.OK) + return; + + var dir = Path.GetDirectoryName(fbd.SelectedPath); + if (dir == null || !Directory.Exists(dir)) + return; + var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, MessageStrings.MsgAskUpdateValues); + Patterns.Load(fbd.SelectedPath, result == DialogResult.Yes); + LoadPattern(Patterns[Index]); + RepopulateList(Index); + return; + } + + var original = Patterns[Index]; + var name = original.DesignName; + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons PRO Design (*.nhpd)|*.nhpd|All files (*.*)|*.*"; + ofd.FileName = $"{name}.nhpd"; + if (ofd.ShowDialog() != DialogResult.OK) + return; + + var file = ofd.FileName; + var expectLength = original.Data.Length; + var fi = new FileInfo(file); + if (fi.Length != expectLength) + { + var msg = string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength); + WinFormsUtil.Error(MessageStrings.MsgCanceling, msg); + return; + } + + var data = File.ReadAllBytes(ofd.FileName); + var d = new DesignPatternPRO(data); + var player0 = original; + if (!d.IsOriginatedFrom(player0)) + { + var notHost = string.Format(MessageStrings.MsgDataDidNotOriginateFromHost_0, player0.PlayerName); + var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, notHost, MessageStrings.MsgAskUpdateValues); + if (result == DialogResult.Cancel) + return; + if (result == DialogResult.Yes) + d.ChangeOrigins(player0, d.Data); + } + + Patterns[Index] = d; + LoadPattern(d); + RepopulateList(Index); + } + + private void RepopulateList(int index) + { + LB_Items.Items.Clear(); + foreach (var p in Patterns) + LB_Items.Items.Add(GetPatternSummary(p)); + LB_Items.SelectedIndex = index; + } + + private void LoadPattern(DesignPatternPRO dp) + { + const int w = DesignPatternPRO.Width * scale; + const int h = DesignPatternPRO.Height * scale; + PB_Sheet0.Image = ImageUtil.ResizeImage(dp.GetImage(0), w, h); + PB_Sheet1.Image = ImageUtil.ResizeImage(dp.GetImage(1), w, h); + PB_Sheet2.Image = ImageUtil.ResizeImage(dp.GetImage(2), w, h); + PB_Sheet3.Image = ImageUtil.ResizeImage(dp.GetImage(3), w, h); + + PB_Palette.Image = ImageUtil.ResizeImage(dp.GetPalette(), 150, 10); + L_PatternName.Text = dp.DesignName + Environment.NewLine + + dp.TownName + Environment.NewLine + + dp.PlayerName; + } + + private void PB_Pattern_MouseEnter(object sender, EventArgs e) => PB_Sheet0.BackColor = Color.GreenYellow; + private void PB_Pattern_MouseLeave(object sender, EventArgs e) => PB_Sheet0.BackColor = Color.Transparent; + + private void Menu_SavePNG_Click(object sender, EventArgs e) + { + if (!WinFormsUtil.TryGetUnderlying(sender, out var pb) || pb.Image is null) + { + WinFormsUtil.Alert(MessageStrings.MsgNoPictureLoaded); + return; + } + + var name = Patterns[Index].DesignName; + using var sfd = new SaveFileDialog(); + sfd.Filter = "png file (*.png)|*.png|All files (*.*)|*.*"; + sfd.FileName = $"{name}.png"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var bmp = pb.Image; + bmp.Save(sfd.FileName, ImageFormat.Png); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/PlayerHouseEditor.cs b/NHSE.WinForms/Subforms/Map/PlayerHouseEditor.cs index 8025989..c330af6 100644 --- a/NHSE.WinForms/Subforms/Map/PlayerHouseEditor.cs +++ b/NHSE.WinForms/Subforms/Map/PlayerHouseEditor.cs @@ -5,316 +5,316 @@ using NHSE.Core; using NHSE.Sprites; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class PlayerHouseEditor : Form { - public partial class PlayerHouseEditor : Form + private readonly MainSave SAV; + private readonly IPlayerHouse[] Houses; + private readonly IReadOnlyList Players; + private RoomItemManager Manager; + private const int scale = 24; + + private int Index = -1; + private int RoomIndex = -1; + + public PlayerHouseEditor(IPlayerHouse[] houses, IReadOnlyList players, MainSave sav, int index) { - private readonly MainSave SAV; - private readonly IPlayerHouse[] Houses; - private readonly IReadOnlyList Players; - private RoomItemManager Manager; - private const int scale = 24; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + SAV = sav; + Houses = houses; + Players = players; + Manager = new RoomItemManager(houses[0].GetRoom(0)); - private int Index = -1; - private int RoomIndex = -1; + var data = GameInfo.Strings.ItemDataSource; + ItemEdit.Initialize(data, true); - public PlayerHouseEditor(IPlayerHouse[] houses, IReadOnlyList players, MainSave sav, int index) + DialogResult = DialogResult.Cancel; + + for (var i = 0; i < Houses.Length; i++) { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - SAV = sav; - Houses = houses; - Players = players; - Manager = new RoomItemManager(houses[0].GetRoom(0)); - - var data = GameInfo.Strings.ItemDataSource; - ItemEdit.Initialize(data, true); - - DialogResult = DialogResult.Cancel; - - for (var i = 0; i < Houses.Length; i++) - { - var obj = Houses[i]; - LB_Items.Items.Add(GetHouseSummary(players, obj, i)); - } - - LB_Items.SelectedIndex = index; + var obj = Houses[i]; + LB_Items.Items.Add(GetHouseSummary(players, obj, i)); } - private void B_Cancel_Click(object sender, EventArgs e) => Close(); + LB_Items.SelectedIndex = index; + } - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - SaveRoom(); - Close(); - } + private void B_Cancel_Click(object sender, EventArgs e) => Close(); - private void SaveRoom() + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + SaveRoom(); + Close(); + } + + private void SaveRoom() + { + if (RoomIndex < 0) + return; + Manager.Save(); + var house = Houses[Index]; + house.SetRoom(RoomIndex, Manager.Room); + } + + private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Items.SelectedIndex < 0) + return; + SaveRoom(); + var house = Houses[Index = LB_Items.SelectedIndex]; + PG_Item.SelectedObject = house; + + ChangeRoom(house); + } + + private void PG_Item_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) + { + LB_Items.Items[Index] = GetHouseSummary(Players, Houses[Index], Index); + } + + public static string GetHouseSummary(IReadOnlyList players, IPlayerHouse house, int index) + { + var houseName = index >= players.Count ? $"House {index}" : $"{players[index].Personal.PlayerName}'s House"; + return $"{houseName} (lv {house.HouseLevel})"; + } + + private void B_DumpHouse_Click(object sender, EventArgs e) + { + MiscDumpHelper.DumpHouse(Players, Houses, Index, ModifierKeys == Keys.Shift); + } + + private void B_LoadHouse_Click(object sender, EventArgs e) + { + if (!MiscDumpHelper.LoadHouse(SAV.Offsets, Players, Houses, Index)) + return; + + RoomIndex = -1; + var house = Houses[Index]; + PG_Item.SelectedObject = house; + ChangeRoom(house); + } + + private void B_EditFlags_Click(object sender, EventArgs e) + { + var flags = Houses[Index].EventFlags; + var edit = flags.ToArray(); + using var editor = new PlayerHouseFlagEditor(edit); + if (editor.ShowDialog() == DialogResult.OK) + edit.CopyTo(flags); + } + + private int HoverX; + private int HoverY; + + private void PB_Room_MouseMove(object sender, MouseEventArgs e) + { + var l = CurrentLayer; + var oldTile = l.GetTile(HoverX, HoverY); + var tile = GetTile(l, e, out var x, out var y); + if (ReferenceEquals(tile, oldTile)) + return; + var str = GameInfo.Strings; + var name = str.GetItemName(tile); + TT_Hover.SetToolTip(PB_Room, name); + SetCoordinateText(x, y, name); + } + + private void SetCoordinateText(int x, int y, string name) => L_Coordinates.Text = $"({x:000},{y:000}) = {name}"; + + private Item GetTile(ItemLayer layer, MouseEventArgs e, out int x, out int y) + { + SetHoveredItem(e); + return layer.GetTile(x = HoverX, y = HoverY); + } + + private void SetHoveredItem(MouseEventArgs e) + { + GetCoordinates(e, out HoverX, out HoverY); + + // Mouse event may fire with a slightly too large x/y; clamp just in case. + Manager.Layers[0].ClampCoordinatesInsideGrid(ref HoverX, ref HoverY); + } + + private static void GetCoordinates(MouseEventArgs e, out int x, out int y) + { + x = e.X / scale; + y = e.Y / scale; + } + + private void ChangeRoom(IPlayerHouse house) + { + RoomIndex = (int) NUD_Room.Value - 1; + ReloadManager(house); + DrawLayer(); + } + + private void ReloadManager(IPlayerHouse house) + { + var unsupported = Manager.GetUnsupportedTiles(); + if (unsupported.Count != 0) + WinFormsUtil.Alert(MessageStrings.MsgFieldItemUnsupportedLayer2Tile); + var room = house.GetRoom(RoomIndex); + Manager = new RoomItemManager(room); + } + + private void DrawLayer() => DrawRoom(CurrentLayer); + + private void DrawRoom(ItemLayer layer) + { + var w = layer.MaxWidth; + var h = layer.MaxHeight; + Span scale1 = stackalloc int[w * h]; + int[] scaleX = new int[scale * scale * scale1.Length]; + var bmp = new Bitmap(scale * w, scale * h); + PB_Room.Image = ItemLayerSprite.GetBitmapItemLayerViewGrid(layer, 0, 0, scale, scale1, scaleX, bmp, gridlineColor: 0x7F000000); + } + + private void NUD_Room_ValueChanged(object sender, EventArgs e) + { + ChangeRoom(Houses[Index]); + } + + private void NUD_Layer_ValueChanged(object sender, EventArgs e) + { + DrawLayer(); + } + + #region Item Editing + + private void PlayerHouseEditor_Click(object sender, MouseEventArgs e) + { + var tile = GetTile(CurrentLayer, e, out var x, out var y); + OmniTile(tile, x, y); + } + + private void OmniTile(Item tile, int x, int y) + { + switch (ModifierKeys) { - if (RoomIndex < 0) + default: + ViewTile(tile, x, y); return; - Manager.Save(); - var house = Houses[Index]; - house.SetRoom(RoomIndex, Manager.Room); - } - - private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Items.SelectedIndex < 0) + case Keys.Shift: + SetTile(tile, x, y); return; - SaveRoom(); - var house = Houses[Index = LB_Items.SelectedIndex]; - PG_Item.SelectedObject = house; - - ChangeRoom(house); - } - - private void PG_Item_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) - { - LB_Items.Items[Index] = GetHouseSummary(Players, Houses[Index], Index); - } - - public static string GetHouseSummary(IReadOnlyList players, IPlayerHouse house, int index) - { - var houseName = index >= players.Count ? $"House {index}" : $"{players[index].Personal.PlayerName}'s House"; - return $"{houseName} (lv {house.HouseLevel})"; - } - - private void B_DumpHouse_Click(object sender, EventArgs e) - { - MiscDumpHelper.DumpHouse(Players, Houses, Index, ModifierKeys == Keys.Shift); - } - - private void B_LoadHouse_Click(object sender, EventArgs e) - { - if (!MiscDumpHelper.LoadHouse(SAV.Offsets, Players, Houses, Index)) + case Keys.Alt: + DeleteTile(tile, x, y); return; - - RoomIndex = -1; - var house = Houses[Index]; - PG_Item.SelectedObject = house; - ChangeRoom(house); - } - - private void B_EditFlags_Click(object sender, EventArgs e) - { - var flags = Houses[Index].GetEventFlags(); - using var editor = new PlayerHouseFlagEditor(flags); - if (editor.ShowDialog() == DialogResult.OK) - Houses[Index].SetEventFlags(flags); - } - - private int HoverX; - private int HoverY; - - private void PB_Room_MouseMove(object sender, MouseEventArgs e) - { - var l = CurrentLayer; - var oldTile = l.GetTile(HoverX, HoverY); - var tile = GetTile(l, e, out var x, out var y); - if (ReferenceEquals(tile, oldTile)) - return; - var str = GameInfo.Strings; - var name = str.GetItemName(tile); - TT_Hover.SetToolTip(PB_Room, name); - SetCoordinateText(x, y, name); - } - - private void SetCoordinateText(int x, int y, string name) => L_Coordinates.Text = $"({x:000},{y:000}) = {name}"; - - private Item GetTile(ItemLayer layer, MouseEventArgs e, out int x, out int y) - { - SetHoveredItem(e); - return layer.GetTile(x = HoverX, y = HoverY); - } - - private void SetHoveredItem(MouseEventArgs e) - { - GetCoordinates(e, out HoverX, out HoverY); - - // Mouse event may fire with a slightly too large x/y; clamp just in case. - Manager.Layers[0].ClampCoordinatesInsideGrid(ref HoverX, ref HoverY); - } - - private static void GetCoordinates(MouseEventArgs e, out int x, out int y) - { - x = e.X / scale; - y = e.Y / scale; - } - - private void ChangeRoom(IPlayerHouse house) - { - RoomIndex = (int) NUD_Room.Value - 1; - ReloadManager(house); - DrawLayer(); - } - - private void ReloadManager(IPlayerHouse house) - { - var unsupported = Manager.GetUnsupportedTiles(); - if (unsupported.Count != 0) - WinFormsUtil.Alert(MessageStrings.MsgFieldItemUnsupportedLayer2Tile); - var room = house.GetRoom(RoomIndex); - Manager = new RoomItemManager(room); - } - - private void DrawLayer() => DrawRoom(CurrentLayer); - - private void DrawRoom(ItemLayer layer) - { - var w = layer.MaxWidth; - var h = layer.MaxHeight; - int[] scale1 = new int[w * h]; - int[] scaleX = new int[scale * scale * scale1.Length]; - var bmp = new Bitmap(scale * w, scale * h); - PB_Room.Image = ItemLayerSprite.GetBitmapItemLayerViewGrid(layer, 0, 0, scale, scale1, scaleX, bmp, gridlineColor: 0x7F000000); - } - - private void NUD_Room_ValueChanged(object sender, EventArgs e) - { - ChangeRoom(Houses[Index]); - } - - private void NUD_Layer_ValueChanged(object sender, EventArgs e) - { - DrawLayer(); - } - - #region Item Editing - - private void PlayerHouseEditor_Click(object sender, MouseEventArgs e) - { - var tile = GetTile(CurrentLayer, e, out var x, out var y); - OmniTile(tile, x, y); - } - - private void OmniTile(Item tile, int x, int y) - { - switch (ModifierKeys) - { - default: - ViewTile(tile, x, y); - return; - case Keys.Shift: - SetTile(tile, x, y); - return; - case Keys.Alt: - DeleteTile(tile, x, y); - return; - } - } - - private void Menu_View_Click(object sender, EventArgs e) - { - var x = HoverX; - var y = HoverY; - - var tile = CurrentLayer.GetTile(x, y); - ViewTile(tile, x, y); - } - - private void Menu_Set_Click(object sender, EventArgs e) - { - var x = HoverX; - var y = HoverY; - - var tile = CurrentLayer.GetTile(x, y); - SetTile(tile, x, y); - } - - private void Menu_Reset_Click(object sender, EventArgs e) - { - var x = HoverX; - var y = HoverY; - - var tile = CurrentLayer.GetTile(x, y); - DeleteTile(tile, x, y); - } - - private ItemLayer CurrentLayer => Manager.Layers[(int)NUD_Layer.Value - 1]; - - private void ViewTile(Item tile, int x, int y) - { - if (CHK_RedirectExtensionLoad.Checked && tile.IsExtension) - { - var l = CurrentLayer; - var rx = Math.Max(0, Math.Min(l.MaxWidth - 1, x - tile.ExtensionX)); - var ry = Math.Max(0, Math.Min(l.MaxHeight - 1, y - tile.ExtensionY)); - var redir = l.GetTile(rx, ry); - if (redir.IsRoot && redir.ItemId == tile.ExtensionItemId) - tile = redir; - } - - ViewTile(tile); - } - - private void ViewTile(Item tile) - { - ItemEdit.LoadItem(tile); - } - - private void SetTile(Item tile, int x, int y) - { - var l = CurrentLayer; - var pgt = new Item(); - ItemEdit.SetItem(pgt); - var permission = l.IsOccupied(pgt, x, y); - switch (permission) - { - case PlacedItemPermission.OutOfBounds: - case PlacedItemPermission.Collision when CHK_NoOverwrite.Checked: - System.Media.SystemSounds.Asterisk.Play(); - return; - } - - // Clean up original placed data - if (tile.IsRoot && CHK_AutoExtension.Checked) - l.DeleteExtensionTiles(tile, x, y); - - // Set new placed data - if (pgt.IsRoot && CHK_AutoExtension.Checked) - l.SetExtensionTiles(pgt, x, y); - tile.CopyFrom(pgt); - - DrawLayer(); - } - - private void DeleteTile(Item tile, int x, int y) - { - if (CHK_AutoExtension.Checked) - { - if (!tile.IsRoot) - { - x -= tile.ExtensionX; - y -= tile.ExtensionY; - tile = CurrentLayer.GetTile(x, y); - } - CurrentLayer.DeleteExtensionTiles(tile, x, y); - } - - tile.Delete(); - DrawLayer(); - } - - #endregion - - private void B_LoadRoom_Click(object sender, EventArgs e) - { - var room = Manager.Room; - MiscDumpHelper.LoadRoom(SAV.Offsets, ref room, RoomIndex); - - var house = Houses[Index]; - house.SetRoom(RoomIndex, room); - ReloadManager(house); - DrawLayer(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_DumpRoom_Click(object sender, EventArgs e) - { - SaveRoom(); - MiscDumpHelper.DumpRoom(Manager.Room, RoomIndex); } } -} + + private void Menu_View_Click(object sender, EventArgs e) + { + var x = HoverX; + var y = HoverY; + + var tile = CurrentLayer.GetTile(x, y); + ViewTile(tile, x, y); + } + + private void Menu_Set_Click(object sender, EventArgs e) + { + var x = HoverX; + var y = HoverY; + + var tile = CurrentLayer.GetTile(x, y); + SetTile(tile, x, y); + } + + private void Menu_Reset_Click(object sender, EventArgs e) + { + var x = HoverX; + var y = HoverY; + + var tile = CurrentLayer.GetTile(x, y); + DeleteTile(tile, x, y); + } + + private ItemLayer CurrentLayer => Manager.Layers[(int)NUD_Layer.Value - 1]; + + private void ViewTile(Item tile, int x, int y) + { + if (CHK_RedirectExtensionLoad.Checked && tile.IsExtension) + { + var l = CurrentLayer; + var rx = Math.Max(0, Math.Min(l.MaxWidth - 1, x - tile.ExtensionX)); + var ry = Math.Max(0, Math.Min(l.MaxHeight - 1, y - tile.ExtensionY)); + var redir = l.GetTile(rx, ry); + if (redir.IsRoot && redir.ItemId == tile.ExtensionItemId) + tile = redir; + } + + ViewTile(tile); + } + + private void ViewTile(Item tile) + { + ItemEdit.LoadItem(tile); + } + + private void SetTile(Item tile, int x, int y) + { + var l = CurrentLayer; + var pgt = new Item(); + ItemEdit.SetItem(pgt); + var permission = l.IsOccupied(pgt, x, y); + switch (permission) + { + case PlacedItemPermission.OutOfBounds: + case PlacedItemPermission.Collision when CHK_NoOverwrite.Checked: + System.Media.SystemSounds.Asterisk.Play(); + return; + } + + // Clean up original placed data + if (tile.IsRoot && CHK_AutoExtension.Checked) + l.DeleteExtensionTiles(tile, x, y); + + // Set new placed data + if (pgt.IsRoot && CHK_AutoExtension.Checked) + l.SetExtensionTiles(pgt, x, y); + tile.CopyFrom(pgt); + + DrawLayer(); + } + + private void DeleteTile(Item tile, int x, int y) + { + if (CHK_AutoExtension.Checked) + { + if (!tile.IsRoot) + { + x -= tile.ExtensionX; + y -= tile.ExtensionY; + tile = CurrentLayer.GetTile(x, y); + } + CurrentLayer.DeleteExtensionTiles(tile, x, y); + } + + tile.Delete(); + DrawLayer(); + } + + #endregion + + private void B_LoadRoom_Click(object sender, EventArgs e) + { + var room = Manager.Room; + MiscDumpHelper.LoadRoom(SAV.Offsets, ref room, RoomIndex); + + var house = Houses[Index]; + house.SetRoom(RoomIndex, room); + ReloadManager(house); + DrawLayer(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpRoom_Click(object sender, EventArgs e) + { + SaveRoom(); + MiscDumpHelper.DumpRoom(Manager.Room, RoomIndex); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/PlayerHouseFlagEditor.cs b/NHSE.WinForms/Subforms/Map/PlayerHouseFlagEditor.cs index 606edc6..dee46ab 100644 --- a/NHSE.WinForms/Subforms/Map/PlayerHouseFlagEditor.cs +++ b/NHSE.WinForms/Subforms/Map/PlayerHouseFlagEditor.cs @@ -2,64 +2,63 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class PlayerHouseFlagEditor : Form { - public partial class PlayerHouseFlagEditor : Form + private readonly short[] Counts; + + public PlayerHouseFlagEditor(short[] counts) { - private readonly short[] Counts; - - public PlayerHouseFlagEditor(short[] counts) - { - Counts = counts; - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - var str = GameInfo.Strings.InternalNameTranslation; - for (ushort i = 0; i < counts.Length; i++) - LB_Counts.Items.Add(EventFlagHouse.GetName(i, counts[i], str)); - DialogResult = DialogResult.Cancel; - LB_Counts.SelectedIndex = 0; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - private int Index; - - private void NUD_Count_ValueChanged(object sender, EventArgs e) - { - if (Index < 0) - return; - - Counts[Index] = (short) NUD_Count.Value; - LB_Counts.Items[Index] = EventFlagHouse.GetName((ushort)Index, Counts[Index], GameInfo.Strings.InternalNameTranslation); - } - - private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Counts.SelectedIndex < 0) - return; - - NUD_Count.Value = Counts[Index = LB_Counts.SelectedIndex]; - } - - private void B_Dump_Click(object sender, EventArgs e) - { - byte[] data = new byte[Counts.Length * 2]; - Buffer.BlockCopy(Counts, 0, data, 0, data.Length); - MiscDumpHelper.DumpFlags(data, nameof(EventFlagHouse)); - } - - private void B_Load_Click(object sender, EventArgs e) - { - var data = MiscDumpHelper.LoadFlags(Counts.Length * 2, nameof(EventFlagHouse)); - if (data.Length != 0) - Buffer.BlockCopy(data, 0, Counts, 0, data.Length); - LB_Counts.SelectedIndex = LB_Counts.SelectedIndex; - } + Counts = counts; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + var str = GameInfo.Strings.InternalNameTranslation; + for (ushort i = 0; i < counts.Length; i++) + LB_Counts.Items.Add(EventFlagHouse.GetName(i, counts[i], str)); + DialogResult = DialogResult.Cancel; + LB_Counts.SelectedIndex = 0; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private int Index; + + private void NUD_Count_ValueChanged(object sender, EventArgs e) + { + if (Index < 0) + return; + + Counts[Index] = (short) NUD_Count.Value; + LB_Counts.Items[Index] = EventFlagHouse.GetName((ushort)Index, Counts[Index], GameInfo.Strings.InternalNameTranslation); + } + + private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Counts.SelectedIndex < 0) + return; + + NUD_Count.Value = Counts[Index = LB_Counts.SelectedIndex]; + } + + private void B_Dump_Click(object sender, EventArgs e) + { + byte[] data = new byte[Counts.Length * 2]; + Buffer.BlockCopy(Counts, 0, data, 0, data.Length); + MiscDumpHelper.DumpFlags(data, nameof(EventFlagHouse)); + } + + private void B_Load_Click(object sender, EventArgs e) + { + var data = MiscDumpHelper.LoadFlags(Counts.Length * 2, nameof(EventFlagHouse)); + if (data.Length != 0) + Buffer.BlockCopy(data, 0, Counts, 0, data.Length); + LB_Counts.SelectedIndex = LB_Counts.SelectedIndex; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/TerrainBrushEditor.cs b/NHSE.WinForms/Subforms/Map/TerrainBrushEditor.cs index f30e0e9..1c51b07 100644 --- a/NHSE.WinForms/Subforms/Map/TerrainBrushEditor.cs +++ b/NHSE.WinForms/Subforms/Map/TerrainBrushEditor.cs @@ -1,309 +1,286 @@ using NHSE.Core; using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; -namespace NHSE.WinForms.Subforms.Map +namespace NHSE.WinForms.Subforms.Map; + +public partial class TerrainBrushEditor : Form { - public partial class TerrainBrushEditor : Form + public readonly PropertyGrid PG_TerrainTile; + private readonly FieldItemEditor FIEWindow; + + public TrackBar Slider_thickness => slider_thickness; + + public bool IsBrushSelected; + + public bool RandomizeVariation; + + public TerrainBrushEditor(PropertyGrid pG_TerrainTile, FieldItemEditor fieWindow) { - public PropertyGrid PG_TerrainTile; - private FieldItemEditor FIEWindow; - - public TrackBar Slider_thickness { get => slider_thickness; } - - public bool brushSelected; - - public bool randomizeVariation; - - public TerrainBrushEditor(PropertyGrid pG_TerrainTile, FieldItemEditor fieWindow) - { - InitializeComponent(); - PG_TerrainTile = pG_TerrainTile; - FIEWindow = fieWindow; - } - - #region Tiles buttons - - #region Dirt tiles - - private void NW_Rounded_Tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff3B, - LandMakingAngle = 0, - Elevation = (ushort)slider_elevation.Value, - }; - - private void N_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff5B, - LandMakingAngle = 3, - Elevation = (ushort)slider_elevation.Value, - }; - - private void NE_rounded_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff3B, - LandMakingAngle = 3, - Elevation = (ushort)slider_elevation.Value, - }; - - private void W_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff5B, - LandMakingAngle = 0, - Elevation = (ushort)slider_elevation.Value, - }; - - private void Middle_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - Elevation = (ushort)slider_elevation.Value, - }; - - private void E_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff5B, - LandMakingAngle = 2, - Elevation = (ushort)slider_elevation.Value, - }; - - private void SW_rounded_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff3B, - LandMakingAngle = 1, - Elevation = (ushort)slider_elevation.Value, - }; - - private void S_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff5B, - LandMakingAngle = 1, - Elevation = (ushort)slider_elevation.Value, - }; - - private void SE_rounded_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff3B, - LandMakingAngle = 2, - Elevation = (ushort)slider_elevation.Value, - }; - - private void NW_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff3C, - Elevation = (ushort)slider_elevation.Value, - }; - - private void NE_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff3C, - LandMakingAngle = 3, - Elevation = (ushort)slider_elevation.Value, - }; - - private void SW_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff3C, - LandMakingAngle = 1, - Elevation = (ushort)slider_elevation.Value, - }; - - private void SE_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff3C, - LandMakingAngle = 2, - Elevation = (ushort)slider_elevation.Value, - }; - - private void TR_dirt_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff7A, - LandMakingAngle = 2, - Elevation = (ushort)slider_elevation.Value, - }; - - private void DL_dirt_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff7A, - Elevation = (ushort)slider_elevation.Value, - }; - - private void DR_dirt_inside_Click(object sender, EventArgs e) - { - PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff7A, - LandMakingAngle = 1, - Elevation = (ushort)slider_elevation.Value, - }; - } - - #endregion Dirt tiles - - #region Water tiles - - private void NW_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River3B, - Elevation = (ushort)slider_elevation.Value, - }; - - private void N_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River5B, - LandMakingAngle = 3, - Elevation = (ushort)slider_elevation.Value, - }; - - private void NE_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River3B, - LandMakingAngle = 3, - Elevation = (ushort)slider_elevation.Value, - }; - - private void W_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River5B, - Elevation = (ushort)slider_elevation.Value, - }; - - private void Center_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River8A, - Elevation = (ushort)slider_elevation.Value, - }; - - private void e_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River5B, - LandMakingAngle = 2, - Elevation = (ushort)slider_elevation.Value, - }; - - private void sw_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River3B, - LandMakingAngle = 1, - Elevation = (ushort)slider_elevation.Value, - }; - - private void s_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River5B, - LandMakingAngle = 1, - Elevation = (ushort)slider_elevation.Value, - }; - - private void SE_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River3B, - LandMakingAngle = 2, - Elevation = (ushort)slider_elevation.Value, - }; - - private void NW_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River3C, - Elevation = (ushort)slider_elevation.Value, - }; - - private void NE_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River3C, - LandMakingAngle = 3, - Elevation = (ushort)slider_elevation.Value, - }; - - private void SW_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River3C, - LandMakingAngle = 1, - Elevation = (ushort)slider_elevation.Value, - }; - - private void SE_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River3C, - LandMakingAngle = 2, - Elevation = (ushort)slider_elevation.Value, - }; - - private void TL_dirt_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.Cliff7A, - LandMakingAngle = 3, - Elevation = (ushort)slider_elevation.Value, - }; - - private void TL_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River7A, - LandMakingAngle = 3, - Elevation = (ushort)slider_elevation.Value, - }; - - private void TR_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River7A, - LandMakingAngle = 2, - Elevation = (ushort)slider_elevation.Value, - }; - - private void DL_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River7A, - Elevation = (ushort)slider_elevation.Value, - }; - - private void DR_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile - { - UnitModel = TerrainUnitModel.River7A, - LandMakingAngle = 1, - Elevation = (ushort)slider_elevation.Value, - }; - - #endregion Water tiles - - #endregion Tiles buttons - - private void SliderThicknessValueChanged(object sender, EventArgs e) - { - lbl_size_count.Text = slider_thickness.Value.ToString(); - } - - private void SliderElevationValueChanged(object sender, EventArgs e) - { - lbl_elevation_count.Text = slider_elevation.Value.ToString(); - TerrainTile currentTile = (TerrainTile)PG_TerrainTile.SelectedObject; - currentTile.Elevation = (ushort)slider_elevation.Value; - PG_TerrainTile.SelectedObject = currentTile; - } - - private void B_Brush_Click(object sender, EventArgs e) - { - brushSelected = true; - } - - private void TerrainBrushEditor_FormClosed(object sender, FormClosedEventArgs e) - { - brushSelected = false; - } - - private void B_Normal_Click(object sender, EventArgs e) - { - brushSelected = false; - } - - private void CB_TileVariation_CheckedChanged(object sender, EventArgs e) - { - randomizeVariation = cb_tileVariation.Checked; - } + PG_TerrainTile = pG_TerrainTile; + FIEWindow = fieWindow; + InitializeComponent(); } + + #region Tiles buttons + + #region Dirt tiles + + private void NW_Rounded_Tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff3B, + LandMakingAngle = 0, + Elevation = (ushort)slider_elevation.Value, + }; + + private void N_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff5B, + LandMakingAngle = 3, + Elevation = (ushort)slider_elevation.Value, + }; + + private void NE_rounded_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff3B, + LandMakingAngle = 3, + Elevation = (ushort)slider_elevation.Value, + }; + + private void W_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff5B, + LandMakingAngle = 0, + Elevation = (ushort)slider_elevation.Value, + }; + + private void Middle_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + Elevation = (ushort)slider_elevation.Value, + }; + + private void E_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff5B, + LandMakingAngle = 2, + Elevation = (ushort)slider_elevation.Value, + }; + + private void SW_rounded_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff3B, + LandMakingAngle = 1, + Elevation = (ushort)slider_elevation.Value, + }; + + private void S_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff5B, + LandMakingAngle = 1, + Elevation = (ushort)slider_elevation.Value, + }; + + private void SE_rounded_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff3B, + LandMakingAngle = 2, + Elevation = (ushort)slider_elevation.Value, + }; + + private void NW_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff3C, + Elevation = (ushort)slider_elevation.Value, + }; + + private void NE_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff3C, + LandMakingAngle = 3, + Elevation = (ushort)slider_elevation.Value, + }; + + private void SW_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff3C, + LandMakingAngle = 1, + Elevation = (ushort)slider_elevation.Value, + }; + + private void SE_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff3C, + LandMakingAngle = 2, + Elevation = (ushort)slider_elevation.Value, + }; + + private void TR_dirt_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff7A, + LandMakingAngle = 2, + Elevation = (ushort)slider_elevation.Value, + }; + + private void DL_dirt_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff7A, + Elevation = (ushort)slider_elevation.Value, + }; + + private void DR_dirt_inside_Click(object sender, EventArgs e) + { + PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff7A, + LandMakingAngle = 1, + Elevation = (ushort)slider_elevation.Value, + }; + } + + #endregion Dirt tiles + + #region Water tiles + + private void NW_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River3B, + Elevation = (ushort)slider_elevation.Value, + }; + + private void N_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River5B, + LandMakingAngle = 3, + Elevation = (ushort)slider_elevation.Value, + }; + + private void NE_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River3B, + LandMakingAngle = 3, + Elevation = (ushort)slider_elevation.Value, + }; + + private void W_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River5B, + Elevation = (ushort)slider_elevation.Value, + }; + + private void Center_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River8A, + Elevation = (ushort)slider_elevation.Value, + }; + + private void e_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River5B, + LandMakingAngle = 2, + Elevation = (ushort)slider_elevation.Value, + }; + + private void sw_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River3B, + LandMakingAngle = 1, + Elevation = (ushort)slider_elevation.Value, + }; + + private void s_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River5B, + LandMakingAngle = 1, + Elevation = (ushort)slider_elevation.Value, + }; + + private void SE_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River3B, + LandMakingAngle = 2, + Elevation = (ushort)slider_elevation.Value, + }; + + private void NW_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River3C, + Elevation = (ushort)slider_elevation.Value, + }; + + private void NE_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River3C, + LandMakingAngle = 3, + Elevation = (ushort)slider_elevation.Value, + }; + + private void SW_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River3C, + LandMakingAngle = 1, + Elevation = (ushort)slider_elevation.Value, + }; + + private void SE_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River3C, + LandMakingAngle = 2, + Elevation = (ushort)slider_elevation.Value, + }; + + private void TL_dirt_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.Cliff7A, + LandMakingAngle = 3, + Elevation = (ushort)slider_elevation.Value, + }; + + private void TL_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River7A, + LandMakingAngle = 3, + Elevation = (ushort)slider_elevation.Value, + }; + + private void TR_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River7A, + LandMakingAngle = 2, + Elevation = (ushort)slider_elevation.Value, + }; + + private void DL_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River7A, + Elevation = (ushort)slider_elevation.Value, + }; + + private void DR_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile + { + UnitModel = TerrainUnitModel.River7A, + LandMakingAngle = 1, + Elevation = (ushort)slider_elevation.Value, + }; + + #endregion Water tiles + + #endregion Tiles buttons + + private void SliderThicknessValueChanged(object sender, EventArgs e) + { + lbl_size_count.Text = slider_thickness.Value.ToString(); + } + + private void SliderElevationValueChanged(object sender, EventArgs e) + { + lbl_elevation_count.Text = slider_elevation.Value.ToString(); + TerrainTile currentTile = (TerrainTile)PG_TerrainTile.SelectedObject!; + currentTile.Elevation = (ushort)slider_elevation.Value; + PG_TerrainTile.SelectedObject = currentTile; + } + + private void B_Brush_Click(object sender, EventArgs e) => IsBrushSelected = true; + private void TerrainBrushEditor_FormClosed(object sender, FormClosedEventArgs e) => IsBrushSelected = false; + private void B_Normal_Click(object sender, EventArgs e) => IsBrushSelected = false; + private void CB_TileVariation_CheckedChanged(object sender, EventArgs e) => RandomizeVariation = cb_tileVariation.Checked; } \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Map/VillagerHouseEditor.cs b/NHSE.WinForms/Subforms/Map/VillagerHouseEditor.cs index 11b77a5..f6d2b9c 100644 --- a/NHSE.WinForms/Subforms/Map/VillagerHouseEditor.cs +++ b/NHSE.WinForms/Subforms/Map/VillagerHouseEditor.cs @@ -4,133 +4,128 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class VillagerHouseEditor : Form { - public partial class VillagerHouseEditor : Form + private readonly MainSave SAV; + private readonly IVillagerHouse[] Houses; + private readonly IReadOnlyList Villagers; + + private int Index; + + public VillagerHouseEditor(IVillagerHouse[] houses, IReadOnlyList villagers, MainSave sav, int index) { - private readonly MainSave SAV; - private readonly IVillagerHouse[] Houses; - private readonly IReadOnlyList Villagers; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + SAV = sav; + Houses = houses; + Villagers = villagers; + DialogResult = DialogResult.Cancel; - private int Index; + foreach (var obj in Houses) + LB_Items.Items.Add(GetHouseSummary(obj)); - public VillagerHouseEditor(IVillagerHouse[] houses, IReadOnlyList villagers, MainSave sav, int index) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - SAV = sav; - Houses = houses; - Villagers = villagers; - DialogResult = DialogResult.Cancel; - - foreach (var obj in Houses) - LB_Items.Items.Add(GetHouseSummary(obj)); - - var hIndex = Array.FindIndex(houses, z => z.NPC1 == index); - if (hIndex < 0) - hIndex = 0; - LB_Items.SelectedIndex = hIndex; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Items.SelectedIndex < 0) - return; - PG_Item.SelectedObject = Houses[Index = LB_Items.SelectedIndex]; - } - - private void PG_Item_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) - { - LB_Items.Items[Index] = GetHouseSummary(Houses[Index]); - } - - private string GetHouseSummary(IVillagerHouse house) => $"{GetVillagerName(house)}'s House"; - - private string GetVillagerName(IVillagerHouse house) - { - var villagerIndex = house.NPC1; - var v = (uint) villagerIndex >= Villagers.Count ? "???" : Villagers[villagerIndex].InternalName; - var name = GameInfo.Strings.GetVillager(v); - return name; - } - - private void B_DumpHouse_Click(object sender, EventArgs e) - { - if (ModifierKeys == Keys.Shift) - { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() != DialogResult.OK) - return; - - var dir = Path.GetDirectoryName(fbd.SelectedPath); - if (dir == null || !Directory.Exists(dir)) - return; - SAV.DumpVillagerHouses(fbd.SelectedPath); - return; - } - - var h = Houses[Index]; - var name = GetVillagerName(h); - using var sfd = new SaveFileDialog - { - Filter = "New Horizons Villager House (*.nhvh)|*.nhvh|" + - "New Horizons Villager House (*.nhvh2)|*.nhvh2|" + - "All files (*.*)|*.*", - FileName = $"{name}.{h.Extension}", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var data = h.Write(); - File.WriteAllBytes(sfd.FileName, data); - } - - private void B_LoadHouse_Click(object sender, EventArgs e) - { - var h = Houses[Index]; - var name = GetVillagerName(Houses[Index]); - if (name == "???") - name = "*"; - using var ofd = new OpenFileDialog - { - Filter = "New Horizons Villager House (*.nhvh)|*.nhvh|" + - "New Horizons Villager House (*.nhvh2)|*.nhvh2|" + - "All files (*.*)|*.*", - FileName = $"{name}.{h.Extension}", - }; - if (ofd.ShowDialog() != DialogResult.OK) - return; - - var path = ofd.FileName; - var expectLength = SAV.Offsets.VillagerHouseSize; - var fi = new FileInfo(path); - if (!VillagerHouseConverter.IsCompatible((int)fi.Length, expectLength)) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); - return; - } - - var data = File.ReadAllBytes(ofd.FileName); - data = VillagerHouseConverter.GetCompatible(data, expectLength); - if (data.Length != expectLength) - { - WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); - return; - } - - h = SAV.Offsets.ReadVillagerHouse(data); - var current = Houses[Index]; - h.NPC1 = current.NPC1; - Houses[Index] = h; - PG_Item.SelectedObject = h; - } + var hIndex = Array.FindIndex(houses, z => z.NPC1 == index); + if (hIndex < 0) + hIndex = 0; + LB_Items.SelectedIndex = hIndex; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private void LB_Items_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Items.SelectedIndex < 0) + return; + PG_Item.SelectedObject = Houses[Index = LB_Items.SelectedIndex]; + } + + private void PG_Item_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) + { + LB_Items.Items[Index] = GetHouseSummary(Houses[Index]); + } + + private string GetHouseSummary(IVillagerHouse house) => $"{GetVillagerName(house)}'s House"; + + private string GetVillagerName(IVillagerHouse house) + { + var villagerIndex = house.NPC1; + var v = (uint) villagerIndex >= Villagers.Count ? "???" : Villagers[villagerIndex].InternalName; + var name = GameInfo.Strings.GetVillager(v); + return name; + } + + private void B_DumpHouse_Click(object sender, EventArgs e) + { + if (ModifierKeys == Keys.Shift) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() != DialogResult.OK) + return; + + var dir = Path.GetDirectoryName(fbd.SelectedPath); + if (dir == null || !Directory.Exists(dir)) + return; + SAV.DumpVillagerHouses(fbd.SelectedPath); + return; + } + + var h = Houses[Index]; + var name = GetVillagerName(h); + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Villager House (*.nhvh)|*.nhvh|" + + "New Horizons Villager House (*.nhvh2)|*.nhvh2|" + + "All files (*.*)|*.*"; + sfd.FileName = $"{name}.{h.Extension}"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var data = h.Write(); + File.WriteAllBytes(sfd.FileName, data); + } + + private void B_LoadHouse_Click(object sender, EventArgs e) + { + var h = Houses[Index]; + var name = GetVillagerName(Houses[Index]); + if (name == "???") + name = "*"; + using var ofd = new OpenFileDialog(); + ofd.Filter = "New Horizons Villager House (*.nhvh)|*.nhvh|" + + "New Horizons Villager House (*.nhvh2)|*.nhvh2|" + + "All files (*.*)|*.*"; + ofd.FileName = $"{name}.{h.Extension}"; + if (ofd.ShowDialog() != DialogResult.OK) + return; + + var path = ofd.FileName; + var expectLength = SAV.Offsets.VillagerHouseSize; + var fi = new FileInfo(path); + if (!VillagerHouseConverter.IsCompatible((int)fi.Length, expectLength)) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); + return; + } + + Memory data = File.ReadAllBytes(ofd.FileName); + data = VillagerHouseConverter.GetCompatible(data, expectLength); + if (data.Length != expectLength) + { + WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path); + return; + } + + h = SAV.Offsets.ReadVillagerHouse(data); + var current = Houses[Index]; + h.NPC1 = current.NPC1; + Houses[Index] = h; + PG_Item.SelectedObject = h; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Player/AchievementEditor.cs b/NHSE.WinForms/Subforms/Player/AchievementEditor.cs index 93d94f1..cca3e3f 100644 --- a/NHSE.WinForms/Subforms/Player/AchievementEditor.cs +++ b/NHSE.WinForms/Subforms/Player/AchievementEditor.cs @@ -2,135 +2,134 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class AchievementEditor : Form { - public partial class AchievementEditor : Form + private readonly Personal Personal; + private readonly AchievementList List; + private readonly AchievementRow[] Rows; + + private int Index = -1; + + public AchievementEditor(Personal personal) { - private readonly Personal Personal; - private readonly AchievementList List; - private readonly AchievementRow[] Rows; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - private int Index = -1; + Personal = personal; + var list = List = personal.Achievements; + var str = GameInfo.Strings.InternalNameTranslation; + for (int i = 0; i < list.Counts.Length; i++) + LB_Counts.Items.Add(LifeSupportAchievement.GetName(i, list.Counts[i], str)); - public AchievementEditor(Personal personal) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); + Rows = [AR_1, AR_2, AR_3, AR_4, AR_5, AR_6]; - Personal = personal; - var list = List = personal.Achievements; - var str = GameInfo.Strings.InternalNameTranslation; - for (int i = 0; i < list.Counts.Length; i++) - LB_Counts.Items.Add(LifeSupportAchievement.GetName(i, list.Counts[i], str)); - - Rows = new[] {AR_1, AR_2, AR_3, AR_4, AR_5, AR_6}; - - LB_Counts.SelectedIndex = 0; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - SaveIndex(Index); - Personal.Achievements = List; - Close(); - } - - private void NUD_Count_ValueChanged(object sender, EventArgs e) - { - if (Index < 0) - return; - - List.Counts[Index] = (uint) NUD_Count.Value; - - for (int i = 0; i < Rows.Length; i++) - Rows[i].ChangeCount(Index, i, List.Counts[Index]); - - SetEntryDescription(Index); - } - - private void SetEntryDescription(int index) - { - LB_Counts.Items[index] = LifeSupportAchievement.GetName(index, List.Counts[index], GameInfo.Strings.InternalNameTranslation); - } - - private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Counts.SelectedIndex < 0) - return; - - SaveIndex(Index); - LoadIndex(Index = LB_Counts.SelectedIndex); - } - - private void LoadIndex(int index) - { - if (index < 0) - return; - - for (int i = 0; i < Rows.Length; i++) - Rows[i].LoadRow(List, Index, i); - - NUD_Unk.Value = List.Flags[index]; - - var val = List.Counts[index]; - NUD_Count.Value = (int)val; - } - - private void SaveIndex(in int index) - { - if (index < 0) - return; - - for (int i = 0; i < Rows.Length; i++) - Rows[i].SaveRow(List, index, i); - - List.Flags[index] = (byte)NUD_Unk.Value; - - // count updated on value changed - } - - private void B_Clear_Click(object sender, EventArgs e) - { - List.ClearAll(Index); - LoadIndex(Index); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Max_Click(object sender, EventArgs e) - { - List.GiveAll(Index, DateTime.Now); - LoadIndex(Index); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_GiveAll_Click(object sender, EventArgs e) - { - SaveIndex(Index); - var index = Index; - Index = -1; - - List.GiveAll(DateTime.Now); - for (int i = 0; i < List.Counts.Length; i++) - SetEntryDescription(i); - - LoadIndex(Index = index); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ClearAll_Click(object sender, EventArgs e) - { - SaveIndex(Index); - var index = Index; - Index = -1; - - List.ClearAll(); - for (int i = 0; i < List.Counts.Length; i++) - SetEntryDescription(i); - - LoadIndex(Index = index); - System.Media.SystemSounds.Asterisk.Play(); - } + LB_Counts.SelectedIndex = 0; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + SaveIndex(Index); + Personal.Achievements = List; + Close(); + } + + private void NUD_Count_ValueChanged(object sender, EventArgs e) + { + if (Index < 0) + return; + + List.Counts[Index] = (uint) NUD_Count.Value; + + for (int i = 0; i < Rows.Length; i++) + Rows[i].ChangeCount(Index, i, List.Counts[Index]); + + SetEntryDescription(Index); + } + + private void SetEntryDescription(int index) + { + LB_Counts.Items[index] = LifeSupportAchievement.GetName(index, List.Counts[index], GameInfo.Strings.InternalNameTranslation); + } + + private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Counts.SelectedIndex < 0) + return; + + SaveIndex(Index); + LoadIndex(Index = LB_Counts.SelectedIndex); + } + + private void LoadIndex(int index) + { + if (index < 0) + return; + + for (int i = 0; i < Rows.Length; i++) + Rows[i].LoadRow(List, Index, i); + + NUD_Unk.Value = List.Flags[index]; + + var val = List.Counts[index]; + NUD_Count.Value = (int)val; + } + + private void SaveIndex(in int index) + { + if (index < 0) + return; + + for (int i = 0; i < Rows.Length; i++) + Rows[i].SaveRow(List, index, i); + + List.Flags[index] = (byte)NUD_Unk.Value; + + // count updated on value changed + } + + private void B_Clear_Click(object sender, EventArgs e) + { + List.ClearAll(Index); + LoadIndex(Index); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Max_Click(object sender, EventArgs e) + { + List.GiveAll(Index, DateTime.Now); + LoadIndex(Index); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_GiveAll_Click(object sender, EventArgs e) + { + SaveIndex(Index); + var index = Index; + Index = -1; + + List.GiveAll(DateTime.Now); + for (int i = 0; i < List.Counts.Length; i++) + SetEntryDescription(i); + + LoadIndex(Index = index); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ClearAll_Click(object sender, EventArgs e) + { + SaveIndex(Index); + var index = Index; + Index = -1; + + List.ClearAll(); + for (int i = 0; i < List.Counts.Length; i++) + SetEntryDescription(i); + + LoadIndex(Index = index); + System.Media.SystemSounds.Asterisk.Play(); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Player/FlagEditor.cs b/NHSE.WinForms/Subforms/Player/FlagEditor.cs index fd4e111..7156721 100644 --- a/NHSE.WinForms/Subforms/Player/FlagEditor.cs +++ b/NHSE.WinForms/Subforms/Player/FlagEditor.cs @@ -3,75 +3,74 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class FlagEditor : Form { - public partial class FlagEditor : Form + private readonly short[] Counts; + + public FlagEditor(short[] counts) { - private readonly short[] Counts; - - public FlagEditor(short[] counts) - { - Counts = counts; - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - var str = GameInfo.Strings.InternalNameTranslation; - for (ushort i = 0; i < counts.Length; i++) - LB_Counts.Items.Add(EventFlagPlayer.GetName(i, counts[i], str)); - DialogResult = DialogResult.Cancel; - LB_Counts.SelectedIndex = 0; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - private int Index; - - private void NUD_Count_ValueChanged(object sender, EventArgs e) - { - if (Index < 0) - return; - - Counts[Index] = (short) NUD_Count.Value; - LB_Counts.Items[Index] = EventFlagPlayer.GetName((ushort)Index, Counts[Index], GameInfo.Strings.InternalNameTranslation); - } - - private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Counts.SelectedIndex < 0) - return; - - NUD_Count.Value = Counts[Index = LB_Counts.SelectedIndex]; - } - - private void B_Dump_Click(object sender, EventArgs e) - { - byte[] data = new byte[Counts.Length * 2]; - Buffer.BlockCopy(Counts, 0, data, 0, data.Length); - MiscDumpHelper.DumpFlags(data, nameof(EventFlagPlayer)); - } - - private void B_Load_Click(object sender, EventArgs e) - { - var data = MiscDumpHelper.LoadFlags(Counts.Length * 2, nameof(EventFlagPlayer)); - if (data.Length != 0) - Buffer.BlockCopy(data, 0, Counts, 0, data.Length); - LB_Counts.SelectedIndex = LB_Counts.SelectedIndex; - } - - private void B_Copy_Click(object sender, EventArgs e) - { - var exportBuffer = new StringBuilder(); - - var str = GameInfo.Strings.InternalNameTranslation; - for (ushort i = 0; i < Counts.Length; i++) - exportBuffer.AppendLine(EventFlagPlayer.GetName(i, Counts[i], str)); - - MiscDumpHelper.DumpFlagsToClipboard(exportBuffer.ToString()); - } + Counts = counts; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + var str = GameInfo.Strings.InternalNameTranslation; + for (ushort i = 0; i < counts.Length; i++) + LB_Counts.Items.Add(EventFlagPlayer.GetName(i, counts[i], str)); + DialogResult = DialogResult.Cancel; + LB_Counts.SelectedIndex = 0; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private int Index; + + private void NUD_Count_ValueChanged(object sender, EventArgs e) + { + if (Index < 0) + return; + + Counts[Index] = (short) NUD_Count.Value; + LB_Counts.Items[Index] = EventFlagPlayer.GetName((ushort)Index, Counts[Index], GameInfo.Strings.InternalNameTranslation); + } + + private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Counts.SelectedIndex < 0) + return; + + NUD_Count.Value = Counts[Index = LB_Counts.SelectedIndex]; + } + + private void B_Dump_Click(object sender, EventArgs e) + { + byte[] data = new byte[Counts.Length * 2]; + Buffer.BlockCopy(Counts, 0, data, 0, data.Length); + MiscDumpHelper.DumpFlags(data, nameof(EventFlagPlayer)); + } + + private void B_Load_Click(object sender, EventArgs e) + { + var data = MiscDumpHelper.LoadFlags(Counts.Length * 2, nameof(EventFlagPlayer)); + if (data.Length != 0) + Buffer.BlockCopy(data, 0, Counts, 0, data.Length); + LB_Counts.SelectedIndex = LB_Counts.SelectedIndex; + } + + private void B_Copy_Click(object sender, EventArgs e) + { + var exportBuffer = new StringBuilder(); + + var str = GameInfo.Strings.InternalNameTranslation; + for (ushort i = 0; i < Counts.Length; i++) + exportBuffer.AppendLine(EventFlagPlayer.GetName(i, Counts[i], str)); + + MiscDumpHelper.DumpFlagsToClipboard(exportBuffer.ToString()); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Player/ItemReceivedEditor.cs b/NHSE.WinForms/Subforms/Player/ItemReceivedEditor.cs index ba919c8..7dcbeed 100644 --- a/NHSE.WinForms/Subforms/Player/ItemReceivedEditor.cs +++ b/NHSE.WinForms/Subforms/Player/ItemReceivedEditor.cs @@ -1,190 +1,193 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class ItemReceivedEditor : Form { - public partial class ItemReceivedEditor : Form + private readonly Player Player; + + public ItemReceivedEditor(Player player) { - private readonly Player Player; + Player = player; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + FillCheckBoxes(); + Initialize(GameInfo.Strings.ItemDataSource); + CLB_Remake.SelectedIndex = 0; + CLB_Items.SelectedIndex = 0x50; // clackercart + } - public ItemReceivedEditor(Player player) + public void Initialize(List items) + { + CB_Item.DisplayMember = nameof(ComboItem.Text); + CB_Item.ValueMember = nameof(ComboItem.Value); + CB_Item.DataSource = items; + } + + private void FillCheckBoxes() + { + var items = GameInfo.Strings.itemlistdisplay; + FillCollect(items); + FillRemake(items); + } + + private void FillCollect(ReadOnlySpan items) + { + var ofs = Player.Personal.Offsets.ItemCollectBit; + var data = Player.Personal.Data; + for (int i = 0; i < items.Length; i++) { - Player = player; - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - FillCheckBoxes(); - Initialize(GameInfo.Strings.ItemDataSource); - CLB_Remake.SelectedIndex = 0; - CLB_Items.SelectedIndex = 0x50; // clackercart - } - - public void Initialize(List items) - { - CB_Item.DisplayMember = nameof(ComboItem.Text); - CB_Item.ValueMember = nameof(ComboItem.Value); - CB_Item.DataSource = items; - } - - private void FillCheckBoxes() - { - var items = GameInfo.Strings.itemlistdisplay; - FillCollect(items); - FillRemake(items); - } - - private void FillCollect(IReadOnlyList items) - { - var ofs = Player.Personal.Offsets.ItemCollectBit; - var data = Player.Personal.Data; - for (int i = 0; i < items.Count; i++) - { - var flag = FlagUtil.GetFlag(data, ofs, i); - string value = items[i]; - string name = $"0x{i:X3} - {value}"; - CLB_Items.Items.Add(name, flag); - } - } - - private void FillRemake(IReadOnlyList items) - { - var str = GameInfo.Strings; - var invert = ItemRemakeUtil.GetInvertedDictionary(); - var ofs = Player.Personal.Offsets.ItemRemakeCollectBit; - var max = Player.Personal.Offsets.MaxRemakeBitFlag; - var data = Player.Personal.Data; - for (int i = 0; i < max; i++) - { - var remakeIndex = i >> 3; // ItemRemakeInfo.BodyColorCountMax - var variant = i & 7; - - ushort itemId = invert.TryGetValue((short)remakeIndex, out var id) ? id : (ushort)0; - var itemName = remakeIndex == 0652 ? "photo" : items[itemId]; - - var flag = FlagUtil.GetFlag(data, ofs, i); - string name = $"{remakeIndex:0000} V{variant:0} - {itemName}"; - - if (ItemRemakeInfoData.List.TryGetValue((short)remakeIndex, out var info)) - name = $"{name} ({info.GetBodyDescription(variant, str)})"; - - CLB_Remake.Items.Add(name, flag); - } - } - - public void GiveAll(IReadOnlyList indexes, bool value = true) - { - foreach (var item in indexes) - GiveItem(item, value, CB_VariantBodiesOnly.Checked); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void GiveEverything(IReadOnlyList items, bool value = true) - { - if (!value) - { - for (ushort i = 0; i < CLB_Items.Items.Count; i++) - GiveItem(i, false, CB_VariantBodiesOnly.Checked); - return; - } - - var skip = GameLists.NoCheckReceived; - for (ushort i = 1; i < CLB_Items.Items.Count; i++) - { - if (string.IsNullOrEmpty(items[i])) - continue; - if (skip.Contains(i)) - continue; - GiveItem(i, remakeOnly: CB_VariantBodiesOnly.Checked); - } - System.Media.SystemSounds.Asterisk.Play(); - } - - private void GiveAllFurniture(IReadOnlyList items, bool value = true) - { - var skip = new HashSet(GameLists.NoCheckReceived); - skip.UnionWith(GameLists.Bugs); - skip.UnionWith(GameLists.Fish); - skip.UnionWith(GameLists.Art); - skip.UnionWith(GameLists.Dive); - - for (ushort i = 1; i < CLB_Items.Items.Count; i++) - { - if (string.IsNullOrEmpty(items[i])) - continue; - if (skip.Contains(i)) - continue; - GiveItem(i, value, CB_VariantBodiesOnly.Checked); - } - System.Media.SystemSounds.Asterisk.Play(); - } - private void GiveItem(ushort item, bool value = true, bool remakeOnly = false) - { - if (!remakeOnly) - CLB_Items.SetItemChecked(item, value); - - var remakeIndex = ItemRemakeUtil.GetRemakeIndex(item); - if (!ItemRemakeInfoData.List.TryGetValue(remakeIndex, out var info)) - return; - - for (int i = 0; i < ItemRemakeInfo.BodyColorCountMax; i++) - { - if (!info.HasBodyColor(i)) - continue; - int rIndex = (remakeIndex * ItemRemakeInfo.BodyColorCountMax) + i; - CLB_Remake.SetItemChecked(rIndex, value); - } - } - - private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new System.Drawing.Point(0, n.Height))); - private void B_GiveAll_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Buttons, (Control)sender); - private void B_AllBugs_Click(object sender, EventArgs e) => GiveAll(GameLists.Bugs, ModifierKeys != Keys.Alt); - private void B_AllFish_Click(object sender, EventArgs e) => GiveAll(GameLists.Fish, ModifierKeys != Keys.Alt); - private void B_AllArt_Click(object sender, EventArgs e) => GiveAll(GameLists.Art, ModifierKeys != Keys.Alt); - private void B_AllDive_Click(object sender, EventArgs e) => GiveAll(GameLists.Dive, ModifierKeys != Keys.Alt); - private void B_AllFurniture_Click(object sender, EventArgs e) => GiveAllFurniture(GameInfo.Strings.itemlist, ModifierKeys != Keys.Alt); - private void B_GiveEverything_Click(object sender, EventArgs e) => GiveEverything(GameInfo.Strings.itemlist, ModifierKeys != Keys.Alt); - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - SetCollect(); - SetRemake(); - Close(); - } - - private void SetCollect() - { - var ofs = Player.Personal.Offsets.ItemCollectBit; - var data = Player.Personal.Data; - for (int i = 0; i < CLB_Items.Items.Count; i++) - FlagUtil.SetFlag(data, ofs, i, CLB_Items.GetItemChecked(i)); - } - - private void SetRemake() - { - var ofs = Player.Personal.Offsets.ItemRemakeCollectBit; - var data = Player.Personal.Data; - for (int i = 0; i < CLB_Remake.Items.Count; i++) - FlagUtil.SetFlag(data, ofs, i, CLB_Remake.GetItemChecked(i)); - } - - private void CB_Item_SelectedValueChanged(object sender, EventArgs e) - { - var index = WinFormsUtil.GetIndex(CB_Item); - if ((uint)index >= CLB_Items.Items.Count) - index = 0; - CLB_Items.SelectedIndex = index; - - var remake = ItemRemakeUtil.GetRemakeIndex((ushort)index); - if (remake > 0) - CLB_Remake.SelectedIndex = remake * ItemRemakeInfo.BodyColorCountMax; - } - - private void CLB_Items_SelectedIndexChanged(object sender, EventArgs e) - { - var index = CLB_Items.SelectedIndex; - CB_Item.SelectedValue = index; + var flag = FlagUtil.GetFlag(data, ofs, i); + string value = items[i]; + string name = $"0x{i:X3} - {value}"; + CLB_Items.Items.Add(name, flag); } } -} + + private void FillRemake(ReadOnlySpan items) + { + var str = GameInfo.Strings; + var invert = ItemRemakeUtil.GetInvertedDictionary(); + var ofs = Player.Personal.Offsets.ItemRemakeCollectBit; + var max = Player.Personal.Offsets.MaxRemakeBitFlag; + var data = Player.Personal.Data; + for (int i = 0; i < max; i++) + { + var remakeIndex = i >> 3; // ItemRemakeInfo.BodyColorCountMax + var variant = i & 7; + + ushort itemId = invert.GetValueOrDefault((short)remakeIndex, (ushort)0); + var itemName = remakeIndex == 0652 ? "photo" : items[itemId]; + + var flag = FlagUtil.GetFlag(data, ofs, i); + string name = $"{remakeIndex:0000} V{variant:0} - {itemName}"; + + if (ItemRemakeInfoData.List.TryGetValue((short)remakeIndex, out var info)) + name = $"{name} ({info.GetBodyDescription(variant, str)})"; + + CLB_Remake.Items.Add(name, flag); + } + } + + public void GiveAll(ReadOnlySpan indexes, bool value = true) + { + foreach (var item in indexes) + GiveItem(item, value, CB_VariantBodiesOnly.Checked); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void GiveEverything(ReadOnlySpan items, bool value = true) + { + if (!value) + { + for (ushort i = 0; i < CLB_Items.Items.Count; i++) + GiveItem(i, false, CB_VariantBodiesOnly.Checked); + return; + } + + var skip = GameLists.NoCheckReceived; + for (ushort i = 1; i < CLB_Items.Items.Count; i++) + { + if (string.IsNullOrEmpty(items[i])) + continue; + if (skip.Contains(i)) + continue; + GiveItem(i, remakeOnly: CB_VariantBodiesOnly.Checked); + } + System.Media.SystemSounds.Asterisk.Play(); + } + + private void GiveAllFurniture(ReadOnlySpan items, bool value = true) + { + var skip = new List(); + skip.AddRange(GameLists.NoCheckReceived); + skip.AddRange(GameLists.Bugs); + skip.AddRange(GameLists.Fish); + skip.AddRange(GameLists.Art); + skip.AddRange(GameLists.Dive); + + skip = skip.Distinct().ToList(); + + for (ushort i = 1; i < CLB_Items.Items.Count; i++) + { + if (string.IsNullOrEmpty(items[i])) + continue; + if (skip.Contains(i)) + continue; + GiveItem(i, value, CB_VariantBodiesOnly.Checked); + } + System.Media.SystemSounds.Asterisk.Play(); + } + private void GiveItem(ushort item, bool value = true, bool remakeOnly = false) + { + if (!remakeOnly) + CLB_Items.SetItemChecked(item, value); + + var remakeIndex = ItemRemakeUtil.GetRemakeIndex(item); + if (!ItemRemakeInfoData.List.TryGetValue(remakeIndex, out var info)) + return; + + for (int i = 0; i < ItemRemakeInfo.BodyColorCountMax; i++) + { + if (!info.HasBodyColor(i)) + continue; + int rIndex = (remakeIndex * ItemRemakeInfo.BodyColorCountMax) + i; + CLB_Remake.SetItemChecked(rIndex, value); + } + } + + private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new System.Drawing.Point(0, n.Height))); + private void B_GiveAll_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_Buttons, (Control)sender); + private void B_AllBugs_Click(object sender, EventArgs e) => GiveAll(GameLists.Bugs, ModifierKeys != Keys.Alt); + private void B_AllFish_Click(object sender, EventArgs e) => GiveAll(GameLists.Fish, ModifierKeys != Keys.Alt); + private void B_AllArt_Click(object sender, EventArgs e) => GiveAll(GameLists.Art, ModifierKeys != Keys.Alt); + private void B_AllDive_Click(object sender, EventArgs e) => GiveAll(GameLists.Dive, ModifierKeys != Keys.Alt); + private void B_AllFurniture_Click(object sender, EventArgs e) => GiveAllFurniture(GameInfo.Strings.itemlist, ModifierKeys != Keys.Alt); + private void B_GiveEverything_Click(object sender, EventArgs e) => GiveEverything(GameInfo.Strings.itemlist, ModifierKeys != Keys.Alt); + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + SetCollect(); + SetRemake(); + Close(); + } + + private void SetCollect() + { + var ofs = Player.Personal.Offsets.ItemCollectBit; + var data = Player.Personal.Data; + for (int i = 0; i < CLB_Items.Items.Count; i++) + FlagUtil.SetFlag(data, ofs, i, CLB_Items.GetItemChecked(i)); + } + + private void SetRemake() + { + var ofs = Player.Personal.Offsets.ItemRemakeCollectBit; + var data = Player.Personal.Data; + for (int i = 0; i < CLB_Remake.Items.Count; i++) + FlagUtil.SetFlag(data, ofs, i, CLB_Remake.GetItemChecked(i)); + } + + private void CB_Item_SelectedValueChanged(object sender, EventArgs e) + { + var index = WinFormsUtil.GetIndex(CB_Item); + if ((uint)index >= CLB_Items.Items.Count) + index = 0; + CLB_Items.SelectedIndex = index; + + var remake = ItemRemakeUtil.GetRemakeIndex((ushort)index); + if (remake > 0) + CLB_Remake.SelectedIndex = remake * ItemRemakeInfo.BodyColorCountMax; + } + + private void CLB_Items_SelectedIndexChanged(object sender, EventArgs e) + { + var index = CLB_Items.SelectedIndex; + CB_Item.SelectedValue = index; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Player/MiscPlayerEditor.cs b/NHSE.WinForms/Subforms/Player/MiscPlayerEditor.cs index d18ddac..18280da 100644 --- a/NHSE.WinForms/Subforms/Player/MiscPlayerEditor.cs +++ b/NHSE.WinForms/Subforms/Player/MiscPlayerEditor.cs @@ -2,60 +2,59 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class MiscPlayerEditor : Form { - public partial class MiscPlayerEditor : Form + private readonly Player Player; + + public MiscPlayerEditor(Player p) { - private readonly Player Player; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + Player = p; - public MiscPlayerEditor(Player p) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - Player = p; + var fruits = ComboItemUtil.GetArray(GameLists.Fruits, GameInfo.Strings.itemlistdisplay); + ProfileFruit.Initialize(fruits); - var fruits = ComboItemUtil.GetArray(GameLists.Fruits, GameInfo.Strings.itemlistdisplay); - ProfileFruit.Initialize(fruits); - - LoadPlayer(); - } - - private void LoadPlayer() - { - var p = Player; - var pers = p.Personal; - - var bd = pers.Birthday; - NUD_BirthDay.Value = bd.Day; - NUD_BirthMonth.Value = bd.Month; - - CHK_ProfileMadeVillage.Checked = pers.ProfileIsMakeVillage; - ProfileFruit.Value = pers.ProfileFruit; - CAL_ProfileTimestamp.Value = pers.ProfileTimestamp; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - SavePlayer(); - Close(); - } - - private void SavePlayer() - { - var p = Player; - var pers = p.Personal; - - var bd = pers.Birthday; - bd.Day = (byte) NUD_BirthDay.Value; - bd.Month = (byte) NUD_BirthMonth.Value; - - pers.Birthday = bd; - pers.ProfileBirthday = bd; - pers.ProfileIsMakeVillage = CHK_ProfileMadeVillage.Checked; - pers.ProfileFruit = ProfileFruit.Value; - pers.ProfileTimestamp = CAL_ProfileTimestamp.Value; - } + LoadPlayer(); } -} + + private void LoadPlayer() + { + var p = Player; + var pers = p.Personal; + + var bd = pers.Birthday; + NUD_BirthDay.Value = bd.Day; + NUD_BirthMonth.Value = bd.Month; + + CHK_ProfileMadeVillage.Checked = pers.ProfileIsMakeVillage; + ProfileFruit.Value = pers.ProfileFruit; + CAL_ProfileTimestamp.Value = pers.ProfileTimestamp; + } + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + SavePlayer(); + Close(); + } + + private void SavePlayer() + { + var p = Player; + var pers = p.Personal; + + var bd = pers.Birthday; + bd.Day = (byte) NUD_BirthDay.Value; + bd.Month = (byte) NUD_BirthMonth.Value; + + pers.Birthday = bd; + pers.ProfileBirthday = bd; + pers.ProfileIsMakeVillage = CHK_ProfileMadeVillage.Checked; + pers.ProfileFruit = ProfileFruit.Value; + pers.ProfileTimestamp = CAL_ProfileTimestamp.Value; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Player/ReactionEditor.cs b/NHSE.WinForms/Subforms/Player/ReactionEditor.cs index 35b18a0..b35907c 100644 --- a/NHSE.WinForms/Subforms/Player/ReactionEditor.cs +++ b/NHSE.WinForms/Subforms/Player/ReactionEditor.cs @@ -2,39 +2,38 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class ReactionEditor : Form { - public partial class ReactionEditor : Form + private readonly Personal Personal; + + public ReactionEditor(Personal p) { - private readonly Personal Personal; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - public ReactionEditor(Personal p) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); + Personal = p; + var manpu = p.Reactions; - Personal = p; - var manpu = p.Reactions; - - PG_Manpu.SelectedObject = manpu; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - var val = (IReactionStore) PG_Manpu.SelectedObject; - Personal.Reactions = val; - Close(); - } - - private void B_GiveAll_Click(object sender, EventArgs e) - { - var val = (IReactionStore)PG_Manpu.SelectedObject; - val.AddMissingReactions(); - PG_Manpu.SelectedObject = val; - System.Media.SystemSounds.Asterisk.Play(); - } + PG_Manpu.SelectedObject = manpu; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + var val = (IReactionStore) PG_Manpu.SelectedObject!; + Personal.Reactions = val; + Close(); + } + + private void B_GiveAll_Click(object sender, EventArgs e) + { + var val = (IReactionStore)PG_Manpu.SelectedObject!; + val.AddMissingReactions(); + PG_Manpu.SelectedObject = val; + System.Media.SystemSounds.Asterisk.Play(); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Player/RecipeListEditor.cs b/NHSE.WinForms/Subforms/Player/RecipeListEditor.cs index c82e563..7784b0b 100644 --- a/NHSE.WinForms/Subforms/Player/RecipeListEditor.cs +++ b/NHSE.WinForms/Subforms/Player/RecipeListEditor.cs @@ -3,155 +3,154 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class RecipeListEditor : Form { - public partial class RecipeListEditor : Form + private readonly Player Player; + private readonly RecipeBook Book; + private const string Unknown = "???"; + + public RecipeListEditor(Player player) { - private readonly Player Player; - private readonly RecipeBook Book; - private const string Unknown = "???"; + Player = player; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - public RecipeListEditor(Player player) - { - Player = player; - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - - Book = player.Personal.GetRecipeBook(); - var gotoSource = FillCheckBoxes(); - gotoSource.SortByText(); - CB_Goto.DisplayMember = nameof(ComboItem.Text); - CB_Goto.ValueMember = nameof(ComboItem.Value); - CB_Goto.DataSource = new BindingSource(gotoSource, null); - } - - private List FillCheckBoxes() - { - var book = Book; - var recipes = RecipeList.Recipes; - var strings = GameInfo.Strings.itemlist; - const ushort max = RecipeBook.RecipeCount; - FillListBox(max, recipes, strings, book); - - var gotoSource = new List(); - return GetJumpList(max, recipes, strings, gotoSource); - } - - private void FillListBox(ushort max, IReadOnlyDictionary recipes, string[] strings, RecipeBook book) - { - Loading = true; - for (ushort i = 0; i <= max; i++) - { - var name = GetItemName(i, recipes, strings); - var text = GetEntryText(book, i, name); - LB_Recipes.Items.Add(text); - } - Loading = false; - } - - private static List GetJumpList(ushort max, IReadOnlyDictionary recipes, string[] strings, List gotoSource) - { - for (ushort i = 0; i <= max; i++) - { - var name = GetItemName(i, recipes, strings); - if (recipes.ContainsKey(i)) - gotoSource.Add(new ComboItem(name, i)); - } - - return gotoSource; - } - - private static string GetItemName(ushort index, IReadOnlyDictionary recipes, string[] itemNames) - { - bool exists = recipes.TryGetValue(index, out var value); - string item = exists ? itemNames[value] : Unknown; - if (string.IsNullOrEmpty(item)) - item = value.ToString(); - return item; - } - - private static object GetEntryText(RecipeBook recipeBook, ushort index, string item) - { - var known = recipeBook.GetIsKnown(index) ? "✅" : "❌"; - return $"0x{index:X3} - {known} {item}"; - } - - private void B_All_Click(object sender, EventArgs e) => DoAll(() => Book.GiveAll(RecipeList.Recipes, ModifierKeys != Keys.Control)); - private void B_ClearAll_Click(object sender, EventArgs e) => DoAll(Book.ClearAll); - private void B_CraftAll_Click(object sender, EventArgs e) => DoAll(Book.CraftAll); - - private void DoAll(Action action) - { - var index = LB_Recipes.SelectedIndex; - var book = Book; - var recipes = RecipeList.Recipes; - var strings = GameInfo.Strings.itemlist; - const ushort max = RecipeBook.RecipeCount; - - action(); - LB_Recipes.Items.Clear(); - FillListBox(max, recipes, strings, book); - LoadIndex(index); - LB_Recipes.SelectedIndex = index; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - Player.Personal.SetRecipeBook(Book); - Close(); - } - - private void CB_Goto_SelectedValueChanged(object sender, EventArgs e) => LB_Recipes.SelectedIndex = WinFormsUtil.GetIndex(CB_Goto); - - private int Index = -1; - private bool Loading; - private void LB_Recipes_SelectedIndexChanged(object sender, EventArgs e) - { - if (Loading) - return; - SaveIndex(Index); - Index = LB_Recipes.SelectedIndex; - Loading = true; - LoadIndex(Index); - Loading = false; - } - - private void LoadIndex(in int index) - { - if (index < 0) - return; - var book = Book; - CHK_Known.Checked = book.GetIsKnown(index); - CHK_New.Checked = book.GetIsNew(index); - CHK_Made.Checked = book.GetIsMade(index); - CHK_Favorite.Checked = book.GetIsFavorite(index); - } - - private void SaveIndex(in int index) - { - if (index < 0) - return; - var book = Book; - book.SetIsKnown(index, CHK_Known.Checked); - book.SetIsNew(index, CHK_New.Checked); - book.SetIsMade(index, CHK_Made.Checked); - book.SetIsFavorite(index, CHK_Favorite.Checked); - } - - private void CHK_Known_CheckedChanged(object sender, EventArgs e) - { - if (Loading) - return; - Loading = true; - var book = Book; - book.SetIsKnown(Index, CHK_Known.Checked); - var recipes = RecipeList.Recipes; - var strings = GameInfo.Strings.itemlist; - var name = GetItemName((ushort)Index, recipes, strings); - LB_Recipes.Items[Index] = GetEntryText(book, (ushort)Index, name); - Loading = false; - } + Book = player.Personal.GetRecipeBook(); + var gotoSource = FillCheckBoxes(); + gotoSource.SortByText(); + CB_Goto.DisplayMember = nameof(ComboItem.Text); + CB_Goto.ValueMember = nameof(ComboItem.Value); + CB_Goto.DataSource = new BindingSource(gotoSource, string.Empty); } -} + + private List FillCheckBoxes() + { + var book = Book; + var recipes = RecipeList.Recipes; + var strings = GameInfo.Strings.itemlist; + const ushort max = RecipeBook.RecipeCount; + FillListBox(max, recipes, strings, book); + + var gotoSource = new List(); + return GetJumpList(max, recipes, strings, gotoSource); + } + + private void FillListBox(ushort max, IReadOnlyDictionary recipes, ReadOnlySpan strings, RecipeBook book) + { + Loading = true; + for (ushort i = 0; i <= max; i++) + { + var name = GetItemName(i, recipes, strings); + var text = GetEntryText(book, i, name); + LB_Recipes.Items.Add(text); + } + Loading = false; + } + + private static List GetJumpList(ushort max, IReadOnlyDictionary recipes, ReadOnlySpan strings, List gotoSource) + { + for (ushort i = 0; i <= max; i++) + { + var name = GetItemName(i, recipes, strings); + if (recipes.ContainsKey(i)) + gotoSource.Add(new ComboItem(name, i)); + } + + return gotoSource; + } + + private static string GetItemName(ushort index, IReadOnlyDictionary recipes, ReadOnlySpan itemNames) + { + bool exists = recipes.TryGetValue(index, out var value); + string item = exists ? itemNames[value] : Unknown; + if (string.IsNullOrEmpty(item)) + item = value.ToString(); + return item; + } + + private static string GetEntryText(RecipeBook recipeBook, ushort index, string item) + { + var known = recipeBook.GetIsKnown(index) ? "✅" : "❌"; + return $"0x{index:X3} - {known} {item}"; + } + + private void B_All_Click(object sender, EventArgs e) => DoAll(() => Book.GiveAll(RecipeList.Recipes, ModifierKeys != Keys.Control)); + private void B_ClearAll_Click(object sender, EventArgs e) => DoAll(Book.ClearAll); + private void B_CraftAll_Click(object sender, EventArgs e) => DoAll(Book.CraftAll); + + private void DoAll(Action action) + { + var index = LB_Recipes.SelectedIndex; + var book = Book; + var recipes = RecipeList.Recipes; + var strings = GameInfo.Strings.itemlist; + const ushort max = RecipeBook.RecipeCount; + + action(); + LB_Recipes.Items.Clear(); + FillListBox(max, recipes, strings, book); + LoadIndex(index); + LB_Recipes.SelectedIndex = index; + } + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + Player.Personal.SetRecipeBook(Book); + Close(); + } + + private void CB_Goto_SelectedValueChanged(object sender, EventArgs e) => LB_Recipes.SelectedIndex = WinFormsUtil.GetIndex(CB_Goto); + + private int Index = -1; + private bool Loading; + private void LB_Recipes_SelectedIndexChanged(object sender, EventArgs e) + { + if (Loading) + return; + SaveIndex(Index); + Index = LB_Recipes.SelectedIndex; + Loading = true; + LoadIndex(Index); + Loading = false; + } + + private void LoadIndex(in int index) + { + if (index < 0) + return; + var book = Book; + CHK_Known.Checked = book.GetIsKnown(index); + CHK_New.Checked = book.GetIsNew(index); + CHK_Made.Checked = book.GetIsMade(index); + CHK_Favorite.Checked = book.GetIsFavorite(index); + } + + private void SaveIndex(in int index) + { + if (index < 0) + return; + var book = Book; + book.SetIsKnown(index, CHK_Known.Checked); + book.SetIsNew(index, CHK_New.Checked); + book.SetIsMade(index, CHK_Made.Checked); + book.SetIsFavorite(index, CHK_Favorite.Checked); + } + + private void CHK_Known_CheckedChanged(object sender, EventArgs e) + { + if (Loading) + return; + Loading = true; + var book = Book; + book.SetIsKnown(Index, CHK_Known.Checked); + var recipes = RecipeList.Recipes; + var strings = GameInfo.Strings.itemlist; + var name = GetItemName((ushort)Index, recipes, strings); + LB_Recipes.Items[Index] = GetEntryText(book, (ushort)Index, name); + Loading = false; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/PlayerItemEditor.cs b/NHSE.WinForms/Subforms/PlayerItemEditor.cs index c7d48c9..5984e66 100644 --- a/NHSE.WinForms/Subforms/PlayerItemEditor.cs +++ b/NHSE.WinForms/Subforms/PlayerItemEditor.cs @@ -7,168 +7,163 @@ using NHSE.Core; using NHSE.Injection; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class PlayerItemEditor : Form { - public partial class PlayerItemEditor : Form + private readonly Action LoadItems; + private readonly ItemGridEditor ItemGrid; + private readonly ItemArrayEditor ItemArray; + + public PlayerItemEditor(IReadOnlyList array, int width, int height, bool sysbot = false) { - private readonly Action LoadItems; - private readonly ItemGridEditor ItemGrid; - private readonly ItemArrayEditor ItemArray; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + ItemArray = new ItemArrayEditor(array); - public PlayerItemEditor(IReadOnlyList array, int width, int height, bool sysbot = false) + var Editor = ItemGrid = new ItemGridEditor(ItemEditor, array) {Dock = DockStyle.Fill}; + Editor.InitializeGrid(width, height, 64, 64); + PAN_Items.Controls.Add(Editor); + + ItemEditor.Initialize(GameInfo.Strings.ItemDataSource); + Editor.LoadItems(); + DialogResult = DialogResult.Cancel; + LoadItems = () => Editor.LoadItems(); + B_Inject.Visible = sysbot; + + EnableDragDrop(this, ItemEditor_DragEnter, PlayerItemEditor_DragDrop); + EnableDragDrop(PAN_Items, ItemEditor_DragEnter, PlayerItemEditor_DragDrop); + EnableDragDrop(ItemEditor, ItemEditor_DragEnter, PlayerItemEditor_DragDrop); + } + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private void B_Dump_Click(object sender, EventArgs e) + { + using var sfd = new SaveFileDialog(); + sfd.Filter = "New Horizons Inventory (*.nhi)|*.nhi|All files (*.*)|*.*"; + sfd.FileName = "items.nhi"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + var bytes = ItemArray.Write(); + File.WriteAllBytes(sfd.FileName, bytes); + } + + private void B_Load_Click(object sender, EventArgs e) + { + bool skipOccupiedSlots = (ModifierKeys & Keys.Alt) != 0; + bool importCheatClipboard = (ModifierKeys & Keys.Control) != 0; + if (importCheatClipboard && Clipboard.ContainsText()) { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - ItemArray = new ItemArrayEditor(array); - - var Editor = ItemGrid = new ItemGridEditor(ItemEditor, array) {Dock = DockStyle.Fill}; - Editor.InitializeGrid(width, height, 64, 64); - PAN_Items.Controls.Add(Editor); - - ItemEditor.Initialize(GameInfo.Strings.ItemDataSource); - Editor.LoadItems(); - DialogResult = DialogResult.Cancel; - LoadItems = () => Editor.LoadItems(); - B_Inject.Visible = sysbot; - - EnableDragDrop(this, ItemEditor_DragEnter, PlayerItemEditor_DragDrop); - EnableDragDrop(PAN_Items, ItemEditor_DragEnter, PlayerItemEditor_DragDrop); - EnableDragDrop(ItemEditor, ItemEditor_DragEnter, PlayerItemEditor_DragDrop); - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - private void B_Dump_Click(object sender, EventArgs e) - { - using var sfd = new SaveFileDialog + var text = Clipboard.GetText(); + var bytes = ItemCheatCode.ReadCode(text); + if (bytes.Length % ItemArray.ItemSize == 0) { - Filter = "New Horizons Inventory (*.nhi)|*.nhi|All files (*.*)|*.*", - FileName = "items.nhi", - }; - if (sfd.ShowDialog() != DialogResult.OK) + ImportItemData(bytes, skipOccupiedSlots); return; - var bytes = ItemArray.Write(); - File.WriteAllBytes(sfd.FileName, bytes); + } } - private void B_Load_Click(object sender, EventArgs e) + using var sfd = new OpenFileDialog(); + sfd.Filter = "New Horizons Inventory (*.nhi)|*.nhi|All files (*.*)|*.*"; + sfd.FileName = "items.nhi"; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var data = File.ReadAllBytes(sfd.FileName); + ImportItemData(data, skipOccupiedSlots); + } + + private void ImportItemData(byte[] data, bool skipOccupiedSlots, int start = 0) + { + ItemArray.ImportItemDataX(data, skipOccupiedSlots, start); + + LoadItems(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Inject_Click(object sender, EventArgs e) + { + var exist = WinFormsUtil.FirstFormOfType(); + if (exist != null) + { + exist.Show(); + exist.BringToFront(); + exist.CenterToForm(this); + return; + } + + void AfterRead(InjectionResult r) + { + if (r == InjectionResult.Success) + LoadItems(); + } + + static void AfterWrite(InjectionResult r) + { + Debug.WriteLine($"Write result: {r}"); + System.Media.SystemSounds.Asterisk.Play(); + } + + var sb = new SysBotController(InjectionType.Pouch); + var pockInject = new PocketInjector(ItemArray.Items, sb.Bot); + var ai = new AutoInjector(pockInject, AfterRead, AfterWrite); + var ub = new USBBotController(); + var pockInjectUSB = new PocketInjector(ItemArray.Items, ub.Bot); + var aiUSB = new AutoInjector(pockInjectUSB, AfterRead, AfterWrite); + + ItemGrid.ItemChanged = () => ai.Write(); + var sysbot = new SysBotUI(ai, sb, aiUSB, ub); + sysbot.Show(); + } + + private void ItemEditor_DragEnter(object? sender, DragEventArgs e) + { + if (e.Data?.GetDataPresent(DataFormats.FileDrop) == true) + e.Effect = DragDropEffects.Copy; + } + + private void PlayerItemEditor_DragDrop(object? sender, DragEventArgs e) + { + var files = (string[]?)e.Data?.GetData(DataFormats.FileDrop); + if (files?.Length != 1 || Directory.Exists(files[0])) + return; + + string path = files[0]; // open first D&D + var fi = new FileInfo(path); + if (fi.Length > ItemArray.TotalSize || fi.Length % Item.SIZE != 0) + return; + + System.Media.SystemSounds.Asterisk.Play(); + var data = File.ReadAllBytes(path); + if (sender == ItemEditor) + { + var item = new Item(System.Buffers.Binary.BinaryPrimitives.ReadUInt64LittleEndian(data)); + ItemEditor.LoadItem(item); + } + else { bool skipOccupiedSlots = (ModifierKeys & Keys.Alt) != 0; - bool importCheatClipboard = (ModifierKeys & Keys.Control) != 0; - if (importCheatClipboard && Clipboard.ContainsText()) - { - var text = Clipboard.GetText(); - var bytes = ItemCheatCode.ReadCode(text); - if (bytes.Length % ItemArray.ItemSize == 0) - { - ImportItemData(bytes, skipOccupiedSlots); - return; - } - } - - using var sfd = new OpenFileDialog - { - Filter = "New Horizons Inventory (*.nhi)|*.nhi|All files (*.*)|*.*", - FileName = "items.nhi", - }; - if (sfd.ShowDialog() != DialogResult.OK) - return; - - var data = File.ReadAllBytes(sfd.FileName); ImportItemData(data, skipOccupiedSlots); } + } - private void ImportItemData(byte[] data, bool skipOccupiedSlots, int start = 0) + public static void EnableDragDrop(Control parent, DragEventHandler enter, DragEventHandler drop) + { + parent.AllowDrop = true; + parent.DragEnter += enter; + parent.DragDrop += drop; + foreach (var control in parent.Controls.OfType()) { - ItemArray.ImportItemDataX(data, skipOccupiedSlots, start); - - LoadItems(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Inject_Click(object sender, EventArgs e) - { - var exist = WinFormsUtil.FirstFormOfType(); - if (exist != null) - { - exist.Show(); - exist.BringToFront(); - exist.CenterToForm(this); - return; - } - - void AfterRead(InjectionResult r) - { - if (r == InjectionResult.Success) - LoadItems(); - } - - static void AfterWrite(InjectionResult r) - { - Debug.WriteLine($"Write result: {r}"); - System.Media.SystemSounds.Asterisk.Play(); - } - - var sb = new SysBotController(InjectionType.Pouch); - var pockInject = new PocketInjector(ItemArray.Items, sb.Bot); - var ai = new AutoInjector(pockInject, AfterRead, AfterWrite); - var ub = new USBBotController(); - var pockInjectUSB = new PocketInjector(ItemArray.Items, ub.Bot); - var aiUSB = new AutoInjector(pockInjectUSB, AfterRead, AfterWrite); - - ItemGrid.ItemChanged = () => ai.Write(); - var sysbot = new SysBotUI(ai, sb, aiUSB, ub); - sysbot.Show(); - } - - private void ItemEditor_DragEnter(object? sender, DragEventArgs e) - { - if (e.Data?.GetDataPresent(DataFormats.FileDrop) == true) - e.Effect = DragDropEffects.Copy; - } - - private void PlayerItemEditor_DragDrop(object? sender, DragEventArgs e) - { - var files = (string[]?)e.Data?.GetData(DataFormats.FileDrop); - if (files?.Length != 1 || Directory.Exists(files[0])) - return; - - string path = files[0]; // open first D&D - var fi = new FileInfo(path); - if (fi.Length > ItemArray.TotalSize || fi.Length % Item.SIZE != 0) - return; - - System.Media.SystemSounds.Asterisk.Play(); - var data = File.ReadAllBytes(path); - if (sender == ItemEditor) - { - var item = new Item(BitConverter.ToUInt64(data, 0)); - ItemEditor.LoadItem(item); - } - else - { - bool skipOccupiedSlots = (ModifierKeys & Keys.Alt) != 0; - ImportItemData(data, skipOccupiedSlots); - } - } - - public static void EnableDragDrop(Control parent, DragEventHandler enter, DragEventHandler drop) - { - parent.AllowDrop = true; - parent.DragEnter += enter; - parent.DragDrop += drop; - foreach (var control in parent.Controls.OfType()) - { - control.AllowDrop = true; - control.DragEnter += enter; - control.DragDrop += drop; - } + control.AllowDrop = true; + control.DragEnter += enter; + control.DragDrop += drop; } } -} +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Program/ImageFetcher.cs b/NHSE.WinForms/Subforms/Program/ImageFetcher.cs index f1db6a9..c664f59 100644 --- a/NHSE.WinForms/Subforms/Program/ImageFetcher.cs +++ b/NHSE.WinForms/Subforms/Program/ImageFetcher.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.IO.Compression; @@ -8,44 +7,42 @@ using System.Windows.Forms; using NHSE.Sprites; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public sealed partial class ImageFetcher : Form { - public sealed partial class ImageFetcher : Form + private const string Filename = "image.zip"; + private static string ZipFilePath => Path.Combine(ItemSprite.PlatformAppDataPath, Filename); + + private readonly string[] AllHosts; + + public ImageFetcher() { - private const string Filename = "image.zip"; - private static string ZipFilePath => Path.Combine(ItemSprite.PlatformAppDataPath, Filename); + InitializeComponent(); + L_Status.Text = L_FileSize.Text = string.Empty; - private readonly IReadOnlyList AllHosts; + var splitHosts = AllHosts = LoadHosts(); - public ImageFetcher() - { - InitializeComponent(); - L_Status.Text = L_FileSize.Text = string.Empty; + CB_HostSelect.Items.Clear(); + foreach (var host in splitHosts) + CB_HostSelect.Items.Add(CleanUrl(host)); - var splitHosts = AllHosts = LoadHosts(); + CB_HostSelect.SelectedIndex = 0; // set outside of initialise to update filesize via HEAD response - CB_HostSelect.Items.Clear(); - foreach (var host in splitHosts) - CB_HostSelect.Items.Add(CleanUrl(host)); + CheckFileStatusLabel(); + } - CB_HostSelect.SelectedIndex = 0; // set outside of initialise to update filesize via HEAD response + private static string[] LoadHosts() + { + var hosts = Properties.Resources.hosts_images; + var splitHosts = hosts.Split(["\r", "\n", "\r\n"], StringSplitOptions.RemoveEmptyEntries); - CheckFileStatusLabel(); - } + return splitHosts; + } - private static string[] LoadHosts() - { - var hosts = Properties.Resources.hosts_images; - var splitHosts = hosts.Split(new[] { "\r", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries); - - return splitHosts; - } - -#if NETFRAMEWORK - private void B_Download_Click(object sender, EventArgs e) -#elif NETCOREAPP - private async void B_Download_Click(object sender, EventArgs e) -#endif + private async void B_Download_Click(object sender, EventArgs e) + { + try { var path = ItemSprite.PlatformAppDataPath; var hostSelected = AllHosts[CB_HostSelect.SelectedIndex]; @@ -54,126 +51,116 @@ private async void B_Download_Click(object sender, EventArgs e) L_Status.Text = "Downloading..."; - try - { - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); -#if NETFRAMEWORK - using var webClient = new WebClient(); - webClient.DownloadFileCompleted += Completed; - webClient.DownloadProgressChanged += ProgressChanged; - webClient.DownloadFileAsync(new Uri(hostSelected), ZipFilePath); -#elif NETCOREAPP - using var httpClient = new System.Net.Http.HttpClient(); - using var stream = await httpClient.GetStreamAsync(hostSelected).ConfigureAwait(false); - using var fileStream = new FileStream(ZipFilePath, FileMode.CreateNew); - await stream.CopyToAsync(fileStream).ConfigureAwait(false); -#endif - } - catch (Exception ex) - { - WinFormsUtil.Error(ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message); - SetUIDownloadState(true); - } + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + using var httpClient = new System.Net.Http.HttpClient(); + await using var stream = await httpClient.GetStreamAsync(hostSelected).ConfigureAwait(false); + await using var fileStream = new FileStream(ZipFilePath, FileMode.CreateNew); + await stream.CopyToAsync(fileStream).ConfigureAwait(false); } - - private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) => PBar_MultiUse.Value = e.ProgressPercentage; - - private void Completed(object? sender, AsyncCompletedEventArgs e) + catch (Exception ex) { - if (e.Error != null) - { - WinFormsUtil.Error(e.Error.Message, e.Error.InnerException == null ? string.Empty : e.Error.InnerException.Message); - SetUIDownloadState(true); - return; - } - - PBar_MultiUse.Value = 100; - L_Status.Text = "Unzipping..."; - UnzipFile(); + WinFormsUtil.Error(ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message); + SetUIDownloadState(true); } + } - private async void UnzipFile() + private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) => PBar_MultiUse.Value = e.ProgressPercentage; + + private void Completed(object? sender, AsyncCompletedEventArgs e) + { + if (e.Error != null) { - try - { - var outputFolderPath = ItemSprite.PlatformAppDataImagePath; - - if (Directory.Exists(outputFolderPath)) // overwrite existing - Directory.Delete(outputFolderPath, true); - - Directory.CreateDirectory(outputFolderPath); - - await Task.Run(() => ZipFile.ExtractToDirectory(ZipFilePath, outputFolderPath)).ConfigureAwait(false); - - SetUIDownloadState(true, true); - } - catch (Exception ex) - { - WinFormsUtil.Error(ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message); - SetUIDownloadState(true); - } + WinFormsUtil.Error(e.Error.Message, e.Error.InnerException == null ? string.Empty : e.Error.InnerException.Message); + SetUIDownloadState(true); + return; } - private void SetUIDownloadState(bool val, bool success = false) + PBar_MultiUse.Value = 100; + L_Status.Text = "Unzipping..."; + UnzipFile(); + } + + private async void UnzipFile() + { + try { - ControlBox = val; - B_Download.Enabled = val; - PBar_MultiUse.Value = 0; + var outputFolderPath = ItemSprite.PlatformAppDataImagePath; - L_Status.Text = success ? "Images installed successfully." : string.Empty; + if (Directory.Exists(outputFolderPath)) // overwrite existing + Directory.Delete(outputFolderPath, true); - CheckFileStatusLabel(); + Directory.CreateDirectory(outputFolderPath); - if (success) - ItemSprite.Initialize(Core.GameInfo.GetStrings("en").itemlist); + await Task.Run(() => ZipFile.ExtractToDirectory(ZipFilePath, outputFolderPath)).ConfigureAwait(false); - if (File.Exists(ZipFilePath)) - File.Delete(ZipFilePath); + SetUIDownloadState(true, true); } - - private void CB_HostSelect_SelectedIndexChanged(object sender, EventArgs e) + catch (Exception ex) { - CheckNetworkFileSizeAsync(); + WinFormsUtil.Error(ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message); + SetUIDownloadState(true); } + } - private async void CheckNetworkFileSizeAsync() + private void SetUIDownloadState(bool val, bool success = false) + { + ControlBox = val; + B_Download.Enabled = val; + PBar_MultiUse.Value = 0; + + L_Status.Text = success ? "Images installed successfully." : string.Empty; + + CheckFileStatusLabel(); + + if (success) + ItemSprite.Initialize(Core.GameInfo.GetStrings("en").itemlist); + + if (File.Exists(ZipFilePath)) + File.Delete(ZipFilePath); + } + + private void CB_HostSelect_SelectedIndexChanged(object sender, EventArgs e) + { + CheckNetworkFileSizeAsync(); + } + + private async void CheckNetworkFileSizeAsync() + { + try { L_FileSize.Text = string.Empty; - try - { - var host = AllHosts[CB_HostSelect.SelectedIndex]; + var host = AllHosts[CB_HostSelect.SelectedIndex]; #if NETFRAMEWORK using var webClient = new WebClient(); await webClient.OpenReadTaskAsync(new Uri(host, UriKind.Absolute)).ConfigureAwait(false); var hdr = webClient.ResponseHeaders?["Content-Length"]; #elif NETCOREAPP - using var httpClient = new System.Net.Http.HttpClient(); - var httpInitialResponse = await httpClient.GetAsync(host).ConfigureAwait(false); - var hdr = httpInitialResponse.Content.Headers.ContentLength; + using var httpClient = new System.Net.Http.HttpClient(); + var httpInitialResponse = await httpClient.GetAsync(host).ConfigureAwait(false); + var hdr = httpInitialResponse.Content.Headers.ContentLength; #endif - if (hdr == null) - { - L_FileSize.Text = "Failed."; - return; - } - var totalSizeBytes = Convert.ToInt64(hdr); - var totalSizeMb = totalSizeBytes / 1e+6; - L_FileSize.Text = $"{totalSizeMb:0.##}MB"; - } - catch (Exception ex) + if (hdr == null) { - L_FileSize.Text = ex.Message; + L_FileSize.Text = "Failed."; + return; } + var totalSizeBytes = Convert.ToInt64(hdr); + var totalSizeMb = totalSizeBytes / 1e+6; + L_FileSize.Text = $"{totalSizeMb:0.##}MB"; } - - private static string CleanUrl(string url) + catch (Exception ex) { - var uri = new Uri(url); - return uri.Segments.Length < 2 ? url : $"{uri.Host}/{uri.Segments[1]}"; + L_FileSize.Text = ex.Message; } - - private bool CheckFileStatusLabel() => L_ImgStatus.Visible = ItemSprite.SingleSpriteExists; } -} + + private static string CleanUrl(string url) + { + var uri = new Uri(url); + return uri.Segments.Length < 2 ? url : $"{uri.Host}/{uri.Segments[1]}"; + } + + private bool CheckFileStatusLabel() => L_ImgStatus.Visible = ItemSprite.SingleSpriteExists; +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Program/SettingsEditor.cs b/NHSE.WinForms/Subforms/Program/SettingsEditor.cs index e5eaa9e..3bf0208 100644 --- a/NHSE.WinForms/Subforms/Program/SettingsEditor.cs +++ b/NHSE.WinForms/Subforms/Program/SettingsEditor.cs @@ -1,28 +1,27 @@ using System.Windows.Forms; using NHSE.WinForms.Properties; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class SettingsEditor : Form { - public partial class SettingsEditor : Form + private readonly Settings obj; + + public SettingsEditor() { - private readonly Settings obj; - - public SettingsEditor() - { - obj = Settings.Default; - InitializeComponent(); - PG_Settings.SelectedObject = obj; - } - - private void SettingsEditor_FormClosing(object sender, FormClosingEventArgs e) - { - obj.Save(); - } - - private void SettingsEditor_KeyDown(object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.W && ModifierKeys == Keys.Control) - Close(); - } + obj = Settings.Default; + InitializeComponent(); + PG_Settings.SelectedObject = obj; } -} + + private void SettingsEditor_FormClosing(object sender, FormClosingEventArgs e) + { + obj.Save(); + } + + private void SettingsEditor_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.W && ModifierKeys == Keys.Control) + Close(); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/SingleItemEditor.cs b/NHSE.WinForms/Subforms/SingleItemEditor.cs index 4792507..36b5a30 100644 --- a/NHSE.WinForms/Subforms/SingleItemEditor.cs +++ b/NHSE.WinForms/Subforms/SingleItemEditor.cs @@ -2,31 +2,30 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class SingleItemEditor : Form { - public partial class SingleItemEditor : Form + public Item Item { get; } + + public SingleItemEditor(Item item) { - public Item Item { get; } + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - public SingleItemEditor(Item item) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); + // disassociate from original reference + Item = item.ToBytesClass().ToClass(); - // disassociate from original reference - Item = item.ToBytesClass().ToClass(); - - ItemEditor.Initialize(GameInfo.Strings.ItemDataSource); - ItemEditor.LoadItem(Item); - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - ItemEditor.SetItem(Item); - DialogResult = DialogResult.OK; - Close(); - } + ItemEditor.Initialize(GameInfo.Strings.ItemDataSource); + ItemEditor.LoadItem(Item); } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + ItemEditor.SetItem(Item); + DialogResult = DialogResult.OK; + Close(); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/SingleObjectEditor.cs b/NHSE.WinForms/Subforms/SingleObjectEditor.cs index ea5135a..1a3a655 100644 --- a/NHSE.WinForms/Subforms/SingleObjectEditor.cs +++ b/NHSE.WinForms/Subforms/SingleObjectEditor.cs @@ -2,30 +2,29 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class SingleObjectEditor : Form where T : class { - public partial class SingleObjectEditor : Form where T : class + public SingleObjectEditor(T obj, PropertySort sort, bool showHelp) { - public SingleObjectEditor(T obj, PropertySort sort, bool showHelp) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - DialogResult = DialogResult.Cancel; - PG_Item.HelpVisible = showHelp; - PG_Item.PropertySort = sort; - PG_Item.SelectedObject = obj; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - private void PG_Item_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) - { - } + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + DialogResult = DialogResult.Cancel; + PG_Item.HelpVisible = showHelp; + PG_Item.PropertySort = sort; + PG_Item.SelectedObject = obj; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private void PG_Item_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) + { + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/SysBot/BatchEditor.cs b/NHSE.WinForms/Subforms/SysBot/BatchEditor.cs index 2df5583..bd75275 100644 --- a/NHSE.WinForms/Subforms/SysBot/BatchEditor.cs +++ b/NHSE.WinForms/Subforms/SysBot/BatchEditor.cs @@ -5,150 +5,149 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class BatchEditor : Form { - public partial class BatchEditor : Form + private readonly ItemMutator Mutator; + private readonly ItemProcessor Processor; + private readonly IReadOnlyList Items; + private readonly Item item; + private int currentFormat = -1; + + public BatchEditor(IReadOnlyList items, Item item) { - private readonly ItemMutator Mutator; - private readonly ItemProcessor Processor; - private readonly IReadOnlyList Items; - private readonly Item item; - private int currentFormat = -1; + InitializeComponent(); + Items = items; + this.item = item; + Mutator = new ItemMutator(); + Processor = new ItemProcessor(Mutator); - public BatchEditor(IReadOnlyList items, Item item) + CB_Format.Items.Clear(); + CB_Format.Items.Add("Any"); + foreach (Type t in Mutator.Reflect.Types) + CB_Format.Items.Add(t.Name.ToLower()); + CB_Format.Items.Add("All"); + + CB_Format.SelectedIndex = CB_Require.SelectedIndex = 0; + toolTip1.SetToolTip(CB_Property, "Name"); + toolTip2.SetToolTip(L_PropType, "Type"); + toolTip3.SetToolTip(L_PropValue, "Value"); + } + + private void SysBotRAMEdit_FormClosing(object sender, FormClosingEventArgs e) + { + } + + private void B_Go_Click(object sender, EventArgs e) + { + RunBackgroundWorker(); + } + + private void B_Add_Click(object sender, EventArgs e) + { + if (CB_Property.SelectedIndex < 0) + { WinFormsUtil.Alert("Invalid Property"); return; } + + var prefix = StringInstruction.Prefixes; + string s = prefix[CB_Require.SelectedIndex] + CB_Property.Items[CB_Property.SelectedIndex]!.ToString() + StringInstruction.SplitInstruction; + if (RTB_Instructions.Lines.Length != 0 && RTB_Instructions.Lines[^1].Length > 0) + s = Environment.NewLine + s; + + RTB_Instructions.AppendText(s); + } + + private void CB_Format_SelectedIndexChanged(object sender, EventArgs e) + { + if (currentFormat == CB_Format.SelectedIndex) + return; + + int format = CB_Format.SelectedIndex; + CB_Property.Items.Clear(); + CB_Property.Items.AddRange(Mutator.Reflect.Properties[format]); + CB_Property.SelectedIndex = 0; + currentFormat = format; + } + + private void CB_Property_SelectedIndexChanged(object sender, EventArgs e) + { + L_PropType.Text = Mutator.GetPropertyType(CB_Property.Text, CB_Format.SelectedIndex); + if (Mutator.TryGetHasProperty(item, CB_Property.Text, out var pi)) { - InitializeComponent(); - Items = items; - this.item = item; - Mutator = new ItemMutator(); - Processor = new ItemProcessor(Mutator); - - CB_Format.Items.Clear(); - CB_Format.Items.Add("Any"); - foreach (Type t in Mutator.Reflect.Types) - CB_Format.Items.Add(t.Name.ToLower()); - CB_Format.Items.Add("All"); - - CB_Format.SelectedIndex = CB_Require.SelectedIndex = 0; - toolTip1.SetToolTip(CB_Property, "Name"); - toolTip2.SetToolTip(L_PropType, "Type"); - toolTip3.SetToolTip(L_PropValue, "Value"); + L_PropValue.Text = pi.GetValue(item)?.ToString(); + L_PropType.ForeColor = L_PropValue.ForeColor; // reset color } - - private void SysBotRAMEdit_FormClosing(object sender, FormClosingEventArgs e) + else // no property, flag { - } - - private void B_Go_Click(object sender, EventArgs e) - { - RunBackgroundWorker(); - } - - private void B_Add_Click(object sender, EventArgs e) - { - if (CB_Property.SelectedIndex < 0) - { WinFormsUtil.Alert("Invalid Property"); return; } - - var prefix = StringInstruction.Prefixes; - string s = prefix[CB_Require.SelectedIndex] + CB_Property.Items[CB_Property.SelectedIndex]!.ToString() + StringInstruction.SplitInstruction; - if (RTB_Instructions.Lines.Length != 0 && RTB_Instructions.Lines.Last().Length > 0) - s = Environment.NewLine + s; - - RTB_Instructions.AppendText(s); - } - - private void CB_Format_SelectedIndexChanged(object sender, EventArgs e) - { - if (currentFormat == CB_Format.SelectedIndex) - return; - - int format = CB_Format.SelectedIndex; - CB_Property.Items.Clear(); - CB_Property.Items.AddRange(Mutator.Reflect.Properties[format]); - CB_Property.SelectedIndex = 0; - currentFormat = format; - } - - private void CB_Property_SelectedIndexChanged(object sender, EventArgs e) - { - L_PropType.Text = Mutator.GetPropertyType(CB_Property.Text, CB_Format.SelectedIndex); - if (Mutator.TryGetHasProperty(item, CB_Property.Text, out var pi)) - { - L_PropValue.Text = pi.GetValue(item)?.ToString(); - L_PropType.ForeColor = L_PropValue.ForeColor; // reset color - } - else // no property, flag - { - L_PropValue.Text = string.Empty; - L_PropType.ForeColor = Color.Red; - } - } - - private void RunBackgroundWorker() - { - if (RTB_Instructions.Lines.Any(line => line.Length == 0)) - { WinFormsUtil.Error("Invalid instruction detected."); return; } - - var sets = StringInstructionSet.GetBatchSets(RTB_Instructions.Lines).ToArray(); - if (sets.Any(s => s.Filters.Any(z => string.IsNullOrWhiteSpace(z.PropertyValue)))) - { WinFormsUtil.Error("Filter empty."); return; } - - if (sets.Any(z => z.Instructions.Count == 0)) - { WinFormsUtil.Error("No instructions."); return; } - - var emptyVal = sets.SelectMany(s => s.Instructions.Where(z => string.IsNullOrWhiteSpace(z.PropertyValue))).ToArray(); - if (emptyVal.Length > 0) - { - string props = string.Join(", ", emptyVal.Select(z => z.PropertyName)); - string invalid = "Property empty." + Environment.NewLine + props; - if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, invalid, "Continue?")) - return; - } - - RTB_Instructions.Enabled = B_Go.Enabled = false; - RunBatchEdit(sets); - } - - private void RunBatchEdit(StringInstructionSet[] sets) - { - bool finished = false, displayed = false; // hack cuz DoWork event isn't cleared after completion - b.DoWork += (sender, e) => - { - if (finished) - return; - // don't bother reporting progress... - Processor.Process(sets, Items); - finished = true; - }; - - b.ProgressChanged += (sender, e) => SetProgressBar(e.ProgressPercentage); - b.RunWorkerCompleted += (sender, e) => - { - string result = Processor.GetEditorResults(sets); - if (!displayed) WinFormsUtil.Alert(result); - displayed = true; - RTB_Instructions.Enabled = B_Go.Enabled = true; - SetupProgressBar(0); - }; - b.RunWorkerAsync(); - } - - // Progress Bar - private void SetupProgressBar(int count) - { - MethodInvoker mi = () => { PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = count; }; - if (PB_Show.InvokeRequired) - PB_Show.Invoke(mi); - else - mi.Invoke(); - } - - private void SetProgressBar(int i) - { - if (PB_Show.InvokeRequired) - PB_Show.Invoke((MethodInvoker)(() => PB_Show.Value = i)); - else - PB_Show.Value = i; + L_PropValue.Text = string.Empty; + L_PropType.ForeColor = Color.Red; } } -} + + private void RunBackgroundWorker() + { + if (RTB_Instructions.Lines.Any(line => line.Length == 0)) + { WinFormsUtil.Error("Invalid instruction detected."); return; } + + var sets = StringInstructionSet.GetBatchSets(RTB_Instructions.Lines).ToArray(); + if (sets.Any(s => s.Filters.Any(z => string.IsNullOrWhiteSpace(z.PropertyValue)))) + { WinFormsUtil.Error("Filter empty."); return; } + + if (sets.Any(z => z.Instructions.Count == 0)) + { WinFormsUtil.Error("No instructions."); return; } + + var emptyVal = sets.SelectMany(s => s.Instructions.Where(z => string.IsNullOrWhiteSpace(z.PropertyValue))).ToArray(); + if (emptyVal.Length > 0) + { + string props = string.Join(", ", emptyVal.Select(z => z.PropertyName)); + string invalid = "Property empty." + Environment.NewLine + props; + if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, invalid, "Continue?")) + return; + } + + RTB_Instructions.Enabled = B_Go.Enabled = false; + RunBatchEdit(sets); + } + + private void RunBatchEdit(StringInstructionSet[] sets) + { + bool finished = false, displayed = false; // hack cuz DoWork event isn't cleared after completion + b.DoWork += (sender, e) => + { + if (finished) + return; + // don't bother reporting progress... + Processor.Process(sets, Items); + finished = true; + }; + + b.ProgressChanged += (sender, e) => SetProgressBar(e.ProgressPercentage); + b.RunWorkerCompleted += (sender, e) => + { + string result = Processor.GetEditorResults(sets); + if (!displayed) WinFormsUtil.Alert(result); + displayed = true; + RTB_Instructions.Enabled = B_Go.Enabled = true; + SetupProgressBar(0); + }; + b.RunWorkerAsync(); + } + + // Progress Bar + private void SetupProgressBar(int count) + { + MethodInvoker mi = () => { PB_Show.Minimum = 0; PB_Show.Step = 1; PB_Show.Value = 0; PB_Show.Maximum = count; }; + if (PB_Show.InvokeRequired) + PB_Show.Invoke(mi); + else + mi.Invoke(); + } + + private void SetProgressBar(int i) + { + if (PB_Show.InvokeRequired) + PB_Show.Invoke((MethodInvoker)(() => PB_Show.Value = i)); + else + PB_Show.Value = i; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/SysBot/SimpleHexEditor.cs b/NHSE.WinForms/Subforms/SysBot/SimpleHexEditor.cs index 5389c59..31cdb27 100644 --- a/NHSE.WinForms/Subforms/SysBot/SimpleHexEditor.cs +++ b/NHSE.WinForms/Subforms/SysBot/SimpleHexEditor.cs @@ -3,26 +3,25 @@ using NHSE.Core; using NHSE.Injection; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class SimpleHexEditor : Form { - public partial class SimpleHexEditor : Form + public byte[] Bytes; + + public SimpleHexEditor(byte[] originalBytes) { - public byte[] Bytes; - - public SimpleHexEditor(byte[] originalBytes) - { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - RTB_RAM.Text = string.Join(" ", originalBytes.Select(z => $"{z:X2}")); - Bytes = originalBytes; - } - - private void Update_Click(object sender, System.EventArgs e) - { - var bytestring = RTB_RAM.Text.Replace("\t", "").Replace(" ", "").Trim(); - Bytes = Decoder.StringToByteArray(bytestring); - DialogResult = DialogResult.OK; - Close(); - } + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + RTB_RAM.Text = string.Join(" ", originalBytes.Select(z => $"{z:X2}")); + Bytes = originalBytes; } -} + + private void Update_Click(object sender, System.EventArgs e) + { + var bytestring = RTB_RAM.Text.Replace("\t", "").Replace(" ", "").Trim(); + Bytes = Decoder.StringToByteArray(bytestring); + DialogResult = DialogResult.OK; + Close(); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/SysBot/SysBotController.cs b/NHSE.WinForms/Subforms/SysBot/SysBotController.cs index 88e1e8b..dd75399 100644 --- a/NHSE.WinForms/Subforms/SysBot/SysBotController.cs +++ b/NHSE.WinForms/Subforms/SysBot/SysBotController.cs @@ -3,109 +3,108 @@ using NHSE.Injection; using NHSE.WinForms.Properties; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public class SysBotController { - public class SysBotController + public SysBotController(InjectionType type) => Type = type; + + private readonly InjectionType Type; + public readonly SysBot Bot = new(); + private readonly Settings Settings = Settings.Default; + + public string IP => Settings.SysBotIP; + public string Port => Settings.SysBotPort.ToString(); + + public bool Connect(string ip, string port) { - public SysBotController(InjectionType type) => Type = type; + if (!int.TryParse(port, out var p)) + p = 6000; - private readonly InjectionType Type; - public readonly SysBot Bot = new(); - private readonly Settings Settings = Settings.Default; - - public string IP => Settings.SysBotIP; - public string Port => Settings.SysBotPort.ToString(); - - public bool Connect(string ip, string port) + try { - if (!int.TryParse(port, out var p)) - p = 6000; - - try - { - Bot.Connect(ip, p); - } - catch (Exception ex) - { - WinFormsUtil.Error(ex.Message); - return false; - } - - var settings = Settings; - settings.SysBotIP = ip; - settings.SysBotPort = p; - settings.Save(); - - return true; + Bot.Connect(ip, p); + } + catch (Exception ex) + { + WinFormsUtil.Error(ex.Message); + return false; } - public uint GetDefaultOffset() - { - var settings = Settings; - return Type switch - { - InjectionType.Generic => settings.SysBotGenericOffset, - InjectionType.Pouch => settings.SysBotPouchOffset, - _ => throw new ArgumentOutOfRangeException() - }; - } + var settings = Settings; + settings.SysBotIP = ip; + settings.SysBotPort = p; + settings.Save(); - public void SetOffset(uint value) - { - var settings = Settings; - switch (Type) - { - case InjectionType.Generic: settings.SysBotGenericOffset = value; break; - case InjectionType.Pouch: settings.SysBotPouchOffset = value; break; - default: return; - } - settings.Save(); - } + return true; + } - public void HexEdit(uint offset, int length) + public uint GetDefaultOffset() + { + var settings = Settings; + return Type switch { - var read = ReadBytes(offset, length); - using var ram = new SimpleHexEditor(read); - if (ram.ShowDialog() != DialogResult.OK) + InjectionType.Generic => settings.SysBotGenericOffset, + InjectionType.Pouch => settings.SysBotPouchOffset, + _ => throw new ArgumentOutOfRangeException() + }; + } + + public void SetOffset(uint value) + { + var settings = Settings; + switch (Type) + { + case InjectionType.Generic: settings.SysBotGenericOffset = value; break; + case InjectionType.Pouch: settings.SysBotPouchOffset = value; break; + default: return; + } + settings.Save(); + } + + public void HexEdit(uint offset, int length) + { + var read = ReadBytes(offset, length); + using var ram = new SimpleHexEditor(read); + if (ram.ShowDialog() != DialogResult.OK) + return; + + var write = ram.Bytes; + if (read.Length != write.Length) + { + var prompt = WinFormsUtil.Prompt(MessageBoxButtons.OKCancel, + string.Format(MessageStrings.MsgDataSizeMismatchRAM, read.Length, write.Length), + MessageStrings.MsgAskWriteAnyway); + + if (prompt != DialogResult.OK) return; - - var write = ram.Bytes; - if (read.Length != write.Length) - { - var prompt = WinFormsUtil.Prompt(MessageBoxButtons.OKCancel, - string.Format(MessageStrings.MsgDataSizeMismatchRAM, read.Length, write.Length), - MessageStrings.MsgAskWriteAnyway); - - if (prompt != DialogResult.OK) - return; - } - - WriteBytes(ram.Bytes, offset); - SetOffset(offset); - System.Media.SystemSounds.Asterisk.Play(); } - public void PopPrompt() - { - if (Settings.SysBotPrompted) - return; + WriteBytes(ram.Bytes, offset); + SetOffset(offset); + System.Media.SystemSounds.Asterisk.Play(); + } - WinFormsUtil.Alert(MessageStrings.MsgSysBotInfo, MessageStrings.MsgSysBotRequired); - Settings.SysBotPrompted = true; - Settings.Save(); - } + public void PopPrompt() + { + if (Settings.SysBotPrompted) + return; - public void WriteBytes(byte[] data, uint offset) - { - Bot.WriteBytes(data, offset); - SetOffset(offset); - } + WinFormsUtil.Alert(MessageStrings.MsgSysBotInfo, MessageStrings.MsgSysBotRequired); + Settings.SysBotPrompted = true; + Settings.Save(); + } - public byte[] ReadBytes(uint offset, int length) - { - var result = Bot.ReadBytes(offset, length); - SetOffset(offset); - return result; - } + public void WriteBytes(byte[] data, uint offset) + { + Bot.WriteBytes(data, offset); + SetOffset(offset); + } + + public byte[] ReadBytes(uint offset, int length) + { + var result = Bot.ReadBytes(offset, length); + SetOffset(offset); + return result; } } \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/SysBot/SysBotRAMEdit.cs b/NHSE.WinForms/Subforms/SysBot/SysBotRAMEdit.cs index 6ad2983..a871356 100644 --- a/NHSE.WinForms/Subforms/SysBot/SysBotRAMEdit.cs +++ b/NHSE.WinForms/Subforms/SysBot/SysBotRAMEdit.cs @@ -3,57 +3,56 @@ using NHSE.Core; using NHSE.Injection; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class SysBotRAMEdit : Form { - public partial class SysBotRAMEdit : Form + private readonly SysBotController Bot; + + public SysBotRAMEdit(InjectionType type) { - private readonly SysBotController Bot; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + Bot = new SysBotController(type); + RamOffset.Text = Bot.GetDefaultOffset().ToString("X8"); - public SysBotRAMEdit(InjectionType type) + TB_IP.Text = Bot.IP; + TB_Port.Text = Bot.Port; + Bot.PopPrompt(); + } + + private void B_Connect_Click(object sender, EventArgs e) + { + if (!Bot.Connect(TB_IP.Text, TB_Port.Text)) + return; + GB_Inject.Enabled = true; + } + + private void SysBotRAMEdit_FormClosing(object sender, FormClosingEventArgs e) + { + if (!Bot.Bot.Connected) + return; + + try { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - Bot = new SysBotController(type); - RamOffset.Text = Bot.GetDefaultOffset().ToString("X8"); - - TB_IP.Text = Bot.IP; - TB_Port.Text = Bot.Port; - Bot.PopPrompt(); + Bot.Bot.Disconnect(); } - - private void B_Connect_Click(object sender, EventArgs e) + catch (Exception ex) { - if (!Bot.Connect(TB_IP.Text, TB_Port.Text)) - return; - GB_Inject.Enabled = true; - } - - private void SysBotRAMEdit_FormClosing(object sender, FormClosingEventArgs e) - { - if (!Bot.Bot.Connected) - return; - - try - { - Bot.Bot.Disconnect(); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - - private void B_Edit_Click(object sender, EventArgs e) - { - var offset = StringUtil.GetHexValue(RamOffset.Text); - if (offset == 0) - { - WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); - return; - } - - var length = (int)NUD_Offset.Value; - Bot.HexEdit(offset, length); + Console.WriteLine(ex.Message); } } -} + + private void B_Edit_Click(object sender, EventArgs e) + { + var offset = StringUtil.GetHexValue(RamOffset.Text); + if (offset == 0) + { + WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); + return; + } + + var length = (int)NUD_Offset.Value; + Bot.HexEdit(offset, length); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/SysBot/SysBotUI.cs b/NHSE.WinForms/Subforms/SysBot/SysBotUI.cs index 9a7b7a7..dae2313 100644 --- a/NHSE.WinForms/Subforms/SysBot/SysBotUI.cs +++ b/NHSE.WinForms/Subforms/SysBot/SysBotUI.cs @@ -3,207 +3,206 @@ using NHSE.Core; using NHSE.Injection; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class SysBotUI : Form { - public partial class SysBotUI : Form + private readonly AutoInjector Injector; + private readonly SysBotController Bot; + private readonly AutoInjector InjectorUSB; + private readonly USBBotController BotUSB; + + public SysBotUI(AutoInjector injector, SysBotController c, AutoInjector injectorUSB, USBBotController b) { - private readonly AutoInjector Injector; - private readonly SysBotController Bot; - private readonly AutoInjector InjectorUSB; - private readonly USBBotController BotUSB; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + Bot = c; + Injector = injector; + BotUSB = b; + InjectorUSB = injectorUSB; - public SysBotUI(AutoInjector injector, SysBotController c, AutoInjector injectorUSB, USBBotController b) + var offset = Bot.GetDefaultOffset(); + Injector.SetWriteOffset(offset); + RamOffset.Text = offset.ToString("X8"); + RamOffsetUSB.Text = offset.ToString("X8"); + + TB_IP.Text = Bot.IP; + TB_Port.Text = Bot.Port; + + Bot.PopPrompt(); + + TIM_Interval.Tick += (s, e) => injector.Read(); + } + + private void B_Connect_Click(object sender, EventArgs e) + { + if (!Bot.Connect(TB_IP.Text, TB_Port.Text)) + return; + GB_Inject.Enabled = true; + } + + private void SysBotUI_FormClosing(object sender, FormClosingEventArgs e) + { + TurnOffAuto(); + if (!Bot.Bot.Connected) + return; + + try { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - Bot = c; - Injector = injector; - BotUSB = b; - InjectorUSB = injectorUSB; - - var offset = Bot.GetDefaultOffset(); - Injector.SetWriteOffset(offset); - RamOffset.Text = offset.ToString("X8"); - RamOffsetUSB.Text = offset.ToString("X8"); - - TB_IP.Text = Bot.IP; - TB_Port.Text = Bot.Port; - - Bot.PopPrompt(); - - TIM_Interval.Tick += (s, e) => injector.Read(); + Bot.Bot.Disconnect(); } - - private void B_Connect_Click(object sender, EventArgs e) + catch (Exception ex) { - if (!Bot.Connect(TB_IP.Text, TB_Port.Text)) - return; - GB_Inject.Enabled = true; - } - - private void SysBotUI_FormClosing(object sender, FormClosingEventArgs e) - { - TurnOffAuto(); - if (!Bot.Bot.Connected) - return; - - try - { - Bot.Bot.Disconnect(); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - - private void B_WriteCurrent_Click(object sender, EventArgs e) - { - var offset = StringUtil.GetHexValue(RamOffset.Text); - if (offset == 0) - { - WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); - return; - } - - Injector.SetWriteOffset(offset); - - try - { - InjectionResult result; - if (Injector.Injector is PocketInjector p) - { - p.SpoofInventoryWrite = ModifierKeys == Keys.Control; - result = Injector.Write(true); - p.SpoofInventoryWrite = false; - } - else - { - result = Injector.Write(true); - } - if (result == InjectionResult.Success) - return; - WinFormsUtil.Alert(result.ToString()); - } - catch (Exception ex) - { - WinFormsUtil.Error(ex.Message); - } - TurnOffAuto(); - } - - private void B_ReadCurrent_Click(object sender, EventArgs e) - { - try - { - var result = Injector.Read(true); - if (result == InjectionResult.Success) - return; - WinFormsUtil.Alert(result.ToString()); - } - catch (Exception ex) - { - WinFormsUtil.Error(ex.Message); - } - TurnOffAuto(); - } - - private void TurnOffAuto() - { - if (CHK_AutoRead.Checked) - CHK_AutoRead.Checked = false; - if (CHK_AutoWrite.Checked) - CHK_AutoWrite.Checked = false; - } - - private void CHK_AutoWrite_CheckedChanged(object sender, EventArgs e) => Injector.AutoInjectEnabled = CHK_AutoWrite.Checked; - private void CHK_AutoRead_CheckedChanged(object sender, EventArgs e) => TIM_Interval.Enabled = CHK_AutoRead.Checked; - private void CHK_Validate_CheckedChanged(object sender, EventArgs e) => Injector.ValidateEnabled = CHK_Validate.Checked; - - private void RamOffset_TextChanged(object sender, EventArgs e) - { - var offset = StringUtil.GetHexValue(RamOffset.Text); - if (offset == 0) - { - WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); - return; - } - - Injector.SetWriteOffset(offset); - Bot.SetOffset(offset); - } - - private void ReadUSB_Click(object sender, EventArgs e) - { - if (!BotUSB.Connect()) - return; - - var offset = StringUtil.GetHexValue(RamOffsetUSB.Text); - if (offset == 0) - { - WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); - return; - } - - InjectorUSB.SetWriteOffset(offset); - Bot.SetOffset(offset); - - try - { - var result = InjectorUSB.Read(true); - if (result == InjectionResult.Success) - return; - WinFormsUtil.Alert(result.ToString()); - } - catch (Exception ex) - { - WinFormsUtil.Error(ex.Message); - } - - BotUSB.Disconnect(); - } - - private void WriteUSB_Click(object sender, EventArgs e) - { - if (!BotUSB.Connect()) - return; - - var offset = StringUtil.GetHexValue(RamOffsetUSB.Text); - if (offset == 0) - { - WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); - return; - } - - InjectorUSB.SetWriteOffset(offset); - Bot.SetOffset(offset); - - try - { - var result = InjectorUSB.Write(true); - if (result == InjectionResult.Success) - return; - WinFormsUtil.Alert(result.ToString()); - } - catch (Exception ex) - { - WinFormsUtil.Error(ex.Message); - } - - BotUSB.Disconnect(); - } - - private void RamOffsetUSB_TextChanged(object sender, EventArgs e) - { - var offset = StringUtil.GetHexValue(RamOffsetUSB.Text); - if (offset == 0) - { - WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); - return; - } - - Injector.SetWriteOffset(offset); - Bot.SetOffset(offset); + Console.WriteLine(ex.Message); } } -} + + private void B_WriteCurrent_Click(object sender, EventArgs e) + { + var offset = StringUtil.GetHexValue(RamOffset.Text); + if (offset == 0) + { + WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); + return; + } + + Injector.SetWriteOffset(offset); + + try + { + InjectionResult result; + if (Injector.Injector is PocketInjector p) + { + p.SpoofInventoryWrite = ModifierKeys == Keys.Control; + result = Injector.Write(true); + p.SpoofInventoryWrite = false; + } + else + { + result = Injector.Write(true); + } + if (result == InjectionResult.Success) + return; + WinFormsUtil.Alert(result.ToString()); + } + catch (Exception ex) + { + WinFormsUtil.Error(ex.Message); + } + TurnOffAuto(); + } + + private void B_ReadCurrent_Click(object sender, EventArgs e) + { + try + { + var result = Injector.Read(true); + if (result == InjectionResult.Success) + return; + WinFormsUtil.Alert(result.ToString()); + } + catch (Exception ex) + { + WinFormsUtil.Error(ex.Message); + } + TurnOffAuto(); + } + + private void TurnOffAuto() + { + if (CHK_AutoRead.Checked) + CHK_AutoRead.Checked = false; + if (CHK_AutoWrite.Checked) + CHK_AutoWrite.Checked = false; + } + + private void CHK_AutoWrite_CheckedChanged(object sender, EventArgs e) => Injector.AutoInjectEnabled = CHK_AutoWrite.Checked; + private void CHK_AutoRead_CheckedChanged(object sender, EventArgs e) => TIM_Interval.Enabled = CHK_AutoRead.Checked; + private void CHK_Validate_CheckedChanged(object sender, EventArgs e) => Injector.ValidateEnabled = CHK_Validate.Checked; + + private void RamOffset_TextChanged(object sender, EventArgs e) + { + var offset = StringUtil.GetHexValue(RamOffset.Text); + if (offset == 0) + { + WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); + return; + } + + Injector.SetWriteOffset(offset); + Bot.SetOffset(offset); + } + + private void ReadUSB_Click(object sender, EventArgs e) + { + if (!BotUSB.Connect()) + return; + + var offset = StringUtil.GetHexValue(RamOffsetUSB.Text); + if (offset == 0) + { + WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); + return; + } + + InjectorUSB.SetWriteOffset(offset); + Bot.SetOffset(offset); + + try + { + var result = InjectorUSB.Read(true); + if (result == InjectionResult.Success) + return; + WinFormsUtil.Alert(result.ToString()); + } + catch (Exception ex) + { + WinFormsUtil.Error(ex.Message); + } + + BotUSB.Disconnect(); + } + + private void WriteUSB_Click(object sender, EventArgs e) + { + if (!BotUSB.Connect()) + return; + + var offset = StringUtil.GetHexValue(RamOffsetUSB.Text); + if (offset == 0) + { + WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); + return; + } + + InjectorUSB.SetWriteOffset(offset); + Bot.SetOffset(offset); + + try + { + var result = InjectorUSB.Write(true); + if (result == InjectionResult.Success) + return; + WinFormsUtil.Alert(result.ToString()); + } + catch (Exception ex) + { + WinFormsUtil.Error(ex.Message); + } + + BotUSB.Disconnect(); + } + + private void RamOffsetUSB_TextChanged(object sender, EventArgs e) + { + var offset = StringUtil.GetHexValue(RamOffsetUSB.Text); + if (offset == 0) + { + WinFormsUtil.Error(MessageStrings.MsgInvalidHexValue); + return; + } + + Injector.SetWriteOffset(offset); + Bot.SetOffset(offset); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/SysBot/USBBotController.cs b/NHSE.WinForms/Subforms/SysBot/USBBotController.cs index 206937c..5b9ea18 100644 --- a/NHSE.WinForms/Subforms/SysBot/USBBotController.cs +++ b/NHSE.WinForms/Subforms/SysBot/USBBotController.cs @@ -1,51 +1,50 @@ using System; using NHSE.Injection; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public class USBBotController { - public class USBBotController + public readonly USBBot Bot = new(); + + public bool Connect() { - public readonly USBBot Bot = new(); - - public bool Connect() + try { - try - { - return Bot.Connect(); - } - catch (Exception ex) - { - WinFormsUtil.Error(ex.Message); - return false; - } + return Bot.Connect(); } - - public void Disconnect() + catch (Exception ex) { - Bot.Disconnect(); - } - - //todo: this - //public uint GetDefaultOffset() - //{ - // return Settings.Default.SysBotPouchOffset; - //} - - //public void PopPrompt() - //{ - //} - - public void WriteBytes(byte[] data, uint offset) - { - Bot.WriteBytes(data, offset); - //SetOffset(offset); - } - - public byte[] ReadBytes(uint offset, int length) - { - var result = Bot.ReadBytes(offset, length); - //SetOffset(offset); - return result; + WinFormsUtil.Error(ex.Message); + return false; } } -} + + public void Disconnect() + { + Bot.Disconnect(); + } + + //todo: this + //public uint GetDefaultOffset() + //{ + // return Settings.Default.SysBotPouchOffset; + //} + + //public void PopPrompt() + //{ + //} + + public void WriteBytes(byte[] data, uint offset) + { + Bot.WriteBytes(data, offset); + //SetOffset(offset); + } + + public byte[] ReadBytes(uint offset, int length) + { + var result = Bot.ReadBytes(offset, length); + //SetOffset(offset); + return result; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Villager/SaveRoomFloorWallEditor.cs b/NHSE.WinForms/Subforms/Villager/SaveRoomFloorWallEditor.cs index 6d7065f..c2c01cf 100644 --- a/NHSE.WinForms/Subforms/Villager/SaveRoomFloorWallEditor.cs +++ b/NHSE.WinForms/Subforms/Villager/SaveRoomFloorWallEditor.cs @@ -2,80 +2,79 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class SaveRoomFloorWallEditor : Form { - public partial class SaveRoomFloorWallEditor : Form + public GSaveRoomFloorWall Entity { get; private set; } + + public SaveRoomFloorWallEditor(GSaveRoomFloorWall v) { - public GSaveRoomFloorWall Entity { get; private set; } + Entity = v; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + DialogResult = DialogResult.Cancel; - public SaveRoomFloorWallEditor(GSaveRoomFloorWall v) - { - Entity = v; - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - DialogResult = DialogResult.Cancel; + var ent = Entity; + NUD_DesignAccent.Value = ent.AccentWallMyDesignID; + NUD_DesignWall.Value = ent.WallMyDesignID; + NUD_DesignFloor.Value = ent.FloorMyDesignID; - var ent = Entity; - NUD_DesignAccent.Value = ent.AccentWallMyDesignID; - NUD_DesignWall.Value = ent.WallMyDesignID; - NUD_DesignFloor.Value = ent.FloorMyDesignID; - - NUD_DirAccent.Value = ent.AccentWallDirection; - NUD_InfoBit.Value = ent.InfoBit; - NUD_DirFloor.Value = ent.FloorDirection; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - var ent = Entity; - - ent.AccentWallMyDesignID = (ushort)NUD_DesignAccent.Value; - ent.WallMyDesignID = (ushort)NUD_DesignWall.Value; - ent.FloorMyDesignID = (ushort)NUD_DesignFloor.Value; - - ent.AccentWallDirection = (byte)NUD_DirAccent.Value; - ent.InfoBit = (byte)NUD_InfoBit.Value; - ent.FloorDirection = (byte)NUD_DirFloor.Value; - - Entity = ent; - - DialogResult = DialogResult.OK; - Close(); - } - - private void B_AccentWall_Click(object sender, EventArgs e) - { - var ent = Entity; - var accent = ent.AccentWallItem.ToBytes().ToClass(); - using var editor = new SingleItemEditor(accent); - editor.ShowDialog(); - if (editor.DialogResult == DialogResult.OK) - ent.AccentWallItem = editor.Item.ToBytesClass().ToStructure(); - Entity = ent; - } - - private void B_Wall_Click(object sender, EventArgs e) - { - var ent = Entity; - var accent = ent.WallItem.ToBytes().ToClass(); - using var editor = new SingleItemEditor(accent); - editor.ShowDialog(); - if (editor.DialogResult == DialogResult.OK) - ent.WallItem = editor.Item.ToBytesClass().ToStructure(); - Entity = ent; - } - - private void B_Floor_Click(object sender, EventArgs e) - { - var ent = Entity; - var accent = ent.FloorItem.ToBytes().ToClass(); - using var editor = new SingleItemEditor(accent); - editor.ShowDialog(); - if (editor.DialogResult == DialogResult.OK) - ent.FloorItem = editor.Item.ToBytesClass().ToStructure(); - Entity = ent; - } + NUD_DirAccent.Value = ent.AccentWallDirection; + NUD_InfoBit.Value = ent.InfoBit; + NUD_DirFloor.Value = ent.FloorDirection; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + var ent = Entity; + + ent.AccentWallMyDesignID = (ushort)NUD_DesignAccent.Value; + ent.WallMyDesignID = (ushort)NUD_DesignWall.Value; + ent.FloorMyDesignID = (ushort)NUD_DesignFloor.Value; + + ent.AccentWallDirection = (byte)NUD_DirAccent.Value; + ent.InfoBit = (byte)NUD_InfoBit.Value; + ent.FloorDirection = (byte)NUD_DirFloor.Value; + + Entity = ent; + + DialogResult = DialogResult.OK; + Close(); + } + + private void B_AccentWall_Click(object sender, EventArgs e) + { + var ent = Entity; + var accent = ent.AccentWallItem.ToBytes().ToClass(); + using var editor = new SingleItemEditor(accent); + editor.ShowDialog(); + if (editor.DialogResult == DialogResult.OK) + ent.AccentWallItem = editor.Item.ToBytesClass().ToStructure(); + Entity = ent; + } + + private void B_Wall_Click(object sender, EventArgs e) + { + var ent = Entity; + var accent = ent.WallItem.ToBytes().ToClass(); + using var editor = new SingleItemEditor(accent); + editor.ShowDialog(); + if (editor.DialogResult == DialogResult.OK) + ent.WallItem = editor.Item.ToBytesClass().ToStructure(); + Entity = ent; + } + + private void B_Floor_Click(object sender, EventArgs e) + { + var ent = Entity; + var accent = ent.FloorItem.ToBytes().ToClass(); + using var editor = new SingleItemEditor(accent); + editor.ShowDialog(); + if (editor.DialogResult == DialogResult.OK) + ent.FloorItem = editor.Item.ToBytesClass().ToStructure(); + Entity = ent; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.cs b/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.cs index 939333e..9b4a934 100644 --- a/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.cs +++ b/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.cs @@ -3,71 +3,70 @@ using System.Collections.Generic; using System.Windows.Forms; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class VillagerDIYTimerEditor : Form { - public partial class VillagerDIYTimerEditor : Form + private readonly List Recipes = GameInfo.Strings.CreateItemDataSource(RecipeList.Recipes, false); + + private readonly IVillager Villager; + + private byte Hour, Minute, Second; + private ushort RecipeIndex; + + public VillagerDIYTimerEditor(IVillager v) { - private readonly List Recipes = GameInfo.Strings.CreateItemDataSource(RecipeList.Recipes, false); + Villager = v; + Hour = Villager.DIYEndHour; + Minute = Villager.DIYEndMinute; + Second = Villager.DIYEndSecond; - private readonly IVillager Villager; + InitializeComponent(); - private byte Hour, Minute, Second; - private ushort RecipeIndex; + // Both hour and minute will be 255 in most cases when villager is idling. + // If another villager's end time is earlier, this villager will not craft UNLESS the villager is crafting an "event" item, in which case it seems it will take priority. + bool idleState = Hour == byte.MaxValue || Minute == byte.MaxValue; + DT_Time.Value = idleState ? new DateTime(1970, 01, 01, 0, 0, 0) : new DateTime(1970, 01, 01, Hour, Minute, Second); - public VillagerDIYTimerEditor(IVillager v) - { - Villager = v; - Hour = Villager.DIYEndHour; - Minute = Villager.DIYEndMinute; - Second = Villager.DIYEndSecond; + CHK_Crafting.Checked = DT_Time.Enabled = !idleState; - InitializeComponent(); + CB_Recipe.DisplayMember = nameof(ComboItem.Text); + CB_Recipe.ValueMember = nameof(ComboItem.Value); + CB_Recipe.DataSource = Recipes; - // Both hour and minute will be 255 in most cases when villager is idling. - // If another villager's end time is earlier, this villager will not craft UNLESS the villager is crafting an "event" item, in which case it seems it will take priority. - bool idleState = Hour == byte.MaxValue || Minute == byte.MaxValue; - DT_Time.Value = idleState ? new DateTime(1970, 01, 01, 0, 0, 0) : new DateTime(1970, 01, 01, Hour, Minute, Second); - - CHK_Crafting.Checked = DT_Time.Enabled = !idleState; - - CB_Recipe.DisplayMember = nameof(ComboItem.Text); - CB_Recipe.ValueMember = nameof(ComboItem.Value); - CB_Recipe.DataSource = Recipes; - - RecipeIndex = Villager.DIYRecipeIndex; - CB_Recipe.SelectedValue = (int)RecipeIndex; - } - - private void CB_Recipe_SelectedIndexChanged(object sender, EventArgs e) - { - var val = WinFormsUtil.GetIndex((ComboBox)sender); - RecipeIndex = (ushort)Math.Max(0, Math.Min(ushort.MaxValue, val)); - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - Villager.DIYEndHour = Hour; - Villager.DIYEndMinute = Minute; - Villager.DIYEndSecond = Second; - Villager.DIYRecipeIndex = RecipeIndex; - DialogResult = DialogResult.OK; - Close(); - } - - private void CHK_Crafting_CheckedChanged(object sender, EventArgs e) - { - Hour = CHK_Crafting.Checked ? (byte)DT_Time.Value.Hour : byte.MaxValue; - Minute = CHK_Crafting.Checked ? (byte)DT_Time.Value.Minute : byte.MaxValue; - DT_Time.Enabled = CHK_Crafting.Checked; - } - - private void DT_Time_ValueChanged(object sender, EventArgs e) - { - Hour = (byte)DT_Time.Value.Hour; - Minute = (byte)DT_Time.Value.Minute; - Second = (byte)DT_Time.Value.Second; - } + RecipeIndex = Villager.DIYRecipeIndex; + CB_Recipe.SelectedValue = (int)RecipeIndex; } -} + + private void CB_Recipe_SelectedIndexChanged(object sender, EventArgs e) + { + var val = WinFormsUtil.GetIndex((ComboBox)sender); + RecipeIndex = (ushort)Math.Max(0, Math.Min(ushort.MaxValue, val)); + } + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + Villager.DIYEndHour = Hour; + Villager.DIYEndMinute = Minute; + Villager.DIYEndSecond = Second; + Villager.DIYRecipeIndex = RecipeIndex; + DialogResult = DialogResult.OK; + Close(); + } + + private void CHK_Crafting_CheckedChanged(object sender, EventArgs e) + { + Hour = CHK_Crafting.Checked ? (byte)DT_Time.Value.Hour : byte.MaxValue; + Minute = CHK_Crafting.Checked ? (byte)DT_Time.Value.Minute : byte.MaxValue; + DT_Time.Enabled = CHK_Crafting.Checked; + } + + private void DT_Time_ValueChanged(object sender, EventArgs e) + { + Hour = (byte)DT_Time.Value.Hour; + Minute = (byte)DT_Time.Value.Minute; + Second = (byte)DT_Time.Value.Second; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Villager/VillagerFlagEditor.cs b/NHSE.WinForms/Subforms/Villager/VillagerFlagEditor.cs index 61ab95f..25aa67d 100644 --- a/NHSE.WinForms/Subforms/Villager/VillagerFlagEditor.cs +++ b/NHSE.WinForms/Subforms/Villager/VillagerFlagEditor.cs @@ -2,64 +2,63 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class VillagerFlagEditor : Form { - public partial class VillagerFlagEditor : Form + private readonly ushort[] Counts; + + public VillagerFlagEditor(ushort[] counts) { - private readonly ushort[] Counts; - - public VillagerFlagEditor(ushort[] counts) - { - Counts = counts; - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - var str = GameInfo.Strings.InternalNameTranslation; - for (ushort i = 0; i < counts.Length; i++) - LB_Counts.Items.Add(EventFlagVillager.GetName(i, counts[i], str)); - DialogResult = DialogResult.Cancel; - LB_Counts.SelectedIndex = 0; - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - private int Index; - - private void NUD_Count_ValueChanged(object sender, EventArgs e) - { - if (Index < 0) - return; - - Counts[Index] = (ushort) NUD_Count.Value; - LB_Counts.Items[Index] = EventFlagVillager.GetName((ushort)Index, Counts[Index], GameInfo.Strings.InternalNameTranslation); - } - - private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Counts.SelectedIndex < 0) - return; - - NUD_Count.Value = Counts[Index = LB_Counts.SelectedIndex]; - } - - private void B_Dump_Click(object sender, EventArgs e) - { - byte[] data = new byte[Counts.Length * 2]; - Buffer.BlockCopy(Counts, 0, data, 0, data.Length); - MiscDumpHelper.DumpFlags(data, nameof(EventFlagVillager)); - } - - private void B_Load_Click(object sender, EventArgs e) - { - var data = MiscDumpHelper.LoadFlags(Counts.Length * 2, nameof(EventFlagVillager)); - if (data.Length != 0) - Buffer.BlockCopy(data, 0, Counts, 0, data.Length); - LB_Counts.SelectedIndex = LB_Counts.SelectedIndex; - } + Counts = counts; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); + var str = GameInfo.Strings.InternalNameTranslation; + for (ushort i = 0; i < counts.Length; i++) + LB_Counts.Items.Add(EventFlagVillager.GetName(i, counts[i], str)); + DialogResult = DialogResult.Cancel; + LB_Counts.SelectedIndex = 0; } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private int Index; + + private void NUD_Count_ValueChanged(object sender, EventArgs e) + { + if (Index < 0) + return; + + Counts[Index] = (ushort) NUD_Count.Value; + LB_Counts.Items[Index] = EventFlagVillager.GetName((ushort)Index, Counts[Index], GameInfo.Strings.InternalNameTranslation); + } + + private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Counts.SelectedIndex < 0) + return; + + NUD_Count.Value = Counts[Index = LB_Counts.SelectedIndex]; + } + + private void B_Dump_Click(object sender, EventArgs e) + { + byte[] data = new byte[Counts.Length * 2]; + Buffer.BlockCopy(Counts, 0, data, 0, data.Length); + MiscDumpHelper.DumpFlags(data, nameof(EventFlagVillager)); + } + + private void B_Load_Click(object sender, EventArgs e) + { + var data = MiscDumpHelper.LoadFlags(Counts.Length * 2, nameof(EventFlagVillager)); + if (data.Length != 0) + Buffer.BlockCopy(data, 0, Counts, 0, data.Length); + LB_Counts.SelectedIndex = LB_Counts.SelectedIndex; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Villager/VillagerMemoryEditor.cs b/NHSE.WinForms/Subforms/Villager/VillagerMemoryEditor.cs index 14f3af6..3cf6ae6 100644 --- a/NHSE.WinForms/Subforms/Villager/VillagerMemoryEditor.cs +++ b/NHSE.WinForms/Subforms/Villager/VillagerMemoryEditor.cs @@ -3,167 +3,166 @@ using System.Windows.Forms; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public partial class VillagerMemoryEditor : Form { - public partial class VillagerMemoryEditor : Form + private readonly IVillager Villager; + private readonly GSaveMemory[] Memories; + + private int PlayerIndex = -1; + private int FlagIndex = -1; + private byte[] Flags = []; + + private readonly TextBox[] Greetings; + + public VillagerMemoryEditor(IVillager villager) { - private readonly IVillager Villager; - private readonly GSaveMemory[] Memories; + InitializeComponent(); + this.TranslateInterface(GameInfo.CurrentLanguage); - private int PlayerIndex = -1; - private int FlagIndex = -1; - private byte[] Flags = Array.Empty(); + Greetings = + [ + TB_Greeting, + TB_Greeting1, TB_Greeting2, TB_Greeting3, TB_Greeting4, TB_Greeting5, + TB_Greeting6, TB_Greeting7, TB_Greeting8, TB_Greeting9, TB_Greeting10 + ]; - private readonly TextBox[] Greetings; + Villager = villager; + Memories = villager.GetMemories(); - public VillagerMemoryEditor(IVillager villager) + UpdatePlayerIslandStrings(); + + LB_Players.SelectedIndex = 0; + + DialogResult = DialogResult.Cancel; + LB_Counts.SelectedIndex = 0; + } + + private void UpdatePlayerIslandStrings() + { + if (LB_Players.Items.Count < 1) { - InitializeComponent(); - this.TranslateInterface(GameInfo.CurrentLanguage); - - Greetings = new[] - { - TB_Greeting, - TB_Greeting1, TB_Greeting2, TB_Greeting3, TB_Greeting4, TB_Greeting5, - TB_Greeting6, TB_Greeting7, TB_Greeting8, TB_Greeting9, TB_Greeting10 - }; - - Villager = villager; - Memories = villager.GetMemories(); - - UpdatePlayerIslandStrings(); - - LB_Players.SelectedIndex = 0; - - DialogResult = DialogResult.Cancel; - LB_Counts.SelectedIndex = 0; + for (int i = 0; i < Memories.Length; i++) + LB_Players.Items.Add($"{i} - {Memories[i].PlayerName} ({Memories[i].TownName})"); } - - private void UpdatePlayerIslandStrings() + else { - if (LB_Players.Items.Count < 1) - { - for (int i = 0; i < Memories.Length; i++) - LB_Players.Items.Add($"{i} - {Memories[i].PlayerName} ({Memories[i].TownName})"); - } - else - { - for (int i = 0; i < LB_Players.Items.Count; i++) - LB_Players.Items[i] = $"{i} - {Memories[i].PlayerName} ({Memories[i].TownName})"; - } - } - - private void B_Cancel_Click(object sender, EventArgs e) => Close(); - - private void B_Save_Click(object sender, EventArgs e) - { - SavePlayer(PlayerIndex); - Villager.SetMemories(Memories); - DialogResult = DialogResult.OK; - Close(); - } - - private static string GetFlagDescription(int index, IReadOnlyList flags, IReadOnlyDictionary str) - { - return EventFlagVillagerMemoryPlayer.GetName((ushort)index, flags[index], str); - } - - private void NUD_Count_ValueChanged(object sender, EventArgs e) - { - var flagIndex = FlagIndex; - if (flagIndex < 0) - return; - - Flags[FlagIndex] = (byte) NUD_Count.Value; - LB_Counts.Items[FlagIndex] = GetFlagDescription(flagIndex, Flags, GameInfo.Strings.InternalNameTranslation); - } - - private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) - { - if (LB_Counts.SelectedIndex < 0) - return; - - NUD_Count.Value = Flags[FlagIndex = LB_Counts.SelectedIndex]; - } - - private void LB_Players_SelectedIndexChanged(object sender, EventArgs e) - { - SavePlayer(PlayerIndex); - PlayerIndex = LB_Players.SelectedIndex; - if (PlayerIndex >= 0) - LoadPlayer(PlayerIndex); - } - - private void LoadPlayer(in int playerIndex) - { - FlagIndex = -1; - var index = LB_Counts.SelectedIndex; - var memory = Memories[playerIndex]; - var flags = memory.GetEventFlags(); - - var str = GameInfo.Strings.InternalNameTranslation; - LB_Counts.Items.Clear(); - for (int i = 0; i < flags.Length; i++) - LB_Counts.Items.Add(GetFlagDescription((byte)i, flags, str)); - - Flags = flags; - LB_Counts.SelectedIndex = FlagIndex = index; - - TB_NickName.Text = memory.NickName; - for (int i = 0; i < Greetings.Length; i++) - Greetings[i].Text = memory.GetGreeting(i); - - var date = memory.GreetingSetDate; - if (date < CAL_GreetDate.MinDate) - date = CAL_GreetDate.MinDate; - CAL_GreetDate.Value = date; - - TB_NamePlayer.Text = memory.PlayerName; - TB_Island.Text = memory.TownName; - } - - private void SavePlayer(in int playerIndex) - { - if (playerIndex < 0) - return; - - var memory = Memories[playerIndex]; - memory.SetEventFlags(Flags); - - memory.NickName = TB_NickName.Text; - for (int i = 0; i < Greetings.Length; i++) - memory.SetGreeting(Greetings[i].Text, i); - memory.GreetingSetDate = CAL_GreetDate.Value == CAL_GreetDate.MinDate ? new GSaveDate() : CAL_GreetDate.Value; - } - - private void B_Dump_Click(object sender, EventArgs e) - { - SavePlayer(PlayerIndex); - MiscDumpHelper.DumpVillagerMemoryPlayer(Villager, Memories[PlayerIndex]); - } - - private void B_Load_Click(object sender, EventArgs e) - { - if (!MiscDumpHelper.LoadVillagerMemoryPlayer(Villager, Memories, PlayerIndex)) - return; - LoadPlayer(PlayerIndex); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void TB_NamePlayer_TextChanged(object sender, EventArgs e) - { - if (LB_Players.SelectedIndex < 0) - return; - Memories[LB_Players.SelectedIndex].PlayerName = TB_NamePlayer.Text; // this should be enough for player name changes within NHSE as identities are never changed by the end-user - UpdatePlayerIslandStrings(); - } - - private void TB_Island_TextChanged(object sender, EventArgs e) - { - if (LB_Players.SelectedIndex < 0) - return; - Memories[LB_Players.SelectedIndex].TownName = TB_Island.Text; // as above - UpdatePlayerIslandStrings(); + for (int i = 0; i < LB_Players.Items.Count; i++) + LB_Players.Items[i] = $"{i} - {Memories[i].PlayerName} ({Memories[i].TownName})"; } } -} + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + SavePlayer(PlayerIndex); + Villager.SetMemories(Memories); + DialogResult = DialogResult.OK; + Close(); + } + + private static string GetFlagDescription(int index, ReadOnlySpan flags, IReadOnlyDictionary str) + { + return EventFlagVillagerMemoryPlayer.GetName((ushort)index, flags[index], str); + } + + private void NUD_Count_ValueChanged(object sender, EventArgs e) + { + var flagIndex = FlagIndex; + if (flagIndex < 0) + return; + + Flags[FlagIndex] = (byte) NUD_Count.Value; + LB_Counts.Items[FlagIndex] = GetFlagDescription(flagIndex, Flags, GameInfo.Strings.InternalNameTranslation); + } + + private void LB_Counts_SelectedIndexChanged(object sender, EventArgs e) + { + if (LB_Counts.SelectedIndex < 0) + return; + + NUD_Count.Value = Flags[FlagIndex = LB_Counts.SelectedIndex]; + } + + private void LB_Players_SelectedIndexChanged(object sender, EventArgs e) + { + SavePlayer(PlayerIndex); + PlayerIndex = LB_Players.SelectedIndex; + if (PlayerIndex >= 0) + LoadPlayer(PlayerIndex); + } + + private void LoadPlayer(in int playerIndex) + { + FlagIndex = -1; + var index = LB_Counts.SelectedIndex; + var memory = Memories[playerIndex]; + var flags = memory.GetEventFlags(); + + var str = GameInfo.Strings.InternalNameTranslation; + LB_Counts.Items.Clear(); + for (int i = 0; i < flags.Length; i++) + LB_Counts.Items.Add(GetFlagDescription((byte)i, flags, str)); + + Flags = flags; + LB_Counts.SelectedIndex = FlagIndex = index; + + TB_NickName.Text = memory.NickName; + for (int i = 0; i < Greetings.Length; i++) + Greetings[i].Text = memory.GetGreeting(i); + + var date = memory.GreetingSetDate; + if (date < CAL_GreetDate.MinDate) + date = CAL_GreetDate.MinDate; + CAL_GreetDate.Value = date; + + TB_NamePlayer.Text = memory.PlayerName; + TB_Island.Text = memory.TownName; + } + + private void SavePlayer(in int playerIndex) + { + if (playerIndex < 0) + return; + + var memory = Memories[playerIndex]; + memory.SetEventFlags(Flags); + + memory.NickName = TB_NickName.Text; + for (int i = 0; i < Greetings.Length; i++) + memory.SetGreeting(Greetings[i].Text, i); + memory.GreetingSetDate = CAL_GreetDate.Value == CAL_GreetDate.MinDate ? new GSaveDate() : CAL_GreetDate.Value; + } + + private void B_Dump_Click(object sender, EventArgs e) + { + SavePlayer(PlayerIndex); + MiscDumpHelper.DumpVillagerMemoryPlayer(Villager, Memories[PlayerIndex]); + } + + private void B_Load_Click(object sender, EventArgs e) + { + if (!MiscDumpHelper.LoadVillagerMemoryPlayer(Villager, Memories, PlayerIndex)) + return; + LoadPlayer(PlayerIndex); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void TB_NamePlayer_TextChanged(object sender, EventArgs e) + { + if (LB_Players.SelectedIndex < 0) + return; + Memories[LB_Players.SelectedIndex].PlayerName = TB_NamePlayer.Text; // this should be enough for player name changes within NHSE as identities are never changed by the end-user + UpdatePlayerIslandStrings(); + } + + private void TB_Island_TextChanged(object sender, EventArgs e) + { + if (LB_Players.SelectedIndex < 0) + return; + Memories[LB_Players.SelectedIndex].TownName = TB_Island.Text; // as above + UpdatePlayerIslandStrings(); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Util/DevUtil.cs b/NHSE.WinForms/Util/DevUtil.cs index 89d011c..2b39990 100644 --- a/NHSE.WinForms/Util/DevUtil.cs +++ b/NHSE.WinForms/Util/DevUtil.cs @@ -6,163 +6,164 @@ using NHSE.Core; using NHSE.WinForms.Properties; -namespace NHSE.WinForms -{ +namespace NHSE.WinForms; #if DEBUG - public static class DevUtil +public static class DevUtil +{ + // excludes default language + private static readonly string[] Languages = ["jp", "de", "es", "fr", "it", "ko", "zhs", "zht"]; + private const string DefaultLanguage = GameLanguage.DefaultLanguage; + + public static bool IsUpdatingTranslations { get; private set; } + + /// + /// Call this to update all translatable resources (Program Messages, Legality Text, Program GUI) + /// + public static void UpdateAll() { - private static readonly string[] Languages = { "jp", "de", "es", "fr", "it", "ko", "zhs", "zht" }; - private const string DefaultLanguage = GameLanguage.DefaultLanguage; + if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Update translation files with current values?")) + return; + IsUpdatingTranslations = true; + DumpStringsMessage(); + UpdateTranslations(); + UpdateInternalNameTranslations(); + IsUpdatingTranslations = false; + } - public static bool IsUpdatingTranslations { get; private set; } + private static void UpdateTranslations() + { + var assembly = System.Reflection.Assembly.GetExecutingAssembly(); + var types = assembly.GetTypes(); + WinFormsTranslator.LoadSpecialForms = LoadSpecialForms; + WinFormsTranslator.SetRemovalMode(false); // add mode + WinFormsTranslator.LoadAllForms(types, LoadBanlist); // populate with every possible control + WinFormsTranslator.UpdateAll(DefaultLanguage, Languages); // propagate to others + WinFormsTranslator.DumpAll(Banlist); // dump current to file + WinFormsTranslator.SetRemovalMode(); // remove used keys, don't add any + WinFormsTranslator.LoadAllForms(types, LoadBanlist); // de-populate + WinFormsTranslator.RemoveAll(DefaultLanguage, PurgeBanlist); // remove all lines from above generated files that still remain - /// - /// Call this to update all translatable resources (Program Messages, Legality Text, Program GUI) - /// - public static void UpdateAll() + // Move translated files from the debug exe loc to their project location + var files = Directory.GetFiles(Application.StartupPath); + var dir = GetResourcePath().Replace("NHSE.Core", "NHSE.WinForms"); + foreach (var f in files) { - if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Update translation files with current values?")) - return; - IsUpdatingTranslations = true; - DumpStringsMessage(); - UpdateTranslations(); - UpdateInternalNameTranslations(); - IsUpdatingTranslations = false; + var fn = Path.GetFileName(f); + if (!fn.EndsWith(".txt")) + continue; + if (!fn.StartsWith("lang_")) + continue; + + var loc = Path.Combine(dir, fn); + if (File.Exists(loc)) + File.Delete(loc); + File.Move(f, loc); } - private static void UpdateTranslations() + Application.Exit(); + } + + private static void LoadSpecialForms() + { + // For forms that require more complete initialization (dynamically added user controls) + var path = Settings.Default.LastFilePath; + var sav = new HorizonSave(path); + using var editor = new Editor(sav); + using var so = new SingleObjectEditor(new object(), PropertySort.NoSort, false); + } + + private static readonly string[] LoadBanlist = + [ + nameof(SettingsEditor), + nameof(Editor) // special handling above + ]; + + private static readonly string[] Banlist = + [ + "Editor=NHSE", // Program Title + "InternalName=", + "ExternalName=", + "AcreEditor.L_X", + "AcreEditor.L_Y", + "L_Coordinates", + "L_PatternName=", + "L_RemakeBody=", + "L_RemakeFabric=", + "AchievementEditor.L_Threshold" + ]; + + private static readonly string[] PurgeBanlist = + [ + nameof(SettingsEditor) + ]; + + private static void UpdateInternalNameTranslations() + { + string[] langs = [DefaultLanguage, .. Languages]; + var available = new[] { - WinFormsTranslator.LoadSpecialForms = LoadSpecialForms; - WinFormsTranslator.SetRemovalMode(false); // add mode - WinFormsTranslator.LoadAllForms(LoadBanlist); // populate with every possible control - WinFormsTranslator.UpdateAll(DefaultLanguage, Languages); // propagate to others - WinFormsTranslator.DumpAll(Banlist); // dump current to file - WinFormsTranslator.SetRemovalMode(); // remove used keys, don't add any - WinFormsTranslator.LoadAllForms(LoadBanlist); // de-populate - WinFormsTranslator.RemoveAll(DefaultLanguage, PurgeBanlist); // remove all lines from above generated files that still remain + LifeSupportAchievement.List.Values.Select(z => z.Name), + EventFlagPlayer.List.Values.Select(z => z.Name), + EventFlagLand.List.Values.Select(z => z.Name), + EventFlagVillager.List.Values.Select(z => z.Name), + }.SelectMany(z => z); - // Move translated files from the debug exe loc to their project location - var files = Directory.GetFiles(Application.StartupPath); - var dir = GetResourcePath().Replace("NHSE.Core", "NHSE.WinForms"); - foreach (var f in files) - { - var fn = Path.GetFileName(f); - if (!fn.EndsWith(".txt")) - continue; - if (!fn.StartsWith("lang_")) - continue; - - var loc = Path.Combine(dir, fn); - if (File.Exists(loc)) - File.Delete(loc); - File.Move(f, loc); - } - - Application.Exit(); - } - - private static void LoadSpecialForms() + var translatables = new HashSet(available); + foreach (var lang in langs) { - // For forms that require more complete initialization (dynamically added user controls) - var path = Settings.Default.LastFilePath; - var sav = new HorizonSave(path); - using var editor = new Editor(sav); - using var so = new SingleObjectEditor(new object(), PropertySort.NoSort, false); - } + var str = GameInfo.GetStrings(lang); + var dict = str.InternalNameTranslation; - private static readonly string[] LoadBanlist = - { - nameof(SettingsEditor), - nameof(Editor), // special handling above - }; + var oldKeys = dict + .Where(kvp => translatables.Contains(kvp.Key)); + var newKeys = translatables + .Where(key => !dict.ContainsKey(key)) + .Select(z => new KeyValuePair(z, z)); - private static readonly string[] Banlist = - { - "Editor=NHSE", // Program Title - "InternalName=", - "ExternalName=", - "AcreEditor.L_X", - "AcreEditor.L_Y", - "L_Coordinates", - "L_PatternName=", - "L_RemakeBody=", - "L_RemakeFabric=", - "AchievementEditor.L_Threshold", - }; + var allKeys = oldKeys.Concat(newKeys); - private static readonly string[] PurgeBanlist = - { - nameof(SettingsEditor), - }; + var newDict = allKeys.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - private static void UpdateInternalNameTranslations() - { - var langs = new[] { DefaultLanguage }.Concat(Languages); - var available = new[] - { - LifeSupportAchievement.List.Values.Select(z => z.Name), - EventFlagPlayer.List.Values.Select(z => z.Name), - EventFlagLand.List.Values.Select(z => z.Name), - EventFlagVillager.List.Values.Select(z => z.Name), - }.SelectMany(z => z); - - var translatables = new HashSet(available); - foreach (var lang in langs) - { - var str = GameInfo.GetStrings(lang); - var dict = str.InternalNameTranslation; - - var oldKeys = dict - .Where(kvp => translatables.Contains(kvp.Key)); - var newKeys = translatables - .Where(key => !dict.ContainsKey(key)) - .Select(z => new KeyValuePair(z, z)); - - var allKeys = oldKeys.Concat(newKeys); - - var newDict = allKeys.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - - var result = newDict.Select(z => $"{z.Key}={z.Value}"); - var dir = GetResourcePath(); - var location = GetFileLocationInText("internal", dir, lang); - File.WriteAllLines(location, result); - } - } - - private static void DumpStringsMessage() => DumpStrings(typeof(MessageStrings)); - - private static void DumpStrings(Type t) - { - var langs = new[] { DefaultLanguage }.Concat(Languages); + var result = newDict.Select(z => $"{z.Key}={z.Value}"); var dir = GetResourcePath(); - foreach (var lang in langs) - { - TranslationUtil.SetLocalization(t, lang); - var entries = TranslationUtil.GetLocalization(t); - var location = GetFileLocationInText(t.Name, dir, lang); - File.WriteAllLines(location, entries); - TranslationUtil.SetLocalization(t, DefaultLanguage); - } - } - - private static string GetFileLocationInText(string fileType, string dir, string lang) - { - var path = Path.Combine(dir, lang); - if (!Directory.Exists(path)) - path = Path.Combine(dir, "other"); - - var fn = $"{fileType}_{lang}.txt"; - return Path.Combine(path, fn); - } - - private static string GetResourcePath() - { - var path = Application.StartupPath; - const string projname = "NHSE\\"; - var pos = path.LastIndexOf(projname, StringComparison.Ordinal); - var str = path.Substring(0, pos + projname.Length); - return Path.Combine(str, "NHSE.Core", "Resources", "text"); + var location = GetFileLocationInText("internal", dir, lang); + File.WriteAllLines(location, result); } } -#endif + + private static void DumpStringsMessage() => DumpStrings(typeof(MessageStrings)); + + private static void DumpStrings(Type t) + { + string[] langs = [DefaultLanguage, ..Languages]; + var dir = GetResourcePath(); + foreach (var lang in langs) + { + TranslationUtil.SetLocalization(t, lang); + var entries = TranslationUtil.GetLocalization(t); + var location = GetFileLocationInText(t.Name, dir, lang); + File.WriteAllLines(location, entries); + TranslationUtil.SetLocalization(t, DefaultLanguage); + } + } + + private static string GetFileLocationInText(string fileType, string dir, string lang) + { + var path = Path.Combine(dir, lang); + if (!Directory.Exists(path)) + path = Path.Combine(dir, "other"); + + var fn = $"{fileType}_{lang}.txt"; + return Path.Combine(path, fn); + } + + private static string GetResourcePath() + { + var path = Application.StartupPath; + const string projname = "NHSE\\"; + var pos = path.LastIndexOf(projname, StringComparison.Ordinal); + var str = path[..(pos + projname.Length)]; + return Path.Combine(str, "NHSE.Core", "Resources", "text"); + } } +#endif \ No newline at end of file diff --git a/NHSE.WinForms/Util/FileUtil.cs b/NHSE.WinForms/Util/FileUtil.cs index 65c79f7..22b42a6 100644 --- a/NHSE.WinForms/Util/FileUtil.cs +++ b/NHSE.WinForms/Util/FileUtil.cs @@ -1,28 +1,27 @@ using System.IO; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public static class FileUtil { - public static class FileUtil + public static void CopyFolder(string source, string dest, bool subfolders = true) { - public static void CopyFolder(string source, string dest, bool subfolders = true) + Directory.CreateDirectory(dest); + + var dir = new DirectoryInfo(source); + foreach (var file in dir.EnumerateFiles()) { - Directory.CreateDirectory(dest); + var path = Path.Combine(dest, file.Name); + file.CopyTo(path, false); + } - var dir = new DirectoryInfo(source); - foreach (var file in dir.EnumerateFiles()) - { - var path = Path.Combine(dest, file.Name); - file.CopyTo(path, false); - } + if (!subfolders) + return; - if (!subfolders) - return; - - foreach (var folder in dir.EnumerateDirectories()) - { - var path = Path.Combine(dest, folder.Name); - CopyFolder(folder.FullName, path); - } + foreach (var folder in dir.EnumerateDirectories()) + { + var path = Path.Combine(dest, folder.Name); + CopyFolder(folder.FullName, path); } } -} +} \ No newline at end of file diff --git a/NHSE.WinForms/Util/InterpolatingPictureBox.cs b/NHSE.WinForms/Util/InterpolatingPictureBox.cs index 6c2304e..013301e 100644 --- a/NHSE.WinForms/Util/InterpolatingPictureBox.cs +++ b/NHSE.WinForms/Util/InterpolatingPictureBox.cs @@ -1,22 +1,21 @@ using System.Drawing.Drawing2D; using System.Windows.Forms; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public class InterpolatingPictureBox : PictureBox { - public class InterpolatingPictureBox : PictureBox + private readonly InterpolationMode InterpolationMode = InterpolationMode.HighQualityBicubic; + + protected override void OnPaint(PaintEventArgs eventArgs) { - private readonly InterpolationMode InterpolationMode = InterpolationMode.HighQualityBicubic; - - protected override void OnPaint(PaintEventArgs eventArgs) - { - eventArgs.Graphics.InterpolationMode = InterpolationMode; - base.OnPaint(eventArgs); - } - - protected override void OnPaintBackground(PaintEventArgs pevent) - { - pevent.Graphics.InterpolationMode = InterpolationMode; - base.OnPaintBackground(pevent); - } + eventArgs.Graphics.InterpolationMode = InterpolationMode; + base.OnPaint(eventArgs); } -} + + protected override void OnPaintBackground(PaintEventArgs pevent) + { + pevent.Graphics.InterpolationMode = InterpolationMode; + base.OnPaintBackground(pevent); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Util/MessageStrings.cs b/NHSE.WinForms/Util/MessageStrings.cs index 467afe1..002ffdf 100644 --- a/NHSE.WinForms/Util/MessageStrings.cs +++ b/NHSE.WinForms/Util/MessageStrings.cs @@ -1,56 +1,55 @@ // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public static class MessageStrings { - public static class MessageStrings - { - public static string MsgBackupCreateLocation { get; set; } = "NHSE can perform automatic backups if you create a folder with the name '{0}' in the same folder as the executable."; - public static string MsgBackupCreateQuestion { get; set; } = "Would you NHSE to automatically keep a backup of your save data?"; + public static string MsgBackupCreateLocation { get; set; } = "NHSE can perform automatic backups if you create a folder with the name '{0}' in the same folder as the executable."; + public static string MsgBackupCreateQuestion { get; set; } = "Would you NHSE to automatically keep a backup of your save data?"; - public static string MsgDataSizeMismatchImport { get; set; } = "The size of the imported file (0x{0:X}) does not match the required size (0x{1:X})."; - public static string MsgDataSizeMismatchRAM { get; set; } = "Read size (0x{0:X}) != Write size (0x{1:X})."; - public static string MsgDataDidNotOriginateFromHost_0 { get; set; } = "Imported data did not originate from Villager0 ({0})'s data."; + public static string MsgDataSizeMismatchImport { get; set; } = "The size of the imported file (0x{0:X}) does not match the required size (0x{1:X})."; + public static string MsgDataSizeMismatchRAM { get; set; } = "Read size (0x{0:X}) != Write size (0x{1:X})."; + public static string MsgDataDidNotOriginateFromHost_0 { get; set; } = "Imported data did not originate from Villager0 ({0})'s data."; - public static string MsgAskUpdateValues { get; set; } = "Update values?"; - public static string MsgAskContinue { get; set; } = "Continue?"; - public static string MsgAskWriteAnyway { get; set; } = "Write anyway?"; - public static string MsgAskExportResultToClipboard { get; set; } = "Export results to clipboard?"; - public static string MsgAskExportResultsWithFileIndex { get; set; } = "Export results with file index at the front of the file name?"; - public static string MsgCanceling { get; set; } = "Canceling:"; - public static string MsgInvalidHexValue { get; set; } = "Bad hex value."; - public static string MsgImportDirectoryDoesNotExist { get; set; } = "Directory does not exist!"; - public static string MsgNoPictureLoaded { get; set; } = "No picture loaded."; + public static string MsgAskUpdateValues { get; set; } = "Update values?"; + public static string MsgAskContinue { get; set; } = "Continue?"; + public static string MsgAskWriteAnyway { get; set; } = "Write anyway?"; + public static string MsgAskExportResultToClipboard { get; set; } = "Export results to clipboard?"; + public static string MsgAskExportResultsWithFileIndex { get; set; } = "Export results with file index at the front of the file name?"; + public static string MsgCanceling { get; set; } = "Canceling:"; + public static string MsgInvalidHexValue { get; set; } = "Bad hex value."; + public static string MsgImportDirectoryDoesNotExist { get; set; } = "Directory does not exist!"; + public static string MsgNoPictureLoaded { get; set; } = "No picture loaded."; - public static string MsgSaveDataImportFail { get; set; } = "Unable to open the folder that contains the save file."; - public static string MsgSaveDataImportSuggest { get; set; } = "Try moving it to another location and opening from there."; - public static string MsgSaveDataExportSuccess { get; set; } = "Saved all save data!"; - public static string MsgSaveDataExportFail { get; set; } = "Unable to save files to their original location."; - public static string MsgSaveDataHashesValid { get; set; } = "Hashes are valid."; - public static string MsgSaveDataSizeMismatch { get; set; } = "Save file sizes appear to be incorrect."; + public static string MsgSaveDataImportFail { get; set; } = "Unable to open the folder that contains the save file."; + public static string MsgSaveDataImportSuggest { get; set; } = "Try moving it to another location and opening from there."; + public static string MsgSaveDataExportSuccess { get; set; } = "Saved all save data!"; + public static string MsgSaveDataExportFail { get; set; } = "Unable to save files to their original location."; + public static string MsgSaveDataHashesValid { get; set; } = "Hashes are valid."; + public static string MsgSaveDataSizeMismatch { get; set; } = "Save file sizes appear to be incorrect."; - public static string MsgMoveOut { get; set; } = "Are you trying to make the Villager move out?"; - public static string MsgMoveOutSuggest { get; set; } = "If so, set the Event Flag (024 - ForceMoveOut) to 1 so that the Villager is removed by the game."; - public static string MsgMoveOutAll { get; set; } = "This will check the 'Moving Out' box for all Villagers."; + public static string MsgMoveOut { get; set; } = "Are you trying to make the Villager move out?"; + public static string MsgMoveOutSuggest { get; set; } = "If so, set the Event Flag (024 - ForceMoveOut) to 1 so that the Villager is removed by the game."; + public static string MsgMoveOutAll { get; set; } = "This will check the 'Moving Out' box for all Villagers."; - public static string MsgFieldItemRemoveAsk { get; set; } = "Are you sure you want to remove {0}?"; - public static string MsgFieldItemRemoveNone { get; set; } = "Nothing removed (none found)."; - public static string MsgFieldItemRemoveCount { get; set; } = "Removed {0} from the map."; - public static string MsgFieldItemModifyAsk { get; set; } = "Are you sure you want to {0}?"; - public static string MsgFieldItemModifyNone { get; set; } = "Nothing modified (none found)."; - public static string MsgFieldItemModifyCount { get; set; } = "Modified {0} tiles on the map."; - public static string MsgFieldItemUnsupportedLayer2Tile { get; set; } = "Unsupported Layer2 items detected."; - public static string MsgFieldItemNoNHI { get; set; } = "No .nhi file selected to import!"; + public static string MsgFieldItemRemoveAsk { get; set; } = "Are you sure you want to remove {0}?"; + public static string MsgFieldItemRemoveNone { get; set; } = "Nothing removed (none found)."; + public static string MsgFieldItemRemoveCount { get; set; } = "Removed {0} from the map."; + public static string MsgFieldItemModifyAsk { get; set; } = "Are you sure you want to {0}?"; + public static string MsgFieldItemModifyNone { get; set; } = "Nothing modified (none found)."; + public static string MsgFieldItemModifyCount { get; set; } = "Modified {0} tiles on the map."; + public static string MsgFieldItemUnsupportedLayer2Tile { get; set; } = "Unsupported Layer2 items detected."; + public static string MsgFieldItemNoNHI { get; set; } = "No .nhi file selected to import!"; - public static string MsgSysBotInfo { get; set; } = "This SysBot reads and writes RAM directly to your game when called to Read/Write."; - public static string MsgSysBotRequired { get; set; } = "Using this functionality requires the sys-botbase sysmodule running on the console. Your console must be on the same network as the PC running this program."; + public static string MsgSysBotInfo { get; set; } = "This SysBot reads and writes RAM directly to your game when called to Read/Write."; + public static string MsgSysBotRequired { get; set; } = "Using this functionality requires the sys-botbase sysmodule running on the console. Your console must be on the same network as the PC running this program."; - public static string MsgTerrainSetElevation0 { get; set; } = "Set the elevation of all tiles on the map to 0?"; - public static string MsgTerrainSetAll { get; set; } = "Set the tile from the Tile Editor to all tiles on the map?"; - public static string MsgTerrainSetAllSkipExterior { get; set; } = "Do you want to skip the tiles in exterior acres (beach/rocks)?"; + public static string MsgTerrainSetElevation0 { get; set; } = "Set the elevation of all tiles on the map to 0?"; + public static string MsgTerrainSetAll { get; set; } = "Set the tile from the Tile Editor to all tiles on the map?"; + public static string MsgTerrainSetAllSkipExterior { get; set; } = "Do you want to skip the tiles in exterior acres (beach/rocks)?"; - public static string MsgVillagerFriendshipMax { get; set; } = "Do you want to set all Villager Friendship memories to 255?"; + public static string MsgVillagerFriendshipMax { get; set; } = "Do you want to set all Villager Friendship memories to 255?"; - public static string MsgVillagerReplaceNoText { get; set; } = "Clipboard: No text found! Expected internal villager name."; - public static string MsgVillagerReplaceOutdatedSaveFormat { get; set; } = "Save file is not up to date with latest villager format. Please update in-game."; - public static string MsgVillagerReplaceUnknownName { get; set; } = "Clipboard: {0} is not a valid internal villager name."; - } -} + public static string MsgVillagerReplaceNoText { get; set; } = "Clipboard: No text found! Expected internal villager name."; + public static string MsgVillagerReplaceOutdatedSaveFormat { get; set; } = "Save file is not up to date with latest villager format. Please update in-game."; + public static string MsgVillagerReplaceUnknownName { get; set; } = "Clipboard: {0} is not a valid internal villager name."; +} \ No newline at end of file diff --git a/NHSE.WinForms/Util/TranslationUtil.cs b/NHSE.WinForms/Util/TranslationUtil.cs index 9442f81..cd3f442 100644 --- a/NHSE.WinForms/Util/TranslationUtil.cs +++ b/NHSE.WinForms/Util/TranslationUtil.cs @@ -4,129 +4,107 @@ using System.Linq; using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public static class TranslationUtil { - public static class TranslationUtil + private const char TranslationSplitter = '='; + + /// + /// Gets the names of the properties defined in the given input + /// + /// Enumerable of translation definitions in the form "Property = Value". + private static string[] GetProperties(IEnumerable input) { - private const char TranslationSplitter = '='; + return input.Select(l => l[..l.IndexOf(TranslationSplitter)]) + .ToArray(); + } - /// - /// Gets the names of the properties defined in the given input - /// - /// Enumerable of translation definitions in the form "Property = Value". - private static string[] GetProperties(IEnumerable input) + private static IEnumerable DumpStrings(Type t) + { + var props = ReflectUtil.GetPropertiesStartWithPrefix(t, string.Empty); + return props.Select(p => $"{p}{TranslationSplitter}{ReflectUtil.GetValue(t, p)}"); + } + + /// + /// Gets the current localization in a static class containing language-specific strings + /// + /// + public static string[] GetLocalization(Type t) => DumpStrings(t).ToArray(); + + /// + /// Applies localization to a static class containing language-specific strings. + /// + /// Type of the static class containing the desired strings. + /// Lines containing the localized strings + private static void SetLocalization(Type t, ReadOnlySpan lines) + { + if (lines.Length == 0) + return; + foreach (var line in lines) { - return input.Select(l => l.Substring(0, l.IndexOf(TranslationSplitter))) - .ToArray(); - } + var index = line.IndexOf(TranslationSplitter); + if (index < 0) + continue; + var prop = line[..index]; + var value = line[(index + 1)..]; - private static IEnumerable DumpStrings(Type t) - { - var props = ReflectUtil.GetPropertiesStartWithPrefix(t, string.Empty); - return props.Select(p => $"{p}{TranslationSplitter}{ReflectUtil.GetValue(t, p)}"); - } - - /// - /// Gets the current localization in a static class containing language-specific strings - /// - /// - public static string[] GetLocalization(Type t) => DumpStrings(t).ToArray(); - - /// - /// Gets the current localization in a static class containing language-specific strings - /// - /// - /// Existing localization lines (if provided) - public static string[] GetLocalization(Type t, string[] existingLines) - { - var currentLines = GetLocalization(t); - var existing = GetProperties(existingLines); - var current = GetProperties(currentLines); - - var result = new string[currentLines.Length]; - for (int i = 0; i < current.Length; i++) + try { - int index = Array.IndexOf(existing, current[i]); - result[i] = index < 0 ? currentLines[i] : existingLines[index]; + ReflectUtil.SetValue(t, prop, value); } - - return result; - } - - /// - /// Applies localization to a static class containing language-specific strings. - /// - /// Type of the static class containing the desired strings. - /// Lines containing the localized strings - private static void SetLocalization(Type t, IReadOnlyCollection lines) - { - if (lines.Count == 0) - return; - foreach (var line in lines) + catch (Exception e) { - var index = line.IndexOf(TranslationSplitter); - if (index < 0) - continue; - var prop = line.Substring(0, index); - var value = line.Substring(index + 1); - - try - { - ReflectUtil.SetValue(t, prop, value); - } - catch (Exception e) - { - Debug.WriteLine($"Property not present: {prop} || Value written: {value}"); - Debug.WriteLine(e.Message); - } + Debug.WriteLine($"Property not present: {prop} || Value written: {value}"); + Debug.WriteLine(e.Message); } } - - /// - /// Applies localization to a static class containing language-specific strings. - /// - /// Dictionary of translatable strings - /// Lines containing the localized strings - private static void SetLocalization(IDictionary dict, IReadOnlyCollection lines) - { - if (lines.Count == 0) - return; - foreach (var line in lines) - { - var index = line.IndexOf(TranslationSplitter); - if (index < 0) - continue; - var prop = line.Substring(0, index); - dict[prop] = line.Substring(index + 1); - } - } - - /// - /// Applies localization to a static class containing language-specific strings. - /// - /// Type of the static class containing the desired strings. - /// Prefix of the language file to use. Example: if the target is legality_en.txt, should be "legality". - /// Culture information - private static void SetLocalization(Type t, string languageFilePrefix, string currentCultureCode) - { - SetLocalization(t, ResourceUtil.GetStringList($"{languageFilePrefix}_{currentCultureCode}")); - } - - /// - /// Applies localization to a static class containing language-specific strings. - /// - /// Type of the static class containing the desired strings. - /// The values used to translate the given static class are retrieved from [TypeName]_[CurrentLangCode2].txt in the resource manager of NHSE.Core. - /// Culture information - public static void SetLocalization(Type t, string currentCultureCode) - { - SetLocalization(t, t.Name, currentCultureCode); - } - - public static void SetLocalization(IDictionary dict, string currentCultureCode) - { - var lines = ResourceUtil.GetStringList($"internal_{currentCultureCode}"); - SetLocalization(dict, lines); - } } -} + + /// + /// Applies localization to a static class containing language-specific strings. + /// + /// Dictionary of translatable strings + /// Lines containing the localized strings + private static void SetLocalization(Dictionary dict, ReadOnlySpan lines) + { + if (lines.Length == 0) + return; + foreach (var line in lines) + { + var index = line.IndexOf(TranslationSplitter); + if (index < 0) + continue; + var prop = line[..index]; + dict[prop] = line[(index + 1)..]; + } + } + + /// + /// Applies localization to a static class containing language-specific strings. + /// + /// Type of the static class containing the desired strings. + /// Prefix of the language file to use. Example: if the target is legality_en.txt, should be "legality". + /// Culture information + private static void SetLocalization(Type t, string languageFilePrefix, string currentCultureCode) + { + SetLocalization(t, ResourceUtil.GetStringList($"{languageFilePrefix}_{currentCultureCode}")); + } + + /// + /// Applies localization to a static class containing language-specific strings. + /// + /// Type of the static class containing the desired strings. + /// The values used to translate the given static class are retrieved from [TypeName]_[CurrentLangCode2].txt in the resource manager of NHSE.Core. + /// Culture information + public static void SetLocalization(Type t, string currentCultureCode) + { + SetLocalization(t, t.Name, currentCultureCode); + } + + public static void SetLocalization(Dictionary dict, string currentCultureCode) + { + var lines = ResourceUtil.GetStringList($"internal_{currentCultureCode}"); + SetLocalization(dict, lines); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Util/WinFormsTranslator.cs b/NHSE.WinForms/Util/WinFormsTranslator.cs index 40b7b28..1b2d7c9 100644 --- a/NHSE.WinForms/Util/WinFormsTranslator.cs +++ b/NHSE.WinForms/Util/WinFormsTranslator.cs @@ -1,286 +1,351 @@ -using System; +using NHSE.Core; +using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using System.Windows.Forms; -using NHSE.Core; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +public static class WinFormsTranslator { - public static class WinFormsTranslator + private static readonly Dictionary Context = []; + internal static void TranslateInterface(this Control form, string lang) => TranslateForm(form, GetContext(lang)); + + private static string GetTranslationFileNameInternal(string lang) => $"lang_{lang}"; + private static string GetTranslationFileNameExternal(string lang) => $"lang_{lang}.txt"; + + internal static Action LoadSpecialForms = () => { }; + + private static TranslationContext GetContext(string lang) { - private static readonly Dictionary Context = new(); - internal static void TranslateInterface(this Control form, string lang) => TranslateForm(form, GetContext(lang)); - - private static string GetTranslationFileNameInternal(string lang) => $"lang_{lang}"; - private static string GetTranslationFileNameExternal(string lang) => $"lang_{lang}.txt"; - - internal static Action LoadSpecialForms = () => { }; - - private static TranslationContext GetContext(string lang) - { - if (Context.TryGetValue(lang, out var context)) - return context; - - var lines = GetTranslationFile(lang); - Context.Add(lang, context = new TranslationContext(lines)); + if (Context.TryGetValue(lang, out var context)) return context; - } - private static void TranslateForm(Control form, TranslationContext context) + var lines = GetTranslationFile(lang); + Context.Add(lang, context = new TranslationContext(lines)); + return context; + } + + private static void TranslateForm(Control form, TranslationContext context) + { + form.SuspendLayout(); + var formname = form.Name; + // Translate Title + form.Text = context.GetTranslatedText(formname, form.Text); + var translatable = GetTranslatableControls(form); + foreach (var c in translatable) { - form.SuspendLayout(); - var formname = form.Name; - // Translate Title - form.Text = context.GetTranslatedText(formname, form.Text); - var translatable = GetTranslatableControls(form); - foreach (var c in translatable) + if (c is Control r) { - if (c is Control r) - { - var current = r.Text; - var updated = context.GetTranslatedText($"{formname}.{r.Name}", current); - if (!ReferenceEquals(current, updated)) - r.Text = updated; - } - else if (c is ToolStripItem t) - { - var current = t.Text!; - var updated = context.GetTranslatedText($"{formname}.{t.Name}", current); - if (!ReferenceEquals(current, updated)) - t.Text = updated; - } + var current = r.Text; + var updated = context.GetTranslatedText($"{formname}.{r.Name}", current); + if (!ReferenceEquals(current, updated)) + r.Text = updated; } - form.ResumeLayout(); - } - - private static IEnumerable GetTranslationFile(string lang) - { - var file = GetTranslationFileNameInternal(lang); - // Check to see if a the translation file exists in the same folder as the executable - string externalLangPath = GetTranslationFileNameExternal(file); - if (File.Exists(externalLangPath)) + else if (c is ToolStripItem t) { - try - { - return File.ReadAllLines(externalLangPath); - } - catch (Exception e) - { - /* In use? Just return the internal resource. */ - Console.WriteLine(e.Message); - } + var current = t.Text!; + var updated = context.GetTranslatedText($"{formname}.{t.Name}", current); + if (!ReferenceEquals(current, updated)) + t.Text = updated; } + } + form.ResumeLayout(); + } - if (ResourceUtil.IsStringListCached(file, out var result)) - return result; - var obj = Properties.Resources.ResourceManager.GetObject(file); - if (obj is not string txt) - return Array.Empty(); - return ResourceUtil.LoadStringList(file, txt); + private static string[] GetTranslationFile(string lang) + { + var file = GetTranslationFileNameInternal(lang); + // Check to see if the translation file exists in the same folder as the executable + string externalLangPath = GetTranslationFileNameExternal(file); + if (File.Exists(externalLangPath)) + { + try + { + return File.ReadAllLines(externalLangPath); + } + catch (Exception e) + { + /* In use? Just return the internal resource. */ + Console.WriteLine(e.Message); + } } - private static IEnumerable GetTranslatableControls(Control f) + if (ResourceUtil.IsStringListCached(file, out var result)) + return result; + var obj = Properties.Resources.ResourceManager.GetObject(file); + if (obj is not string txt) + return []; + return ResourceUtil.LoadStringList(file, txt); + } + + private static IEnumerable GetTranslatableControls(Control f) + { + foreach (var z in f.GetChildrenOfType()) { - foreach (var z in f.GetChildrenOfType()) + switch (z) { - switch (z) - { - case ToolStrip menu: - foreach (var obj in GetToolStripMenuItems(menu)) + case ToolStrip menu: + foreach (var obj in GetToolStripMenuItems(menu)) + yield return obj; + + break; + default: + if (string.IsNullOrWhiteSpace(z.Name)) + break; + + if (z.ContextMenuStrip is not null) // control has attached MenuStrip + { + foreach (var obj in GetToolStripMenuItems(z.ContextMenuStrip)) yield return obj; + } - break; - default: - if (string.IsNullOrWhiteSpace(z.Name)) - break; + if (Application.IsDarkModeEnabled) // NET10 + ReformatDark(z); - if (z.ContextMenuStrip != null) // control has attached menustrip + if (z is ListControl or TextBoxBase or LinkLabel or NumericUpDown or ContainerControl) + break; // undesirable to modify, ignore + + if (z is DataGridView { ColumnHeadersVisible: true } dgv) + { + foreach (DataGridViewColumn col in dgv.Columns) { - foreach (var obj in GetToolStripMenuItems(z.ContextMenuStrip)) - yield return obj; + if (col.Visible && !string.IsNullOrWhiteSpace(col.HeaderText)) + yield return col; } + } - if (z is ListControl || z is TextBoxBase || z is LinkLabel || z is NumericUpDown || z is ContainerControl) - break; // undesirable to modify, ignore - - if (!string.IsNullOrWhiteSpace(z.Text)) - yield return z; - break; - } - } - } - - private static IEnumerable GetChildrenOfType(this Control control) where T : class - { - foreach (var child in control.Controls.OfType()) - { - if (child is T childOfT) - yield return childOfT; - - if (!child.HasChildren) - continue; - - foreach (var descendant in GetChildrenOfType(child)) - yield return descendant; - } - } - - private static IEnumerable GetToolStripMenuItems(ToolStrip menu) - { - foreach (var i in menu.Items.OfType()) - { - if (!string.IsNullOrWhiteSpace(i.Text)) - yield return i; - foreach (var sub in GetToolsStripDropDownItems(i).Where(z => !string.IsNullOrWhiteSpace(z.Text))) - yield return sub; - } - } - - private static IEnumerable GetToolsStripDropDownItems(ToolStripDropDownItem item) - { - foreach (var dropDownItem in item.DropDownItems.OfType()) - { - yield return dropDownItem; - if (!dropDownItem.HasDropDownItems) continue; - foreach (ToolStripMenuItem subItem in GetToolsStripDropDownItems(dropDownItem)) - yield return subItem; - } - } - - public static void UpdateAll(string baseLanguage, IEnumerable others) - { - var basecontext = GetContext(baseLanguage); - foreach (var lang in others) - { - var c = GetContext(lang); - c.UpdateFrom(basecontext); - } - } - - public static void DumpAll(params string[] banlist) - { - var results = Context.Select(z => new { Lang = z.Key, Lines = z.Value.Write() }); - foreach (var c in results) - { - var lang = c.Lang; - var fn = GetTranslationFileNameExternal(lang); - var lines = c.Lines; - var result = lines.Where(z => !banlist.Any(z.Contains)); - File.WriteAllLines(fn, result); - } - } - - public static void LoadAllForms(params string[] banlist) - { - LoadSpecialForms(); - - var q = from t in System.Reflection.Assembly.GetExecutingAssembly().GetTypes() - where t.BaseType == typeof(Form) && !banlist.Contains(t.Name) - select t; - foreach (var t in q) - { - var constructors = t.GetConstructors(); - if (constructors.Length == 0) - { - Console.WriteLine($"No constructors: {t.Name}"); - continue; - } - var argCount = constructors[0].GetParameters().Length; - try - { - var _ = Activator.CreateInstance(t, new object[argCount]); - } - catch - { - // ignored - } - } - } - - public static void SetRemovalMode(bool status = true) - { - foreach (TranslationContext c in Context.Values) - { - c.RemoveUsedKeys = status; - c.AddNew = !status; - } - } - - public static void RemoveAll(string defaultLanguage, params string[] banlist) - { - var badKeys = Context[defaultLanguage]; - var split = badKeys.Write().Select(z => z.Split(TranslationContext.Separator)[0]) - .Where(l => !banlist.Any(l.StartsWith)).ToArray(); - foreach (var c in Context) - { - var lang = c.Key; - var fn = GetTranslationFileNameExternal(lang); - var lines = File.ReadAllLines(fn); - var result = lines.Where(l => !split.Any(s => l.StartsWith(s + TranslationContext.Separator))); - File.WriteAllLines(fn, result); + if (!string.IsNullOrWhiteSpace(z.Text)) + yield return z; + break; } } } - public sealed class TranslationContext + private static void ReformatDark(Control z) { - public bool AddNew { private get; set; } - public bool RemoveUsedKeys { private get; set; } - public const char Separator = '='; - private readonly Dictionary Translation = new(); - - public TranslationContext(IEnumerable content, char separator = Separator) + if (z is TabControl tc) { - var entries = GetContent(content, separator); - foreach (var kvp in entries.Where(z => !Translation.ContainsKey(z.Key))) - Translation.Add(kvp.Key, kvp.Value); + foreach (TabPage tab in tc.TabPages) + tab.UseVisualStyleBackColor = false; } - - private static IEnumerable> GetContent(IEnumerable content, char separator) + else if (z is DataGridView dg) { - foreach (var line in content) + dg.EnableHeadersVisualStyles = false; + dg.BorderStyle = BorderStyle.None; + } + else if (z is ComboBox cb) + { + cb.FlatStyle = FlatStyle.Popup; + } + else if (z is ListBox lb) + { + lb.BorderStyle = BorderStyle.None; + } + else if (z is TextBoxBase tb) + { + tb.BorderStyle = BorderStyle.FixedSingle; + } + else if (z is NumericUpDown nud) + { + nud.BorderStyle = BorderStyle.FixedSingle; + } + else if (z is GroupBox gb) + { + gb.FlatStyle = FlatStyle.Popup; + } + else if (z is RichTextBox rtb) + { + rtb.BorderStyle = BorderStyle.None; + } + else if (z is ButtonBase b) + { + b.FlatStyle = FlatStyle.Popup; + } + } + + private static IEnumerable GetChildrenOfType(this Control control) where T : class + { + foreach (var child in control.Controls.OfType()) + { + if (child is T childOfT) + yield return childOfT; + + if (!child.HasChildren) + continue; + + foreach (var descendant in child.GetChildrenOfType()) + yield return descendant; + } + } + + private static IEnumerable GetToolStripMenuItems(ToolStrip menu) + { + foreach (var i in menu.Items.OfType()) + { + if (!string.IsNullOrWhiteSpace(i.Text)) + yield return i; + foreach (var sub in GetToolsStripDropDownItems(i).Where(z => !string.IsNullOrWhiteSpace(z.Text))) + yield return sub; + } + } + + private static IEnumerable GetToolsStripDropDownItems(ToolStripDropDownItem item) + { + foreach (var dropDownItem in item.DropDownItems.OfType()) + { + yield return dropDownItem; + if (!dropDownItem.HasDropDownItems) continue; + foreach (ToolStripMenuItem subItem in GetToolsStripDropDownItems(dropDownItem)) + yield return subItem; + } + } + + public static void UpdateAll(string baseLanguage, IEnumerable others) + { + var basecontext = GetContext(baseLanguage); + foreach (var lang in others) + { + var c = GetContext(lang); + c.UpdateFrom(basecontext); + } + } + + public static void DumpAll(params string[] banlist) + { + var results = Context.Select(z => new { Lang = z.Key, Lines = z.Value.Write() }); + foreach (var c in results) + { + var lang = c.Lang; + var fn = GetTranslationFileNameExternal(lang); + var lines = c.Lines; + var result = lines.Where(z => !banlist.Any(z.Contains)); + File.WriteAllLines(fn, result); + } + } + + private static bool IsBannedStartsWith(ReadOnlySpan line, ReadOnlySpan banlist) + { + foreach (var banned in banlist) + { + if (line.StartsWith(banned, StringComparison.Ordinal)) + return true; + } + return false; + } + + public static void LoadAllForms(IEnumerable types, ReadOnlySpan banlist) + { + foreach (var t in types) + { + if (!typeof(Form).IsAssignableFrom(t) || IsBannedStartsWith(t.Name, banlist)) + continue; + + var constructors = t.GetConstructors(); + if (constructors.Length == 0) + { System.Diagnostics.Debug.WriteLine($"No constructors: {t.Name}"); continue; } + var argCount = constructors[0].GetParameters().Length; + try { - var index = line.IndexOf(separator); - if (index < 0) - continue; - var key = line.Substring(0, index); - var value = line.Substring(index + 1); - yield return new KeyValuePair(key, value); + var form = (Form?)Activator.CreateInstance(t, new object[argCount]); + form?.Dispose(); + } + // This is a debug utility method, will always be logging. Shouldn't ever fail. + catch (TargetInvocationException) + { + // Don't care; forms will sometimes fail to load. + } + catch + { + System.Diagnostics.Debug.Write($"Failed to create a new form {t}"); } } + } - public string GetTranslatedText(string val, string fallback) + public static void SetRemovalMode(bool status = true) + { + foreach (TranslationContext c in Context.Values) { - if (RemoveUsedKeys) - Translation.Remove(val); - - if (Translation.TryGetValue(val, out var translated)) - return translated; - - if (AddNew) - Translation.Add(val, fallback); - return fallback; + c.RemoveUsedKeys = status; + c.AddNew = !status; } + } - public IEnumerable Write(char separator = Separator) + public static void RemoveAll(string defaultLanguage, params string[] banlist) + { + var badKeys = Context[defaultLanguage]; + var split = badKeys.Write().Select(z => z.Split(TranslationContext.Separator)[0]) + .Where(l => !banlist.Any(l.StartsWith)).ToArray(); + foreach (var c in Context) { - return Translation.Select(z => $"{z.Key}{separator}{z.Value}").OrderBy(z => z.Contains(".")).ThenBy(z => z); - } - - public void UpdateFrom(TranslationContext other) - { - bool oldAdd = AddNew; - AddNew = true; - foreach (var kvp in other.Translation) - GetTranslatedText(kvp.Key, kvp.Value); - AddNew = oldAdd; - } - - public void RemoveKeys(TranslationContext other) - { - foreach (var kvp in other.Translation) - Translation.Remove(kvp.Key); + var lang = c.Key; + var fn = GetTranslationFileNameExternal(lang); + var lines = File.ReadAllLines(fn); + var result = lines.Where(l => !split.Any(s => l.StartsWith(s + TranslationContext.Separator))); + File.WriteAllLines(fn, result); } } } + +public sealed class TranslationContext +{ + public bool AddNew { private get; set; } + public bool RemoveUsedKeys { private get; set; } + public const char Separator = '='; + private readonly Dictionary Translation = []; + + public TranslationContext(string[] content, char separator = Separator) + { + var entries = GetContent(content, separator); + foreach (var kvp in entries.Where(z => !Translation.ContainsKey(z.Key))) + Translation.Add(kvp.Key, kvp.Value); + } + + private static IEnumerable> GetContent(string[] content, char separator) + { + foreach (var line in content) + { + var index = line.IndexOf(separator); + if (index < 0) + continue; + var key = line[..index]; + var value = line[(index + 1)..]; + yield return new KeyValuePair(key, value); + } + } + + public string GetTranslatedText(string val, string fallback) + { + if (RemoveUsedKeys) + Translation.Remove(val); + + if (Translation.TryGetValue(val, out var translated)) + return translated; + + if (AddNew) + Translation.Add(val, fallback); + return fallback; + } + + public IEnumerable Write(char separator = Separator) + { + return Translation.Select(z => $"{z.Key}{separator}{z.Value}").OrderBy(z => z.Contains('.')).ThenBy(z => z); + } + + public void UpdateFrom(TranslationContext other) + { + bool oldAdd = AddNew; + AddNew = true; + foreach (var kvp in other.Translation) + GetTranslatedText(kvp.Key, kvp.Value); + AddNew = oldAdd; + } + + public void RemoveKeys(TranslationContext other) + { + foreach (var kvp in other.Translation) + Translation.Remove(kvp.Key); + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Util/WinFormsUtil.cs b/NHSE.WinForms/Util/WinFormsUtil.cs index a9fdb95..5e67a22 100644 --- a/NHSE.WinForms/Util/WinFormsUtil.cs +++ b/NHSE.WinForms/Util/WinFormsUtil.cs @@ -1,85 +1,92 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Linq; using System.Windows.Forms; -namespace NHSE.WinForms +namespace NHSE.WinForms; + +internal static class WinFormsUtil { - internal static class WinFormsUtil + internal static void TranslateInterface(Control form, string lang) => form.TranslateInterface(lang); + + #region Message Displays + /// + /// Displays a dialog showing the details of an error. + /// + /// User-friendly message about the error. + /// The associated with the dialog. + internal static DialogResult Error(params string[] lines) { - internal static void TranslateInterface(Control form, string lang) => form.TranslateInterface(lang); + System.Media.SystemSounds.Hand.Play(); + string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); + return MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } - #region Message Displays - /// - /// Displays a dialog showing the details of an error. - /// - /// User-friendly message about the error. - /// The associated with the dialog. - internal static DialogResult Error(params string[] lines) - { - System.Media.SystemSounds.Hand.Play(); - string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); - return MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } + internal static DialogResult Alert(params string[] lines) => Alert(true, lines); - internal static DialogResult Alert(params string[] lines) => Alert(true, lines); - - internal static DialogResult Alert(bool sound, params string[] lines) - { - if (sound) - System.Media.SystemSounds.Asterisk.Play(); - string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); - return MessageBox.Show(msg, "Alert", MessageBoxButtons.OK, sound ? MessageBoxIcon.Information : MessageBoxIcon.None); - } - - internal static DialogResult Prompt(MessageBoxButtons btn, params string[] lines) - { + internal static DialogResult Alert(bool sound, params string[] lines) + { + if (sound) System.Media.SystemSounds.Asterisk.Play(); - string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); - return MessageBox.Show(msg, "Prompt", btn, MessageBoxIcon.Question); - } - #endregion + string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); + return MessageBox.Show(msg, "Alert", MessageBoxButtons.OK, sound ? MessageBoxIcon.Information : MessageBoxIcon.None); + } - public static T? GetUnderlyingControl(object sender) where T : Control + internal static DialogResult Prompt(MessageBoxButtons btn, params string[] lines) + { + System.Media.SystemSounds.Asterisk.Play(); + string msg = string.Join(Environment.NewLine + Environment.NewLine, lines); + return MessageBox.Show(msg, "Prompt", btn, MessageBoxIcon.Question); + } + #endregion + + /// + /// Searches upwards through the control hierarchy to find the first parent control of type . + /// + /// Child control to start searching from. + /// The first parent control of type , or null if none found. + public static bool TryGetUnderlying(object sender, [NotNullWhen(true)] out T? result) where T : class + { + while (true) { - while (true) + switch (sender) { - switch (sender) - { - case ToolStripItem t: - sender = t.Owner!; - continue; - case ContextMenuStrip c: - sender = c.SourceControl!; - continue; - case T p: - return p; - default: - return null; - } + case T p: + result = p; + return true; + case ToolStripItem { Owner: { } o }: + sender = o; + continue; + case ContextMenuStrip { SourceControl: { } s }: + sender = s; + continue; + default: + result = null; + return false; } } - - /// - /// Gets the selected value of the input . If no value is selected, will return 0. - /// - /// ComboBox to retrieve value for. - internal static int GetIndex(ListControl cb) => (int)(cb.SelectedValue ?? 0); - - public static T? FirstFormOfType() where T : Form => (T?)Application.OpenForms.Cast
().FirstOrDefault(form => form is T); - - public static void RemoveDropCB(object sender, KeyEventArgs e) => ((ComboBox)sender).DroppedDown = false; - - /// - /// Centers the horizontally and vertically so that its center is the same as the 's center. - /// - /// - /// - internal static void CenterToForm(this Control child, Control parent) - { - int x = parent.Location.X + ((parent.Width - child.Width) / 2); - int y = parent.Location.Y + ((parent.Height - child.Height) / 2); - child.Location = new Point(Math.Max(x, 0), Math.Max(y, 0)); - } } -} + + /// + /// Gets the selected value of the input . If no value is selected, will return 0. + /// + /// ComboBox to retrieve value for. + internal static int GetIndex(ListControl cb) => (int)(cb.SelectedValue ?? 0); + + public static T? FirstFormOfType() where T : Form => (T?)Application.OpenForms.Cast().FirstOrDefault(form => form is T); + + public static void RemoveDropCB(object sender, KeyEventArgs e) => ((ComboBox)sender).DroppedDown = false; + + /// + /// Centers the horizontally and vertically so that its center is the same as the 's center. + /// + /// + /// + internal static void CenterToForm(this Control child, Control parent) + { + int x = parent.Location.X + ((parent.Width - child.Width) / 2); + int y = parent.Location.Y + ((parent.Height - child.Height) / 2); + child.Location = new Point(Math.Max(x, 0), Math.Max(y, 0)); + } +} \ No newline at end of file diff --git a/NHSE.sln b/NHSE.sln deleted file mode 100644 index 8fcb18b..0000000 --- a/NHSE.sln +++ /dev/null @@ -1,91 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29613.14 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NHSE.WinForms", "NHSE.WinForms\NHSE.WinForms.csproj", "{86B1C45C-6D42-414C-80AD-5B2333308CC1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NHSE.Core", "NHSE.Core\NHSE.Core.csproj", "{688B8976-584E-404A-8BAA-90FA45ADC428}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NHSE.Sprites", "NHSE.Sprites\NHSE.Sprites.csproj", "{D4984821-00C3-4F1C-BAEC-F66CDA7B7388}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NHSE.Parsing", "NHSE.Parsing\NHSE.Parsing.csproj", "{D6E5CE99-6182-49BA-AD8D-EC12E90A20E3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NHSE.Tests", "NHSE.Tests\NHSE.Tests.csproj", "{AD3412A3-74EA-443D-BB07-B36E39D5166F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NHSE.Injection", "NHSE.Injection\NHSE.Injection.csproj", "{319E810B-A516-480E-88BD-F648222344D3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NHSE.Villagers", "NHSE.Villagers\NHSE.Villagers.csproj", "{83026766-A61B-49DC-BBF7-D876813ECAA1}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {86B1C45C-6D42-414C-80AD-5B2333308CC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86B1C45C-6D42-414C-80AD-5B2333308CC1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {86B1C45C-6D42-414C-80AD-5B2333308CC1}.Debug|x86.ActiveCfg = Debug|x86 - {86B1C45C-6D42-414C-80AD-5B2333308CC1}.Debug|x86.Build.0 = Debug|x86 - {86B1C45C-6D42-414C-80AD-5B2333308CC1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {86B1C45C-6D42-414C-80AD-5B2333308CC1}.Release|Any CPU.Build.0 = Release|Any CPU - {86B1C45C-6D42-414C-80AD-5B2333308CC1}.Release|x86.ActiveCfg = Release|x86 - {86B1C45C-6D42-414C-80AD-5B2333308CC1}.Release|x86.Build.0 = Release|x86 - {688B8976-584E-404A-8BAA-90FA45ADC428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {688B8976-584E-404A-8BAA-90FA45ADC428}.Debug|Any CPU.Build.0 = Debug|Any CPU - {688B8976-584E-404A-8BAA-90FA45ADC428}.Debug|x86.ActiveCfg = Debug|Any CPU - {688B8976-584E-404A-8BAA-90FA45ADC428}.Debug|x86.Build.0 = Debug|Any CPU - {688B8976-584E-404A-8BAA-90FA45ADC428}.Release|Any CPU.ActiveCfg = Release|Any CPU - {688B8976-584E-404A-8BAA-90FA45ADC428}.Release|Any CPU.Build.0 = Release|Any CPU - {688B8976-584E-404A-8BAA-90FA45ADC428}.Release|x86.ActiveCfg = Release|Any CPU - {688B8976-584E-404A-8BAA-90FA45ADC428}.Release|x86.Build.0 = Release|Any CPU - {D4984821-00C3-4F1C-BAEC-F66CDA7B7388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D4984821-00C3-4F1C-BAEC-F66CDA7B7388}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D4984821-00C3-4F1C-BAEC-F66CDA7B7388}.Debug|x86.ActiveCfg = Debug|Any CPU - {D4984821-00C3-4F1C-BAEC-F66CDA7B7388}.Debug|x86.Build.0 = Debug|Any CPU - {D4984821-00C3-4F1C-BAEC-F66CDA7B7388}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D4984821-00C3-4F1C-BAEC-F66CDA7B7388}.Release|Any CPU.Build.0 = Release|Any CPU - {D4984821-00C3-4F1C-BAEC-F66CDA7B7388}.Release|x86.ActiveCfg = Release|Any CPU - {D4984821-00C3-4F1C-BAEC-F66CDA7B7388}.Release|x86.Build.0 = Release|Any CPU - {D6E5CE99-6182-49BA-AD8D-EC12E90A20E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D6E5CE99-6182-49BA-AD8D-EC12E90A20E3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6E5CE99-6182-49BA-AD8D-EC12E90A20E3}.Debug|x86.ActiveCfg = Debug|Any CPU - {D6E5CE99-6182-49BA-AD8D-EC12E90A20E3}.Debug|x86.Build.0 = Debug|Any CPU - {D6E5CE99-6182-49BA-AD8D-EC12E90A20E3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D6E5CE99-6182-49BA-AD8D-EC12E90A20E3}.Release|Any CPU.Build.0 = Release|Any CPU - {D6E5CE99-6182-49BA-AD8D-EC12E90A20E3}.Release|x86.ActiveCfg = Release|Any CPU - {D6E5CE99-6182-49BA-AD8D-EC12E90A20E3}.Release|x86.Build.0 = Release|Any CPU - {AD3412A3-74EA-443D-BB07-B36E39D5166F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AD3412A3-74EA-443D-BB07-B36E39D5166F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AD3412A3-74EA-443D-BB07-B36E39D5166F}.Debug|x86.ActiveCfg = Debug|Any CPU - {AD3412A3-74EA-443D-BB07-B36E39D5166F}.Debug|x86.Build.0 = Debug|Any CPU - {AD3412A3-74EA-443D-BB07-B36E39D5166F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AD3412A3-74EA-443D-BB07-B36E39D5166F}.Release|Any CPU.Build.0 = Release|Any CPU - {AD3412A3-74EA-443D-BB07-B36E39D5166F}.Release|x86.ActiveCfg = Release|Any CPU - {AD3412A3-74EA-443D-BB07-B36E39D5166F}.Release|x86.Build.0 = Release|Any CPU - {319E810B-A516-480E-88BD-F648222344D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {319E810B-A516-480E-88BD-F648222344D3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {319E810B-A516-480E-88BD-F648222344D3}.Debug|x86.ActiveCfg = Debug|Any CPU - {319E810B-A516-480E-88BD-F648222344D3}.Debug|x86.Build.0 = Debug|Any CPU - {319E810B-A516-480E-88BD-F648222344D3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {319E810B-A516-480E-88BD-F648222344D3}.Release|Any CPU.Build.0 = Release|Any CPU - {319E810B-A516-480E-88BD-F648222344D3}.Release|x86.ActiveCfg = Release|Any CPU - {319E810B-A516-480E-88BD-F648222344D3}.Release|x86.Build.0 = Release|Any CPU - {83026766-A61B-49DC-BBF7-D876813ECAA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {83026766-A61B-49DC-BBF7-D876813ECAA1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83026766-A61B-49DC-BBF7-D876813ECAA1}.Debug|x86.ActiveCfg = Debug|Any CPU - {83026766-A61B-49DC-BBF7-D876813ECAA1}.Debug|x86.Build.0 = Debug|Any CPU - {83026766-A61B-49DC-BBF7-D876813ECAA1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83026766-A61B-49DC-BBF7-D876813ECAA1}.Release|Any CPU.Build.0 = Release|Any CPU - {83026766-A61B-49DC-BBF7-D876813ECAA1}.Release|x86.ActiveCfg = Release|Any CPU - {83026766-A61B-49DC-BBF7-D876813ECAA1}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {3B68542E-189F-4448-A305-0F6B99B8F920} - EndGlobalSection -EndGlobal diff --git a/NHSE.slnx b/NHSE.slnx new file mode 100644 index 0000000..f17e441 --- /dev/null +++ b/NHSE.slnx @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index b592a26..564c0c1 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,6 @@ Save Editor for Animal Crossing: New Horizons Edits savedata dumped from the Nintendo Switch. * Bring your own save file data; this program does not dump it from your console. -## See Also - -[MyHorizons](https://github.com/Cuyler36/MyHorizons) by [Cuyler36](https://github.com/Cuyler36/) -* Some portions of code are liberally adapted from Cuyler36's project above. - ## Other Refer to the [Wiki](https://github.com/kwsch/NHSE/wiki) for more information. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e964d62..820cf37 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,53 +9,53 @@ trigger: pool: vmImage: 'windows-latest' +# Build number format: YYYYMMDD. +# Example: 20260110.3 +name: $(Date:yyyyMMdd).$(Rev:r) + variables: - solution: '**/*.sln' + solution: '**/*.slnx' buildPlatform: 'Any CPU' buildConfiguration: 'Release' steps: -- task: Assembly-Info-NetCore@2 - inputs: - Path: '$(Build.SourcesDirectory)' - FileNames: '**/*.csproj' - InsertAttributes: false - FileEncoding: 'auto' - WriteBOM: false - VersionNumber: '$(Build.BuildNumber)' - PackageVersion: '$(Build.BuildNumber)' - LogLevel: 'verbose' - FailOnWarning: false - DisableTelemetry: false - -- task: Assembly-Info-NetFramework@2 - inputs: - Path: '$(Build.SourcesDirectory)' - FileNames: '**\AssemblyInfo.cs' - InsertAttributes: false - FileEncoding: 'auto' - WriteBOM: false - VersionNumber: '$(Build.BuildNumber)' - FileVersionNumber: '$(Build.BuildNumber)' - LogLevel: 'verbose' - FailOnWarning: false - DisableTelemetry: false - +# Restore - task: NuGetToolInstaller@1 - task: NuGetCommand@2 inputs: restoreSolution: '$(solution)' +# Build with version stamping - task: VSBuild@1 inputs: solution: '$(solution)' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' + msbuildArgs: > + /p:AssemblyVersion=$(Build.BuildId) + /p:Version=$(Build.BuildNumber) + /p:FileVersion=$(Build.BuildId) + /p:InformationalVersion=$(Build.SourceVersion) +# Dynamically detect the TFM folder (net9.0-windows, net10.0-windows, etc.) +- powershell: | + $path = Get-ChildItem -Recurse -Directory -Path "$(Build.SourcesDirectory)\NHSE.WinForms\bin\Release" | + Where-Object { $_.Name -match '^net.*-windows$' } | + Select-Object -First 1 -ExpandProperty FullName + + if (-not $path) { + Write-Error "Could not find TFM output folder" + exit 1 + } + + Write-Host "##vso[task.setvariable variable=PublishPath]$path" + displayName: "Detect TFM output folder" + +# Publish - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: NHSE' inputs: - PathtoPublish: 'NHSE.WinForms\bin\Release\net46' + PathtoPublish: '$(PublishPath)' ArtifactName: NHSE condition: succeededOrFailed()