PKHeX/PKHeX.Core/Items/ItemStorage9SV.cs
Kurt fa9a809751
Encapsulate item pouch arrays/etc for finer control (#3860)
* Extract/encapsulate inventory legal arrays to interface+class

Hiding them behind methods allows these to be left as ReadOnlySpan<ushort> and thus never allocate on the heap.
Also refactors out some logic for checking if an item is legal.

End result feels more maintainable and is less bloaty (no more passing in a nullable func)

Batch editing
* Add HasType filter

```
=HasType=11
.HeldItem=Meadow Plate
```

slaps a meadow plate on any pkm with grass type
Use `=PersonalType1=11` for only primary grass types; only-secondary-type grass will not match it.
2023-04-16 12:58:07 -07:00

304 lines
12 KiB
C#

using System;
namespace PKHeX.Core;
public sealed class ItemStorage9SV : IItemStorage
{
public static readonly ItemStorage9SV Instance = new();
private static ReadOnlySpan<ushort> Pouch_Medicine_SV => new ushort[]
{
0017, 0018, 0019, 0020, 0021, 0022, 0023, 0024, 0025, 0026,
0027, 0028, 0029, 0030, 0031, 0032, 0033, 0034, 0035, 0036,
0037, 0038, 0039, 0040, 0041, 0708, 0709,
};
private static ReadOnlySpan<ushort> Pouch_Ball_SV => new ushort[]
{
0001, 0002, 0003, 0004, 0005, 0006, 0007, 0008, 0009, 0010,
0011, 0012, 0013, 0014, 0015, 0016, 0492, 0493, 0494, 0495,
0496, 0497, 0498, 0499, 0500, 0576, 0851, 1785,
};
private static ReadOnlySpan<ushort> Pouch_Battle_SV => new ushort[]
{
0055, 0056, 0057, 0058, 0059, 0060, 0061, 0062, 0063,
};
private static ReadOnlySpan<ushort> Pouch_Berries_SV => new ushort[]
{
0149, 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 0158,
0159, 0160, 0161, 0162, 0163, 0169, 0170, 0171, 0172, 0173,
0174, 0184, 0185, 0186, 0187, 0188, 0189, 0190, 0191, 0192,
0193, 0194, 0195, 0196, 0197, 0198, 0199, 0200, 0201, 0202,
0203, 0204, 0205, 0206, 0207, 0208, 0209, 0210, 0211, 0212,
0686, 0687, 0688,
};
private static ReadOnlySpan<ushort> Pouch_Other_SV => new ushort[]
{
0045, 0046, 0047, 0048, 0049, 0050, 0051, 0052, 0053, 0080,
0081, 0082, 0083, 0084, 0085, 0107, 0108, 0109, 0110, 0111,
0112, 0135, 0136, 0213, 0214, 0217, 0218, 0219, 0220, 0221,
0222, 0223, 0224, 0228, 0229, 0230, 0231, 0232, 0233, 0234,
0236, 0237, 0238, 0239, 0240, 0241, 0242, 0243, 0244, 0245,
0246, 0247, 0248, 0249, 0250, 0251, 0253, 0265, 0266, 0267,
0268, 0269, 0270, 0271, 0272, 0273, 0275, 0276, 0277, 0278,
0279, 0280, 0281, 0282, 0283, 0284, 0285, 0286, 0287, 0288,
0289, 0290, 0291, 0292, 0293, 0294, 0295, 0296, 0297, 0298,
0299, 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 0308,
0309, 0310, 0311, 0312, 0313, 0326, 0485, 0486, 0487, 0488,
0489, 0490, 0491, 0538, 0539, 0540, 0541, 0542, 0543, 0544,
0545, 0546, 0547, 0564, 0565, 0566, 0567, 0568, 0569, 0570,
0639, 0640, 0644, 0645, 0648, 0649, 0650, 0795, 0796, 0846,
0849, 0853, 0854, 0855, 0856, 0879, 0880, 0881, 0882, 0883,
0884, 1103, 1104, 1116, 1117, 1118, 1119, 1120, 1121, 1122,
1123, 1124, 1125, 1126, 1127, 1128, 1231, 1232, 1233, 1234,
1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244,
1245, 1246, 1247, 1248, 1249, 1250, 1251, 1253, 1254, 1582,
1592, 1606, 1777, 1778, 1779, 1861, 1862, 1863, 1864, 1865,
1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875,
1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885,
1886, 2344, 2345,
};
private static ReadOnlySpan<ushort> Pouch_TM_SV => new ushort[]
{
0328, 0329, 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
0338, 0339, 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
0348, 0349, 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
0358, 0359, 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0368, 0369, 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
0378, 0379, 0380, 0381, 0382, 0383, 0384, 0385, 0386, 0387,
0388, 0389, 0390, 0391, 0392, 0393, 0394, 0395, 0396, 0397,
0398, 0399, 0400, 0401, 0402, 0403, 0404, 0405, 0406, 0407,
0408, 0409, 0410, 0411, 0412, 0413, 0414, 0415, 0416, 0417,
0418, 0419, 0618, 0619, 0620, 0690, 0691, 0692, 0693, 1230,
2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169,
2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179,
2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189,
2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199,
2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209,
2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219,
2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229,
2230, 2231,
};
private static ReadOnlySpan<ushort> Pouch_Treasure_SV => new ushort[]
{
0086, 0087, 0088, 0089, 0090, 0091, 0092, 0094, 0106, 0571,
0580, 0581, 0582, 0583, 1842, 1843,
};
private static ReadOnlySpan<ushort> Pouch_Picnic_SV => new ushort[]
{
1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897,
1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907,
1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917,
1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927,
1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937,
1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946,
2311, 2313,
2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323,
2324, 2325, 2326, 2327, 2329, 2330, 2331, 2332, 2333, 2334,
2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2348, 2349,
2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359,
2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369,
2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379,
2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389,
2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399,
2400,
// Item data is present, but the items have no associated text or sprites, so they do not appear in the bag.
// 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955,
};
private static ReadOnlySpan<ushort> Pouch_Event_SV => new ushort[]
{
0632, 0638, 0703, 0765, 1278, 1590, 1591, 1829, 1830, 1831,
1832, 1833, 1834, 1835, 1836, 1857, 1858,
// Item data is present, but the items have no associated text or sprites, so they do not appear in the bag.
// 0078, 0466, 0631, 1267, 1587, 1589, 1837, 1838, 1839, 1840, 1841,
};
private static ReadOnlySpan<ushort> Pouch_Material_SV => new ushort[]
{
1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965,
1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975,
1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985,
1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025,
2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035,
2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045,
2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055,
2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065,
2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075,
2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085,
2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095,
2096, 2097, 2098, 2099, 2103, 2104, 2105,
2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115,
2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2126, 2127,
2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137,
2156, 2157,
2158, 2159,
// Item data is present, but the items have no associated text or sprites, so they do not appear in the bag.
// 2100, 2101, 2102,
// 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147,
// 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155,
};
internal static ReadOnlySpan<InventoryType> ValidTypes => new[]
{
InventoryType.Items, InventoryType.KeyItems,
InventoryType.TMHMs,
InventoryType.Medicine, InventoryType.Berries, InventoryType.Balls, InventoryType.BattleItems,
InventoryType.Treasure,
InventoryType.Ingredients, InventoryType.Candy,
};
private static ReadOnlySpan<InventoryType> ValidHeldTypes => new[]
{
InventoryType.Items,
InventoryType.TMHMs,
InventoryType.Medicine, InventoryType.Berries, InventoryType.Balls, InventoryType.BattleItems,
InventoryType.Treasure,
};
// [AUCTION] Porto Marinada specialty auctioneer, locked behind HOME in 2023.
public static ReadOnlySpan<ushort> Unreleased => new ushort[]
{
0005, // Safari Ball
0016, // Cherish Ball
0111, // Odd Keystone
0112, // [AUCTION] Griseous Orb
0135, // [AUCTION] Adamant Orb
0136, // [AUCTION] Lustrous Orb
0208, // Enigma Berry
0209, // Micle Berry
0210, // Custap Berry
0211, // Jaboca Berry
0212, // Rowap Berry
0298, // [AUCTION] Flame Plate
0299, // [AUCTION] Splash Plate
0300, // [AUCTION] Zap Plate
0301, // [AUCTION] Meadow Plate
0302, // [AUCTION] Icicle Plate
0303, // [AUCTION] Fist Plate
0304, // [AUCTION] Toxic Plate
0305, // [AUCTION] Earth Plate
0306, // [AUCTION] Sky Plate
0307, // [AUCTION] Mind Plate
0308, // [AUCTION] Insect Plate
0309, // [AUCTION] Stone Plate
0310, // [AUCTION] Spooky Plate
0311, // [AUCTION] Draco Plate
0312, // [AUCTION] Dread Plate
0313, // [AUCTION] Iron Plate
0485, // Red Apricorn
0486, // Blue Apricorn
0487, // Yellow Apricorn
0488, // Green Apricorn
0489, // Pink Apricorn
0490, // White Apricorn
0491, // Black Apricorn
0499, // Sport Ball
0500, // Park Ball
0644, // [AUCTION] Pixie Plate
0708, // Lumiose Galette
0709, // Shalour Sable
1103, // [AUCTION] Rusted Sword
1104, // [AUCTION] Rusted Shield
1230, // TM00 - Mega Punch (Nothing learns, not obtainable even though it is assigned a move.)
1582, // [AUCTION] Galarica Cuff
1592, // [AUCTION] Galarica Wreath
1777, // [AUCTION] Adamant Crystal
1778, // [AUCTION] Lustrous Globe
1779, // [AUCTION] Griseous Core
1785, // Strange Ball
};
public int GetMax(InventoryType type) => type switch
{
InventoryType.Items => 999,
InventoryType.KeyItems => 1,
InventoryType.TMHMs => 999,
InventoryType.Medicine => 999,
InventoryType.Berries => 999,
InventoryType.Balls => 999,
InventoryType.BattleItems => 999,
InventoryType.Treasure => 999,
InventoryType.Ingredients => 999, // 999
InventoryType.Candy => 999, // 999
_ => throw new ArgumentOutOfRangeException(nameof(type)),
};
public bool IsLegal(InventoryType type, int itemIndex, int itemCount)
{
return Unreleased.BinarySearch((ushort)itemIndex) < 0;
}
public ReadOnlySpan<ushort> GetItems(InventoryType type) => GetLegal(type);
public static ReadOnlySpan<ushort> GetLegal(InventoryType type) => type switch
{
InventoryType.Items => Pouch_Other_SV,
InventoryType.KeyItems => Pouch_Event_SV,
InventoryType.TMHMs => Pouch_TM_SV,
InventoryType.Medicine => Pouch_Medicine_SV,
InventoryType.Berries => Pouch_Berries_SV,
InventoryType.Balls => Pouch_Ball_SV,
InventoryType.BattleItems => Pouch_Battle_SV,
InventoryType.Treasure => Pouch_Treasure_SV,
InventoryType.Ingredients => Pouch_Picnic_SV,
InventoryType.Candy => Pouch_Material_SV,
_ => throw new ArgumentOutOfRangeException(nameof(type)),
};
public static ushort[] GetAllHeld()
{
var valid = ValidHeldTypes;
var sum = 0;
foreach (var type in valid)
sum += GetLegal(type).Length;
var result = new ushort[sum];
LoadAllHeld(valid, result);
return result;
}
private static void LoadAllHeld(ReadOnlySpan<InventoryType> valid, Span<ushort> dest)
{
foreach (var type in valid)
{
var legal = GetLegal(type);
legal.CopyTo(dest);
dest = dest[legal.Length..];
}
}
public static InventoryType GetInventoryPouch(ushort itemIndex)
{
foreach (var type in ValidTypes)
{
var legal = GetLegal(type);
if (legal.Contains(itemIndex))
return type;
}
return InventoryType.None;
}
}