Files
Craftimizer/Craftimizer/Utils/FoodStatus.cs
T
JonKazama-Hellion b598c03e9e Apply csharpier reflow across source tree
Reformats the entire Craftimizer source tree with dotnet csharpier 1.2.6
to match the Hellion Forge house style (matches what HellionChat enforces
in its pre-push pipeline). Pure whitespace + using-block sorting; no
semantic changes.

This is a one-time noisy commit. Future code edits in this fork should
land csharpier-clean because the pre-push hook (introduced in the next
commit) runs `dotnet csharpier check Craftimizer/` as Block C of the
preflight gate.

Trade-off acknowledged: this widens the merge gap with upstream
Craftimizer should Asriel ever resume maintenance. Given the upstream
has been dormant since FFXIV 7.4 and the fork is light-rename only
(internal namespaces unchanged), the marginal cost is acceptable.
2026-05-26 20:21:21 +02:00

138 lines
4.2 KiB
C#

using System.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Craftimizer.Plugin;
using Lumina.Excel.Sheets;
namespace Craftimizer.Utils;
public static class FoodStatus
{
private static readonly FrozenDictionary<uint, uint> ItemFoodToItemLUT;
private static readonly FrozenDictionary<uint, Food> FoodItems;
private static readonly FrozenDictionary<uint, Food> MedicineItems;
private static readonly ImmutableArray<uint> FoodOrder;
private static readonly ImmutableArray<uint> MedicineOrder;
public readonly record struct FoodStat(
bool IsRelative,
int Value,
int Max,
int ValueHQ,
int MaxHQ
);
public readonly record struct Food(
Item Item,
FoodStat? Craftsmanship,
FoodStat? Control,
FoodStat? CP
);
static FoodStatus()
{
var lut = new Dictionary<uint, uint>();
var foods = new Dictionary<uint, Food>();
var medicines = new Dictionary<uint, Food>();
foreach (var item in LuminaSheets.ItemSheet)
{
var isFood = item.ItemUICategory.RowId == 46;
var isMedicine = item.ItemUICategory.RowId == 44;
if (!isFood && !isMedicine)
continue;
if (item.ItemAction.ValueNullable is not { } itemAction)
continue;
if (itemAction.Action.RowId is not (844 or 845 or 846))
continue;
if (LuminaSheets.ItemFoodSheet.GetRowOrDefault(itemAction.Data[1]) is not { } itemFood)
continue;
FoodStat? craftsmanship = null,
control = null,
cp = null;
foreach (var stat in itemFood.Params)
{
if (stat.BaseParam.RowId == 0)
continue;
var foodStat = new FoodStat(
stat.IsRelative,
stat.Value,
stat.Max,
stat.ValueHQ,
stat.MaxHQ
);
switch (stat.BaseParam.RowId)
{
case Gearsets.ParamCraftsmanship:
craftsmanship = foodStat;
break;
case Gearsets.ParamControl:
control = foodStat;
break;
case Gearsets.ParamCP:
cp = foodStat;
break;
default:
continue;
}
}
if (craftsmanship != null || control != null || cp != null)
{
var food = new Food(item, craftsmanship, control, cp);
if (isFood)
foods.Add(item.RowId, food);
if (isMedicine)
medicines.Add(item.RowId, food);
}
lut.TryAdd(itemFood.RowId, item.RowId);
}
ItemFoodToItemLUT = lut.ToFrozenDictionary();
FoodItems = foods.ToFrozenDictionary();
MedicineItems = medicines.ToFrozenDictionary();
FoodOrder =
[
.. FoodItems.OrderByDescending(a => a.Value.Item.LevelItem.RowId).Select(a => a.Key),
];
MedicineOrder =
[
.. MedicineItems
.OrderByDescending(a => a.Value.Item.LevelItem.RowId)
.Select(a => a.Key),
];
}
public static void Initialize() { }
public static IEnumerable<Food> OrderedFoods => FoodOrder.Select(id => FoodItems[id]);
public static IEnumerable<Food> OrderedMedicines =>
MedicineOrder.Select(id => MedicineItems[id]);
public static (uint ItemId, bool IsHQ)? ResolveFoodParam(ushort param)
{
var isHq = param > 10000;
param -= 10000;
if (!ItemFoodToItemLUT.TryGetValue(param, out var itemId))
return null;
return (itemId, isHq);
}
public static Food? TryGetFood(uint itemId)
{
if (FoodItems.TryGetValue(itemId, out var food))
return food;
if (MedicineItems.TryGetValue(itemId, out food))
return food;
return null;
}
}