From 6b2b46ec1dcc80d342ac85968c68a8214b4c0064 Mon Sep 17 00:00:00 2001 From: Charlie U <52503242+cpurules@users.noreply.github.com> Date: Tue, 29 Sep 2020 22:55:06 -0400 Subject: [PATCH] Add feature to populate max item stack (#396) * Add event handler for count label click --- NHSE.Core/Resources/byte/item_kind.bin | Bin 13496 -> 13496 bytes NHSE.Core/Structures/Item/ItemInfo.cs | 147 +++++++++++++++++- NHSE.Core/Structures/Item/ItemKind.cs | 1 + NHSE.Parsing/GameBCSVDumper.cs | 63 ++++++++ NHSE.WinForms/Controls/ItemEditor.Designer.cs | 1 + NHSE.WinForms/Controls/ItemEditor.cs | 10 ++ 6 files changed, 221 insertions(+), 1 deletion(-) diff --git a/NHSE.Core/Resources/byte/item_kind.bin b/NHSE.Core/Resources/byte/item_kind.bin index 490d0b6226c9e2425975a0f873c93b6f0a5048bd..426fc3fb7eefdd2ce9839926002aa63d1d51e869 100644 GIT binary patch literal 13496 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 literal 13496 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 NsM(gJ+sbH*{{xp#4B`L) diff --git a/NHSE.Core/Structures/Item/ItemInfo.cs b/NHSE.Core/Structures/Item/ItemInfo.cs index 8267569..6223d4c 100644 --- a/NHSE.Core/Structures/Item/ItemInfo.cs +++ b/NHSE.Core/Structures/Item/ItemInfo.cs @@ -1,4 +1,7 @@ -namespace NHSE.Core +using System.Collections.Generic; +using static NHSE.Core.ItemKind; + +namespace NHSE.Core { /// /// Fetching metadata about an @@ -40,5 +43,147 @@ public static ItemMenuIconType GetMenuIcon(ushort id) 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); + return MaxCountByKind.TryGetValue(kind, out max); + } + + private static readonly Dictionary MaxCountByKind = new Dictionary + { + {Kind_Ftr, 00001}, + {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_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_PartyPopper, 00010}, + {Kind_Ocarina, 00001}, + {Kind_Panflute, 00001}, + {Kind_Tambourine, 00001}, + {Kind_FierworkHand, 00010}, + {Kind_StickLight, 00001}, + {Kind_Uchiwa, 00001}, + {Kind_Windmill, 00001}, + {Kind_BlowBubble, 00010}, + {Kind_Partyhorn, 00001}, + {Kind_Balloon, 00001}, + {Kind_Timer, 00001}, + {Kind_HandheldPennant, 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_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_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_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_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_DummyWrapping, 00001}, + {Kind_DummyPresentbox, 00001}, + {Kind_DummyCardboard, 00001}, + {Kind_EventObjFtr, 00001}, + {Kind_NnpcRoomMarker, 00001}, + {Kind_PhotoStudioList, 00001}, + }; } } diff --git a/NHSE.Core/Structures/Item/ItemKind.cs b/NHSE.Core/Structures/Item/ItemKind.cs index 1f2e92c..14bde6c 100644 --- a/NHSE.Core/Structures/Item/ItemKind.cs +++ b/NHSE.Core/Structures/Item/ItemKind.cs @@ -147,6 +147,7 @@ public enum ItemKind : byte Kind_WoodenStickTool, Kind_WrappingPaper, Kind_YutaroWisp, + Kind_XmasDeco, Onepiece_Dress, Onepiece_Long, Onepiece_Middle, diff --git a/NHSE.Parsing/GameBCSVDumper.cs b/NHSE.Parsing/GameBCSVDumper.cs index 911e535..eec5d95 100644 --- a/NHSE.Parsing/GameBCSVDumper.cs +++ b/NHSE.Parsing/GameBCSVDumper.cs @@ -56,6 +56,14 @@ void DumpU(string fn, ushort[] ushorts, string dir = "bin") Console.WriteLine($"Created {fn}"); } + void DumpD(string fn, Dictionary dict, string dir = "text") + { + 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)); @@ -83,6 +91,8 @@ void DumpU(string fn, ushort[] ushorts, string dir = "bin") 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)); @@ -227,6 +237,59 @@ public static byte[] GetItemSizeArray(string pathBCSV, string fn = "ItemParam.bc 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 List + { + "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); diff --git a/NHSE.WinForms/Controls/ItemEditor.Designer.cs b/NHSE.WinForms/Controls/ItemEditor.Designer.cs index 8258434..4dbc07c 100644 --- a/NHSE.WinForms/Controls/ItemEditor.Designer.cs +++ b/NHSE.WinForms/Controls/ItemEditor.Designer.cs @@ -154,6 +154,7 @@ private void InitializeComponent() this.L_Count.TabIndex = 7; this.L_Count.Text = "Count:"; this.L_Count.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.L_Count.DoubleClick += new System.EventHandler(this.L_Count_DoubleClick); // // L_Uses // diff --git a/NHSE.WinForms/Controls/ItemEditor.cs b/NHSE.WinForms/Controls/ItemEditor.cs index b1d9024..fca5b92 100644 --- a/NHSE.WinForms/Controls/ItemEditor.cs +++ b/NHSE.WinForms/Controls/ItemEditor.cs @@ -278,6 +278,16 @@ private void ToggleEditorVisibility(ItemKind k) } } + 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);