using System.Collections.Generic; using System.Linq; using System.Numerics; using Dalamud.Plugin.Services; using LLib.Shop.Model; using Lumina.Excel; using Lumina.Excel.Sheets; namespace LLib.Shop.Searchers; internal sealed class SpecialShopSearcher { private const uint SpecialShopHandlerType = 27u; private static readonly Dictionary SpecialCurrencies = new Dictionary { { 1u, 28u }, { 2u, 33913u }, { 4u, 33914u }, { 6u, 41784u }, { 7u, 41785u } }; private readonly IDataManager _dataManager; private readonly NpcPositionCache _positionCache; private readonly uint[] _tomestoneItemIds; public SpecialShopSearcher(IDataManager dataManager, NpcPositionCache positionCache) { _dataManager = dataManager; _positionCache = positionCache; _tomestoneItemIds = (from t in dataManager.GetExcelSheet() where t.Tomestones.RowId != 0 orderby t.Tomestones.RowId select t.Item.RowId).ToArray(); } public List Search(uint itemId) { List list = new List(); ExcelSheet excelSheet = _dataManager.GetExcelSheet(); ExcelSheet excelSheet2 = _dataManager.GetExcelSheet(); foreach (ENpcBase item in excelSheet) { if (item.RowId == 0) { continue; } (ushort, Vector3)? position = _positionCache.GetPosition(item.RowId); if (!position.HasValue) { continue; } (ushort, Vector3) valueOrDefault = position.GetValueOrDefault(); int num = 0; foreach (RowRef eNpcDatum in item.ENpcData) { if (eNpcDatum.RowId >> 16 != 27) { continue; } uint rowId = eNpcDatum.RowId; if (!excelSheet2.TryGetRow(rowId, out var row)) { num++; continue; } bool flag = false; uint currencyItemId = 0u; uint price = 0u; for (int i = 0; i < row.Item.Count; i++) { SpecialShop.ItemStruct itemStruct = row.Item[i]; for (int j = 0; j < itemStruct.ReceiveItems.Count; j++) { if (itemStruct.ReceiveItems[j].Item.RowId != itemId) { continue; } flag = true; for (int k = 0; k < itemStruct.ItemCosts.Count; k++) { SpecialShop.ItemStruct.ItemCostsStruct itemCostsStruct = itemStruct.ItemCosts[k]; if (itemCostsStruct.ItemCost.RowId != 0) { currencyItemId = ConvertCurrencyItemId(itemCostsStruct.ItemCost.RowId, in row); price = itemCostsStruct.CurrencyCost; break; } } break; } if (flag) { break; } } if (flag) { list.Add(new ShopSearchResult(rowId, item.RowId, valueOrDefault.Item1, valueOrDefault.Item2, EShopType.SpecialShop, price, currencyItemId, num)); } num++; } } return list; } private uint ConvertCurrencyItemId(uint costItemId, in SpecialShop shop) { if (costItemId == 0 || costItemId >= 8) { return costItemId; } ushort num = shop.UseCurrencyType; uint rowId = shop.RowId; if (rowId - 1770637 <= 1) { num = 16; } return num switch { 16 => SpecialCurrencies.GetValueOrDefault(costItemId, costItemId), 8 => 1u, 4 => (costItemId <= _tomestoneItemIds.Length) ? _tomestoneItemIds[costItemId - 1] : costItemId, _ => costItemId, }; } }