diff --git a/public/ui/items-atlas.png b/public/ui/items-atlas.png index c9778c6..f607ba1 100644 Binary files a/public/ui/items-atlas.png and b/public/ui/items-atlas.png differ diff --git a/public/ui/manifest.json b/public/ui/manifest.json index 1fa5f6c..32463db 100644 --- a/public/ui/manifest.json +++ b/public/ui/manifest.json @@ -1,9 +1,9 @@ { "version": "1.13c", - "decodedDc6Count": 444, + "decodedDc6Count": 453, "dc6DecodeFailures": 0, "atlasWidth": 1024, - "atlasHeight": 1880, + "atlasHeight": 1882, "questsAtlasWidth": 432, "questsAtlasHeight": 774, "codeToInvFile": { @@ -610,9 +610,9 @@ "skl": "invskl", "skz": "invskz", "hrb": "invhrb", - "cm1": "invchm", - "cm2": "invwnd", - "cm3": "invsst", + "cm1": "invch1", + "cm2": "invch4", + "cm3": "invch7", "rps": "invrps", "rpl": "invrpl", "bps": "invbps", @@ -1190,7 +1190,20 @@ "invbet": "invbet", "invfed": "invfed", "invamu2": "invamu2", + "invch1": "invch1", + "invch2": "invch2", + "invch3": "invch3", + "invch4": "invch4", + "invch5": "invch5", + "invch6": "invch6", + "invch7": "invch7", + "invch8": "invch8", + "invch9": "invch9", + "gheeds": "invch7", + "Gheed's Fortune": "invch7", + "anni": "invmss", "trch": "invtrch", + "torch": "invtrch", "Harlequin Crest": "invcap_cgrn", "Tal Rasha's Guardianship": "invgth_dpur", "Tal Rasha's Howling Wind": "invgth_dpur", @@ -1641,1905 +1654,1959 @@ "w": 28, "h": 28 }, - "invchm": { + "invch1": { "x": 496, "y": 342, "w": 28, "h": 28 }, + "invch2": { + "x": 526, + "y": 342, + "w": 28, + "h": 56 + }, + "invch3": { + "x": 556, + "y": 342, + "w": 28, + "h": 84 + }, + "invch4": { + "x": 586, + "y": 342, + "w": 28, + "h": 28 + }, + "invch5": { + "x": 616, + "y": 342, + "w": 28, + "h": 56 + }, + "invch6": { + "x": 646, + "y": 342, + "w": 28, + "h": 84 + }, + "invch7": { + "x": 676, + "y": 342, + "w": 28, + "h": 28 + }, + "invch8": { + "x": 706, + "y": 342, + "w": 28, + "h": 56 + }, + "invch9": { + "x": 736, + "y": 342, + "w": 28, + "h": 84 + }, + "invchm": { + "x": 766, + "y": 342, + "w": 28, + "h": 28 + }, "invchn": { - "x": 526, + "x": 796, "y": 342, "w": 56, "h": 84 }, "invci0": { - "x": 584, + "x": 854, "y": 342, "w": 56, "h": 56 }, "invci1": { - "x": 642, + "x": 912, "y": 342, "w": 56, "h": 56 }, "invci2": { - "x": 700, - "y": 342, + "x": 0, + "y": 428, "w": 56, "h": 56 }, "invci3": { - "x": 758, - "y": 342, + "x": 58, + "y": 428, "w": 56, "h": 56 }, "invclb": { - "x": 816, - "y": 342, + "x": 116, + "y": 428, "w": 28, "h": 84 }, "invclbu": { - "x": 846, - "y": 342, + "x": 146, + "y": 428, "w": 28, "h": 84 }, "invclm": { - "x": 876, - "y": 342, + "x": 176, + "y": 428, "w": 28, "h": 112 }, "invclw": { - "x": 906, - "y": 342, + "x": 206, + "y": 428, "w": 28, "h": 84 }, "invcqv": { - "x": 936, - "y": 342, + "x": 236, + "y": 428, "w": 28, "h": 84 }, "invcrn": { - "x": 966, - "y": 342, + "x": 266, + "y": 428, "w": 56, "h": 56 }, "invcrs": { - "x": 0, - "y": 456, + "x": 324, + "y": 428, "w": 56, "h": 84 }, "invcrsu": { - "x": 58, - "y": 456, + "x": 382, + "y": 428, "w": 56, "h": 84 }, "invcst": { - "x": 116, - "y": 456, + "x": 440, + "y": 428, "w": 28, "h": 112 }, "invcstu": { - "x": 146, - "y": 456, + "x": 470, + "y": 428, "w": 28, "h": 112 }, "invd33": { - "x": 176, - "y": 456, + "x": 500, + "y": 428, "w": 28, "h": 56 }, "invdgr": { - "x": 206, - "y": 456, + "x": 530, + "y": 428, "w": 28, "h": 56 }, "invdir": { - "x": 236, - "y": 456, + "x": 560, + "y": 428, "w": 28, "h": 56 }, "invdr1": { - "x": 266, - "y": 456, + "x": 590, + "y": 428, "w": 56, "h": 56 }, "invdr2": { - "x": 324, - "y": 456, + "x": 648, + "y": 428, "w": 56, "h": 56 }, "invdr3": { - "x": 382, - "y": 456, + "x": 706, + "y": 428, "w": 56, "h": 56 }, "invdr4": { - "x": 440, - "y": 456, + "x": 764, + "y": 428, "w": 56, "h": 56 }, "invdr5": { - "x": 498, - "y": 456, + "x": 822, + "y": 428, "w": 56, "h": 56 }, "invear": { - "x": 556, - "y": 456, + "x": 880, + "y": 428, "w": 28, "h": 28 }, "inveye": { - "x": 586, - "y": 456, + "x": 910, + "y": 428, "w": 28, "h": 28 }, "invfang": { - "x": 616, - "y": 456, + "x": 940, + "y": 428, "w": 28, "h": 28 }, "invfed": { - "x": 646, - "y": 456, + "x": 970, + "y": 428, "w": 28, "h": 28 }, "invfhl": { - "x": 676, - "y": 456, + "x": 0, + "y": 542, "w": 56, "h": 56 }, "invfhlu": { - "x": 734, - "y": 456, + "x": 58, + "y": 542, "w": 56, "h": 56 }, "invfla": { - "x": 792, - "y": 456, + "x": 116, + "y": 542, "w": 56, "h": 84 }, "invflag": { - "x": 850, - "y": 456, + "x": 174, + "y": 542, "w": 28, "h": 28 }, "invflb": { - "x": 880, - "y": 456, + "x": 204, + "y": 542, "w": 56, "h": 112 }, "invflc": { - "x": 938, - "y": 456, + "x": 262, + "y": 542, "w": 28, "h": 84 }, "invflcu": { - "x": 968, - "y": 456, + "x": 292, + "y": 542, "w": 28, "h": 84 }, "invfld": { - "x": 0, - "y": 570, + "x": 322, + "y": 542, "w": 56, "h": 84 }, "invful": { - "x": 58, - "y": 570, + "x": 380, + "y": 542, "w": 56, "h": 84 }, "invfulu": { - "x": 116, - "y": 570, + "x": 438, + "y": 542, "w": 56, "h": 84 }, "invg33": { - "x": 174, - "y": 570, + "x": 496, + "y": 542, "w": 28, "h": 56 }, "invgax": { - "x": 204, - "y": 570, + "x": 526, + "y": 542, "w": 56, "h": 112 }, "invgaxu": { - "x": 262, - "y": 570, + "x": 584, + "y": 542, "w": 56, "h": 112 }, "invgbi": { - "x": 320, - "y": 570, + "x": 642, + "y": 542, "w": 28, "h": 56 }, "invghm": { - "x": 350, - "y": 570, + "x": 672, + "y": 542, "w": 56, "h": 56 }, "invgis": { - "x": 408, - "y": 570, + "x": 730, + "y": 542, "w": 28, "h": 112 }, "invgisu": { - "x": 438, - "y": 570, + "x": 760, + "y": 542, "w": 28, "h": 112 }, "invgix": { - "x": 468, - "y": 570, + "x": 790, + "y": 542, "w": 56, "h": 84 }, "invgld": { - "x": 526, - "y": 570, + "x": 848, + "y": 542, "w": 28, "h": 28 }, "invglv": { - "x": 556, - "y": 570, + "x": 878, + "y": 542, "w": 28, "h": 112 }, "invgma": { - "x": 586, - "y": 570, + "x": 908, + "y": 542, "w": 56, "h": 84 }, "invgpl": { - "x": 644, - "y": 570, + "x": 966, + "y": 542, "w": 28, "h": 28 }, "invgpm": { - "x": 674, - "y": 570, + "x": 996, + "y": 542, "w": 28, "h": 28 }, "invgps": { - "x": 704, - "y": 570, + "x": 0, + "y": 656, "w": 28, "h": 28 }, "invgsba": { - "x": 734, - "y": 570, + "x": 30, + "y": 656, "w": 28, "h": 28 }, "invgsbb": { - "x": 764, - "y": 570, + "x": 60, + "y": 656, "w": 28, "h": 28 }, "invgsbc": { - "x": 794, - "y": 570, + "x": 90, + "y": 656, "w": 28, "h": 28 }, "invgsbd": { - "x": 824, - "y": 570, + "x": 120, + "y": 656, "w": 28, "h": 28 }, "invgsbe": { - "x": 854, - "y": 570, + "x": 150, + "y": 656, "w": 28, "h": 28 }, "invgsc": { - "x": 884, - "y": 570, + "x": 180, + "y": 656, "w": 28, "h": 84 }, "invgsd": { - "x": 914, - "y": 570, + "x": 210, + "y": 656, "w": 56, "h": 112 }, "invgsdu": { - "x": 0, - "y": 684, + "x": 268, + "y": 656, "w": 56, "h": 112 }, "invgsga": { - "x": 58, - "y": 684, + "x": 326, + "y": 656, "w": 28, "h": 28 }, "invgsgb": { - "x": 88, - "y": 684, + "x": 356, + "y": 656, "w": 28, "h": 28 }, "invgsgc": { - "x": 118, - "y": 684, + "x": 386, + "y": 656, "w": 28, "h": 28 }, "invgsgd": { - "x": 148, - "y": 684, + "x": 416, + "y": 656, "w": 28, "h": 28 }, "invgsge": { - "x": 178, - "y": 684, + "x": 446, + "y": 656, "w": 28, "h": 28 }, "invgsra": { - "x": 208, - "y": 684, + "x": 476, + "y": 656, "w": 28, "h": 28 }, "invgsrb": { - "x": 238, - "y": 684, + "x": 506, + "y": 656, "w": 28, "h": 28 }, "invgsrc": { - "x": 268, - "y": 684, + "x": 536, + "y": 656, "w": 28, "h": 28 }, "invgsrd": { - "x": 298, - "y": 684, + "x": 566, + "y": 656, "w": 28, "h": 28 }, "invgsre": { - "x": 328, - "y": 684, + "x": 596, + "y": 656, "w": 28, "h": 28 }, "invgsva": { - "x": 358, - "y": 684, + "x": 626, + "y": 656, "w": 28, "h": 28 }, "invgsvb": { - "x": 388, - "y": 684, + "x": 656, + "y": 656, "w": 28, "h": 28 }, "invgsvc": { - "x": 418, - "y": 684, + "x": 686, + "y": 656, "w": 28, "h": 28 }, "invgsvd": { - "x": 448, - "y": 684, + "x": 716, + "y": 656, "w": 28, "h": 28 }, "invgsve": { - "x": 478, - "y": 684, + "x": 746, + "y": 656, "w": 28, "h": 28 }, "invgswa": { - "x": 508, - "y": 684, + "x": 776, + "y": 656, "w": 28, "h": 28 }, "invgswb": { - "x": 538, - "y": 684, + "x": 806, + "y": 656, "w": 28, "h": 28 }, "invgswc": { - "x": 568, - "y": 684, + "x": 836, + "y": 656, "w": 28, "h": 28 }, "invgswd": { - "x": 598, - "y": 684, + "x": 866, + "y": 656, "w": 28, "h": 28 }, "invgswe": { - "x": 628, - "y": 684, + "x": 896, + "y": 656, "w": 28, "h": 28 }, "invgsya": { - "x": 658, - "y": 684, + "x": 926, + "y": 656, "w": 28, "h": 28 }, "invgsyb": { - "x": 688, - "y": 684, + "x": 956, + "y": 656, "w": 28, "h": 28 }, "invgsyc": { - "x": 718, - "y": 684, + "x": 986, + "y": 656, "w": 28, "h": 28 }, "invgsyd": { - "x": 748, - "y": 684, + "x": 0, + "y": 770, "w": 28, "h": 28 }, "invgsye": { - "x": 778, - "y": 684, + "x": 30, + "y": 770, "w": 28, "h": 28 }, "invgth": { - "x": 808, - "y": 684, + "x": 60, + "y": 770, "w": 56, "h": 84 }, "invgts": { - "x": 866, - "y": 684, + "x": 118, + "y": 770, "w": 56, "h": 112 }, "invgtsu": { - "x": 924, - "y": 684, + "x": 176, + "y": 770, "w": 56, "h": 112 }, "invgwn": { - "x": 982, - "y": 684, + "x": 234, + "y": 770, "w": 28, "h": 56 }, "invhal": { - "x": 0, - "y": 798, + "x": 264, + "y": 770, "w": 56, "h": 112 }, "invhax": { - "x": 58, - "y": 798, + "x": 322, + "y": 770, "w": 28, "h": 84 }, "invhaxu": { - "x": 88, - "y": 798, + "x": 352, + "y": 770, "w": 28, "h": 84 }, "invhbl": { - "x": 118, - "y": 798, + "x": 382, + "y": 770, "w": 56, "h": 28 }, "invhbt": { - "x": 176, - "y": 798, + "x": 440, + "y": 770, "w": 56, "h": 56 }, "invhbw": { - "x": 234, - "y": 798, + "x": 498, + "y": 770, "w": 56, "h": 84 }, "invhfh": { - "x": 292, - "y": 798, + "x": 556, + "y": 770, "w": 56, "h": 84 }, "invhgl": { - "x": 350, - "y": 798, + "x": 614, + "y": 770, "w": 56, "h": 56 }, "invhla": { - "x": 408, - "y": 798, + "x": 672, + "y": 770, "w": 56, "h": 84 }, "invhlm": { - "x": 466, - "y": 798, + "x": 730, + "y": 770, "w": 56, "h": 56 }, "invhlmu": { - "x": 524, - "y": 798, + "x": 788, + "y": 770, "w": 56, "h": 56 }, "invhmr": { - "x": 582, - "y": 798, + "x": 846, + "y": 770, "w": 28, "h": 56 }, "invhorn": { - "x": 612, - "y": 798, + "x": 876, + "y": 770, "w": 28, "h": 28 }, "invhp1": { - "x": 642, - "y": 798, + "x": 906, + "y": 770, "w": 28, "h": 28 }, "invhp2": { - "x": 672, - "y": 798, + "x": 936, + "y": 770, "w": 28, "h": 28 }, "invhp3": { - "x": 702, - "y": 798, + "x": 966, + "y": 770, "w": 28, "h": 28 }, "invhp4": { - "x": 732, - "y": 798, + "x": 996, + "y": 770, "w": 28, "h": 28 }, "invhp5": { - "x": 762, - "y": 798, + "x": 0, + "y": 884, "w": 28, "h": 28 }, "invhrb": { - "x": 792, - "y": 798, + "x": 30, + "y": 884, "w": 28, "h": 28 }, "invhrt": { - "x": 822, - "y": 798, + "x": 60, + "y": 884, "w": 28, "h": 28 }, "invhscr": { - "x": 852, - "y": 798, + "x": 90, + "y": 884, "w": 56, "h": 56 }, "invhst": { - "x": 910, - "y": 798, + "x": 148, + "y": 884, "w": 28, "h": 112 }, "invhxb": { - "x": 940, - "y": 798, + "x": 178, + "y": 884, "w": 56, "h": 112 }, "invhxbu": { - "x": 0, - "y": 912, + "x": 236, + "y": 884, "w": 56, "h": 112 }, "invjav": { - "x": 58, - "y": 912, + "x": 294, + "y": 884, "w": 28, "h": 84 }, "invjaw": { - "x": 88, - "y": 912, + "x": 324, + "y": 884, "w": 28, "h": 28 }, "invjbi": { - "x": 118, - "y": 912, + "x": 354, + "y": 884, "w": 28, "h": 56 }, "invkey": { - "x": 148, - "y": 912, + "x": 384, + "y": 884, "w": 28, "h": 28 }, "invkit": { - "x": 178, - "y": 912, + "x": 414, + "y": 884, "w": 56, "h": 84 }, "invkitu": { - "x": 236, - "y": 912, + "x": 472, + "y": 884, "w": 56, "h": 84 }, "invkrs": { - "x": 294, - "y": 912, + "x": 530, + "y": 884, "w": 28, "h": 84 }, "invkrsu": { - "x": 324, - "y": 912, + "x": 560, + "y": 884, "w": 28, "h": 84 }, "invktr": { - "x": 354, - "y": 912, + "x": 590, + "y": 884, "w": 28, "h": 84 }, "invlax": { - "x": 384, - "y": 912, + "x": 620, + "y": 884, "w": 56, "h": 84 }, "invlbb": { - "x": 442, - "y": 912, + "x": 678, + "y": 884, "w": 56, "h": 112 }, "invlbl": { - "x": 500, - "y": 912, + "x": 736, + "y": 884, "w": 56, "h": 28 }, "invlbt": { - "x": 558, - "y": 912, + "x": 794, + "y": 884, "w": 56, "h": 56 }, "invlbw": { - "x": 616, - "y": 912, + "x": 852, + "y": 884, "w": 56, "h": 112 }, "invlea": { - "x": 674, - "y": 912, + "x": 910, + "y": 884, "w": 56, "h": 84 }, "invleg": { - "x": 732, - "y": 912, + "x": 968, + "y": 884, "w": 28, "h": 84 }, "invlgl": { - "x": 762, - "y": 912, + "x": 0, + "y": 998, "w": 56, "h": 56 }, "invlrg": { - "x": 820, - "y": 912, + "x": 58, + "y": 998, "w": 56, "h": 84 }, "invlrgu": { - "x": 878, - "y": 912, + "x": 116, + "y": 998, "w": 56, "h": 84 }, "invlsd": { - "x": 936, - "y": 912, + "x": 174, + "y": 998, "w": 56, "h": 84 }, "invlsdu": { - "x": 0, - "y": 1026, + "x": 232, + "y": 998, "w": 56, "h": 84 }, "invlst": { - "x": 58, - "y": 1026, + "x": 290, + "y": 998, "w": 28, "h": 112 }, "invltp": { - "x": 88, - "y": 1026, + "x": 320, + "y": 998, "w": 56, "h": 84 }, "invlwb": { - "x": 146, - "y": 1026, + "x": 378, + "y": 998, "w": 56, "h": 112 }, "invlxb": { - "x": 204, - "y": 1026, + "x": 436, + "y": 998, "w": 56, "h": 84 }, "invlxbu": { - "x": 262, - "y": 1026, + "x": 494, + "y": 998, "w": 56, "h": 84 }, "invmac": { - "x": 320, - "y": 1026, + "x": 552, + "y": 998, "w": 28, "h": 84 }, "invmau": { - "x": 350, - "y": 1026, + "x": 582, + "y": 998, "w": 56, "h": 112 }, "invmauu": { - "x": 408, - "y": 1026, + "x": 640, + "y": 998, "w": 56, "h": 112 }, "invmbl": { - "x": 466, - "y": 1026, + "x": 698, + "y": 998, "w": 56, "h": 28 }, "invmbt": { - "x": 524, - "y": 1026, + "x": 756, + "y": 998, "w": 56, "h": 56 }, "invmgl": { - "x": 582, - "y": 1026, + "x": 814, + "y": 998, "w": 56, "h": 56 }, "invmp1": { - "x": 640, - "y": 1026, + "x": 872, + "y": 998, "w": 28, "h": 28 }, "invmp2": { - "x": 670, - "y": 1026, + "x": 902, + "y": 998, "w": 28, "h": 28 }, "invmp3": { - "x": 700, - "y": 1026, + "x": 932, + "y": 998, "w": 28, "h": 28 }, "invmp4": { - "x": 730, - "y": 1026, + "x": 962, + "y": 998, "w": 28, "h": 28 }, "invmp5": { - "x": 760, - "y": 1026, + "x": 992, + "y": 998, "w": 28, "h": 28 }, "invmph": { - "x": 790, - "y": 1026, + "x": 0, + "y": 1112, "w": 28, "h": 56 }, "invmpi": { - "x": 820, - "y": 1026, + "x": 30, + "y": 1112, "w": 56, "h": 84 }, "invmpiu": { - "x": 878, - "y": 1026, + "x": 88, + "y": 1112, "w": 56, "h": 84 }, "invmsf": { - "x": 936, - "y": 1026, + "x": 146, + "y": 1112, "w": 28, "h": 84 }, "invmsk": { - "x": 966, - "y": 1026, + "x": 176, + "y": 1112, "w": 56, "h": 56 }, "invmss": { - "x": 0, - "y": 1140, + "x": 234, + "y": 1112, "w": 28, "h": 28 }, "invmst": { - "x": 30, - "y": 1140, + "x": 264, + "y": 1112, "w": 28, "h": 84 }, "invmstu": { - "x": 60, - "y": 1140, + "x": 294, + "y": 1112, "w": 28, "h": 84 }, "invmxb": { - "x": 90, - "y": 1140, + "x": 324, + "y": 1112, "w": 56, "h": 84 }, "invmxbu": { - "x": 148, - "y": 1140, + "x": 382, + "y": 1112, "w": 56, "h": 84 }, "invne1": { - "x": 206, - "y": 1140, + "x": 440, + "y": 1112, "w": 56, "h": 56 }, "invne2": { - "x": 264, - "y": 1140, + "x": 498, + "y": 1112, "w": 56, "h": 56 }, "invne3": { - "x": 322, - "y": 1140, + "x": 556, + "y": 1112, "w": 56, "h": 56 }, "invne4": { - "x": 380, - "y": 1140, + "x": 614, + "y": 1112, "w": 56, "h": 56 }, "invne5": { - "x": 438, - "y": 1140, + "x": 672, + "y": 1112, "w": 56, "h": 56 }, "invnps": { - "x": 496, - "y": 1140, + "x": 730, + "y": 1112, "w": 28, "h": 28 }, "invob1": { - "x": 526, - "y": 1140, + "x": 760, + "y": 1112, "w": 28, "h": 56 }, "invob2": { - "x": 556, - "y": 1140, + "x": 790, + "y": 1112, "w": 28, "h": 56 }, "invob3": { - "x": 586, - "y": 1140, + "x": 820, + "y": 1112, "w": 28, "h": 56 }, "invob4": { - "x": 616, - "y": 1140, + "x": 850, + "y": 1112, "w": 28, "h": 56 }, "invob5": { - "x": 646, - "y": 1140, + "x": 880, + "y": 1112, "w": 28, "h": 84 }, "invopl": { - "x": 676, - "y": 1140, + "x": 910, + "y": 1112, "w": 28, "h": 28 }, "invopm": { - "x": 706, - "y": 1140, + "x": 940, + "y": 1112, "w": 28, "h": 28 }, "invops": { - "x": 736, - "y": 1140, + "x": 970, + "y": 1112, "w": 28, "h": 28 }, "invpa1": { - "x": 766, - "y": 1140, + "x": 0, + "y": 1198, "w": 56, "h": 56 }, "invpa2": { - "x": 824, - "y": 1140, + "x": 58, + "y": 1198, "w": 56, "h": 56 }, "invpa3": { - "x": 882, - "y": 1140, + "x": 116, + "y": 1198, "w": 56, "h": 112 }, "invpa4": { - "x": 940, - "y": 1140, + "x": 174, + "y": 1198, "w": 56, "h": 112 }, "invpa5": { - "x": 0, - "y": 1254, + "x": 232, + "y": 1198, "w": 56, "h": 56 }, "invpax": { - "x": 58, - "y": 1254, + "x": 290, + "y": 1198, "w": 56, "h": 112 }, "invpik": { - "x": 116, - "y": 1254, + "x": 348, + "y": 1198, "w": 56, "h": 112 }, "invpil": { - "x": 174, - "y": 1254, + "x": 406, + "y": 1198, "w": 28, "h": 84 }, "invplt": { - "x": 204, - "y": 1254, + "x": 436, + "y": 1198, "w": 56, "h": 84 }, "invpot": { - "x": 262, - "y": 1254, + "x": 494, + "y": 1198, "w": 28, "h": 28 }, "invqf1": { - "x": 292, - "y": 1254, + "x": 524, + "y": 1198, "w": 56, "h": 84 }, "invqf2": { - "x": 350, - "y": 1254, + "x": 582, + "y": 1198, "w": 56, "h": 84 }, "invqlt": { - "x": 408, - "y": 1254, + "x": 640, + "y": 1198, "w": 56, "h": 84 }, "invquil": { - "x": 466, - "y": 1254, + "x": 698, + "y": 1198, "w": 28, "h": 28 }, "invqvr": { - "x": 496, - "y": 1254, + "x": 728, + "y": 1198, "w": 28, "h": 84 }, "invramn": { - "x": 526, - "y": 1254, + "x": 758, + "y": 1198, "w": 28, "h": 28 }, "invrber": { - "x": 556, - "y": 1254, + "x": 788, + "y": 1198, "w": 28, "h": 28 }, "invrbk": { - "x": 586, - "y": 1254, + "x": 818, + "y": 1198, "w": 28, "h": 56 }, "invrcham": { - "x": 616, - "y": 1254, + "x": 848, + "y": 1198, "w": 28, "h": 28 }, "invrdol": { - "x": 646, - "y": 1254, + "x": 878, + "y": 1198, "w": 28, "h": 28 }, "invrel": { - "x": 676, - "y": 1254, + "x": 908, + "y": 1198, "w": 28, "h": 28 }, "invreld": { - "x": 706, - "y": 1254, + "x": 938, + "y": 1198, "w": 28, "h": 28 }, "invreth": { - "x": 736, - "y": 1254, + "x": 968, + "y": 1198, "w": 28, "h": 28 }, "invrfal": { - "x": 766, - "y": 1254, + "x": 0, + "y": 1312, "w": 28, "h": 28 }, "invrgul": { - "x": 796, - "y": 1254, + "x": 30, + "y": 1312, "w": 28, "h": 28 }, "invrhel": { - "x": 826, - "y": 1254, + "x": 60, + "y": 1312, "w": 28, "h": 28 }, "invrin": { - "x": 856, - "y": 1254, + "x": 90, + "y": 1312, "w": 28, "h": 28 }, "invrio": { - "x": 886, - "y": 1254, + "x": 120, + "y": 1312, "w": 28, "h": 28 }, "invrist": { - "x": 916, - "y": 1254, + "x": 150, + "y": 1312, "w": 28, "h": 28 }, "invrith": { - "x": 946, - "y": 1254, + "x": 180, + "y": 1312, "w": 28, "h": 28 }, "invrjo": { - "x": 976, - "y": 1254, + "x": 210, + "y": 1312, "w": 28, "h": 28 }, "invrko": { - "x": 0, - "y": 1368, + "x": 240, + "y": 1312, "w": 28, "h": 28 }, "invrlem": { - "x": 30, - "y": 1368, + "x": 270, + "y": 1312, "w": 28, "h": 28 }, "invrlo": { - "x": 60, - "y": 1368, + "x": 300, + "y": 1312, "w": 28, "h": 28 }, "invrlum": { - "x": 90, - "y": 1368, + "x": 330, + "y": 1312, "w": 28, "h": 28 }, "invrmal": { - "x": 120, - "y": 1368, + "x": 360, + "y": 1312, "w": 28, "h": 28 }, "invrnef": { - "x": 150, - "y": 1368, + "x": 390, + "y": 1312, "w": 28, "h": 28 }, "invrng": { - "x": 180, - "y": 1368, + "x": 420, + "y": 1312, "w": 56, "h": 84 }, "invrohm": { - "x": 238, - "y": 1368, + "x": 478, + "y": 1312, "w": 28, "h": 28 }, "invrort": { - "x": 268, - "y": 1368, + "x": 508, + "y": 1312, "w": 28, "h": 28 }, "invrpl": { - "x": 298, - "y": 1368, + "x": 538, + "y": 1312, "w": 28, "h": 28 }, "invrps": { - "x": 328, - "y": 1368, + "x": 568, + "y": 1312, "w": 28, "h": 28 }, "invrpul": { - "x": 358, - "y": 1368, + "x": 598, + "y": 1312, "w": 28, "h": 28 }, "invrral": { - "x": 388, - "y": 1368, + "x": 628, + "y": 1312, "w": 28, "h": 28 }, "invrsc": { - "x": 418, - "y": 1368, + "x": 658, + "y": 1312, "w": 28, "h": 28 }, "invrshae": { - "x": 448, - "y": 1368, + "x": 688, + "y": 1312, "w": 28, "h": 28 }, "invrsol": { - "x": 478, - "y": 1368, + "x": 718, + "y": 1312, "w": 28, "h": 28 }, "invrsur": { - "x": 508, - "y": 1368, + "x": 748, + "y": 1312, "w": 28, "h": 28 }, "invrtal": { - "x": 538, - "y": 1368, + "x": 778, + "y": 1312, "w": 28, "h": 28 }, "invrthul": { - "x": 568, - "y": 1368, + "x": 808, + "y": 1312, "w": 28, "h": 28 }, "invrtir": { - "x": 598, - "y": 1368, + "x": 838, + "y": 1312, "w": 28, "h": 28 }, "invrum": { - "x": 628, - "y": 1368, + "x": 868, + "y": 1312, "w": 28, "h": 28 }, "invrvex": { - "x": 658, - "y": 1368, + "x": 898, + "y": 1312, "w": 28, "h": 28 }, "invrxb": { - "x": 688, - "y": 1368, + "x": 928, + "y": 1312, "w": 56, "h": 84 }, "invrxbu": { - "x": 746, - "y": 1368, + "x": 0, + "y": 1398, "w": 56, "h": 84 }, "invrzod": { - "x": 804, - "y": 1368, + "x": 58, + "y": 1398, "w": 28, "h": 28 }, "invsbb": { - "x": 834, - "y": 1368, + "x": 88, + "y": 1398, "w": 56, "h": 84 }, "invsbbu": { - "x": 892, - "y": 1368, + "x": 146, + "y": 1398, "w": 56, "h": 84 }, "invsbk": { - "x": 950, - "y": 1368, + "x": 204, + "y": 1398, "w": 56, "h": 56 }, "invsbr": { - "x": 0, - "y": 1454, + "x": 262, + "y": 1398, "w": 28, "h": 84 }, "invsbru": { - "x": 30, - "y": 1454, + "x": 292, + "y": 1398, "w": 28, "h": 84 }, "invsbw": { - "x": 60, - "y": 1454, + "x": 322, + "y": 1398, "w": 56, "h": 84 }, "invscb": { - "x": 118, - "y": 1454, + "x": 380, + "y": 1398, "w": 56, "h": 56 }, "invscl": { - "x": 176, - "y": 1454, + "x": 438, + "y": 1398, "w": 56, "h": 84 }, "invscm": { - "x": 234, - "y": 1454, + "x": 496, + "y": 1398, "w": 28, "h": 84 }, "invscmu": { - "x": 264, - "y": 1454, + "x": 526, + "y": 1398, "w": 28, "h": 84 }, "invscp": { - "x": 294, - "y": 1454, + "x": 556, + "y": 1398, "w": 28, "h": 84 }, "invscy": { - "x": 324, - "y": 1454, + "x": 586, + "y": 1398, "w": 56, "h": 112 }, "invscyu": { - "x": 382, - "y": 1454, + "x": 644, + "y": 1398, "w": 56, "h": 112 }, "invskc": { - "x": 440, - "y": 1454, + "x": 702, + "y": 1398, "w": 28, "h": 28 }, "invskf": { - "x": 470, - "y": 1454, + "x": 732, + "y": 1398, "w": 28, "h": 28 }, "invskl": { - "x": 500, - "y": 1454, + "x": 762, + "y": 1398, "w": 28, "h": 28 }, "invskp": { - "x": 530, - "y": 1454, + "x": 792, + "y": 1398, "w": 56, "h": 56 }, "invskr": { - "x": 588, - "y": 1454, + "x": 850, + "y": 1398, "w": 28, "h": 84 }, "invskru": { - "x": 618, - "y": 1454, + "x": 880, + "y": 1398, "w": 28, "h": 84 }, "invsku": { - "x": 648, - "y": 1454, + "x": 910, + "y": 1398, "w": 28, "h": 28 }, "invskz": { - "x": 678, - "y": 1454, + "x": 940, + "y": 1398, "w": 28, "h": 28 }, "invsml": { - "x": 708, - "y": 1454, + "x": 0, + "y": 1512, "w": 56, "h": 56 }, "invsmlu": { - "x": 766, - "y": 1454, + "x": 58, + "y": 1512, "w": 56, "h": 56 }, "invspc": { - "x": 824, - "y": 1454, + "x": 116, + "y": 1512, "w": 28, "h": 84 }, "invspcu": { - "x": 854, - "y": 1454, + "x": 146, + "y": 1512, "w": 28, "h": 84 }, "invspk": { - "x": 884, - "y": 1454, + "x": 176, + "y": 1512, "w": 56, "h": 84 }, "invspku": { - "x": 942, - "y": 1454, + "x": 234, + "y": 1512, "w": 56, "h": 84 }, "invspl": { - "x": 0, - "y": 1568, + "x": 292, + "y": 1512, "w": 56, "h": 84 }, "invsple": { - "x": 58, - "y": 1568, + "x": 350, + "y": 1512, "w": 28, "h": 28 }, "invspr": { - "x": 88, - "y": 1568, + "x": 380, + "y": 1512, "w": 56, "h": 112 }, "invspt": { - "x": 146, - "y": 1568, + "x": 438, + "y": 1512, "w": 56, "h": 112 }, "invssd": { - "x": 204, - "y": 1568, + "x": 496, + "y": 1512, "w": 28, "h": 84 }, "invssp": { - "x": 234, - "y": 1568, + "x": 526, + "y": 1512, "w": 28, "h": 84 }, "invsst": { - "x": 264, - "y": 1568, + "x": 556, + "y": 1512, "w": 28, "h": 84 }, "invstu": { - "x": 294, - "y": 1568, + "x": 586, + "y": 1512, "w": 56, "h": 84 }, "invswb": { - "x": 352, - "y": 1568, + "x": 644, + "y": 1512, "w": 56, "h": 84 }, "invswbu": { - "x": 410, - "y": 1568, + "x": 702, + "y": 1512, "w": 56, "h": 84 }, "invtail": { - "x": 468, - "y": 1568, + "x": 760, + "y": 1512, "w": 28, "h": 28 }, "invtax": { - "x": 498, - "y": 1568, + "x": 790, + "y": 1512, "w": 28, "h": 56 }, "invtbl": { - "x": 528, - "y": 1568, + "x": 820, + "y": 1512, "w": 56, "h": 28 }, "invtbt": { - "x": 586, - "y": 1568, + "x": 878, + "y": 1512, "w": 56, "h": 56 }, "invtes": { - "x": 644, - "y": 1568, + "x": 936, + "y": 1512, "w": 28, "h": 28 }, "invtgl": { - "x": 674, - "y": 1568, + "x": 966, + "y": 1512, "w": 56, "h": 56 }, "invtk3": { - "x": 732, - "y": 1568, + "x": 0, + "y": 1626, "w": 28, "h": 56 }, "invtkn": { - "x": 762, - "y": 1568, + "x": 30, + "y": 1626, "w": 28, "h": 56 }, "invtoa": { - "x": 792, - "y": 1568, + "x": 60, + "y": 1626, "w": 28, "h": 28 }, "invtow": { - "x": 822, - "y": 1568, + "x": 90, + "y": 1626, "w": 56, "h": 84 }, "invtowu": { - "x": 880, - "y": 1568, + "x": 148, + "y": 1626, "w": 56, "h": 84 }, "invtrch": { - "x": 938, - "y": 1568, + "x": 206, + "y": 1626, "w": 28, "h": 56 }, "invtri": { - "x": 968, - "y": 1568, + "x": 236, + "y": 1626, "w": 56, "h": 112 }, "invtriu": { - "x": 0, - "y": 1682, + "x": 294, + "y": 1626, "w": 56, "h": 112 }, "invtsp": { - "x": 58, - "y": 1682, + "x": 352, + "y": 1626, "w": 28, "h": 112 }, "invuhms": { - "x": 88, - "y": 1682, + "x": 382, + "y": 1626, "w": 56, "h": 56 }, "invutss": { - "x": 146, - "y": 1682, + "x": 440, + "y": 1626, "w": 56, "h": 112 }, "invvbl": { - "x": 204, - "y": 1682, + "x": 498, + "y": 1626, "w": 56, "h": 28 }, "invvbt": { - "x": 262, - "y": 1682, + "x": 556, + "y": 1626, "w": 56, "h": 56 }, "invvgl": { - "x": 320, - "y": 1682, + "x": 614, + "y": 1626, "w": 56, "h": 56 }, "invvip": { - "x": 378, - "y": 1682, + "x": 672, + "y": 1626, "w": 28, "h": 28 }, "invvou": { - "x": 408, - "y": 1682, + "x": 702, + "y": 1626, "w": 56, "h": 112 }, "invvpl": { - "x": 466, - "y": 1682, + "x": 760, + "y": 1626, "w": 28, "h": 28 }, "invvps": { - "x": 496, - "y": 1682, + "x": 790, + "y": 1626, "w": 28, "h": 28 }, "invwax": { - "x": 526, - "y": 1682, + "x": 820, + "y": 1626, "w": 56, "h": 84 }, "invwhm": { - "x": 584, - "y": 1682, + "x": 878, + "y": 1626, "w": 56, "h": 84 }, "invwnd": { - "x": 642, - "y": 1682, + "x": 936, + "y": 1626, "w": 28, "h": 56 }, "invwndu": { - "x": 672, - "y": 1682, + "x": 966, + "y": 1626, "w": 28, "h": 56 }, "invwps": { - "x": 702, - "y": 1682, + "x": 996, + "y": 1626, "w": 28, "h": 28 }, "invwsc": { - "x": 732, - "y": 1682, + "x": 0, + "y": 1740, "w": 56, "h": 112 }, "invwsd": { - "x": 790, - "y": 1682, + "x": 58, + "y": 1740, "w": 28, "h": 84 }, "invwsp": { - "x": 820, - "y": 1682, + "x": 88, + "y": 1740, "w": 56, "h": 84 }, "invwst": { - "x": 878, - "y": 1682, + "x": 146, + "y": 1740, "w": 56, "h": 112 }, "invxaru": { - "x": 936, - "y": 1682, + "x": 204, + "y": 1740, "w": 56, "h": 84 }, "invxkpu": { - "x": 0, - "y": 1796, + "x": 262, + "y": 1740, "w": 56, "h": 56 }, "invxmlu": { - "x": 58, - "y": 1796, + "x": 320, + "y": 1740, "w": 56, "h": 56 }, "invxpku": { - "x": 116, - "y": 1796, + "x": 378, + "y": 1740, "w": 56, "h": 84 }, "invxrgu": { - "x": 174, - "y": 1796, + "x": 436, + "y": 1740, "w": 56, "h": 84 }, "invxrnu": { - "x": 232, - "y": 1796, + "x": 494, + "y": 1740, "w": 56, "h": 56 }, "invxrss": { - "x": 290, - "y": 1796, + "x": 552, + "y": 1740, "w": 56, "h": 84 }, "invxshu": { - "x": 348, - "y": 1796, + "x": 610, + "y": 1740, "w": 56, "h": 84 }, "invxtuu": { - "x": 406, - "y": 1796, + "x": 668, + "y": 1740, "w": 56, "h": 84 }, "invxyz": { - "x": 464, - "y": 1796, + "x": 726, + "y": 1740, "w": 28, "h": 28 }, "invyps": { - "x": 494, - "y": 1796, + "x": 756, + "y": 1740, "w": 28, "h": 28 }, "invywn": { - "x": 524, - "y": 1796, + "x": 786, + "y": 1740, "w": 28, "h": 56 }, "invcap_cgrn": { - "x": 554, - "y": 1796, + "x": 816, + "y": 1740, "w": 56, "h": 56 }, "invgth_dpur": { - "x": 612, - "y": 1796, + "x": 874, + "y": 1740, "w": 56, "h": 84 }, "invtgl_lgry": { - "x": 670, - "y": 1796, + "x": 932, + "y": 1740, "w": 56, "h": 56 }, "invvbl_blac": { - "x": 728, - "y": 1796, + "x": 0, + "y": 1854, "w": 56, "h": 28 }, "invlbl_blac": { - "x": 786, - "y": 1796, + "x": 58, + "y": 1854, "w": 56, "h": 28 } diff --git a/scripts/pack-ui.ts b/scripts/pack-ui.ts index da217ec..65d7d26 100644 --- a/scripts/pack-ui.ts +++ b/scripts/pack-ui.ts @@ -448,20 +448,40 @@ async function main(): Promise { } } + // Register authentic charm DC6 icons (invch1..invch9) + for (let i = 1; i <= 9; i++) { + const charmInv = `invch${i}` + if (archives.has(`data/global/items/${charmInv}.dc6`)) { + uniqueInvFiles.add(charmInv) + } + } + // Identity mapping for every invfile: codeToInvFile[inv] = inv for (const inv of uniqueInvFiles) { codeToInvFile[inv] = inv } + + // Authentic charm base item code mappings (overriding misc.txt placeholder invfiles invchm, invwnd, invsst) + codeToInvFile['cm1'] = 'invch1' + codeToInvFile['cm2'] = 'invch4' + codeToInvFile['cm3'] = 'invch7' + codeToInvFile['gheeds'] = 'invch7' + codeToInvFile["Gheed's Fortune"] = 'invch7' + // Explicitly guarantee Annihilus and Torch mappings if (archives.has('data/global/items/invmss.dc6')) { uniqueInvFiles.add('invmss') codeToInvFile['mss'] = 'invmss' codeToInvFile['invmss'] = 'invmss' + codeToInvFile['anni'] = 'invmss' + codeToInvFile['Annihilus'] = 'invmss' } if (archives.has('data/global/items/invtrch.dc6')) { uniqueInvFiles.add('invtrch') codeToInvFile['trch'] = 'invtrch' codeToInvFile['invtrch'] = 'invtrch' + codeToInvFile['torch'] = 'invtrch' + codeToInvFile['Hellfire Torch'] = 'invtrch' } // Register transformed item lookups in codeToInvFile diff --git a/src/ui/baked-ui-meta.ts b/src/ui/baked-ui-meta.ts index 497f207..9e891e1 100644 --- a/src/ui/baked-ui-meta.ts +++ b/src/ui/baked-ui-meta.ts @@ -81,10 +81,10 @@ export const ACT_QUEST_ASSET_MAP: Readonly { + const itemRects = BAKED_UI_MANIFEST.itemRects + const codeToInv = BAKED_UI_MANIFEST.codeToInvFile + + it('bakes all authentic charm DC6 icons invch1..invch9, invmss, invtrch into items atlas', () => { + // 1. All 9 charm sprite variants exist in itemRects + for (let i = 1; i <= 9; i++) { + const charmKey = `invch${i}` + expect(itemRects[charmKey], `Expected ${charmKey} in itemRects`).toBeDefined() + expect(itemRects[charmKey]!.w).toBe(28) + expect(itemRects[charmKey]!.h).toBeGreaterThan(0) + } + + // 2. Annihilus and Hellfire Torch icons exist + expect(itemRects['invmss']).toBeDefined() + expect(itemRects['invmss']!.w).toBe(28) + expect(itemRects['invmss']!.h).toBe(28) + + expect(itemRects['invtrch']).toBeDefined() + expect(itemRects['invtrch']!.w).toBe(28) + expect(itemRects['invtrch']!.h).toBe(56) + + // 3. Confirm authentic DC6 dimensions from 1.13c MPQ + expect(itemRects['invch1']!.h).toBe(28) // Small Charm variant 1 + expect(itemRects['invch2']!.h).toBe(56) // Large Charm variant 1 + expect(itemRects['invch3']!.h).toBe(84) // Grand Charm variant 1 + expect(itemRects['invch4']!.h).toBe(28) // Small Charm variant 2 + expect(itemRects['invch5']!.h).toBe(56) // Large Charm variant 2 + expect(itemRects['invch6']!.h).toBe(84) // Grand Charm variant 2 + expect(itemRects['invch7']!.h).toBe(28) // Small Charm variant 3 + expect(itemRects['invch8']!.h).toBe(56) // Large Charm variant 3 + expect(itemRects['invch9']!.h).toBe(84) // Grand Charm variant 3 + }) + + it('maps authentic charm item codes to charm DC6 icons in codeToInvFile', () => { + // Base charm code mappings + expect(codeToInv['cm1']).toBe('invch1') + expect(codeToInv['cm2']).toBe('invch4') + expect(codeToInv['cm3']).toBe('invch7') + + // Identity mappings for all 9 charm invfiles + for (let i = 1; i <= 9; i++) { + expect(codeToInv[`invch${i}`]).toBe(`invch${i}`) + } + + // Unique charms + expect(codeToInv['gheeds']).toBe('invch7') + expect(codeToInv["Gheed's Fortune"]).toBe('invch7') + expect(codeToInv['anni']).toBe('invmss') + expect(codeToInv['Annihilus']).toBe('invmss') + expect(codeToInv['torch']).toBe('invtrch') + expect(codeToInv['Hellfire Torch']).toBe('invtrch') + }) + + describe('resolveItemSpriteRect charm resolution', () => { + it('cm1 (Small Charm) resolves to 1x1 charm rect (invch1, invch2, invch3, or invmss)', () => { + const validSmallCharmKeys = ['invch1', 'invch2', 'invch3', 'invmss'] + const validSmallCharmRects = validSmallCharmKeys.map((k) => itemRects[k]).filter(Boolean) + + // Base item code cm1 + const rectBase = resolveItemSpriteRect({ code: 'cm1' }, itemRects) + expect(rectBase).not.toBeNull() + expect(validSmallCharmRects).toContainEqual(rectBase) + expect(rectBase).toEqual(itemRects['invch1']) + + // Item with name + const rectName = resolveItemSpriteRect({ code: 'cm1', name: 'Small Charm' }, itemRects) + expect(validSmallCharmRects).toContainEqual(rectName) + + // Item with misc.txt placeholder invfile (invchm) + const rectPlaceholder = resolveItemSpriteRect( + { code: 'cm1', invFile: 'invchm', name: 'Small Charm of Vita' }, + itemRects, + ) + expect(rectPlaceholder).not.toBeNull() + expect(validSmallCharmRects).toContainEqual(rectPlaceholder) + + // Specific variants invch2, invch3 + const rectVar2 = resolveItemSpriteRect({ code: 'cm1', invFile: 'invch2' }, itemRects) + expect(rectVar2).toEqual(itemRects['invch2']) + + const rectVar3 = resolveItemSpriteRect({ code: 'cm1', invFile: 'invch3' }, itemRects) + expect(rectVar3).toEqual(itemRects['invch3']) + + // Unique Annihilus + const rectAnni = resolveItemSpriteRect({ code: 'anni', name: 'Annihilus' }, itemRects) + expect(rectAnni).toEqual(itemRects['invmss']) + }) + + it('cm2 (Large Charm) resolves to 1x2 charm rect (invch4, invch5, invch6, or invtrch)', () => { + const validLargeCharmKeys = ['invch4', 'invch5', 'invch6', 'invtrch'] + const validLargeCharmRects = validLargeCharmKeys.map((k) => itemRects[k]).filter(Boolean) + + // Base item code cm2 + const rectBase = resolveItemSpriteRect({ code: 'cm2' }, itemRects) + expect(rectBase).not.toBeNull() + expect(validLargeCharmRects).toContainEqual(rectBase) + expect(rectBase).toEqual(itemRects['invch4']) + + // Item with misc.txt placeholder invfile (invwnd - Wand) + const rectPlaceholder = resolveItemSpriteRect( + { code: 'cm2', invFile: 'invwnd', name: 'Large Charm of Strength' }, + itemRects, + ) + expect(rectPlaceholder).not.toBeNull() + expect(validLargeCharmRects).toContainEqual(rectPlaceholder) + expect(rectPlaceholder).not.toEqual(itemRects['invwnd']) + + // Specific variants invch5, invch6 + const rectVar5 = resolveItemSpriteRect({ code: 'cm2', invFile: 'invch5' }, itemRects) + expect(rectVar5).toEqual(itemRects['invch5']) + + const rectVar6 = resolveItemSpriteRect({ code: 'cm2', invFile: 'invch6' }, itemRects) + expect(rectVar6).toEqual(itemRects['invch6']) + + // Unique Hellfire Torch + const rectTorch = resolveItemSpriteRect({ code: 'torch', name: 'Hellfire Torch' }, itemRects) + expect(rectTorch).toEqual(itemRects['invtrch']) + }) + + it('cm3 (Grand Charm / Gheed) resolves to 1x3 charm rect (invch7, invch8, invch9), and NOT invsst', () => { + const validGrandCharmKeys = ['invch7', 'invch8', 'invch9'] + const validGrandCharmRects = validGrandCharmKeys.map((k) => itemRects[k]).filter(Boolean) + + // Base item code cm3 + const rectBase = resolveItemSpriteRect({ code: 'cm3' }, itemRects) + expect(rectBase).not.toBeNull() + expect(validGrandCharmRects).toContainEqual(rectBase) + expect(rectBase).toEqual(itemRects['invch7']) + expect(rectBase).not.toEqual(itemRects['invsst']) + + // Item with misc.txt placeholder invfile (invsst - Short Staff) + const rectPlaceholder = resolveItemSpriteRect( + { code: 'cm3', invFile: 'invsst', name: 'Grand Charm of Balance' }, + itemRects, + ) + expect(rectPlaceholder).not.toBeNull() + expect(validGrandCharmRects).toContainEqual(rectPlaceholder) + expect(rectPlaceholder).not.toEqual(itemRects['invsst']) + + // Specific variants invch8, invch9 + const rectVar8 = resolveItemSpriteRect({ code: 'cm3', invFile: 'invch8' }, itemRects) + expect(rectVar8).toEqual(itemRects['invch8']) + + const rectVar9 = resolveItemSpriteRect({ code: 'cm3', invFile: 'invch9' }, itemRects) + expect(rectVar9).toEqual(itemRects['invch9']) + + // Unique Gheed's Fortune + const rectGheeds = resolveItemSpriteRect({ code: 'cm3', name: "Gheed's Fortune" }, itemRects) + expect(rectGheeds).not.toBeNull() + expect(validGrandCharmRects).toContainEqual(rectGheeds) + expect(rectGheeds).toEqual(itemRects['invch7']) + expect(rectGheeds).not.toEqual(itemRects['invsst']) + + const rectGheedsAlias = resolveItemSpriteRect({ code: 'gheeds' }, itemRects) + expect(rectGheedsAlias).not.toBeNull() + expect(validGrandCharmRects).toContainEqual(rectGheedsAlias) + expect(rectGheedsAlias).not.toEqual(itemRects['invsst']) + }) + + it('enforces Tier 5 dimension fallback for 1x3 items to avoid rendering as wooden staff', () => { + // 1x3 item with charm name or cm code + const fallbackCharm = { name: 'Unknown Grand Charm', invWidth: 1, invHeight: 3 } + const rectCharm = resolveItemSpriteRect(fallbackCharm, itemRects) + expect(rectCharm).toEqual(itemRects['invch7']) + expect(rectCharm).not.toEqual(itemRects['invsst']) + + // 1x3 item with cm3 code and missing invfile + const fallbackCm3 = { code: 'cm3', invWidth: 1, invHeight: 3 } + const rectCm3 = resolveItemSpriteRect(fallbackCm3, itemRects) + expect(rectCm3).toEqual(itemRects['invch7']) + expect(rectCm3).not.toEqual(itemRects['invsst']) + + // Generic 1x3 item fallback + const generic1x3 = { invWidth: 1, invHeight: 3 } + const rect1x3 = resolveItemSpriteRect(generic1x3, itemRects) + expect(rect1x3).not.toBeNull() + expect(rect1x3).toEqual(itemRects['invch7']) + }) + }) + + describe('Comprehensive Base Item & Starter Inventory Audit', () => { + it('resolves valid non-null sprite rectangles for all codes in codeToInvFile', () => { + let resolvedCount = 0 + for (const [code, invFile] of Object.entries(codeToInv)) { + const rect = resolveItemSpriteRect({ code, invFile }, itemRects) + expect(rect, `Item code "${code}" (invFile "${invFile}") must resolve to sprite rect`).not.toBeNull() + expect(rect!.w, `Item code "${code}" width must be > 0`).toBeGreaterThan(0) + expect(rect!.h, `Item code "${code}" height must be > 0`).toBeGreaterThan(0) + resolvedCount++ + } + expect(resolvedCount).toBeGreaterThanOrEqual(300) + }) + + it('resolves valid sprite rectangles for all starter equipped items and bag items', () => { + for (const [slot, item] of Object.entries(STARTER_EQUIPPED_GEAR)) { + if (!item) continue + const rect = resolveItemSpriteRect(item, itemRects) + expect(rect, `Starter equipped ${slot} (${item.name}) must resolve`).not.toBeNull() + expect(rect!.w).toBeGreaterThan(0) + expect(rect!.h).toBeGreaterThan(0) + } + + for (const { item, col, row } of STARTER_BAG_ITEMS) { + const rect = resolveItemSpriteRect(item, itemRects) + expect(rect, `Starter bag item at (${col}, ${row}) (${item.name}) must resolve`).not.toBeNull() + expect(rect!.w).toBeGreaterThan(0) + expect(rect!.h).toBeGreaterThan(0) + + // Specifically check charms in bag + if (item.id === 'bag-gheeds') { + expect(rect).toEqual(itemRects['invch7']) + expect(rect).not.toEqual(itemRects['invsst']) + } else if (item.id === 'bag-torch') { + expect(rect).toEqual(itemRects['invtrch']) + } else if (item.id === 'bag-anni') { + expect(rect).toEqual(itemRects['invmss']) + } + } + }) + + it('audits all base items from authentic 1.13c misc.txt, weapons.txt, and armor.txt if MPQs present', async () => { + const d2Path = join(process.cwd(), 'samples', 'd2') + if (!existsSync(join(d2Path, 'Patch_D2.mpq'))) { + return // Skip MPQ read if samples/d2 is not mounted in environment + } + + const archives = new MountedArchives() + for (const m of ['d2char.mpq', 'd2data.mpq', 'd2exp.mpq', 'Patch_D2.mpq']) { + archives.add(m, await MpqArchive.open(await fileSource(join(d2Path, m)))) + } + + for (const tblFile of ['weapons.txt', 'armor.txt', 'misc.txt']) { + const data = await archives.read(`data/global/excel/${tblFile}`) + const tbl = parseTable(new TextDecoder().decode(data)) + for (const row of tbl.rows) { + const code = row['code']?.trim() + if (!code) continue + const invfile = row['invfile']?.trim() + const rect = resolveItemSpriteRect({ code, invFile: invfile, name: row['name'] }, itemRects) + expect(rect, `Base item ${code} (${row['name']}) from ${tblFile} must resolve to sprite rect`).not.toBeNull() + expect(rect!.w).toBeGreaterThan(0) + expect(rect!.h).toBeGreaterThan(0) + + // Verify charm items never resolve to staff or wand + if (code === 'cm3') { + expect(rect).not.toEqual(itemRects['invsst']) + } else if (code === 'cm2') { + expect(rect).not.toEqual(itemRects['invwnd']) + } + } + } + }) + }) +})