Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions Anamnesis/Actor/Items/DummyItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,32 @@ namespace Anamnesis.Actor.Items;
using Anamnesis.GameData.Sheets;
using Anamnesis.Services;
using Anamnesis.TexTools;
using Lumina;
using System.Runtime.CompilerServices;

public class DummyItem(ushort modelSet, ushort modelBase, ushort modelVariant) : IItem
public class DummyItem : IItem
{
public DummyItem(ushort modelSet, ushort modelBase, ushort modelVariant)
{
this.ModelSet = modelSet;
this.ModelBase = modelBase;
this.ModelVariant = modelVariant;
this.Model = ExcelPageExtensions.ConvertToModel(modelSet, modelBase, modelVariant);
this.IsWeapon = modelSet != 0;
}

public DummyItem(ulong model, bool isWeapon = false)
{
this.Model = model;
this.IsWeapon = isWeapon;
LuminaExtensions.GetModel(model, isWeapon, out ushort modelSet, out ushort modelBase, out ushort modelVariant);
this.ModelSet = modelSet;
this.ModelBase = modelBase;
this.ModelVariant = modelVariant;
}

public uint RowId => 0;
public bool IsWeapon => true;
public bool IsWeapon { get; private set; }
public bool HasSubModel => false;
public string Name => LocalizationService.GetString("Item_Unknown");
public string Description => string.Empty;
Expand All @@ -20,10 +40,10 @@ public class DummyItem(ushort modelSet, ushort modelBase, ushort modelVariant) :
public Mod? Mod => null;
public byte EquipLevel => 0;

public ulong Model => ExcelPageExtensions.ConvertToModel(this.ModelSet, this.ModelBase, this.ModelVariant);
public ushort ModelBase { get; private set; } = modelBase;
public ushort ModelVariant { get; private set; } = modelVariant;
public ushort ModelSet { get; private set; } = modelSet;
public ulong Model { get; private set; }
public ushort ModelBase { get; private set; }
public ushort ModelVariant { get; private set; }
public ushort ModelSet { get; private set; }

public ulong SubModel => ExcelPageExtensions.ConvertToModel(this.SubModelSet, this.SubModelBase, this.SubModelVariant);
public ushort SubModelBase { get; }
Expand Down
2 changes: 1 addition & 1 deletion Anamnesis/Actor/Refresh/AnamnesisActorRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ private static (byte[] Buffer, int Length) PackRedrawPayload(ActorMemory actor,

writer.WriteByte((byte)flags);

if (flags.HasFlag(RedrawFlags.Weapons))
if (flags.HasFlag(RedrawFlags.Weapons) || flags.HasFlag(RedrawFlags.Appearance))
{
writer.Write(actor.DrawData.MainHand?.WeaponModelId ?? default);
writer.Write(actor.DrawData.OffHand?.WeaponModelId ?? default);
Expand Down
79 changes: 30 additions & 49 deletions Anamnesis/Actor/Utilities/ItemUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
namespace Anamnesis.Actor.Utilities;

using Anamnesis.Actor.Items;
using Anamnesis.Core.Extensions;
using Anamnesis.GameData;
using Anamnesis.GameData.Excel;
using Anamnesis.GameData.Sheets;
using Anamnesis.Services;
using System;
using System.Linq;

public static class ItemUtility
Expand All @@ -33,42 +35,30 @@ public static class ItemUtility
/// <summary>
/// Searches the gamedata service item list for an item with the given model attributes.
/// </summary>
public static IItem GetItem(ItemSlots slot, ushort modelSet, ushort modelBase, ushort modelVariant, bool isChocobo)
public static IItem GetItem(ItemSlots slot, ushort modelSet, ushort modelBase, ushort modelVariant, bool isChocobo = false)
{
if ((modelBase == 0 || modelBase == 1) && modelVariant == 0)
bool isWeaponSlot = (slot & ItemSlots.Weapons) != 0;
if ((isWeaponSlot && modelSet == 0) || modelBase == 0)
return NoneItem;

if (modelBase == NpcBodyItem.ModelBase)
return NpcBodyItem;

return isChocobo
? ChocoboItemSearch(slot, modelSet, modelBase, modelVariant)
: ItemSearch(slot, modelSet, modelBase, modelVariant);
}

public static IItem GetDummyItem(ushort modelSet, ushort modelBase, ushort modelVariant)
{
var model = ExcelPageExtensions.ConvertToModel(modelSet, modelBase, modelVariant);

if (NoneItem.Model == model)
return NoneItem;
ulong model = ExcelPageExtensions.ConvertToModel(modelSet, modelBase, modelVariant);

if (NpcBodyItem.Model == model)
if (model == NpcBodyItem.Model)
return NpcBodyItem;

if (InvisibileBodyItem.Model == model)
if (model == InvisibileBodyItem.Model)
return InvisibileBodyItem;

if (InvisibileHeadItem.Model == model)
if (model == InvisibileHeadItem.Model)
return InvisibileHeadItem;

return new DummyItem(modelSet, modelBase, modelVariant);
return isChocobo
? ChocoboItemSearch(slot, model)
: ItemSearch(slot, model, isWeaponSlot);
}

private static IItem ChocoboItemSearch(ItemSlots slot, ushort modelSet, ushort modelBase, ushort modelVariant)
private static IItem ChocoboItemSearch(ItemSlots slot, ulong model)
{
var model = ExcelPageExtensions.ConvertToModel(modelSet, modelBase, modelVariant);

if (slot == ItemSlots.Legs)
{
if (YellowChocoboSkin.Model == model)
Expand All @@ -81,52 +71,43 @@ private static IItem ChocoboItemSearch(ItemSlots slot, ushort modelSet, ushort m
{
foreach (BuddyEquip equip in GameDataService.BuddyEquips)
{
if (equip.Head != null && equip.Head.Slot == slot && equip.Head.Model == model)
return equip.Head;

if (equip.Body != null && equip.Body.Slot == slot && equip.Body.Model == model)
return equip.Body;

if (equip.Feet != null && equip.Feet.Slot == slot && equip.Feet.Model == model)
return equip.Feet;
BuddyEquip.BuddyItem? item = slot switch
{
ItemSlots.Head => equip.Head,
ItemSlots.Body => equip.Body,
ItemSlots.Legs => equip.Feet,
_ => null,
};

if (item != null && item.Model == model)
return item;
}
}

return new DummyItem(modelSet, modelBase, modelVariant);
return new DummyItem(model, isWeapon: false);
}

private static IItem ItemSearch(ItemSlots slot, ushort modelSet, ushort modelBase, ushort modelVariant)
private static IItem ItemSearch(ItemSlots slot, ulong model, bool isWeaponSlot)
{
var model = ExcelPageExtensions.ConvertToModel(modelSet, modelBase, modelVariant);

foreach (uint rowId in GameDataService.ItemsByModel[model])
{
var tItem = GameDataService.Items.GetRow(rowId);

if (slot == ItemSlots.MainHand || slot == ItemSlots.OffHand)
{
if (!tItem.IsWeapon)
continue;
}
else
{
if (!tItem.FitsInSlot(slot))
continue;
}
if (isWeaponSlot ? !tItem.IsWeapon : !tItem.FitsInSlot(slot))
continue;

// Big old hack, but we prefer the emperors bracelets to the promise bracelets (even though they are the same model)
if (slot == ItemSlots.Wrists && tItem.Name.StartsWith("Promise of"))
if (slot == ItemSlots.Wrists && tItem.Name.StartsWith("Promise of", StringComparison.Ordinal))
continue;

return tItem;
}

if (slot == ItemSlots.MainHand || slot == ItemSlots.OffHand)
if (isWeaponSlot)
{
foreach (uint rowId in GameDataService.ItemsBySubModel[model])
{
var tItem = GameDataService.Items.GetRow(rowId);

if (tItem.IsWeapon)
return tItem;
}
Expand All @@ -144,6 +125,6 @@ private static IItem ItemSearch(ItemSlots slot, ushort modelSet, ushort modelBas
return tItem;
}

return new DummyItem(modelSet, modelBase, modelVariant);
return new DummyItem(model, isWeapon: isWeaponSlot);
}
}
23 changes: 15 additions & 8 deletions Anamnesis/Actor/Views/EquipmentSelector.xaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<local:EquipmentSelectorDrawer x:Class="Anamnesis.Actor.Views.EquipmentSelector"
<local:EquipmentSelectorDrawer x:Class="Anamnesis.Actor.Views.EquipmentSelector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:Anamnesis.Styles.Controls"
xmlns:drawers="clr-namespace:Anamnesis.Styles.Drawers"
xmlns:fa="http://schemas.awesome.incremented/wpf/xaml/fontawesome.sharp"
xmlns:XivToolsWpf="clr-namespace:XivToolsWpf.Controls;assembly=XivToolsWpf"
xmlns:xivToolsWpfSelectors="clr-namespace:XivToolsWpf.Selectors;assembly=XivToolsWpf"
xmlns:local="clr-namespace:Anamnesis.Actor.Views"
mc:Ignorable="d"
xmlns:xivToolsWpfSelectors="clr-namespace:XivToolsWpf.Selectors;assembly=XivToolsWpf"
xmlns:local="clr-namespace:Anamnesis.Actor.Views"
mc:Ignorable="d"
d:DesignHeight="450">

<UserControl.Resources>
Expand Down Expand Up @@ -163,21 +163,28 @@
Margin="6, 0, 0, 0"
Visibility="{Binding IsWeaponSlot, Converter={StaticResource B2V}}">

<CheckBox Padding="3" IsChecked="{Binding AutoOffhand}" Visibility="{Binding IsMainHandSlot, Converter={StaticResource B2V}}">
<CheckBox Padding="2, 1" IsChecked="{Binding AutoOffhand}" Visibility="{Binding IsMainHandSlot, Converter={StaticResource B2V}}">
<CheckBox.ToolTip>
<XivToolsWpf:TextBlock Key="EquipmentSelector_AutoOffhandTip"/>
</CheckBox.ToolTip>
<XivToolsWpf:TextBlock Key="EquipmentSelector_AutoOffhand"/>
</CheckBox>

<CheckBox Padding="3" IsChecked="{Binding ForceMainModel}" Visibility="{Binding IsOffHandSlot, Converter={StaticResource B2V}}">
<CheckBox Padding="2, 1" IsChecked="{Binding LinkDyes}">
<CheckBox.ToolTip>
<XivToolsWpf:TextBlock Key="EquipmentSelector_LinkDyesTip"/>
</CheckBox.ToolTip>
<XivToolsWpf:TextBlock Key="EquipmentSelector_LinkDyes"/>
</CheckBox>

<CheckBox Padding="2, 1" IsChecked="{Binding ForceMainModel}" Visibility="{Binding IsOffHandSlot, Converter={StaticResource B2V}}">
<CheckBox.ToolTip>
<XivToolsWpf:TextBlock Key="EquipmentSelector_ForceMainModelTooltip"/>
</CheckBox.ToolTip>
<XivToolsWpf:TextBlock Key="EquipmentSelector_ForceMainModel"/>
</CheckBox>

<CheckBox Padding="3" IsChecked="{Binding ForceOffModel}" Visibility="{Binding IsMainHandSlot, Converter={StaticResource B2V}}">
<CheckBox Padding="2, 1" IsChecked="{Binding ForceOffModel}" Visibility="{Binding IsMainHandSlot, Converter={StaticResource B2V}}">
<CheckBox.ToolTip>
<XivToolsWpf:TextBlock Key="EquipmentSelector_ForceOffModelTooltip"/>
</CheckBox.ToolTip>
Expand Down
15 changes: 14 additions & 1 deletion Anamnesis/Actor/Views/EquipmentSelector.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// © Anamnesis.
// © Anamnesis.
// Licensed under the MIT license.

namespace Anamnesis.Actor.Views;
Expand Down Expand Up @@ -36,6 +36,7 @@ public partial class EquipmentSelector : EquipmentSelectorDrawer
private static bool s_showFilters = false;
private static bool s_forceMainModel = false;
private static bool s_forceOffModel = false;
private static bool s_linkDyes = true;
private static SortModes s_sortMode = SortModes.Row;

private readonly Memory.ActorMemory? actor;
Expand Down Expand Up @@ -63,6 +64,12 @@ public enum SortModes
Level,
}

public static bool LinkWeaponDyes
{
get => s_linkDyes;
set => s_linkDyes = value;
}

// Suppress CA1822: The properties are used in WPF bindings. Do not set them to static.
#pragma warning disable CA1822
public bool ShowFilters
Expand All @@ -76,6 +83,12 @@ public bool AutoOffhand
get => s_autoOffhand;
set => s_autoOffhand = value;
}

public bool LinkDyes
{
get => s_linkDyes;
set => s_linkDyes = value;
}
#pragma warning restore CA1822

public bool IsGpose { get; set; }
Expand Down
51 changes: 44 additions & 7 deletions Anamnesis/Actor/Views/ItemView.xaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<UserControl x:Class="Anamnesis.Actor.Views.ItemView"
<UserControl x:Class="Anamnesis.Actor.Views.ItemView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:fa="http://schemas.awesome.incremented/wpf/xaml/fontawesome.sharp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Expand Down Expand Up @@ -151,16 +151,25 @@
<StackPanel Grid.Row="0" Grid.Column="1" Margin="3,0,0,0" Orientation="Horizontal" IsEnabled="{Binding Actor.CanRefresh, Mode=OneWay}">
<StackPanel Orientation="Horizontal" IsEnabled="{Binding CanEditItem, Mode=OneWay}">
<XivToolsWpf:NumberBox Width="28" Value="{Binding ItemModel.Set}" FontSize="12" FontWeight="Light"
ToolTip="Character_Equipment_ItemSet"
Visibility="{Binding IsWeapon, Converter={StaticResource B2V}, Mode=OneWay}"/>
Visibility="{Binding IsWeapon, Converter={StaticResource B2V}, Mode=OneWay}">
<XivToolsWpf:NumberBox.ToolTip>
<XivToolsWpf:TextBlock Key="Character_Equipment_ItemSet"/>
</XivToolsWpf:NumberBox.ToolTip>
</XivToolsWpf:NumberBox>

<TextBlock Text="," Style="{StaticResource Label}" Margin="2, 2, 4, 0" Visibility="{Binding IsWeapon, Converter={StaticResource B2V}, Mode=OneWay}"/>
<XivToolsWpf:NumberBox Width="28" Value="{Binding ItemModel.Base}" FontSize="12" FontWeight="Light"
ToolTip="Character_Equipment_ItemBase"/>
<XivToolsWpf:NumberBox Width="28" Value="{Binding ItemModel.Base}" FontSize="12" FontWeight="Light">
<XivToolsWpf:NumberBox.ToolTip>
<XivToolsWpf:TextBlock Key="Character_Equipment_ItemBase"/>
</XivToolsWpf:NumberBox.ToolTip>
</XivToolsWpf:NumberBox>

<TextBlock Text="," Style="{StaticResource Label}" Margin="2, 2, 4, 0" />
<XivToolsWpf:NumberBox Width="28" Value="{Binding ItemModel.Variant}" FontSize="12" FontWeight="Light"
ToolTip="Character_Equipment_ItemVariant"/>
<XivToolsWpf:NumberBox Width="28" Value="{Binding ItemModel.Variant}" FontSize="12" FontWeight="Light">
<XivToolsWpf:NumberBox.ToolTip>
<XivToolsWpf:TextBlock Key="Character_Equipment_ItemVariant"/>
</XivToolsWpf:NumberBox.ToolTip>
</XivToolsWpf:NumberBox>
</StackPanel>
</StackPanel>

Expand Down Expand Up @@ -249,6 +258,20 @@
<fa:IconImage Icon="ArrowRightArrowLeft" Foreground="{StaticResource PrimaryHueMidBrush}"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Click="OnToggleLinkDyes" Visibility="{Binding IsWeapon, Converter={StaticResource B2V}, Mode=OneWay}">
<MenuItem.Header>
<Grid>
<XivToolsWpf:TextBlock Key="EquipmentSelector_UnlinkDyes" Visibility="{Binding LinkWeaponDyes, Converter={StaticResource B2V}}"/>
<XivToolsWpf:TextBlock Key="EquipmentSelector_LinkDyes" Visibility="{Binding LinkWeaponDyes, Converter={StaticResource !B2V}}"/>
</Grid>
</MenuItem.Header>
<MenuItem.Icon>
<Grid>
<fa:IconImage Icon="Unlink" Foreground="{StaticResource PrimaryHueMidBrush}" Visibility="{Binding LinkWeaponDyes, Converter={StaticResource B2V}}"/>
<fa:IconImage Icon="Link" Foreground="{StaticResource PrimaryHueMidBrush}" Visibility="{Binding LinkWeaponDyes, Converter={StaticResource !B2V}}"/>
</Grid>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
Expand Down Expand Up @@ -284,6 +307,20 @@
<fa:IconImage Icon="ArrowRightArrowLeft" Foreground="{StaticResource PrimaryHueMidBrush}"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Click="OnToggleLinkDyes" Visibility="{Binding IsWeapon, Converter={StaticResource B2V}, Mode=OneWay}">
<MenuItem.Header>
<Grid>
<XivToolsWpf:TextBlock Key="EquipmentSelector_UnlinkDyes" Visibility="{Binding LinkWeaponDyes, Converter={StaticResource B2V}}"/>
<XivToolsWpf:TextBlock Key="EquipmentSelector_LinkDyes" Visibility="{Binding LinkWeaponDyes, Converter={StaticResource !B2V}}"/>
</Grid>
</MenuItem.Header>
<MenuItem.Icon>
<Grid>
<fa:IconImage Icon="Unlink" Foreground="{StaticResource PrimaryHueMidBrush}" Visibility="{Binding LinkWeaponDyes, Converter={StaticResource B2V}}"/>
<fa:IconImage Icon="Link" Foreground="{StaticResource PrimaryHueMidBrush}" Visibility="{Binding LinkWeaponDyes, Converter={StaticResource !B2V}}"/>
</Grid>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
Expand Down
Loading
Loading