Skip to content

Commit

Permalink
- fixed the "Close" button in the progress indicating window.
Browse files Browse the repository at this point in the history
- fixed an issue causing exceptions during save changes.
- minor ui improvement.
  • Loading branch information
AnthonyZJiang committed May 7, 2018
1 parent 4191868 commit 1491ef0
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 93 deletions.
8 changes: 3 additions & 5 deletions D-OS Save Editor/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,9 @@
<Grid>
<Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition Width="Auto"/></Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="10,0">
<TextBlock x:Name="UpdateTextBox" Text="" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0"/>
<TextBlock VerticalAlignment="Center" Visibility="Collapsed"><Hyperlink Tag="update" Click="Hyperlink_OnRequestNavigate">Update Now</Hyperlink></TextBlock>
<TextBlock VerticalAlignment="Center" Text=" or " Visibility="Collapsed"/>
<TextBlock VerticalAlignment="Center"><Hyperlink Tag="site" Click="Hyperlink_OnRequestNavigate">Go to the download site</Hyperlink></TextBlock>
<TextBlock VerticalAlignment="Center" Text="."/>
<TextBlock x:Name="UpdateTextBox" Text="" MaxWidth="484" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0" TextTrimming="CharacterEllipsis"/>
<TextBlock VerticalAlignment="Center"><Hyperlink Tag="site" Click="Hyperlink_OnRequestNavigate">Update now</Hyperlink></TextBlock>
<TextBlock VerticalAlignment="Center" Text="."/>
</StackPanel>
<Button Grid.Column="1" x:Name="DismissButton" Style="{StaticResource DismissButtonStyle}" Margin="10,5,10,5" HorizontalAlignment="Right" Click="DismissButton_OnClick">
</Button>
Expand Down
2 changes: 1 addition & 1 deletion D-OS Save Editor/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public partial class MainWindow
private readonly string _defaultProfileDir = $"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}{DirectorySeparatorChar}Larian Studios{DirectorySeparatorChar}Divinity Original Sin Enhanced Edition{DirectorySeparatorChar}PlayerProfiles";
private enum BackupStatus { None, Current, Old, NoChecksum, NoImage }

public static string Version { get; } = "v1.5.2";
public static string Version { get; } = "v1.5.3";
private string _updateLink;

public MainWindow()
Expand Down
2 changes: 1 addition & 1 deletion D-OS Save Editor/ProgressIndicator.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
<Grid Margin="20">
<Grid.RowDefinitions><RowDefinition/><RowDefinition Height="Auto"/></Grid.RowDefinitions>
<TextBlock Text="{Binding ProgressText}" HorizontalAlignment="Center"/>
<Button Grid.Row="1" IsCancel="True" Width="60" Content="{Binding CancelButtonText}" IsEnabled="{Binding CanCancel}"/>
<Button Grid.Row="1" IsCancel="True" Width="60" Content="{Binding CancelButtonText}" IsEnabled="{Binding CanCancel}" Click="CloseButton_OnClick"/>
</Grid>
</Window>
6 changes: 6 additions & 0 deletions D-OS Save Editor/ProgressIndicator.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace D_OS_Save_Editor
{
Expand Down Expand Up @@ -63,5 +64,10 @@ public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

private void CloseButton_OnClick(object sender, RoutedEventArgs e)
{
Close();
}
}
}
4 changes: 2 additions & 2 deletions D-OS Save Editor/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.5.2.0")]
[assembly: AssemblyFileVersion("1.5.2.0")]
[assembly: AssemblyVersion("1.5.3.0")]
[assembly: AssemblyFileVersion("1.5.3.0")]
13 changes: 12 additions & 1 deletion D-OS Save Editor/SE/InventoryTab.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
Expand Down Expand Up @@ -314,7 +315,17 @@ private void ApplyChangesButton_OnClick(object sender, RoutedEventArgs e)
((ListBoxItem) ItemsListBox.Items[ItemsListBox.SelectedIndex]).Foreground =
_itemRarityColor[(int) item.ItemRarity];

MessageBox.Show("Changes have been applied.");
var tooltip = new ToolTip { Content = "Changes have been applied!" };
((Button) sender).ToolTip = tooltip;
tooltip.Opened += async delegate (object o, RoutedEventArgs args)
{
var s = o as ToolTip;
await Task.Delay(1000);
s.IsOpen = false;
await Task.Delay(1000);
((Button)sender).ClearValue(ToolTipProperty);
};
tooltip.IsOpen = true;
}
catch (XmlValidationException ex)
{
Expand Down
2 changes: 1 addition & 1 deletion D-OS Save Editor/SE/SaveEditor.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@

<StackPanel Grid.Row="1" Orientation="Horizontal">
<ComboBox x:Name="PlayerSelectionComboBox" HorizontalAlignment="Left" Margin="20,20,0,0" VerticalAlignment="Top" Width="120" Height="21.24" SelectionChanged="PlayerSelectionComboBox_OnSelectionChanged"/>
<Button x:Name="SavePlayer" Content="Apply" Width="60" Margin="20,20,0,0" Click="SavePlayer_OnClick"/>
<Button x:Name="SavePlayer" Content="Apply" Width="60" Margin="20,20,0,0" Click="SavePlayer_OnClick" ToolTip="Apply changes made to the selected charactor"/>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Orientation="Horizontal">
<Button x:Name="ResetButton" Content="Reset" VerticalAlignment="Center" Padding="10,2" Margin ="10,20,40,0" Width="60" Click="ResetButton_OnClick"/>
Expand Down
27 changes: 27 additions & 0 deletions D-OS Save Editor/savegame/Item.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;

namespace D_OS_Save_Editor
{
Expand Down Expand Up @@ -488,6 +490,8 @@ public class ItemChange
public ChangeType ChangeType { get;}
public int ItemIndex { get; set; }

public ItemChange() { }

public ItemChange(Item item, ChangeType changeType, int itemIndex)
{
Item = item.DeepClone();
Expand All @@ -504,4 +508,27 @@ public class ItemParserException : Exception
base($"Item XML:\n\n{XmlUtilities.BeautifyXml(node)}\n\n", inner)
{ }
}

public class ItemSaveException : Exception
{
public ItemSaveException() { }

public ItemSaveException(Exception inner, ItemChange itemChange) :
base (GetItemChangeString(itemChange), inner)
{
}

public static string GetItemChangeString(ItemChange itemChange)
{
var xmlSerializer = new XmlSerializer(itemChange.GetType());
string s;
using (var sw = new StringWriter())
{
xmlSerializer.Serialize(sw, itemChange);
s = sw.ToString();
}

return s;
}
}
}
174 changes: 92 additions & 82 deletions D-OS Save Editor/savegame/LsxParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,106 +337,116 @@ public static XmlDocument WriteItemChanges(XmlDocument doc, Player player)
// find item data
var inventoryData = doc.DocumentElement.SelectNodes($"//attribute [@id='Parent'] [@value='{player.InventoryId}']");

Parallel.ForEach(player.ItemChanges, ic =>
foreach(var ic in player.ItemChanges)
{
if (ic.Value.ChangeType == ChangeType.Add)
{
}
else if (ic.Value.ChangeType == ChangeType.Delete)
{
}
else if (ic.Value.ChangeType == ChangeType.Modify)
try
{
var itemNode = inventoryData[ic.Value.ItemIndex].ParentNode;
var allowedChanges = ic.Value.Item.GetAllowedChangeType();
if (allowedChanges.Contains(nameof(ic.Value.Item.Amount)))
itemNode.SelectSingleNode("attribute [@id='Amount']").Attributes[1].Value =
ic.Value.Item.Amount;
if (allowedChanges.Contains(nameof(ic.Value.Item.LockLevel)))
itemNode.SelectSingleNode("attribute [@id='LockLevel']").Attributes[1].Value =
ic.Value.Item.LockLevel;
if (ic.Value.ChangeType == ChangeType.Add)
{

if (allowedChanges.Contains(nameof(ic.Value.Item.Vitality)))
}
else if (ic.Value.ChangeType == ChangeType.Delete)
{
itemNode.SelectSingleNode("attribute [@id='Vitality']").Attributes[1].Value =
ic.Value.Item.Vitality;
itemNode.SelectSingleNode("attribute [@id='MaxVitalityPatchCheck']").Attributes[1].Value =
ic.Value.Item.MaxVitalityPatchCheck;

}
else if (ic.Value.ChangeType == ChangeType.Modify)
{
var itemNode = inventoryData[ic.Value.ItemIndex].ParentNode;

if (allowedChanges.Contains(nameof(ic.Value.Item.ItemRarity)))
itemNode.SelectSingleNode("attribute [@id='ItemType']").Attributes[1].Value =
ic.Value.Item.ItemRarity.ToString();
var allowedChanges = ic.Value.Item.GetAllowedChangeType();
if (allowedChanges.Contains(nameof(ic.Value.Item.Amount)))
itemNode.SelectSingleNode("attribute [@id='Amount']").Attributes[1].Value =
ic.Value.Item.Amount;

// max durability cannot be changed
//var node = itemNode.SelectSingleNode("attribute [@id='MaxDurabilityPatchCheck']");
//if (allowedChanges.Contains(nameof(ic.Value.Item.Stats)) && node!=null)
//{
// node.Attributes[1].Value = ic.Value.Item.MaxDurabilityPatchCheck;
//}
if (allowedChanges.Contains(nameof(ic.Value.Item.LockLevel)))
itemNode.SelectSingleNode("attribute [@id='LockLevel']").Attributes[1].Value =
ic.Value.Item.LockLevel;

// check if has generation
if (allowedChanges.Contains(nameof(ic.Value.Item.Generation)) && ic.Value.Item.Generation != null)
{
var genNode = itemNode.SelectSingleNode("children/node [@id='Generation']");
if (genNode == null)
if (allowedChanges.Contains(nameof(ic.Value.Item.Vitality)))
{
// crate a generation node
genNode = doc.CreateDocumentFragment();
// TODO Level is taken from stats.level
// ItemType is taken from item.ItemType
genNode.InnerXml =
$"<node id=\"Generation\"><attribute id=\"Base\" value=\"{ic.Value.Item.Generation.Base}\" type=\"22\" /><attribute id=\"ItemType\" value=\"{ic.Value.Item.ItemType}\" type=\"22\" /><attribute id=\"Level\" value=\"{ic.Value.Item.Stats.Level}\" type=\"2\" /><attribute id=\"Random\" value=\"{ic.Value.Item.Generation.Random}\" type=\"4\" /><children /></node>";
// insert after max durability node
itemNode.SelectSingleNode("children").AppendChild(genNode);
genNode = itemNode.SelectSingleNode("children/node [@id='Generation']");
itemNode.SelectSingleNode("attribute [@id='Vitality']").Attributes[1].Value =
ic.Value.Item.Vitality;
itemNode.SelectSingleNode("attribute [@id='MaxVitalityPatchCheck']").Attributes[1].Value =
ic.Value.Item.MaxVitalityPatchCheck;
}

var childrenNode = genNode.SelectSingleNode("children");
if (childrenNode == null)
{
childrenNode = doc.CreateElement("children");
genNode.AppendChild(childrenNode);
childrenNode = genNode.SelectSingleNode("children");
}
if (allowedChanges.Contains(nameof(ic.Value.Item.ItemRarity)))
itemNode.SelectSingleNode("attribute [@id='ItemType']").Attributes[1].Value =
ic.Value.Item.ItemRarity.ToString();

// wipe all existing boost
childrenNode.RemoveAll();
// then add each defined boosts
foreach (var boostName in ic.Value.Item.Generation.Boosts)
// max durability cannot be changed
//var node = itemNode.SelectSingleNode("attribute [@id='MaxDurabilityPatchCheck']");
//if (allowedChanges.Contains(nameof(ic.Value.Item.Stats)) && node!=null)
//{
// node.Attributes[1].Value = ic.Value.Item.MaxDurabilityPatchCheck;
//}

// check if has generation
if (allowedChanges.Contains(nameof(ic.Value.Item.Generation)) &&
ic.Value.Item.Generation != null)
{
var boost = doc.CreateDocumentFragment();
boost.InnerXml =
$"<node id=\"Boost\"><attribute id=\"Object\" value=\"{boostName}\" type=\"22\" /></node>";
childrenNode.AppendChild(boost);
var genNode = itemNode.SelectSingleNode("children/node [@id='Generation']");
if (genNode == null)
{
// create a generation node
genNode = doc.CreateDocumentFragment();
// TODO Level is taken from stats.level
var level = ic.Value.Item.Stats == null ? "1" : ic.Value.Item.Stats.Level;
// ItemType is taken from item.ItemType
genNode.InnerXml =
$"<node id=\"Generation\"><attribute id=\"Base\" value=\"{ic.Value.Item.Generation.Base}\" type=\"22\" /><attribute id=\"ItemType\" value=\"{ic.Value.Item.ItemType}\" type=\"22\" /><attribute id=\"Level\" value=\"{level}\" type=\"2\" /><attribute id=\"Random\" value=\"{ic.Value.Item.Generation.Random}\" type=\"4\" /><children /></node>";
// insert after max durability node
itemNode.SelectSingleNode("children").AppendChild(genNode);
genNode = itemNode.SelectSingleNode("children/node [@id='Generation']");
}

var childrenNode = genNode.SelectSingleNode("children");
if (childrenNode == null)
{
childrenNode = doc.CreateElement("children");
genNode.AppendChild(childrenNode);
childrenNode = genNode.SelectSingleNode("children");
}

// wipe all existing boost
childrenNode.RemoveAll();
// then add each defined boosts
foreach (var boostName in ic.Value.Item.Generation.Boosts)
{
var boost = doc.CreateDocumentFragment();
boost.InnerXml =
$"<node id=\"Boost\"><attribute id=\"Object\" value=\"{boostName}\" type=\"22\" /></node>";
childrenNode.AppendChild(boost);
}

itemNode.SelectSingleNode("attribute [@id='IsGenerated']").Attributes[1].Value = "True";
}

itemNode.SelectSingleNode("attribute [@id='IsGenerated']").Attributes[1].Value = "True";
// check if has stats
var statsNode = itemNode.SelectSingleNode("children/node [@id='Stats']");
if (!allowedChanges.Contains(nameof(ic.Value.Item.Stats)) || statsNode == null ||
ic.Value.Item.Stats == null)
continue;

statsNode.SelectSingleNode("attribute [@id='Durability']").Attributes[1].Value =
ic.Value.Item.Stats.Durability;
statsNode.SelectSingleNode("attribute [@id='DurabilityCounter']").Attributes[1].Value =
ic.Value.Item.Stats.DurabilityCounter;
statsNode.SelectSingleNode("attribute [@id='RepairDurabilityPenalty']").Attributes[1].Value =
ic.Value.Item.Stats.RepairDurabilityPenalty;
statsNode.SelectSingleNode("attribute [@id='Level']").Attributes[1].Value =
ic.Value.Item.Stats.Level;
statsNode.SelectSingleNode("attribute [@id='ItemType']").Attributes[1].Value =
ic.Value.Item.ItemType; // ItemType is taken from item.ItemType
statsNode.SelectSingleNode("attribute [@id='IsIdentified']").Attributes[1].Value = "1";
}

// check if has stats
var statsNode = itemNode.SelectSingleNode("children/node [@id='Stats']");
if (!allowedChanges.Contains(nameof(ic.Value.Item.Stats)) || statsNode == null ||
ic.Value.Item.Stats == null)
return;
statsNode.SelectSingleNode("attribute [@id='Durability']").Attributes[1].Value =
ic.Value.Item.Stats.Durability;
statsNode.SelectSingleNode("attribute [@id='DurabilityCounter']").Attributes[1].Value =
ic.Value.Item.Stats.DurabilityCounter;
statsNode.SelectSingleNode("attribute [@id='RepairDurabilityPenalty']").Attributes[1].Value =
ic.Value.Item.Stats.RepairDurabilityPenalty;
statsNode.SelectSingleNode("attribute [@id='Level']").Attributes[1].Value =
ic.Value.Item.Stats.Level;
statsNode.SelectSingleNode("attribute [@id='ItemType']").Attributes[1].Value =
ic.Value.Item.ItemType; // ItemType is taken from item.ItemType
statsNode.SelectSingleNode("attribute [@id='IsIdentified']").Attributes[1].Value = "1";
}
});
catch (Exception ex)
{
throw new ItemSaveException(ex, ic.Value);
}
}

return doc;
}
Expand Down

0 comments on commit 1491ef0

Please sign in to comment.