Compare commits
No commits in common. "master" and "v2.0" have entirely different histories.
@ -62,7 +62,7 @@ internal sealed class CharacterSwitch : IDisposable
|
|||||||
{
|
{
|
||||||
UIInputData* uiInputData = UIInputData.Instance();
|
UIInputData* uiInputData = UIInputData.Instance();
|
||||||
MouseButtonFlags mouseButtonFlags =
|
MouseButtonFlags mouseButtonFlags =
|
||||||
uiInputData != null ? uiInputData->CursorInputs.MouseButtonHeldThrottledFlags : MouseButtonFlags.LBUTTON;
|
uiInputData != null ? uiInputData->CursorInputs.MouseButtonReleasedFlags : MouseButtonFlags.LBUTTON;
|
||||||
var target = FindCharacter(mouseButtonFlags.HasFlag(MouseButtonFlags.RBUTTON) ? -1 : 1);
|
var target = FindCharacter(mouseButtonFlags.HasFlag(MouseButtonFlags.RBUTTON) ? -1 : 1);
|
||||||
SwitchCharacter(target);
|
SwitchCharacter(target);
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,13 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Dalamud.Game.Addon.Events;
|
||||||
using Dalamud.Game.Addon.Lifecycle;
|
using Dalamud.Game.Addon.Lifecycle;
|
||||||
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
||||||
using Dalamud.Game.Command;
|
using Dalamud.Game.Command;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
|
using Dalamud.Interface.Style;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
@ -26,13 +28,6 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
private const uint ItemMgp = 29;
|
private const uint ItemMgp = 29;
|
||||||
private const uint ItemTrophyCrystals = 36656;
|
private const uint ItemTrophyCrystals = 36656;
|
||||||
|
|
||||||
private static readonly (uint ItemId, string Name)[] AlliedSocietyCurrencies =
|
|
||||||
[
|
|
||||||
(21074, "Vanu Whitebone"),
|
|
||||||
(21079, "Black Copper Gil"),
|
|
||||||
(21081, "Kojin Sango"),
|
|
||||||
];
|
|
||||||
|
|
||||||
private static readonly ImmutableHashSet<uint> MgpMakaiSets = new HashSet<uint>
|
private static readonly ImmutableHashSet<uint> MgpMakaiSets = new HashSet<uint>
|
||||||
{
|
{
|
||||||
// makai gear
|
// makai gear
|
||||||
@ -89,8 +84,6 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
private readonly IAddonLifecycle _addonLifecycle;
|
private readonly IAddonLifecycle _addonLifecycle;
|
||||||
private readonly Configuration _configuration;
|
private readonly Configuration _configuration;
|
||||||
private readonly ReadOnlyCollection<GlamourSet> _glamourSets;
|
private readonly ReadOnlyCollection<GlamourSet> _glamourSets;
|
||||||
|
|
||||||
private readonly Dictionary<uint, int> _ownedCurrencies = [];
|
|
||||||
private Configuration.CharacterData? _characterData;
|
private Configuration.CharacterData? _characterData;
|
||||||
|
|
||||||
public GlamourSetter(IDalamudPluginInterface pluginInterface, IDataManager dataManager, IClientState clientState,
|
public GlamourSetter(IDalamudPluginInterface pluginInterface, IDataManager dataManager, IClientState clientState,
|
||||||
@ -105,34 +98,28 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
_addonLifecycle = addonLifecycle;
|
_addonLifecycle = addonLifecycle;
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
|
|
||||||
SizeConstraints = new WindowSizeConstraints
|
|
||||||
{
|
|
||||||
MinimumSize = new(300, 400)
|
|
||||||
};
|
|
||||||
|
|
||||||
var armoireItems = dataManager.GetExcelSheet<Cabinet>()
|
var armoireItems = dataManager.GetExcelSheet<Cabinet>()
|
||||||
.Where(x => x.RowId > 0)
|
.Where(x => x.RowId > 0)
|
||||||
.Select(x => x.Item.RowId)
|
.Select(x => x.Item.RowId)
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
var specialShopItems = BuildSpecialShopItems(dataManager);
|
var specialShopItems = dataManager.GetExcelSheet<SpecialShop>()
|
||||||
_glamourSets = BuildGlamourSets(dataManager, armoireItems, specialShopItems);
|
.Where(x => x.RowId > 0 && !string.IsNullOrEmpty(x.Name.ToString()))
|
||||||
|
.SelectMany(x => x.Item.SelectMany(y =>
|
||||||
|
y.ReceiveItems.Select(z => new SpecialShopItem
|
||||||
|
{
|
||||||
|
ItemId = z.Item.RowId,
|
||||||
|
CostItemId = y.ItemCosts[0].ItemCost.Value.RowId,
|
||||||
|
CostType = y.ItemCosts[0].ItemCost.Value.ItemUICategory.RowId,
|
||||||
|
CostName = y.ItemCosts[0].ItemCost.Value.Name.ToString(),
|
||||||
|
CostQuantity = y.ItemCosts[0].CurrencyCost,
|
||||||
|
})
|
||||||
|
.Where(z => z.ItemId > 0 && (z.CostItemId < 100 || z.CostType == 100))))
|
||||||
|
.GroupBy(x => x.ItemId)
|
||||||
|
.ToDictionary(x => x.Key, x => x.FirstOrDefault());
|
||||||
|
|
||||||
_commandManager.AddHandler("/glamoursets", new CommandInfo(ProcessCommand)
|
|
||||||
{
|
|
||||||
HelpMessage = "Shows the glamour set tracker"
|
|
||||||
});
|
|
||||||
_addonLifecycle.RegisterListener(AddonEvent.PostRefresh, "MiragePrismPrismBox", UpdateFromGlamourDresser);
|
|
||||||
_clientState.Logout += Reset;
|
|
||||||
|
|
||||||
if (_clientState.IsLoggedIn)
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<GlamourSet> BuildGlamourSets(IDataManager dataManager, HashSet<uint> armoireItems,
|
|
||||||
Dictionary<uint, SpecialShopItem> specialShopItems)
|
|
||||||
{
|
|
||||||
ExcelSheet<Item> itemSheet = dataManager.GetExcelSheet<Item>();
|
ExcelSheet<Item> itemSheet = dataManager.GetExcelSheet<Item>();
|
||||||
return dataManager.GetExcelSheet<MirageStoreSetItem>()
|
_glamourSets = dataManager.GetExcelSheet<MirageStoreSetItem>()
|
||||||
.Where(x => x.RowId > 0)
|
.Where(x => x.RowId > 0)
|
||||||
.Select(x =>
|
.Select(x =>
|
||||||
{
|
{
|
||||||
@ -167,7 +154,20 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
ItemId = x.RowId,
|
ItemId = x.RowId,
|
||||||
Name = itemSheet.GetRow(x.RowId).Name.ToString(),
|
Name = itemSheet.GetRow(x.RowId).Name.ToString(),
|
||||||
Items = items,
|
Items = items,
|
||||||
SetType = DetermineSetType(x, items),
|
SetType =
|
||||||
|
x.RowId == MostRecentPvpSet
|
||||||
|
? ESetType.PvP
|
||||||
|
: UnobtainableSets.Contains(x.RowId)
|
||||||
|
? ESetType.Unobtainable
|
||||||
|
: EternalBondingSets.Contains(x.RowId) || UndyedRathalosSets.Contains(x.RowId) || MgpMakaiSets.Contains(x.RowId)
|
||||||
|
? ESetType.Special
|
||||||
|
: items.FirstOrDefault()?.ShopItem?.CostItemId switch
|
||||||
|
{
|
||||||
|
ItemWolfMarks or ItemTrophyCrystals => ESetType.PvP,
|
||||||
|
ItemMgp => ESetType.MGP,
|
||||||
|
> 100 => ESetType.AlliedSociety,
|
||||||
|
_ => ESetType.Default,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.Where(x => x.Items.Count > 0 && x.Items.Any(y => !armoireItems.Contains(y.ItemId)))
|
.Where(x => x.Items.Count > 0 && x.Items.Any(y => !armoireItems.Contains(y.ItemId)))
|
||||||
@ -175,49 +175,16 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
.ThenBy(x => x.ItemId)
|
.ThenBy(x => x.ItemId)
|
||||||
.ToList()
|
.ToList()
|
||||||
.AsReadOnly();
|
.AsReadOnly();
|
||||||
}
|
|
||||||
|
|
||||||
private static ESetType DetermineSetType(MirageStoreSetItem item, ReadOnlyCollection<GlamourItem> items)
|
_commandManager.AddHandler("/glamoursets", new CommandInfo(ProcessCommand)
|
||||||
{
|
|
||||||
if (item.RowId == MostRecentPvpSet)
|
|
||||||
return ESetType.PvP;
|
|
||||||
|
|
||||||
if (UnobtainableSets.Contains(item.RowId))
|
|
||||||
return ESetType.Unobtainable;
|
|
||||||
|
|
||||||
if (EternalBondingSets.Contains(item.RowId) ||
|
|
||||||
UndyedRathalosSets.Contains(item.RowId) ||
|
|
||||||
MgpMakaiSets.Contains(item.RowId))
|
|
||||||
return ESetType.Special;
|
|
||||||
|
|
||||||
uint? costItemId = items.FirstOrDefault()?.ShopItem?.CostItemId;
|
|
||||||
if (AlliedSocietyCurrencies.Any(x => x.ItemId == costItemId))
|
|
||||||
return ESetType.AlliedSociety;
|
|
||||||
|
|
||||||
return costItemId switch
|
|
||||||
{
|
{
|
||||||
ItemWolfMarks or ItemTrophyCrystals => ESetType.PvP,
|
HelpMessage = "Shows the glamour set tracker"
|
||||||
ItemMgp => ESetType.MGP,
|
});
|
||||||
_ => ESetType.Default,
|
_addonLifecycle.RegisterListener(AddonEvent.PostRefresh, "MiragePrismPrismBox", UpdateFromGlamourDresser);
|
||||||
};
|
_clientState.Logout += Reset;
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<uint, SpecialShopItem> BuildSpecialShopItems(IDataManager dataManager)
|
if (_clientState.IsLoggedIn)
|
||||||
{
|
Update();
|
||||||
return dataManager.GetExcelSheet<SpecialShop>()
|
|
||||||
.Where(x => x.RowId > 0 && !string.IsNullOrEmpty(x.Name.ToString()))
|
|
||||||
.SelectMany(x => x.Item.SelectMany(y =>
|
|
||||||
y.ReceiveItems.Select(z => new SpecialShopItem
|
|
||||||
{
|
|
||||||
ItemId = z.Item.RowId,
|
|
||||||
CostItemId = y.ItemCosts[0].ItemCost.Value.RowId,
|
|
||||||
CostType = y.ItemCosts[0].ItemCost.Value.ItemUICategory.RowId,
|
|
||||||
CostName = y.ItemCosts[0].ItemCost.Value.Name.ToString(),
|
|
||||||
CostQuantity = y.ItemCosts[0].CurrencyCost,
|
|
||||||
})
|
|
||||||
.Where(z => z.ItemId > 0 && (z.CostItemId < 100 || z.CostType == 100))))
|
|
||||||
.GroupBy(x => x.ItemId)
|
|
||||||
.ToDictionary(x => x.Key, x => x.First());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessCommand(string command, string arguments)
|
private void ProcessCommand(string command, string arguments)
|
||||||
@ -260,21 +227,6 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
InventoryManager* inventoryManager = InventoryManager.Instance();
|
|
||||||
if (inventoryManager != null)
|
|
||||||
{
|
|
||||||
_ownedCurrencies[ItemMgp] = inventoryManager->GetItemCountInContainer(ItemMgp, InventoryType.Currency);
|
|
||||||
_ownedCurrencies[ItemWolfMarks] = (int)inventoryManager->GetWolfMarks();
|
|
||||||
_ownedCurrencies[ItemTrophyCrystals] = inventoryManager->GetInventoryItemCount(ItemTrophyCrystals);
|
|
||||||
foreach (var (itemId, _) in AlliedSocietyCurrencies)
|
|
||||||
_ownedCurrencies[itemId] = inventoryManager->GetInventoryItemCount(itemId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_ownedCurrencies.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
var ownedSets = _glamourSets.Where(x => _characterData.GlamourDresserItems.Contains(x.ItemId)).ToList();
|
var ownedSets = _glamourSets.Where(x => _characterData.GlamourDresserItems.Contains(x.ItemId)).ToList();
|
||||||
ImGui.Text(
|
ImGui.Text(
|
||||||
$"Complete Sets: {ownedSets.Count} / {_glamourSets.Count(x => x.SetType != ESetType.Unobtainable || ownedSets.Contains(x))}");
|
$"Complete Sets: {ownedSets.Count} / {_glamourSets.Count(x => x.SetType != ESetType.Unobtainable || ownedSets.Contains(x))}");
|
||||||
@ -315,9 +267,7 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
|
|
||||||
var ownedItems = GetOwnedItems();
|
var ownedItems = GetOwnedItems();
|
||||||
DrawMissingItemHeader(glamourSets, setType, ownedSets, ownedItems);
|
DrawMissingItemHeader(glamourSets, setType, ownedSets, ownedItems);
|
||||||
|
DrawSetRange(glamourSets, ownedSets, ownedItems);
|
||||||
using (ImRaii.Child("Sets"))
|
|
||||||
DrawSetRange(glamourSets, ownedSets, ownedItems);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawSpecialtyTab(List<GlamourSet> ownedSets)
|
private void DrawSpecialtyTab(List<GlamourSet> ownedSets)
|
||||||
@ -340,7 +290,7 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
DrawSetRange(glamourSets.Where(x => UndyedRathalosSets.Contains(x.ItemId)).ToList(), ownedSets, ownedItems);
|
DrawSetRange(glamourSets.Where(x => UndyedRathalosSets.Contains(x.ItemId)).ToList(), ownedSets, ownedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMissingItemHeader(List<GlamourSet> glamourSets, ESetType setType, List<GlamourSet> ownedSets,
|
private static void DrawMissingItemHeader(List<GlamourSet> glamourSets, ESetType setType, List<GlamourSet> ownedSets,
|
||||||
HashSet<uint> ownedItems)
|
HashSet<uint> ownedItems)
|
||||||
{
|
{
|
||||||
var missingItems = glamourSets
|
var missingItems = glamourSets
|
||||||
@ -350,24 +300,15 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
if (setType == ESetType.PvP)
|
if (setType == ESetType.PvP)
|
||||||
{
|
{
|
||||||
ImGui.Text(
|
ImGui.Text(
|
||||||
$"Wolf Marks: {_ownedCurrencies.GetValueOrDefault(ItemWolfMarks):N0} / {missingItems.Where(x => x is { ShopItem.CostItemId: ItemWolfMarks }).Sum(x => x.ShopItem!.CostQuantity):N0}");
|
$"Wolf Marks: {missingItems.Where(x => x is { ShopItem.CostItemId: ItemWolfMarks }).Sum(x => x.ShopItem!.CostQuantity):N0}");
|
||||||
ImGui.Text(
|
ImGui.Text(
|
||||||
$"Trophy Crystals: {_ownedCurrencies.GetValueOrDefault(ItemTrophyCrystals):N0} / {missingItems.Where(x => x is { ShopItem.CostItemId: ItemTrophyCrystals }).Sum(x => x.ShopItem!.CostQuantity):N0}");
|
$"Trophy Crystals: {missingItems.Where(x => x is { ShopItem.CostItemId: ItemTrophyCrystals }).Sum(x => x.ShopItem!.CostQuantity):N0}");
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
}
|
}
|
||||||
else if (setType is ESetType.MGP or ESetType.Special)
|
else if (setType is ESetType.MGP or ESetType.Special)
|
||||||
{
|
{
|
||||||
ImGui.Text(
|
ImGui.Text(
|
||||||
$"MGP: {_ownedCurrencies.GetValueOrDefault(ItemMgp):N0} / {missingItems.Where(x => x is { ShopItem.CostItemId: ItemMgp }).Sum(x => x.ShopItem!.CostQuantity):N0}");
|
$"MGP: {missingItems.Where(x => x is { ShopItem.CostItemId: ItemMgp }).Sum(x => x.ShopItem!.CostQuantity):N0}");
|
||||||
ImGui.Separator();
|
|
||||||
}
|
|
||||||
else if (setType == ESetType.AlliedSociety)
|
|
||||||
{
|
|
||||||
foreach (var (itemId, name) in AlliedSocietyCurrencies)
|
|
||||||
{
|
|
||||||
ImGui.Text(
|
|
||||||
$"{name}: {_ownedCurrencies.GetValueOrDefault(itemId):N0} / {missingItems.Where(x => x is { ShopItem: { } shopItem } && shopItem.CostItemId == itemId).Sum(x => x.ShopItem!.CostQuantity):N0}");
|
|
||||||
}
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -384,13 +325,12 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
int ownedCount = glamourSet.Items.Count(x => ownedItems.Contains(x.ItemId));
|
int ownedCount = glamourSet.Items.Count(x => ownedItems.Contains(x.ItemId));
|
||||||
if (ownedCount == glamourSet.Items.Count)
|
if (ownedCount == glamourSet.Items.Count)
|
||||||
ImGui.TextColored(ImGuiColors.ParsedBlue, $"{glamourSet.Name} (Can be completed)");
|
ImGui.TextColored(ImGuiColors.ParsedBlue, $"{glamourSet.Name} (Can be completed)");
|
||||||
else if (CanAffordAllMissingGearPieces(glamourSet, ownedItems))
|
|
||||||
ImGui.TextColored(ImGuiColors.DalamudViolet, $"{glamourSet.Name} (Can afford)");
|
|
||||||
else if (ownedCount > 0)
|
else if (ownedCount > 0)
|
||||||
ImGui.TextColored(ImGuiColors.DalamudYellow, glamourSet.Name);
|
ImGui.TextColored(ImGuiColors.DalamudYellow, glamourSet.Name);
|
||||||
else
|
else
|
||||||
ImGui.Text(glamourSet.Name);
|
ImGui.Text(glamourSet.Name);
|
||||||
|
|
||||||
|
|
||||||
using (ImRaii.PushIndent())
|
using (ImRaii.PushIndent())
|
||||||
{
|
{
|
||||||
foreach (var item in glamourSet.Items)
|
foreach (var item in glamourSet.Items)
|
||||||
@ -431,9 +371,6 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
foreach (var inventoryType in _inventoryTypes)
|
foreach (var inventoryType in _inventoryTypes)
|
||||||
{
|
{
|
||||||
var inventoryContainer = inventoryManager->GetInventoryContainer(inventoryType);
|
var inventoryContainer = inventoryManager->GetInventoryContainer(inventoryType);
|
||||||
if (inventoryContainer == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int i = 0; i < inventoryContainer->Size; ++i)
|
for (int i = 0; i < inventoryContainer->Size; ++i)
|
||||||
{
|
{
|
||||||
InventoryItem* item = inventoryContainer->GetInventorySlot(i);
|
InventoryItem* item = inventoryContainer->GetInventorySlot(i);
|
||||||
@ -447,25 +384,6 @@ internal sealed class GlamourSetter : Window, IDisposable
|
|||||||
return ownedItems;
|
return ownedItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanAffordAllMissingGearPieces(GlamourSet glamourSet, HashSet<uint> ownedItems)
|
|
||||||
{
|
|
||||||
uint costItemId = 0;
|
|
||||||
uint costQuantity = 0;
|
|
||||||
foreach (var item in glamourSet.Items)
|
|
||||||
{
|
|
||||||
if (ownedItems.Contains(item.ItemId))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (item.ShopItem == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
costItemId = item.ShopItem.CostItemId;
|
|
||||||
costQuantity += item.ShopItem.CostQuantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
return costQuantity <= _ownedCurrencies.GetValueOrDefault(costItemId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe void UpdateFromGlamourDresser(AddonEvent type, AddonArgs args)
|
private unsafe void UpdateFromGlamourDresser(AddonEvent type, AddonArgs args)
|
||||||
{
|
{
|
||||||
if (_characterData == null)
|
if (_characterData == null)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project>
|
<Project>
|
||||||
<Target Name="PackagePluginDebug" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
|
<Target Name="PackagePlugin" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
|
||||||
<DalamudPackager
|
<DalamudPackager
|
||||||
ProjectDir="$(ProjectDir)"
|
ProjectDir="$(ProjectDir)"
|
||||||
OutputPath="$(OutputPath)"
|
OutputPath="$(OutputPath)"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Dalamud.NET.Sdk/11.0.0">
|
<Project Sdk="Dalamud.NET.Sdk/11.0.0">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>2.3</Version>
|
<Version>2.0</Version>
|
||||||
<OutputPath>dist</OutputPath>
|
<OutputPath>dist</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user