Change to ExdSheets 2
This commit is contained in:
@@ -20,7 +20,7 @@
|
|||||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.10" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.10" />
|
||||||
<PackageReference Include="BenchmarkDotNet.Diagnostics.dotTrace" Version="0.13.10" />
|
<PackageReference Include="BenchmarkDotNet.Diagnostics.dotTrace" Version="0.13.10" />
|
||||||
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.10" />
|
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.10" />
|
||||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.162">
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.163">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -39,10 +39,11 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DalamudPackager" Version="2.1.13" />
|
<PackageReference Include="DalamudPackager" Version="2.1.13" />
|
||||||
<PackageReference Include="ExdSheets" Version="1.2.2" />
|
<PackageReference Include="ExdSheets" Version="2.1.0" />
|
||||||
<PackageReference Include="Lumina" Version="3.15.2" ExcludeAssets="all" />
|
<PackageReference Include="Lumina" Version="4.1.1" ExcludeAssets="all" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="9.0.0-preview.1.24081.5" ExcludeAssets="all" />
|
||||||
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
|
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
|
||||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.162">
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.163">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ internal static class ImGuiUtils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class SearchableComboData<T> where T : class
|
private sealed class SearchableComboData<T> where T : IEquatable<T>
|
||||||
{
|
{
|
||||||
public readonly ImmutableArray<T> items;
|
public readonly ImmutableArray<T> items;
|
||||||
public List<T> filteredItems;
|
public List<T> filteredItems;
|
||||||
@@ -314,7 +314,7 @@ internal static class ImGuiUtils
|
|||||||
|
|
||||||
public void SetItem(T selectedItem)
|
public void SetItem(T selectedItem)
|
||||||
{
|
{
|
||||||
if (this.selectedItem != selectedItem)
|
if (!this.selectedItem.Equals(selectedItem))
|
||||||
{
|
{
|
||||||
input = GetString(selectedItem);
|
input = GetString(selectedItem);
|
||||||
this.selectedItem = selectedItem;
|
this.selectedItem = selectedItem;
|
||||||
@@ -364,14 +364,14 @@ internal static class ImGuiUtils
|
|||||||
}
|
}
|
||||||
private static readonly Dictionary<uint, object> ComboData = [];
|
private static readonly Dictionary<uint, object> ComboData = [];
|
||||||
|
|
||||||
private static SearchableComboData<T> GetComboData<T>(uint comboKey, IEnumerable<T> items, T selectedItem, Func<T, string> getString) where T : class =>
|
private static SearchableComboData<T> GetComboData<T>(uint comboKey, IEnumerable<T> items, T selectedItem, Func<T, string> getString) where T : IEquatable<T> =>
|
||||||
(SearchableComboData<T>)(
|
(SearchableComboData<T>)(
|
||||||
ComboData.TryGetValue(comboKey, out var data)
|
ComboData.TryGetValue(comboKey, out var data)
|
||||||
? data
|
? data
|
||||||
: ComboData[comboKey] = new SearchableComboData<T>(items, selectedItem, getString));
|
: ComboData[comboKey] = new SearchableComboData<T>(items, selectedItem, getString));
|
||||||
|
|
||||||
// https://github.com/ocornut/imgui/issues/718#issuecomment-1563162222
|
// https://github.com/ocornut/imgui/issues/718#issuecomment-1563162222
|
||||||
public static bool SearchableCombo<T>(string id, ref T selectedItem, IEnumerable<T> items, ImFontPtr selectableFont, float width, Func<T, string> getString, Func<T, string> getId, Action<T> draw) where T : class
|
public static bool SearchableCombo<T>(string id, ref T selectedItem, IEnumerable<T> items, ImFontPtr selectableFont, float width, Func<T, string> getString, Func<T, string> getId, Action<T> draw) where T : IEquatable<T>
|
||||||
{
|
{
|
||||||
var comboKey = ImGui.GetID(id);
|
var comboKey = ImGui.GetID(id);
|
||||||
var data = GetComboData(comboKey, items, selectedItem, getString);
|
var data = GetComboData(comboKey, items, selectedItem, getString);
|
||||||
|
|||||||
+19
-29
@@ -1,37 +1,27 @@
|
|||||||
using Dalamud.Game;
|
using Dalamud.Utility;
|
||||||
using ExdSheets;
|
using ExdSheets;
|
||||||
using Lumina.Excel;
|
using ExdSheets.Sheets;
|
||||||
using System.Collections.Concurrent;
|
using Lumina.Data;
|
||||||
|
|
||||||
namespace Craftimizer.Plugin;
|
namespace Craftimizer.Plugin;
|
||||||
|
|
||||||
public static class LuminaSheets
|
public static class LuminaSheets
|
||||||
{
|
{
|
||||||
public static readonly ExcelSheet<Recipe> RecipeSheet = Service.DataManager.GetExcelSheet<Recipe>()!;
|
private static readonly Module Module = new(Service.DataManager.GameData, Service.DataManager.Language.ToLumina());
|
||||||
public static readonly ExcelSheet<Action> ActionSheet = Service.DataManager.GetExcelSheet<Action>()!;
|
|
||||||
public static readonly ExcelSheet<CraftAction> CraftActionSheet = Service.DataManager.GetExcelSheet<CraftAction>()!;
|
|
||||||
public static readonly ExcelSheet<Status> StatusSheet = Service.DataManager.GetExcelSheet<Status>()!;
|
|
||||||
public static readonly ExcelSheet<Addon> AddonSheet = Service.DataManager.GetExcelSheet<Addon>()!;
|
|
||||||
public static readonly ExcelSheet<ClassJob> ClassJobSheet = Service.DataManager.GetExcelSheet<ClassJob>()!;
|
|
||||||
public static readonly ExcelSheet<Item> ItemSheet = Service.DataManager.GetExcelSheet<Item>()!;
|
|
||||||
public static readonly ExcelSheet<Item> ItemSheetEnglish = Service.DataManager.GetExcelSheet<Item>(ClientLanguage.English)!;
|
|
||||||
public static readonly ExcelSheet<ENpcResident> ENpcResidentSheet = Service.DataManager.GetExcelSheet<ENpcResident>()!;
|
|
||||||
public static readonly ExcelSheet<Level> LevelSheet = Service.DataManager.GetExcelSheet<Level>()!;
|
|
||||||
public static readonly ExcelSheet<Quest> QuestSheet = Service.DataManager.GetExcelSheet<Quest>()!;
|
|
||||||
public static readonly ExcelSheet<Materia> MateriaSheet = Service.DataManager.GetExcelSheet<Materia>()!;
|
|
||||||
public static readonly ExcelSheet<BaseParam> BaseParamSheet = Service.DataManager.GetExcelSheet<BaseParam>()!;
|
|
||||||
public static readonly ExcelSheet<ItemFood> ItemFoodSheet = Service.DataManager.GetExcelSheet<ItemFood>()!;
|
|
||||||
public static readonly ExcelSheet<SatisfactionSupply> SatisfactionSupplySheet = Service.DataManager.GetExcelSheet<SatisfactionSupply>()!;
|
|
||||||
|
|
||||||
private static ConcurrentDictionary<(ExcelSheetImpl, uint), uint> SubRowCountCache { get; } = new();
|
public static readonly Sheet<Recipe> RecipeSheet = Module.GetSheet<Recipe>();
|
||||||
public static uint? GetSubRowCount<T>(this ExcelSheet<T> sheet, uint row) where T : ExcelRow
|
public static readonly Sheet<Action> ActionSheet = Module.GetSheet<Action>();
|
||||||
{
|
public static readonly Sheet<CraftAction> CraftActionSheet = Module.GetSheet<CraftAction>();
|
||||||
if (SubRowCountCache.TryGetValue((sheet, row), out var count))
|
public static readonly Sheet<Status> StatusSheet = Module.GetSheet<Status>();
|
||||||
return count;
|
public static readonly Sheet<Addon> AddonSheet = Module.GetSheet<Addon>();
|
||||||
var parser = sheet.GetRowParser(row);
|
public static readonly Sheet<ClassJob> ClassJobSheet = Module.GetSheet<ClassJob>();
|
||||||
if (parser == null)
|
public static readonly Sheet<Item> ItemSheet = Module.GetSheet<Item>();
|
||||||
return null;
|
public static readonly Sheet<Item> ItemSheetEnglish = Module.GetSheet<Item>(Language.English)!;
|
||||||
SubRowCountCache.TryAdd((sheet, row), parser.RowCount);
|
public static readonly Sheet<ENpcResident> ENpcResidentSheet = Module.GetSheet<ENpcResident>();
|
||||||
return parser.RowCount;
|
public static readonly Sheet<Level> LevelSheet = Module.GetSheet<Level>();
|
||||||
}
|
public static readonly Sheet<Quest> QuestSheet = Module.GetSheet<Quest>();
|
||||||
|
public static readonly Sheet<Materia> MateriaSheet = Module.GetSheet<Materia>();
|
||||||
|
public static readonly Sheet<BaseParam> BaseParamSheet = Module.GetSheet<BaseParam>();
|
||||||
|
public static readonly Sheet<ItemFood> ItemFoodSheet = Module.GetSheet<ItemFood>();
|
||||||
|
public static readonly Sheet<SatisfactionSupply> SatisfactionSupplySheet = Module.GetSheet<SatisfactionSupply>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
SynthHelperWindow = new();
|
SynthHelperWindow = new();
|
||||||
ListWindow = new();
|
ListWindow = new();
|
||||||
|
|
||||||
// Trigger static constructors so a huge hitch doesn't occur on first RecipeNote frame.
|
// Trigger static constructors so a hitch doesn't occur on first RecipeNote frame.
|
||||||
FoodStatus.Initialize();
|
FoodStatus.Initialize();
|
||||||
ActionUtils.Initialize();
|
ActionUtils.Initialize();
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
using Craftimizer.Simulator;
|
using Craftimizer.Simulator;
|
||||||
using Craftimizer.Simulator.Actions;
|
using Craftimizer.Simulator.Actions;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
|
||||||
using Dalamud.Utility;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||||
using ExdSheets;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Action = ExdSheets.Action;
|
using Action = ExdSheets.Sheets.Action;
|
||||||
using ActionType = Craftimizer.Simulator.Actions.ActionType;
|
using ActionType = Craftimizer.Simulator.Actions.ActionType;
|
||||||
using ClassJob = Craftimizer.Simulator.ClassJob;
|
using ClassJob = Craftimizer.Simulator.ClassJob;
|
||||||
using Condition = Craftimizer.Simulator.Condition;
|
using Condition = Craftimizer.Simulator.Condition;
|
||||||
using Status = ExdSheets.Status;
|
using Status = ExdSheets.Sheets.Status;
|
||||||
using Dalamud.Interface.Textures;
|
|
||||||
using Craftimizer.Utils;
|
using Craftimizer.Utils;
|
||||||
|
using ExdSheets.Sheets;
|
||||||
|
using Lumina.Text.ReadOnly;
|
||||||
|
using Lumina.Text.Payloads;
|
||||||
|
|
||||||
namespace Craftimizer.Plugin;
|
namespace Craftimizer.Plugin;
|
||||||
|
|
||||||
@@ -31,33 +29,33 @@ internal static class ActionUtils
|
|||||||
foreach (var actionType in actionTypes)
|
foreach (var actionType in actionTypes)
|
||||||
{
|
{
|
||||||
var actionId = actionType.Base().ActionId;
|
var actionId = actionType.Base().ActionId;
|
||||||
if (LuminaSheets.CraftActionSheet.GetRow(actionId) is CraftAction baseCraftAction)
|
if (LuminaSheets.CraftActionSheet.TryGetRow(actionId) is { } baseCraftAction)
|
||||||
{
|
{
|
||||||
foreach (var classJob in classJobs)
|
foreach (var classJob in classJobs)
|
||||||
{
|
{
|
||||||
ActionRows[(int)actionType, (int)classJob] = (classJob switch
|
ActionRows[(int)actionType, (int)classJob] = (classJob switch
|
||||||
{
|
{
|
||||||
ClassJob.Carpenter => baseCraftAction.CRP.Value!,
|
ClassJob.Carpenter => baseCraftAction.CRP.Value,
|
||||||
ClassJob.Blacksmith => baseCraftAction.BSM.Value!,
|
ClassJob.Blacksmith => baseCraftAction.BSM.Value,
|
||||||
ClassJob.Armorer => baseCraftAction.ARM.Value!,
|
ClassJob.Armorer => baseCraftAction.ARM.Value,
|
||||||
ClassJob.Goldsmith => baseCraftAction.GSM.Value!,
|
ClassJob.Goldsmith => baseCraftAction.GSM.Value,
|
||||||
ClassJob.Leatherworker => baseCraftAction.LTW.Value!,
|
ClassJob.Leatherworker => baseCraftAction.LTW.Value,
|
||||||
ClassJob.Weaver => baseCraftAction.WVR.Value!,
|
ClassJob.Weaver => baseCraftAction.WVR.Value,
|
||||||
ClassJob.Alchemist => baseCraftAction.ALC.Value!,
|
ClassJob.Alchemist => baseCraftAction.ALC.Value,
|
||||||
ClassJob.Culinarian => baseCraftAction.CUL.Value!,
|
ClassJob.Culinarian => baseCraftAction.CUL.Value,
|
||||||
_ => baseCraftAction
|
_ => baseCraftAction
|
||||||
}, null);
|
}, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LuminaSheets.ActionSheet.GetRow(actionId) is Action baseAction)
|
if (LuminaSheets.ActionSheet.TryGetRow(actionId) is { } baseAction)
|
||||||
{
|
{
|
||||||
var possibleActions = LuminaSheets.ActionSheet.Where(r =>
|
var possibleActions = LuminaSheets.ActionSheet.Where(r =>
|
||||||
r.Icon == baseAction.Icon &&
|
r.Icon == baseAction.Icon &&
|
||||||
r.ActionCategory.Row == baseAction.ActionCategory.Row &&
|
r.ActionCategory.RowId == baseAction.ActionCategory.RowId &&
|
||||||
r.Name.RawString.Equals(baseAction.Name.RawString, StringComparison.Ordinal));
|
r.Name.Equals(baseAction.Name));
|
||||||
|
|
||||||
foreach (var classJob in classJobs)
|
foreach (var classJob in classJobs)
|
||||||
ActionRows[(int)actionType, (int)classJob] = (null, possibleActions.First(r => r.ClassJobCategory.Value?.IsClassJob(classJob) ?? false));
|
ActionRows[(int)actionType, (int)classJob] = (null, possibleActions.First(r => r.ClassJobCategory.ValueNullable?.IsClassJob(classJob) ?? false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,32 +68,20 @@ internal static class ActionUtils
|
|||||||
public static uint GetId(this ActionType me, ClassJob classJob)
|
public static uint GetId(this ActionType me, ClassJob classJob)
|
||||||
{
|
{
|
||||||
var (craftAction, action) = GetActionRow(me, classJob);
|
var (craftAction, action) = GetActionRow(me, classJob);
|
||||||
if (craftAction != null)
|
return craftAction?.RowId ?? action?.RowId ?? 0;
|
||||||
return craftAction.RowId;
|
|
||||||
if (action != null)
|
|
||||||
return action.RowId;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetName(this ActionType me, ClassJob classJob)
|
public static string GetName(this ActionType me, ClassJob classJob)
|
||||||
{
|
{
|
||||||
var (craftAction, action) = GetActionRow(me, classJob);
|
var (craftAction, action) = GetActionRow(me, classJob);
|
||||||
if (craftAction != null)
|
return (craftAction?.Name ?? action?.Name)?.AsSpan().ExtractText() ?? "Unknown";
|
||||||
return craftAction.Name.ToDalamudString().TextValue;
|
|
||||||
if (action != null)
|
|
||||||
return action.Name.ToDalamudString().TextValue;
|
|
||||||
return "Unknown";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ITextureIcon GetIcon(this ActionType me, ClassJob classJob)
|
public static ITextureIcon GetIcon(this ActionType me, ClassJob classJob)
|
||||||
{
|
{
|
||||||
var (craftAction, action) = GetActionRow(me, classJob);
|
var (craftAction, action) = GetActionRow(me, classJob);
|
||||||
if (craftAction != null)
|
// 1953 = Old "Steady Hand" action icon
|
||||||
return Service.IconManager.GetIconCached(craftAction.Icon);
|
return Service.IconManager.GetIconCached(craftAction?.Icon ?? action?.Icon ?? 1953);
|
||||||
if (action != null)
|
|
||||||
return Service.IconManager.GetIconCached(action.Icon);
|
|
||||||
// Old "Steady Hand" action icon
|
|
||||||
return Service.IconManager.GetIconCached(1953);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ActionType? GetActionTypeFromId(uint actionId, ClassJob classJob, bool isCraftAction)
|
public static ActionType? GetActionTypeFromId(uint actionId, ClassJob classJob, bool isCraftAction)
|
||||||
@@ -155,18 +141,18 @@ internal static class ClassJobUtils
|
|||||||
PlayerState.Instance()->ClassJobLevels[me.GetExpArrayIdx()];
|
PlayerState.Instance()->ClassJobLevels[me.GetExpArrayIdx()];
|
||||||
|
|
||||||
public static unsafe bool CanPlayerUseManipulation(this ClassJob me) =>
|
public static unsafe bool CanPlayerUseManipulation(this ClassJob me) =>
|
||||||
UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(ActionType.Manipulation.GetActionRow(me).Action!.UnlockLink.Row);
|
UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(ActionType.Manipulation.GetActionRow(me).Action!.Value.UnlockLink.RowId);
|
||||||
|
|
||||||
public static string GetName(this ClassJob me)
|
public static string GetName(this ClassJob me)
|
||||||
{
|
{
|
||||||
var job = LuminaSheets.ClassJobSheet.GetRow(me.GetClassJobIndex())!;
|
var job = LuminaSheets.ClassJobSheet.GetRow(me.GetClassJobIndex());
|
||||||
return job.Name.ToDalamudString().TextValue.ToLowerInvariant();
|
return job.Name.ExtractText().ToLowerInvariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetNameArticle(this ClassJob me)
|
public static string GetNameArticle(this ClassJob me)
|
||||||
{
|
{
|
||||||
var job = LuminaSheets.ClassJobSheet.GetRow(me.GetClassJobIndex())!;
|
var job = LuminaSheets.ClassJobSheet.GetRow(me.GetClassJobIndex());
|
||||||
if (job.SheetLanguage == Lumina.Data.Language.English)
|
if (LuminaSheets.ClassJobSheet.Language == Lumina.Data.Language.English)
|
||||||
{
|
{
|
||||||
if (me is ClassJob.Alchemist or ClassJob.Armorer)
|
if (me is ClassJob.Alchemist or ClassJob.Armorer)
|
||||||
return "an";
|
return "an";
|
||||||
@@ -176,12 +162,12 @@ internal static class ClassJobUtils
|
|||||||
|
|
||||||
public static string GetAbbreviation(this ClassJob me)
|
public static string GetAbbreviation(this ClassJob me)
|
||||||
{
|
{
|
||||||
var job = LuminaSheets.ClassJobSheet.GetRow(me.GetClassJobIndex())!;
|
var job = LuminaSheets.ClassJobSheet.GetRow(me.GetClassJobIndex());
|
||||||
return job.Abbreviation.ToDalamudString().TextValue;
|
return job.Abbreviation.ExtractText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Quest GetUnlockQuest(this ClassJob me) =>
|
public static Quest GetUnlockQuest(this ClassJob me) =>
|
||||||
LuminaSheets.QuestSheet.GetRow(65720 + (uint)me) ?? throw new ArgumentException($"Could not get unlock quest for {me}", nameof(me));
|
LuminaSheets.QuestSheet.GetRow(65720 + (uint)me);
|
||||||
|
|
||||||
public static ushort GetIconId(this ClassJob me) =>
|
public static ushort GetIconId(this ClassJob me) =>
|
||||||
(ushort)(62000 + me.GetClassJobIndex());
|
(ushort)(62000 + me.GetClassJobIndex());
|
||||||
@@ -295,15 +281,23 @@ internal static class ConditionUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static string Name(this Condition me) =>
|
public static string Name(this Condition me) =>
|
||||||
LuminaSheets.AddonSheet.GetRow(me.AddonIds().Name)!.Text.ToDalamudString().TextValue;
|
LuminaSheets.AddonSheet.GetRow(me.AddonIds().Name).Text.ExtractText();
|
||||||
|
|
||||||
public static string Description(this Condition me, bool isRelic)
|
public static string Description(this Condition me, bool isRelic)
|
||||||
{
|
{
|
||||||
var text = LuminaSheets.AddonSheet.GetRow(me.AddonIds().Description)!.Text.ToDalamudString();
|
var text = LuminaSheets.AddonSheet.GetRow(me.AddonIds().Description).Text;
|
||||||
for (var i = 0; i < text.Payloads.Count; ++i)
|
if (!text.Any(p => p is { Type: ReadOnlySePayloadType.Macro, MacroCode: MacroCode.Float }))
|
||||||
if (text.Payloads[i] is RawPayload)
|
return text.ExtractText();
|
||||||
text.Payloads[i] = new TextPayload(isRelic ? "1.75" : "1.5");
|
|
||||||
return text.TextValue;
|
ReadOnlySeString finalText = new();
|
||||||
|
foreach (var payload in text)
|
||||||
|
{
|
||||||
|
if (payload is { Type: ReadOnlySePayloadType.Macro, MacroCode: MacroCode.Float })
|
||||||
|
finalText += new ReadOnlySePayload(ReadOnlySePayloadType.Text, default, Encoding.UTF8.GetBytes(isRelic ? "1.75" : "1.5"));
|
||||||
|
else
|
||||||
|
finalText += payload;
|
||||||
|
}
|
||||||
|
return finalText.ExtractText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +343,7 @@ internal static class EffectUtils
|
|||||||
{
|
{
|
||||||
var status = me.Status();
|
var status = me.Status();
|
||||||
var name = new StringBuilder();
|
var name = new StringBuilder();
|
||||||
name.Append(status.Name.ToDalamudString().TextValue);
|
name.Append(status.Name.ExtractText());
|
||||||
if (status.MaxStacks != 0)
|
if (status.MaxStacks != 0)
|
||||||
name.Append($" {strength}");
|
name.Append($" {strength}");
|
||||||
if (!status.IsPermanent)
|
if (!status.IsPermanent)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Craftimizer.Plugin;
|
using Craftimizer.Plugin;
|
||||||
using ExdSheets;
|
using ExdSheets.Sheets;
|
||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
@@ -25,28 +25,27 @@ public static class FoodStatus
|
|||||||
var medicines = new Dictionary<uint, Food>();
|
var medicines = new Dictionary<uint, Food>();
|
||||||
foreach (var item in LuminaSheets.ItemSheet)
|
foreach (var item in LuminaSheets.ItemSheet)
|
||||||
{
|
{
|
||||||
var isFood = item.ItemUICategory.Row == 46;
|
var isFood = item.ItemUICategory.RowId == 46;
|
||||||
var isMedicine = item.ItemUICategory.Row == 44;
|
var isMedicine = item.ItemUICategory.RowId == 44;
|
||||||
if (!isFood && !isMedicine)
|
if (!isFood && !isMedicine)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (item.ItemAction.Value == null)
|
if (item.ItemAction.ValueNullable is not { } itemAction)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!(item.ItemAction.Value.Type is 844 or 845 or 846))
|
if (itemAction.Type is not (844 or 845 or 846))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var itemFood = LuminaSheets.ItemFoodSheet.GetRow(item.ItemAction.Value.Data[1]);
|
if (LuminaSheets.ItemFoodSheet.TryGetRow(itemAction.Data[1]) is not { } itemFood)
|
||||||
if (itemFood == null)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FoodStat? craftsmanship = null, control = null, cp = null;
|
FoodStat? craftsmanship = null, control = null, cp = null;
|
||||||
foreach (var stat in itemFood.Params)
|
foreach (var stat in itemFood.Params)
|
||||||
{
|
{
|
||||||
if (stat.BaseParam.Row == 0)
|
if (stat.BaseParam.RowId == 0)
|
||||||
continue;
|
continue;
|
||||||
var foodStat = new FoodStat(stat.IsRelative, stat.Value, stat.Max, stat.ValueHQ, stat.MaxHQ);
|
var foodStat = new FoodStat(stat.IsRelative, stat.Value, stat.Max, stat.ValueHQ, stat.MaxHQ);
|
||||||
switch (stat.BaseParam.Row)
|
switch (stat.BaseParam.RowId)
|
||||||
{
|
{
|
||||||
case Gearsets.ParamCraftsmanship: craftsmanship = foodStat; break;
|
case Gearsets.ParamCraftsmanship: craftsmanship = foodStat; break;
|
||||||
case Gearsets.ParamControl: control = foodStat; break;
|
case Gearsets.ParamControl: control = foodStat; break;
|
||||||
@@ -71,8 +70,8 @@ public static class FoodStatus
|
|||||||
FoodItems = foods.ToFrozenDictionary();
|
FoodItems = foods.ToFrozenDictionary();
|
||||||
MedicineItems = medicines.ToFrozenDictionary();
|
MedicineItems = medicines.ToFrozenDictionary();
|
||||||
|
|
||||||
FoodOrder = FoodItems.OrderByDescending(a => a.Value.Item.LevelItem.Row).Select(a => a.Key).ToImmutableArray();
|
FoodOrder = FoodItems.OrderByDescending(a => a.Value.Item.LevelItem.RowId).Select(a => a.Key).ToImmutableArray();
|
||||||
MedicineOrder = MedicineItems.OrderByDescending(a => a.Value.Item.LevelItem.Row).Select(a => a.Key).ToImmutableArray();
|
MedicineOrder = MedicineItems.OrderByDescending(a => a.Value.Item.LevelItem.RowId).Select(a => a.Key).ToImmutableArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Initialize() { }
|
public static void Initialize() { }
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Dalamud.Utility;
|
|||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||||
using ExdSheets;
|
using ExdSheets.Sheets;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Craftimizer.Plugin;
|
using Craftimizer.Plugin;
|
||||||
@@ -62,10 +62,10 @@ public static unsafe class Gearsets
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach (var statIncrease in item.BaseParam.Zip(item.BaseParamValue))
|
foreach (var statIncrease in item.BaseParam.Zip(item.BaseParamValue))
|
||||||
IncreaseStat(statIncrease.First.Row, statIncrease.Second);
|
IncreaseStat(statIncrease.First.RowId, statIncrease.Second);
|
||||||
if (gearsetItem.IsHq)
|
if (gearsetItem.IsHq)
|
||||||
foreach (var statIncrease in item.BaseParamSpecial.Zip(item.BaseParamValueSpecial))
|
foreach (var statIncrease in item.BaseParamSpecial.Zip(item.BaseParamValueSpecial))
|
||||||
IncreaseStat(statIncrease.First.Row, statIncrease.Second);
|
IncreaseStat(statIncrease.First.RowId, statIncrease.Second);
|
||||||
|
|
||||||
foreach (var gearsetMateria in gearsetItem.Materia)
|
foreach (var gearsetMateria in gearsetItem.Materia)
|
||||||
{
|
{
|
||||||
@@ -73,7 +73,7 @@ public static unsafe class Gearsets
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var materia = LuminaSheets.MateriaSheet.GetRow(gearsetMateria.Type)!;
|
var materia = LuminaSheets.MateriaSheet.GetRow(gearsetMateria.Type)!;
|
||||||
IncreaseStat(materia.BaseParam.Row, materia.Value[gearsetMateria.Grade]);
|
IncreaseStat(materia.BaseParam.RowId, materia.Value[gearsetMateria.Grade]);
|
||||||
}
|
}
|
||||||
|
|
||||||
cp = Math.Min(cp, CalculateParamCap(item, ParamCP));
|
cp = Math.Min(cp, CalculateParamCap(item, ParamCP));
|
||||||
@@ -125,17 +125,17 @@ public static unsafe class Gearsets
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
var luminaItem = LuminaSheets.ItemSheet.GetRow(item.ItemId)!;
|
var luminaItem = LuminaSheets.ItemSheet.GetRow(item.ItemId)!;
|
||||||
// Soul Crystal ItemUICategory DoH Category
|
// Soul Crystal ItemUICategory DoH Category
|
||||||
return luminaItem.ItemUICategory.Row == 62 && luminaItem.ClassJobUse.Value!.ClassJobCategory.Row == 33;
|
return luminaItem.ItemUICategory.RowId == 62 && luminaItem.ClassJobUse.Value.ClassJobCategory.RowId == 33;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsSplendorousTool(GearsetItem item) =>
|
public static bool IsSplendorousTool(GearsetItem item) =>
|
||||||
LuminaSheets.ItemSheetEnglish.GetRow(item.ItemId)!.Description.ToDalamudString().TextValue.Contains("Increases to quality are 1.75 times higher than normal when material condition is Good.", StringComparison.Ordinal);
|
LuminaSheets.ItemSheetEnglish.GetRow(item.ItemId).Description.ExtractText().Contains("Increases to quality are 1.75 times higher than normal when material condition is Good.", StringComparison.Ordinal);
|
||||||
|
|
||||||
// https://github.com/ffxiv-teamcraft/ffxiv-teamcraft/blob/24d0db2d9676f264edf53651b21005305267c84c/apps/client/src/app/modules/gearsets/materia.service.ts#L265
|
// https://github.com/ffxiv-teamcraft/ffxiv-teamcraft/blob/24d0db2d9676f264edf53651b21005305267c84c/apps/client/src/app/modules/gearsets/materia.service.ts#L265
|
||||||
private static int CalculateParamCap(Item item, uint paramId)
|
private static int CalculateParamCap(Item item, uint paramId)
|
||||||
{
|
{
|
||||||
var ilvl = item.LevelItem.Value!;
|
var ilvl = item.LevelItem.Value;
|
||||||
var param = LuminaSheets.BaseParamSheet.GetRow(paramId)!;
|
var param = LuminaSheets.BaseParamSheet.GetRow(paramId)!;
|
||||||
|
|
||||||
var baseValue = paramId switch
|
var baseValue = paramId switch
|
||||||
@@ -146,7 +146,7 @@ public static unsafe class Gearsets
|
|||||||
_ => 0
|
_ => 0
|
||||||
};
|
};
|
||||||
// https://github.com/ffxiv-teamcraft/ffxiv-teamcraft/blob/24d0db2d9676f264edf53651b21005305267c84c/apps/data-extraction/src/extractors/items.extractor.ts#L6
|
// https://github.com/ffxiv-teamcraft/ffxiv-teamcraft/blob/24d0db2d9676f264edf53651b21005305267c84c/apps/data-extraction/src/extractors/items.extractor.ts#L6
|
||||||
var slotMod = item.EquipSlotCategory.Row switch
|
var slotMod = item.EquipSlotCategory.RowId switch
|
||||||
{
|
{
|
||||||
1 => param.OneHandWeaponPercent, // column 4
|
1 => param.OneHandWeaponPercent, // column 4
|
||||||
2 => param.OffHandPercent, // column 5
|
2 => param.OffHandPercent, // column 5
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Craftimizer.Plugin;
|
using Craftimizer.Plugin;
|
||||||
using Craftimizer.Simulator;
|
using Craftimizer.Simulator;
|
||||||
using ExdSheets;
|
using ExdSheets.Sheets;
|
||||||
using Lumina.Excel;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -18,7 +17,7 @@ public sealed record RecipeData
|
|||||||
|
|
||||||
public ClassJob ClassJob { get; }
|
public ClassJob ClassJob { get; }
|
||||||
public RecipeInfo RecipeInfo { get; }
|
public RecipeInfo RecipeInfo { get; }
|
||||||
public bool IsCollectable => Recipe.ItemResult.Value?.AlwaysCollectable ?? false;
|
public bool IsCollectable => Recipe.ItemResult.ValueNullable?.AlwaysCollectable ?? false;
|
||||||
public IReadOnlyList<int?>? CollectableThresholds { get; }
|
public IReadOnlyList<int?>? CollectableThresholds { get; }
|
||||||
public IReadOnlyList<(Item Item, int Amount)> Ingredients { get; }
|
public IReadOnlyList<(Item Item, int Amount)> Ingredients { get; }
|
||||||
public int MaxStartingQuality { get; }
|
public int MaxStartingQuality { get; }
|
||||||
@@ -28,11 +27,11 @@ public sealed record RecipeData
|
|||||||
{
|
{
|
||||||
RecipeId = recipeId;
|
RecipeId = recipeId;
|
||||||
|
|
||||||
Recipe = LuminaSheets.RecipeSheet.GetRow(recipeId) ??
|
Recipe = LuminaSheets.RecipeSheet.TryGetRow(recipeId) ??
|
||||||
throw new ArgumentException($"Invalid recipe id {recipeId}", nameof(recipeId));
|
throw new ArgumentException($"Invalid recipe id {recipeId}", nameof(recipeId));
|
||||||
|
|
||||||
Table = Recipe.RecipeLevelTable.Value!;
|
Table = Recipe.RecipeLevelTable.Value;
|
||||||
ClassJob = (ClassJob)Recipe.CraftType.Row;
|
ClassJob = (ClassJob)Recipe.CraftType.RowId;
|
||||||
RecipeInfo = new()
|
RecipeInfo = new()
|
||||||
{
|
{
|
||||||
IsExpert = Recipe.IsExpert,
|
IsExpert = Recipe.IsExpert,
|
||||||
@@ -48,49 +47,44 @@ public sealed record RecipeData
|
|||||||
};
|
};
|
||||||
|
|
||||||
int[]? thresholds = null;
|
int[]? thresholds = null;
|
||||||
if (Recipe.CollectableMetadata is LazyRow<CollectablesShopRefine> { Value: { } row })
|
if (Recipe.CollectableMetadata.TryGetValue<CollectablesShopRefine>() is { } row)
|
||||||
thresholds = [row.LowCollectability, row.MidCollectability, row.HighCollectability];
|
thresholds = [row.LowCollectability, row.MidCollectability, row.HighCollectability];
|
||||||
else if (Recipe.CollectableMetadata is LazyRow<HWDCrafterSupply> { Value: { } row2 })
|
else if (Recipe.CollectableMetadata.TryGetValue<HWDCrafterSupply>() is { } row2)
|
||||||
{
|
{
|
||||||
foreach (var entry in row2.HWDCrafterSupplyParams)
|
foreach (var entry in row2.HWDCrafterSupplyParams)
|
||||||
{
|
{
|
||||||
if (entry.ItemTradeIn.Row == Recipe.ItemResult.Row)
|
if (entry.ItemTradeIn.RowId == Recipe.ItemResult.RowId)
|
||||||
{
|
{
|
||||||
thresholds = [entry.BaseCollectableRating, entry.MidCollectableRating, entry.HighCollectableRating];
|
thresholds = [entry.BaseCollectableRating, entry.MidCollectableRating, entry.HighCollectableRating];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Recipe.CollectableMetadata is LazyRow<SatisfactionSupply> { } row4)
|
else if (Recipe.CollectableMetadata.TryGetValue<SatisfactionSupply>() is { } row3)
|
||||||
{
|
{
|
||||||
var subRowCount = LuminaSheets.SatisfactionSupplySheet.GetSubRowCount(row4.Row);
|
var subrowCount = LuminaSheets.SatisfactionSupplySheet.GetSubrowCount(row3.RowId);
|
||||||
if (subRowCount is { } subRowValue)
|
for (ushort i = 0; i < subrowCount; ++i)
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < subRowValue; ++i)
|
var subrow = LuminaSheets.SatisfactionSupplySheet.GetRow(row3.RowId, i);
|
||||||
|
if (subrow.Item.RowId == Recipe.ItemResult.RowId)
|
||||||
{
|
{
|
||||||
var subRow = LuminaSheets.SatisfactionSupplySheet.GetRow(row4.Row, i);
|
thresholds = [subrow.CollectabilityLow, subrow.CollectabilityMid, subrow.CollectabilityHigh];
|
||||||
if (subRow == null)
|
break;
|
||||||
continue;
|
|
||||||
if (subRow.Item.Row == Recipe.ItemResult.Row)
|
|
||||||
{
|
|
||||||
thresholds = [subRow.CollectabilityLow, subRow.CollectabilityMid, subRow.CollectabilityHigh];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Recipe.CollectableMetadata is LazyRow<SharlayanCraftWorksSupply> { Value: { } row5 })
|
else if (Recipe.CollectableMetadata.TryGetValue<SharlayanCraftWorksSupply>() is { } row5)
|
||||||
{
|
{
|
||||||
foreach (var item in row5.Item)
|
foreach (var item in row5.Item)
|
||||||
{
|
{
|
||||||
if (item.ItemId.Row == Recipe.ItemResult.Row)
|
if (item.ItemId.RowId == Recipe.ItemResult.RowId)
|
||||||
{
|
{
|
||||||
thresholds = [0, item.CollectabilityMid, item.CollectabilityHigh];
|
thresholds = [0, item.CollectabilityMid, item.CollectabilityHigh];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Recipe.CollectableMetadata is LazyRow<CollectablesRefine> { Value: { } row6 })
|
else if (Recipe.CollectableMetadata.TryGetValue<CollectablesRefine>() is { } row6)
|
||||||
{
|
{
|
||||||
if (row6.CollectabilityHigh != 0)
|
if (row6.CollectabilityHigh != 0)
|
||||||
thresholds = [row6.CollectabilityLow, row6.CollectabilityMid, row6.CollectabilityHigh];
|
thresholds = [row6.CollectabilityLow, row6.CollectabilityMid, row6.CollectabilityHigh];
|
||||||
@@ -102,12 +96,12 @@ public sealed record RecipeData
|
|||||||
|
|
||||||
Ingredients = Recipe.Ingredient.Zip(Recipe.AmountIngredient)
|
Ingredients = Recipe.Ingredient.Zip(Recipe.AmountIngredient)
|
||||||
.Take(6)
|
.Take(6)
|
||||||
.Where(i => i.First.Value != null)
|
.Where(i => i.First.IsValid)
|
||||||
.Select(i => (i.First.Value!, (int)i.Second))
|
.Select(i => (i.First.Value, (int)i.Second))
|
||||||
.ToList();
|
.ToList();
|
||||||
MaxStartingQuality = (int)Math.Floor(Recipe.MaterialQualityFactor * RecipeInfo.MaxQuality / 100f);
|
MaxStartingQuality = (int)Math.Floor(Recipe.MaterialQualityFactor * RecipeInfo.MaxQuality / 100f);
|
||||||
|
|
||||||
TotalHqILvls = (int)Ingredients.Where(i => i.Item.CanBeHq).Sum(i => i.Item.LevelItem.Row * i.Amount);
|
TotalHqILvls = (int)Ingredients.Where(i => i.Item.CanBeHq).Sum(i => i.Item.LevelItem.RowId * i.Amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateItemStartingQuality(int itemIdx, int amount)
|
public int CalculateItemStartingQuality(int itemIdx, int amount)
|
||||||
@@ -120,7 +114,7 @@ public sealed record RecipeData
|
|||||||
if (!ingredient.Item.CanBeHq)
|
if (!ingredient.Item.CanBeHq)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
var iLvls = ingredient.Item.LevelItem.Row * amount;
|
var iLvls = ingredient.Item.LevelItem.RowId * amount;
|
||||||
return (int)Math.Floor((float)iLvls / TotalHqILvls * MaxStartingQuality);
|
return (int)Math.Floor((float)iLvls / TotalHqILvls * MaxStartingQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +123,7 @@ public sealed record RecipeData
|
|||||||
if (TotalHqILvls == 0)
|
if (TotalHqILvls == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
var iLvls = Ingredients.Zip(hqQuantities).Sum(i => i.First.Item.LevelItem.Row * i.Second);
|
var iLvls = Ingredients.Zip(hqQuantities).Sum(i => i.First.Item.LevelItem.RowId * i.Second);
|
||||||
|
|
||||||
return (int)Math.Floor((float)iLvls / TotalHqILvls * MaxStartingQuality);
|
return (int)Math.Floor((float)iLvls / TotalHqILvls * MaxStartingQuality);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ using Dalamud.Interface.ManagedFontAtlas;
|
|||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Utility;
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -23,6 +22,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Sim = Craftimizer.Simulator.Simulator;
|
using Sim = Craftimizer.Simulator.Simulator;
|
||||||
using SimNoRandom = Craftimizer.Simulator.SimulatorNoRandom;
|
using SimNoRandom = Craftimizer.Simulator.SimulatorNoRandom;
|
||||||
|
using Recipe = ExdSheets.Sheets.Recipe;
|
||||||
|
|
||||||
namespace Craftimizer.Windows;
|
namespace Craftimizer.Windows;
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
}
|
}
|
||||||
ImGui.SameLine(0, 5);
|
ImGui.SameLine(0, 5);
|
||||||
{
|
{
|
||||||
var manipLevel = ActionType.Manipulation.GetActionRow(RecipeData.ClassJob).Action!.ClassJobLevel;
|
var manipLevel = ActionType.Manipulation.GetActionRow(RecipeData.ClassJob).Action!.Value.ClassJobLevel;
|
||||||
using (var d = ImRaii.Disabled(manipLevel > CharacterStats.Level))
|
using (var d = ImRaii.Disabled(manipLevel > CharacterStats.Level))
|
||||||
{
|
{
|
||||||
var v = CharacterStats.CanUseManipulation && manipLevel <= CharacterStats.Level;
|
var v = CharacterStats.CanUseManipulation && manipLevel <= CharacterStats.Level;
|
||||||
@@ -586,7 +586,7 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
if (input.ItemId == 0)
|
if (input.ItemId == 0)
|
||||||
return "None";
|
return "None";
|
||||||
|
|
||||||
var name = LuminaSheets.ItemSheet.GetRow(input.ItemId)?.Name.ToDalamudString().ToString() ?? $"Unknown ({input.ItemId})";
|
var name = LuminaSheets.ItemSheet.TryGetRow(input.ItemId)?.Name.ExtractText() ?? $"Unknown ({input.ItemId})";
|
||||||
return input.IsHQ ? $"{name} (HQ)" : name;
|
return input.IsHQ ? $"{name} (HQ)" : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,6 +727,16 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
return (int)Math.Ceiling((y - b) / (c + 1));
|
return (int)Math.Ceiling((y - b) / (c + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly struct RecipeWrapper(Recipe recipe) : IEquatable<RecipeWrapper>
|
||||||
|
{
|
||||||
|
public readonly Recipe Recipe = recipe;
|
||||||
|
|
||||||
|
public bool Equals(RecipeWrapper other) =>
|
||||||
|
Recipe.RowId == other.Recipe.RowId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly List<RecipeWrapper> searchableRecipes = LuminaSheets.RecipeSheet.Where(r => r.RecipeLevelTable.RowId != 0 && r.ItemResult.RowId != 0).Select(r => new RecipeWrapper(r)).ToList();
|
||||||
|
|
||||||
private bool DrawRecipeParams()
|
private bool DrawRecipeParams()
|
||||||
{
|
{
|
||||||
var oldStartingQuality = StartingQuality;
|
var oldStartingQuality = StartingQuality;
|
||||||
@@ -752,29 +762,29 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
(isExpert ? badgeSize.X + 3 : 0);
|
(isExpert ? badgeSize.X + 3 : 0);
|
||||||
ImGui.AlignTextToFramePadding();
|
ImGui.AlignTextToFramePadding();
|
||||||
|
|
||||||
ImGui.Image(Service.IconManager.GetIconCached(RecipeData.Recipe.ItemResult.Value!.Icon).ImGuiHandle, new Vector2(imageSize));
|
ImGui.Image(Service.IconManager.GetIconCached(RecipeData.Recipe.ItemResult.Value.Icon).ImGuiHandle, new Vector2(imageSize));
|
||||||
|
|
||||||
ImGui.SameLine(0, 5);
|
ImGui.SameLine(0, 5);
|
||||||
|
|
||||||
ushort? newRecipe = null;
|
ushort? newRecipe = null;
|
||||||
{
|
{
|
||||||
var recipe = RecipeData.Recipe;
|
var recipe = new RecipeWrapper(RecipeData.Recipe);
|
||||||
using var lockedFontHandle = AxisFont.Available ? AxisFont.Lock() : null;
|
using var lockedFontHandle = AxisFont.Available ? AxisFont.Lock() : null;
|
||||||
var fontHandle = lockedFontHandle?.ImFont ?? ImGui.GetFont();
|
var fontHandle = lockedFontHandle?.ImFont ?? ImGui.GetFont();
|
||||||
if (ImGuiUtils.SearchableCombo(
|
if (ImGuiUtils.SearchableCombo(
|
||||||
"combo",
|
"combo",
|
||||||
ref recipe,
|
ref recipe,
|
||||||
LuminaSheets.RecipeSheet.Where(r => r.RecipeLevelTable.Row != 0 && r.ItemResult.Row != 0),
|
searchableRecipes,
|
||||||
fontHandle,
|
fontHandle,
|
||||||
ImGui.GetContentRegionAvail().X - rightSideWidth,
|
ImGui.GetContentRegionAvail().X - rightSideWidth,
|
||||||
r => r.ItemResult.Value!.Name.ToDalamudString().ToString(),
|
r => r.Recipe.ItemResult.Value.Name.ExtractText(),
|
||||||
r => r.RowId.ToString(),
|
r => r.Recipe.RowId.ToString(),
|
||||||
r =>
|
r =>
|
||||||
{
|
{
|
||||||
ImGui.TextUnformatted($"{r.ItemResult.Value!.Name.ToDalamudString()}");
|
ImGui.TextUnformatted($"{r.Recipe.ItemResult.Value.Name.ExtractText()}");
|
||||||
|
|
||||||
var classJob = (ClassJob)r.CraftType.Row;
|
var classJob = (ClassJob)r.Recipe.CraftType.RowId;
|
||||||
var textLevel = SqText.LevelPrefix.ToIconChar() + SqText.ToLevelString(r.RecipeLevelTable.Value!.ClassJobLevel);
|
var textLevel = SqText.LevelPrefix.ToIconChar() + SqText.ToLevelString(r.Recipe.RecipeLevelTable.Value!.ClassJobLevel);
|
||||||
var textLevelSize = ImGui.CalcTextSize(textLevel);
|
var textLevelSize = ImGui.CalcTextSize(textLevel);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
@@ -796,7 +806,7 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
ImGui.TextUnformatted(textLevel);
|
ImGui.TextUnformatted(textLevel);
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
newRecipe = (ushort)recipe.RowId;
|
newRecipe = (ushort)recipe.Recipe.RowId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -923,10 +933,10 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
{
|
{
|
||||||
var perItem = RecipeData.CalculateItemStartingQuality(idx, 1);
|
var perItem = RecipeData.CalculateItemStartingQuality(idx, 1);
|
||||||
var total = RecipeData.CalculateItemStartingQuality(idx, hqCount);
|
var total = RecipeData.CalculateItemStartingQuality(idx, hqCount);
|
||||||
ImGuiUtils.Tooltip($"{ingredient.Item.Name.ToDalamudString()} {SeIconChar.HighQuality.ToIconString()}\n+{perItem} Quality/Item{(total > 0 ? $"\n+{total} Quality" : "")}");
|
ImGuiUtils.Tooltip($"{ingredient.Item.Name.ExtractText()} {SeIconChar.HighQuality.ToIconString()}\n+{perItem} Quality/Item{(total > 0 ? $"\n+{total} Quality" : "")}");
|
||||||
}
|
}
|
||||||
else if (ingredient.Amount != 0)
|
else if (ingredient.Amount != 0)
|
||||||
ImGuiUtils.Tooltip($"{ingredient.Item.Name.ToDalamudString()}");
|
ImGuiUtils.Tooltip($"{ingredient.Item.Name.ExtractText()}");
|
||||||
}
|
}
|
||||||
ImGui.SameLine(0, 5);
|
ImGui.SameLine(0, 5);
|
||||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - (5 + ImGui.CalcTextSize("/").X + 5 + ImGui.CalcTextSize($"99").X));
|
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - (5 + ImGui.CalcTextSize("/").X + 5 + ImGui.CalcTextSize($"99").X));
|
||||||
@@ -1137,7 +1147,7 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
{
|
{
|
||||||
var status = effect.Status();
|
var status = effect.Status();
|
||||||
using var _reset = ImRaii.DefaultFont();
|
using var _reset = ImRaii.DefaultFont();
|
||||||
ImGuiUtils.Tooltip($"{status.Name.ToDalamudString()}\n{status.Description.ToDalamudString()}");
|
ImGuiUtils.Tooltip($"{status.Name.ExtractText()}\n{status.Description.ExtractText()}");
|
||||||
}
|
}
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -527,7 +527,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
ImGuiUtils.TextCentered($"You do not have {RecipeData.ClassJob.GetName()} unlocked.");
|
ImGuiUtils.TextCentered($"You do not have {RecipeData.ClassJob.GetName()} unlocked.");
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
var unlockQuest = RecipeData.ClassJob.GetUnlockQuest();
|
var unlockQuest = RecipeData.ClassJob.GetUnlockQuest();
|
||||||
var (questGiver, questTerritory, questLocation, mapPayload) = ResolveLevelData(unlockQuest.IssuerLocation.Row);
|
var (questGiver, questTerritory, questLocation, mapPayload) = ResolveLevelData(unlockQuest.IssuerLocation.RowId);
|
||||||
|
|
||||||
var unlockText = $"Unlock it from {questGiver}";
|
var unlockText = $"Unlock it from {questGiver}";
|
||||||
ImGuiUtils.AlignCentered(ImGui.CalcTextSize(unlockText).X + 5 + ImGui.GetFrameHeight());
|
ImGuiUtils.AlignCentered(ImGui.CalcTextSize(unlockText).X + 5 + ImGui.GetFrameHeight());
|
||||||
@@ -580,7 +580,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
case CraftableStatus.RequiredItem:
|
case CraftableStatus.RequiredItem:
|
||||||
{
|
{
|
||||||
var item = RecipeData.Recipe.ItemRequired.Value!;
|
var item = RecipeData.Recipe.ItemRequired.Value!;
|
||||||
var itemName = item.Name.ToDalamudString().ToString();
|
var itemName = item.Name.ExtractText();
|
||||||
var imageSize = ImGui.GetFrameHeight();
|
var imageSize = ImGui.GetFrameHeight();
|
||||||
|
|
||||||
ImGuiUtils.TextCentered($"You are missing the required equipment.");
|
ImGuiUtils.TextCentered($"You are missing the required equipment.");
|
||||||
@@ -594,7 +594,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
case CraftableStatus.RequiredStatus:
|
case CraftableStatus.RequiredStatus:
|
||||||
{
|
{
|
||||||
var status = RecipeData.Recipe.StatusRequired.Value!;
|
var status = RecipeData.Recipe.StatusRequired.Value!;
|
||||||
var statusName = status.Name.ToDalamudString().ToString();
|
var statusName = status.Name.ExtractText();
|
||||||
var statusIcon = Service.IconManager.GetIconCached(status.Icon);
|
var statusIcon = Service.IconManager.GetIconCached(status.Icon);
|
||||||
var imageSize = new Vector2(ImGui.GetFrameHeight() * (statusIcon.AspectRatio ?? 1), ImGui.GetFrameHeight());
|
var imageSize = new Vector2(ImGui.GetFrameHeight() * (statusIcon.AspectRatio ?? 1), ImGui.GetFrameHeight());
|
||||||
|
|
||||||
@@ -1073,16 +1073,16 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
return CraftableStatus.SpecialistRequired;
|
return CraftableStatus.SpecialistRequired;
|
||||||
|
|
||||||
var itemRequired = RecipeData.Recipe.ItemRequired;
|
var itemRequired = RecipeData.Recipe.ItemRequired;
|
||||||
if (itemRequired.Row != 0 && itemRequired.Value != null)
|
if (itemRequired.RowId != 0 && itemRequired.IsValid)
|
||||||
{
|
{
|
||||||
if (!gearItems.Any(i => Gearsets.IsItem(i, itemRequired.Row)))
|
if (!gearItems.Any(i => Gearsets.IsItem(i, itemRequired.RowId)))
|
||||||
return CraftableStatus.RequiredItem;
|
return CraftableStatus.RequiredItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
var statusRequired = RecipeData.Recipe.StatusRequired;
|
var statusRequired = RecipeData.Recipe.StatusRequired;
|
||||||
if (statusRequired.Row != 0 && statusRequired.Value != null)
|
if (statusRequired.RowId != 0 && statusRequired.IsValid)
|
||||||
{
|
{
|
||||||
if (!Service.ClientState.LocalPlayer!.StatusList.Any(s => s.StatusId == statusRequired.Row))
|
if (!Service.ClientState.LocalPlayer!.StatusList.Any(s => s.StatusId == statusRequired.RowId))
|
||||||
return CraftableStatus.RequiredStatus;
|
return CraftableStatus.RequiredStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1097,24 +1097,24 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
|
|
||||||
private static (string NpcName, string Territory, Vector2 MapLocation, MapLinkPayload Payload) ResolveLevelData(uint levelRowId)
|
private static (string NpcName, string Territory, Vector2 MapLocation, MapLinkPayload Payload) ResolveLevelData(uint levelRowId)
|
||||||
{
|
{
|
||||||
var level = LuminaSheets.LevelSheet.GetRow(levelRowId) ??
|
var level = LuminaSheets.LevelSheet.TryGetRow(levelRowId) ??
|
||||||
throw new ArgumentNullException(nameof(levelRowId), $"Invalid level row {levelRowId}");
|
throw new ArgumentNullException(nameof(levelRowId), $"Invalid level row {levelRowId}");
|
||||||
var territory = level.Territory.Value!.PlaceName.Value!.Name.ToDalamudString().ToString();
|
var territory = level.Territory.Value.PlaceName.Value.Name.ExtractText();
|
||||||
var location = WorldToMap2(new(level.X, level.Z), level.Map.Value!);
|
var location = WorldToMap2(new(level.X, level.Z), level.Map.Value!);
|
||||||
|
|
||||||
return (ResolveNpcResidentName(level.Object.Row), territory, location, new(level.Territory.Row, level.Map.Row, location.X, location.Y));
|
return (ResolveNpcResidentName(level.Object.RowId), territory, location, new(level.Territory.RowId, level.Map.RowId, location.X, location.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vector2 WorldToMap2(Vector2 worldCoordinates, ExdSheets.Map map)
|
private static Vector2 WorldToMap2(Vector2 worldCoordinates, ExdSheets.Sheets.Map map)
|
||||||
{
|
{
|
||||||
return MapUtil.WorldToMap(worldCoordinates, map.OffsetX, map.OffsetY, map.SizeFactor);
|
return MapUtil.WorldToMap(worldCoordinates, map.OffsetX, map.OffsetY, map.SizeFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ResolveNpcResidentName(uint npcRowId)
|
private static string ResolveNpcResidentName(uint npcRowId)
|
||||||
{
|
{
|
||||||
var resident = LuminaSheets.ENpcResidentSheet.GetRow(npcRowId) ??
|
var resident = LuminaSheets.ENpcResidentSheet.TryGetRow(npcRowId) ??
|
||||||
throw new ArgumentNullException(nameof(npcRowId), $"Invalid npc row {npcRowId}");
|
throw new ArgumentNullException(nameof(npcRowId), $"Invalid npc row {npcRowId}");
|
||||||
return resident.Singular.ToDalamudString().ToString();
|
return resident.Singular.ExtractText();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int? GetGearsetForJob(ClassJob job)
|
private static int? GetGearsetForJob(ClassJob job)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ using Dalamud.Interface.ManagedFontAtlas;
|
|||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Utility;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
@@ -382,7 +381,7 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
{
|
{
|
||||||
var status = effect.Status();
|
var status = effect.Status();
|
||||||
using var _reset = ImRaii.DefaultFont();
|
using var _reset = ImRaii.DefaultFont();
|
||||||
ImGuiUtils.Tooltip($"{status.Name.ToDalamudString()}\n{status.Description.ToDalamudString()}");
|
ImGuiUtils.Tooltip($"{status.Name.ExtractText()}\n{status.Description.ExtractText()}");
|
||||||
}
|
}
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,18 +10,21 @@
|
|||||||
},
|
},
|
||||||
"ExdSheets": {
|
"ExdSheets": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[1.2.2, )",
|
"requested": "[2.1.0, )",
|
||||||
"resolved": "1.2.2",
|
"resolved": "2.1.0",
|
||||||
"contentHash": "oS1oUBhlOpUWY1Wc3SwOLzfAMuSRzBn54I8p84euVUHrUEOzRZwA9vuNKNMAIY66eT1dpc/DxT+C7LNH0nK0jg==",
|
"contentHash": "SfvLFyL8LYsW4AzPLFVfFwtKPl9xegGraIe9oFar3IlWW8Z4kf5dkM+1CiSr/J+PQt4xt2QZc/ydZ4ibs3RosA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Lumina": "3.15.2"
|
"Lumina": "4.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Lumina": {
|
"Lumina": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[3.15.2, )",
|
"requested": "[4.1.1, )",
|
||||||
"resolved": "3.15.2",
|
"resolved": "4.1.1",
|
||||||
"contentHash": "EnoxYEYMepcvAoXdZhaFJiv2aiDBIPjgkgzxR/+ArOxlrALzCgheTsb5yD39a9sxNIi2tNECT93ulZvYjx8fZg=="
|
"contentHash": "Hd+iTtdaPACTpViXaJ/+sQ3ZQ8MEpApCSD+mxTXnUTYDSZOAipuC4LsZqhAkLMeQHSK/R/jiXEXaXS7e0mTXyA==",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.ObjectPool": "9.0.0-preview.1.24081.5"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"MathNet.Numerics": {
|
"MathNet.Numerics": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
@@ -31,14 +34,20 @@
|
|||||||
},
|
},
|
||||||
"Meziantou.Analyzer": {
|
"Meziantou.Analyzer": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[2.0.162, )",
|
"requested": "[2.0.163, )",
|
||||||
"resolved": "2.0.162",
|
"resolved": "2.0.163",
|
||||||
"contentHash": "lU5ZkiNx6Jj++yYhkUkn2qsgl+PSfAy+BDFc0IkoVVeSCnmUOGBa0Eb1XzGLAeyAuIoz6vYN4J97Q/uiGdIkhw=="
|
"contentHash": "vN0YmOkuvPLukMsefLHYCWYaLPzpc6SfoR74aPwuLeK8QdxgxkavywQ1q/II0shLEEaN1RhlMjmL1RxMPW853w=="
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.ObjectPool": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[9.0.0-preview.1.24081.5, )",
|
||||||
|
"resolved": "9.0.0-preview.1.24081.5",
|
||||||
|
"contentHash": "aAR7YW+pUUdvHk3vj7GtAi71dWGDIuY9270lsmQ6lKw23zzY+r8pLP3cGNbJdlnA9VWl+S+gnIVkBCqj2ROlEg=="
|
||||||
},
|
},
|
||||||
"DotNext": {
|
"DotNext": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "5.8.0",
|
"resolved": "5.11.0",
|
||||||
"contentHash": "5PwF7lUwgJKMcQRrMnFo8ilqrFq9OyaQ5Lq/zFHn0LahhLriNeySCPs08Zd15FdBV0G0KpZvPHBC8Rp1LIsrhg==",
|
"contentHash": "aLWtURne05gwWFFsOg9/X1g4V5yHyuWHX5paQIN7pJIDLCbaCDHcQlLeRRvzvksjAflZJ7tTHkowN/Xi1NXPrA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.IO.Hashing": "8.0.0"
|
"System.IO.Hashing": "8.0.0"
|
||||||
}
|
}
|
||||||
@@ -55,7 +64,7 @@
|
|||||||
"type": "Project",
|
"type": "Project",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Craftimizer.Simulator": "[1.0.0, )",
|
"Craftimizer.Simulator": "[1.0.0, )",
|
||||||
"DotNext": "[5.8.0, )"
|
"DotNext": "[5.11.0, )"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.162">
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.163">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DotNext" Version="5.8.0" />
|
<PackageReference Include="DotNext" Version="5.11.0" />
|
||||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.162">
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.163">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.162">
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.163">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
Reference in New Issue
Block a user