Skip to content

Commit c7d873a

Browse files
authored
Virindi Color Tool (#85)
* Added Armor + Virindi Color Tool feature * Removed some useless declarations * Fixed issue with trying to view armor before opening dats
1 parent 2194092 commit c7d873a

30 files changed

Lines changed: 2555 additions & 77 deletions

ACViewer/ACViewer.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020
<None Remove="Content\Content.mgcb" />
2121
<None Remove="Content\Fonts\password.ttf" />
2222
<None Remove="Icons\about.png" />
23+
<None Remove="Icons\Armor.png" />
2324
<None Remove="Icons\Checkmark_16x.png" />
2425
<None Remove="Icons\export-file.png" />
2526
<None Remove="Icons\help.png" />
2627
<None Remove="Icons\HelpApplication_16x.png" />
2728
<None Remove="Icons\OpenFile_16x.png" />
29+
<None Remove="Icons\plume.png" />
2830
<None Remove="Icons\portal.png" />
2931
<None Remove="Icons\question-mark.png" />
3032
<None Remove="Icons\Question_16x.png" />
@@ -60,11 +62,13 @@
6062
<ItemGroup>
6163
<Resource Include="Content\Fonts\password.ttf" />
6264
<Resource Include="Icons\about.png" />
65+
<Resource Include="Icons\armor.png" />
6366
<Resource Include="Icons\Checkmark_16x.png" />
6467
<Resource Include="Icons\export-file.png" />
6568
<Resource Include="Icons\help.png" />
6669
<Resource Include="Icons\HelpApplication_16x.png" />
6770
<Resource Include="Icons\OpenFile_16x.png" />
71+
<Resource Include="Icons\plume.png" />
6872
<Resource Include="Icons\portal.png" />
6973
<Resource Include="Icons\question-mark.png" />
7074
<Resource Include="Icons\Question_16x.png" />
@@ -90,6 +94,9 @@
9094
<None Update="Data\Locations.txt">
9195
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
9296
</None>
97+
<None Update="Data\LootArmor.txt">
98+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
99+
</None>
93100
</ItemGroup>
94101

95102
<PropertyGroup>

ACViewer/Data/LootArmor.txt

Lines changed: 1798 additions & 0 deletions
Large diffs are not rendered by default.

ACViewer/Data/LootArmorList.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace ACViewer.Data
9+
{
10+
11+
public static class LootArmorList
12+
{
13+
public static Dictionary<uint, LootItem> Loot{ get; set; }
14+
15+
static LootArmorList()
16+
{
17+
Loot = new Dictionary<uint, LootItem>();
18+
}
19+
20+
public static void Load()
21+
{
22+
var filename = @"Data\LootArmor.txt";
23+
24+
var lines = File.ReadAllLines(filename);
25+
26+
for (var i = 0; i < lines.Length; i++)
27+
{
28+
var line = lines[i];
29+
30+
// comment
31+
if (line.StartsWith("#"))
32+
continue;
33+
34+
var pieces = line.Split(',');
35+
36+
if (pieces.Length != 5)
37+
{
38+
Console.WriteLine($"LootArmor.Load({filename}): line {i + 1} length {pieces.Length}");
39+
continue;
40+
}
41+
42+
var wcid = pieces[0].Length > 0 ? Convert.ToUInt32(pieces[0]) : 0;
43+
var name = pieces[1].Length > 0 ? pieces[1] : "";
44+
var clothingBase = pieces[2].Length > 0 ? pieces[2].ToUpper() : "";
45+
var palTemp = pieces[3].Length > 0 ? Convert.ToUInt32(pieces[3]) : 0;
46+
var shade = pieces[4].Length > 0 ? Convert.ToSingle(pieces[4]) : 0;
47+
48+
var item = new LootItem(wcid);
49+
item.Name = name;
50+
item.ClothingBase = clothingBase;
51+
item.PaletteTemplate = palTemp;
52+
item.Shade = shade;
53+
54+
Loot.Add(wcid, item);
55+
}
56+
}
57+
58+
public static LootItem Get(uint wcid)
59+
{
60+
Loot.TryGetValue(wcid, out var lootItem);
61+
return lootItem;
62+
}
63+
}
64+
}

ACViewer/Data/LootItem.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace ACViewer.Data
8+
{
9+
public class LootItem : IEquatable<LootItem>
10+
{
11+
public uint WCID { get; set; }
12+
public string Name { get; set; }
13+
public string ClothingBase { get; set; }
14+
public uint PaletteTemplate { get; set; }
15+
public float Shade{ get; set; }
16+
17+
public LootItem() { }
18+
19+
public LootItem(uint wcid)
20+
{
21+
WCID = wcid;
22+
}
23+
24+
public bool Equals(LootItem table)
25+
{
26+
return WCID.Equals(table.WCID);
27+
}
28+
29+
public override int GetHashCode()
30+
{
31+
return WCID.GetHashCode();
32+
}
33+
}
34+
}

ACViewer/Icons/armor.png

2.01 KB
Loading

ACViewer/Icons/plume.png

1.55 KB
Loading

ACViewer/View/About.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
55
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
66
xmlns:local="clr-namespace:ACViewer.View"
7+
ShowInTaskbar="False"
78
mc:Ignorable="d"
89
Title="About" Height="170" Width="280" ResizeMode="NoResize" Icon="../Icons/Question_16x.png" Style="{DynamicResource CustomWindowStyle}">
910
<Grid>

ACViewer/View/About.xaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public partial class About : Window
1515
public About()
1616
{
1717
InitializeComponent();
18+
19+
this.Owner = App.Current.MainWindow;
20+
1821
DataContext = this;
1922
}
2023

ACViewer/View/ArmorList.xaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<Window x:Class="ACViewer.View.ArmorList"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6+
xmlns:local="clr-namespace:ACViewer.View"
7+
mc:Ignorable="d"
8+
WindowStartupLocation="CenterOwner"
9+
ShowInTaskbar="False"
10+
Icon="../Icons/armor.png"
11+
Title="Search Armor..." Height="335" Width="350">
12+
<Grid Margin="0,0,0,0">
13+
<Grid.RowDefinitions>
14+
<RowDefinition Height="90" />
15+
<RowDefinition Height=".1*" />
16+
</Grid.RowDefinitions>
17+
<Canvas Grid.Row="0">
18+
<Label Content="Name:" HorizontalAlignment="Left" VerticalAlignment="Top" RenderTransformOrigin="0.5,1.173" Margin="19,10,0,0"/>
19+
<TextBox Name="txtArmor" HorizontalAlignment="Left" Height="24" TextWrapping="Wrap" VerticalAlignment="Top" Width="257" Canvas.Left="63" Canvas.Top="12"/>
20+
<Button Content="Close" HorizontalAlignment="Center" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.884,0.55" IsCancel="True" Canvas.Left="245" Canvas.Top="50"/>
21+
</Canvas>
22+
<DataGrid x:Name="dgArmorResults" Grid.Row="1">
23+
<DataGrid.Resources>
24+
<Style TargetType="{x:Type DataGridCell}">
25+
<EventSetter Event="MouseDoubleClick" Handler="DataGridCell_MouseDoubleClick"/>
26+
</Style>
27+
</DataGrid.Resources>
28+
29+
<DataGrid.Columns>
30+
<DataGridTextColumn Header="WCID" Binding="{Binding Path=WCID}" IsReadOnly="True" Width="60"/>
31+
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" IsReadOnly="True" Width="1*"></DataGridTextColumn>
32+
</DataGrid.Columns>
33+
</DataGrid>
34+
35+
</Grid>
36+
</Window>

ACViewer/View/ArmorList.xaml.cs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Globalization;
4+
using System.Linq;
5+
using System.Windows;
6+
using System.Windows.Controls;
7+
using System.Windows.Input;
8+
using System.Windows.Media;
9+
10+
using ACViewer.Data;
11+
using ACE.DatLoader;
12+
13+
namespace ACViewer.View
14+
{
15+
/// <summary>
16+
/// Interaction logic for ArmorList.xaml
17+
/// </summary>
18+
public partial class ArmorList : Window
19+
{
20+
public ArmorList()
21+
{
22+
InitializeComponent();
23+
24+
this.Owner = App.Current.MainWindow;
25+
26+
txtArmor.TextChanged += new TextChangedEventHandler(txtArmor_TextChanged);
27+
txtArmor.Focus();
28+
}
29+
30+
private void txtArmor_TextChanged(object sender, TextChangedEventArgs e)
31+
{
32+
SearchArmor(txtArmor.Text.Trim());
33+
}
34+
35+
private void SearchArmor(string criteria)
36+
{
37+
if (criteria != "")
38+
{
39+
dgArmorResults.Items.Clear();
40+
41+
criteria = criteria.ToLower();
42+
var results = LootArmorList.Loot.Where(x => x.Value.Name.ToLower().Contains(criteria)).OrderBy(x => x.Key);
43+
foreach (var s in results)
44+
{
45+
dgArmorResults.Items.Add(s.Value);
46+
}
47+
}
48+
}
49+
50+
// Get the ClothingBase of the item and load it in the window
51+
// - This should be so much easier, Optim hates WPF
52+
// Ref https://wpfadventures.wordpress.com/2008/12/02/wpf-datagrid-detecting-clicked-cell-and-row/
53+
private void DataGridCell_MouseDoubleClick(object sender, MouseButtonEventArgs e)
54+
{
55+
if (DatManager.PortalDat == null)
56+
{
57+
MessageBox.Show($"Please load the DATs before trying to view item.");
58+
return;
59+
}
60+
61+
DependencyObject dep = (DependencyObject)e.OriginalSource;
62+
63+
// iteratively traverse the visual tree
64+
while ((dep != null) &&
65+
!(dep is DataGridRow))
66+
{
67+
dep = VisualTreeHelper.GetParent(dep);
68+
}
69+
70+
if (dep == null)
71+
return;
72+
73+
DataGridRow row = dep as DataGridRow;
74+
// find the object that is related to this row
75+
object data = row.Item;
76+
77+
// extract the property value
78+
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(data);
79+
PropertyDescriptor cbProperty = properties["ClothingBase"];
80+
string clothingBaseString = cbProperty.GetValue(data).ToString();
81+
82+
PropertyDescriptor wcidProperty = properties["WCID"];
83+
uint wcid = Convert.ToUInt32(wcidProperty.GetValue(data));
84+
var lootItem = LootArmorList.Get(wcid);
85+
86+
if (!uint.TryParse(lootItem.ClothingBase, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var clothingBase))
87+
{
88+
// input invalid -- throw error?
89+
MessageBox.Show($"Invalid DID format: {lootItem.ClothingBase}");
90+
return;
91+
}
92+
93+
94+
uint filetype = 0;
95+
96+
if (DatManager.PortalDat.AllFiles.TryGetValue(clothingBase, out var portalFile))
97+
{
98+
filetype = clothingBase >> 24;
99+
var fileTypeSelect = FileExplorer.FileTypes.FirstOrDefault(i => i.ID == filetype);
100+
if (fileTypeSelect == null)
101+
{
102+
Console.WriteLine($"Unknown filetype {clothingBase:X8} found in Portal Dat");
103+
return;
104+
}
105+
106+
var items = FileExplorer.Instance.FileType.Items;
107+
108+
foreach (var item in items)
109+
{
110+
if (item is Entity.FileType entityFileType && entityFileType.ID == filetype)
111+
{
112+
FileExplorer.Instance.FileType.SelectedItem = item;
113+
var didStr = clothingBase.ToString("X8");
114+
foreach (var file in FileExplorer.Instance.Files.Items)
115+
{
116+
if (file.ToString().Equals(didStr))
117+
{
118+
FileExplorer.Instance.Files.SelectedItem = file;
119+
FileExplorer.Instance.Files.ScrollIntoView(file);
120+
121+
var clothing = DatManager.PortalDat.ReadFromDat<ACE.DatLoader.FileTypes.ClothingTable>(clothingBase);
122+
ClothingTableList.Instance.OnClickClothingBase(clothing, clothingBase, lootItem.PaletteTemplate, lootItem.Shade);
123+
this.Close();
124+
}
125+
}
126+
break;
127+
}
128+
129+
}
130+
}
131+
}
132+
133+
}
134+
}

0 commit comments

Comments
 (0)