Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
270f632
Update target framework to .NET 6
jensbrak Feb 19, 2022
5151c19
Load Shared Item Data at runtime from CSV file
jensbrak Feb 19, 2022
21132bb
Updated Shared Item Database with (some) missing items
jensbrak Feb 19, 2022
87a0685
Fix of repair item issue
jensbrak Feb 21, 2022
dca62c6
Merge branch 'bugfix/repair-dont-work'
jensbrak Feb 24, 2022
92304a6
New items for the Cult of the Wolf update
jensbrak Mar 3, 2022
890b3b7
Merge branch 'Features/MinorUpdates'
jensbrak Mar 3, 2022
be16b02
Forgot one item
jensbrak Mar 3, 2022
8329bcc
Merge branch 'Features/MinorUpdates'
jensbrak Mar 3, 2022
18cbeaa
Missed more items...
jensbrak Mar 3, 2022
7325a3c
Merge branch 'Features/MinorUpdates'
jensbrak Mar 3, 2022
a9f4491
Corrected data for some items
jensbrak Mar 3, 2022
21ab79e
Merge branch 'Features/MinorUpdates'
jensbrak Mar 3, 2022
021ba6f
Merge branch 'master' of https://github.com/jensbrak/Loki
jensbrak Dec 21, 2022
70e7ed2
Decouple SharedItemData DB from code
jensbrak Dec 22, 2022
1be8674
Revert "Decouple SharedItemData DB from code"
jensbrak Dec 22, 2022
4432a9a
Decouple SharedItemData from code
jensbrak Dec 22, 2022
daf692f
Update Item.cs
jensbrak Dec 22, 2022
5d13c54
Mistlands: added new item categegories + buggfix
jensbrak Dec 22, 2022
9cd4c12
Mistlands: latest prefab added as SharedItemData
jensbrak Dec 22, 2022
854b1dc
Mistlands: new beards and use of SharedItemData
jensbrak Dec 22, 2022
ad85c14
Mistlands: new hairs and use of SharedItemData
jensbrak Dec 22, 2022
03bb5f7
Update SharedItemData.csv
jensbrak Dec 22, 2022
d852ded
Fixed: crossbow skill missing
jensbrak Jan 3, 2023
6467331
Merge branch 'Features/MistlandUpdate' into Releases/Phivoc-Mistlands
jensbrak Jan 4, 2023
f41a899
Merge branch 'master' of https://github.com/jensbrak/Loki
jensbrak Jan 5, 2023
3601202
Merge branch 'master' into Releases/Phivoc-Mistlands
jensbrak Jan 5, 2023
b719844
Merge conflict and revert upstream character path change
jensbrak Jan 5, 2023
9b02f6d
support moving items in inventory
lazou Jan 22, 2023
7035757
removed line
lazou Jan 22, 2023
99a01f3
fixed not swapping items
lazou Jan 23, 2023
4214c49
formatting
lazou Jan 23, 2023
c9a89c7
fixed issue with TextBox & empty slots
lazou Jan 24, 2023
19be59a
Update SharedItemData.csv
jensbrak Jan 25, 2023
660b19b
Merge branch 'Features/MistlandUpdate' into Releases/Phivoc-Mistlands
jensbrak Jan 25, 2023
6b7e28c
Merge branch 'master' into feat/moving-inventory
lazou Jan 26, 2023
a351a39
Hildir update
jensbrak Oct 10, 2023
a243a36
Support for new stats + some QoL features
jensbrak Oct 25, 2023
35a4097
Profile data added + localisation updates
jensbrak Oct 27, 2023
25d842a
Minor UI tweaks + Updated readme.md
jensbrak Oct 27, 2023
b2b86bc
Typo
jensbrak Oct 27, 2023
78bba66
Misplaced labels
jensbrak Nov 2, 2023
5d4005c
Fixed: missing translation of fishing skill (introducted in Loki with…
jensbrak Nov 10, 2023
428cc80
Support for Ashlands (0.218.15)
jensbrak May 15, 2024
cfb85ec
Support for The Bog Witch (0.219.13/14)
jensbrak Nov 1, 2024
247e50c
Support for Call For Arms (0.221.4)
jensbrak Sep 10, 2025
6180223
Merge branch 'feat/moving-inventory' into fix/update
lazou Sep 14, 2025
108869c
changed readme
lazou Sep 16, 2025
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,5 @@ ASALocalRun/
.localhistory/

# BeatPulse healthcheck temp database
healthchecksdb
healthchecksdb
Loki/SharedItemData.old1.csv
21 changes: 7 additions & 14 deletions Loki/Beard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,13 @@ namespace Loki
{
public readonly struct Beard
{
private static readonly Beard[] SensibleBeards =
{
new Beard(Loki.Properties.Resources.B_No_beard, "BeardNone"),
new Beard(Loki.Properties.Resources.B_Braided_2, "Beard5"),
new Beard(Loki.Properties.Resources.B_Braided_2, "Beard6"),
new Beard(Loki.Properties.Resources.B_Braided_3, "Beard9"),
new Beard(Loki.Properties.Resources.B_Braided_4, "Beard10"),
new Beard(Loki.Properties.Resources.B_Long_1, "Beard1"),
new Beard(Loki.Properties.Resources.B_Long_2, "Beard2"),
new Beard(Loki.Properties.Resources.B_Short_1, "Beard3"),
new Beard(Loki.Properties.Resources.B_Short_2, "Beard4"),
new Beard(Loki.Properties.Resources.B_Short_3, "Beard7"),
new Beard(Loki.Properties.Resources.B_Thick_1, "Beard8"),
};
private static readonly IEnumerable<Beard> SensibleBeards =
ItemDb.AllItems
.Where(i =>
i.ItemType == ItemType.Customization
&& i.ItemName.ToLower().Contains("beard"))
.Select(i =>
new Beard(i.DisplayName, i.ItemName));

private static readonly IEnumerable<Beard> SillyBeards =
ItemDb.AllItems.Where(i => i.ItemType == ItemType.Trophy)
Expand Down
2 changes: 1 addition & 1 deletion Loki/Biome.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ public enum Biome
DeepNorth = 64,
Ocean = 256,
Mistlands = 512,
BiomesMax = 513,
All = 895,
}
}
37 changes: 37 additions & 0 deletions Loki/BoolToLocalizedTextConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;

namespace Loki
{
public class BoolToLocalizedTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return null;
}

if (value is bool boolValue)
{
var localizedText = boolValue
? Loki.Properties.Resources.BoolTrueText
: Loki.Properties.Resources.BoolFalseText;
return localizedText ?? value.ToString();
}

return null;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
17 changes: 14 additions & 3 deletions Loki/CharacterFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,20 @@ public string FilePath

public static CharacterFile[] LoadCharacterFiles()
{
string localLowPath = Shell32.GetKnownFolderPath(Shell32.LocalLowId);
string charactersPath = Path.Join(localLowPath, @"IronGate\Valheim\characters");
return Directory.EnumerateFiles(charactersPath, "*.fch").Select(FromPath).ToArray();

// Explicit load of a character file
if (!string.IsNullOrEmpty(MainWindow.explicitlyLoadThisFile))
{
// File to open given by command line arg (ie "open with -> Loki")
return new CharacterFile[] { FromPath(MainWindow.explicitlyLoadThisFile) };
}
else
{
// Standard behaviour: open all character files in Valheim local save directory
string localLowPath = Shell32.GetKnownFolderPath(Shell32.LocalLowId);
string charactersPath = Path.Join(localLowPath, @"IronGate\Valheim\characters_local");
return Directory.EnumerateFiles(charactersPath, "*.fch").Select(FromPath).ToArray();
}
}

public static CharacterFile FromPath(string characterFilePath)
Expand Down
9 changes: 9 additions & 0 deletions Loki/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,14 @@ public static class Commands

public static RoutedUICommand RestoreCharacter =
new RoutedUICommand("Restore", nameof(RestoreCharacter), typeof(Commands));

public static RoutedUICommand ModifyAllSkills =
new RoutedUICommand("ModifySkills", nameof(ModifyAllSkills), typeof(Commands));

public static RoutedUICommand RepairInventoryItems =
new RoutedUICommand("RepairItems", nameof(RepairInventoryItems), typeof(Commands));

public static RoutedUICommand FillInventoryStacks =
new RoutedUICommand("FillStacks", nameof(RepairInventoryItems), typeof(Commands));
}
}
42 changes: 42 additions & 0 deletions Loki/EnumConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows;

namespace Loki
{
public class EnumConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return null;
}

if (targetType.IsEnum)
{
// int -> Enum
return Enum.ToObject(targetType, value);
}

if (value.GetType().IsEnum)
{
// Enum -> int
return System.Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()));
}

return null;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// Same conversion for both directions
return Convert(value, targetType, parameter, culture);
}
}
}
26 changes: 7 additions & 19 deletions Loki/Hair.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,13 @@ namespace Loki
{
public readonly struct Hair
{
private static readonly Hair[] SensibleHairs =
{
new Hair(Loki.Properties.Resources.No_hair, "HairNone"),
new Hair(Loki.Properties.Resources.Braided_1, "Hair3"),
new Hair(Loki.Properties.Resources.Braided_2, "Hair11"),
new Hair(Loki.Properties.Resources.Braided_3, "Hair12"),
new Hair(Loki.Properties.Resources.Braided_4, "Hair6"),
new Hair(Loki.Properties.Resources.Long_1, "Hair1"),
new Hair(Loki.Properties.Resources.Ponytail_1, "Hair2"),
new Hair(Loki.Properties.Resources.Ponytail_2, "Hair4"),
new Hair(Loki.Properties.Resources.Ponytail_3, "Hair7"),
new Hair(Loki.Properties.Resources.Ponytail_4, "Hair5"),
new Hair(Loki.Properties.Resources.Short_1, "Hair8"),
new Hair(Loki.Properties.Resources.Short_2, "Hair13"),
new Hair(Loki.Properties.Resources.Side_Swept_1, "Hair9"),
new Hair(Loki.Properties.Resources.Side_Swept_2, "Hair10"),
new Hair(Loki.Properties.Resources.Side_Swept_3, "Hair14"),
new Hair(Loki.Properties.Resources.Blob_hair, "TrophyBlob"),
};
private static readonly IEnumerable<Hair> SensibleHairs =
ItemDb.AllItems
.Where(i =>
i.ItemType == ItemType.Customization
&& i.ItemName.ToLower().Contains("hair"))
.Select(i =>
new Hair(i.DisplayName, i.ItemName));

private static readonly IEnumerable<Hair> SillyHairs =
ItemDb.AllItems.Where(i => i.ItemType == ItemType.Trophy)
Expand Down
6 changes: 5 additions & 1 deletion Loki/InventoryListItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,17 @@ private static InventoryListItem CreateListItem(SharedItemData itemData)
ItemType.Legs => Loki.Properties.Resources.Legs,
ItemType.Hands => Loki.Properties.Resources.Hands,
ItemType.Trophy => Loki.Properties.Resources.Trophy,
ItemType.TwoHandedWeapon => Loki.Properties.Resources.Trophy,
ItemType.TwoHandedWeapon => Loki.Properties.Resources.Two_Handed_Weapon,
ItemType.Torch => Loki.Properties.Resources.Torch,
ItemType.Misc => Loki.Properties.Resources.Miscellaneous,
ItemType.Shoulder => Loki.Properties.Resources.Shoulder,
ItemType.Utility => Loki.Properties.Resources.Utility,
ItemType.Tool => Loki.Properties.Resources.Tool,
ItemType.AttachAtgeir => Loki.Properties.Resources.Attach_Atgeir,
ItemType.Fish => Loki.Properties.Resources.Fish,
ItemType.TwoHandedWeaponLeft => Loki.Properties.Resources.Two_Handed_Weapon_Left,
ItemType.AmmoNonEquipable => Loki.Properties.Resources.Ammo_Non_Equipable,
ItemType.Trinket => Loki.Properties.Resources.Trinket,
_ => Loki.Properties.Resources.Unknown,
};
return new InventoryListItem(displayName, category, itemData);
Expand Down
2 changes: 1 addition & 1 deletion Loki/InventorySlotEditor.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
</UserControl.Resources>


<Border CornerRadius="4" x:Name="LayoutRoot" AllowDrop="True" Drop="BorderDrop">
<Border CornerRadius="4" x:Name="LayoutRoot" AllowDrop="True" Drop="BorderDrop" MouseMove="BorderMouseMove">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="DarkGray"/>
Expand Down
35 changes: 32 additions & 3 deletions Loki/InventorySlotEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,48 @@ private void BorderDrop(object sender, DragEventArgs e)
{
if (e.Data.GetData(typeof(SharedItemData)) is SharedItemData itemData)
{
// drop from item picker
if (this.DataContext is InventorySlot slot)
{
var customData = new List<(string, string)>();
slot.Item = new Item(itemData.ItemName, itemData.MaxStack, (float)itemData.MaxDurability, slot.Position,
false, 1, 0, MainWindow.selectedPlayerProfile.PlayerId, MainWindow.selectedPlayerProfile.PlayerName, customData);
false, 1, 0, MainWindow.selectedPlayerProfile.PlayerId, MainWindow.selectedPlayerProfile.PlayerName, customData, 0, false);
}
}
else if (e.Data.GetData(typeof(InventorySlot)) is InventorySlot sourceSlot)
{
// drop from inventory slot
if (this.DataContext is InventorySlot slot && sourceSlot != slot)
{
var targetSlotItem = slot.Item;
slot.Item = sourceSlot.Item;
sourceSlot.Item = targetSlotItem;
}
}
}

private void BorderMouseMove(object sender, MouseEventArgs e)
{
if (e.Source is TextBox)
{
// TextBox has its own Drag&Drop functionality and would raise an InvalidOperationException
return;
}

if (sender is FrameworkElement element && e.LeftButton == MouseButtonState.Pressed)
{
if (element.DataContext is InventorySlot slot && slot.Item != null)
{
var data = new DataObject(slot);
DragDrop.DoDragDrop(element, data, DragDropEffects.Move);
}
}
}

private void StackEditPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (sender is TextBox {IsKeyboardFocusWithin: false} txtStack)
{
if (sender is TextBox { IsKeyboardFocusWithin: false } txtStack)
{
txtStack.SelectAll();
txtStack.Focus();
e.Handled = true;
Expand Down
9 changes: 6 additions & 3 deletions Loki/Item.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ public string CrafterName {

public bool HasCrafterTag => CrafterId != 0;

public double MaxDurability => SharedData.MaxDurability + Math.Max(0, Quality - 1) * SharedData.DurabilityPerLevel;
public double MaxDurability => SharedData == null ? 0d : SharedData.MaxDurability + Math.Max(0, Quality - 1) * SharedData.DurabilityPerLevel;


public Item(string name, int stack, float durability, Vector2i pos, bool equiped, int quality, int variant, long crafterId, string crafterName, List<(string, string)> itemData)
public Item(string name, int stack, float durability, Vector2i pos, bool equiped, int quality, int variant, long crafterId, string crafterName, List<(string, string)> itemData, int worldLevel, bool pickedUp)
{
Name = name;
Stack = stack;
Expand All @@ -99,12 +99,15 @@ public Item(string name, int stack, float durability, Vector2i pos, bool equiped
}

ItemData = itemData;

WorldLevel = worldLevel;
PickedUp = pickedUp;
}

[CanBeNull] // Can be null if the item is unrecognised (very new update not accounted for etc.)
public SharedItemData SharedData { get; }
public List<(string, string)> ItemData { get; }
public int WorldLevel { get; }
public bool PickedUp { get; }

public bool HasQualityLevels => SharedData?.MaxQuality > 1;

Expand Down
7 changes: 7 additions & 0 deletions Loki/Loki.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="DotNetProjects.Extended.Wpf.Toolkit" Version="5.0.103" />
<PackageReference Include="GitVersion.MsBuild" Version="5.11.1">
<PrivateAssets>all</PrivateAssets>
Expand Down Expand Up @@ -73,4 +74,10 @@
</EmbeddedResource>
</ItemGroup>

<ItemGroup>
<None Update="SharedItemData.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Loading