mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-09-19 14:55:24 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b61c99dd1c | ||
|
|
1ccb0d5334 | ||
|
|
7fa01353dd | ||
|
|
4f849d880b | ||
|
|
4b60c96aad |
@@ -28,14 +28,14 @@ public class BuildTemplateManagerTests
|
||||
build.Primary.Should().Be(Profession.Assassin);
|
||||
build.Secondary.Should().Be(Profession.None);
|
||||
build.Attributes.Count.Should().Be(4);
|
||||
build.Attributes[0].Attribute.Should().Be(Attribute.DaggerMastery);
|
||||
build.Attributes[1].Attribute.Should().Be(Attribute.DaggerMastery);
|
||||
build.Attributes[1].Points.Should().Be(11);
|
||||
build.Attributes[2].Attribute.Should().Be(Attribute.DeadlyArts);
|
||||
build.Attributes[2].Points.Should().Be(1);
|
||||
build.Attributes[3].Attribute.Should().Be(Attribute.ShadowArts);
|
||||
build.Attributes[3].Points.Should().Be(5);
|
||||
build.Attributes[0].Attribute.Should().Be(Attribute.CriticalStrikes);
|
||||
build.Attributes[0].Points.Should().Be(11);
|
||||
build.Attributes[1].Attribute.Should().Be(Attribute.DeadlyArts);
|
||||
build.Attributes[1].Points.Should().Be(1);
|
||||
build.Attributes[2].Attribute.Should().Be(Attribute.ShadowArts);
|
||||
build.Attributes[2].Points.Should().Be(5);
|
||||
build.Attributes[3].Attribute.Should().Be(Attribute.CriticalStrikes);
|
||||
build.Attributes[3].Points.Should().Be(11);
|
||||
build.Skills.Count.Should().Be(8);
|
||||
build.Skills[0].Should().Be(Skill.UnsuspectingStrike);
|
||||
build.Skills[1].Should().Be(Skill.WildStrike);
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
namespace Daybreak.Configuration.FocusView;
|
||||
|
||||
public enum EnergyDisplay
|
||||
public enum ExperienceDisplay
|
||||
{
|
||||
TotalCurretAndTotalMax,
|
||||
CurrentLevelCurrentAndCurrentLevelMax,
|
||||
RemainingUntilNextLevel
|
||||
RemainingUntilNextLevel,
|
||||
Percentage
|
||||
}
|
||||
@@ -4,8 +4,8 @@ namespace Daybreak.Configuration.FocusView;
|
||||
|
||||
public sealed class FocusViewOptions
|
||||
{
|
||||
[JsonProperty("EnergyDisplay")]
|
||||
public EnergyDisplay EnergyDisplay { get; set; }
|
||||
[JsonProperty("ExperienceDisplay")]
|
||||
public ExperienceDisplay ExperienceDisplay { get; set; }
|
||||
[JsonProperty("KurzickPointsDisplay")]
|
||||
public PointsDisplay KurzickPointsDisplay { get; set; }
|
||||
[JsonProperty("LuxonPointsDisplay")]
|
||||
@@ -14,6 +14,12 @@ public sealed class FocusViewOptions
|
||||
public PointsDisplay BalthazarPointsDisplay { get; set; }
|
||||
[JsonProperty("ImperialPointsDisplay")]
|
||||
public PointsDisplay ImperialPointsDisplay { get; set; }
|
||||
[JsonProperty("VanquishingDisplay")]
|
||||
public PointsDisplay VanquishingDisplay { get; set; }
|
||||
[JsonProperty("HealthDisplay")]
|
||||
public PointsDisplay HealthDisplay { get; set; }
|
||||
[JsonProperty("EnergyDisplay")]
|
||||
public PointsDisplay EnergyDisplay { get; set; }
|
||||
[JsonProperty("BrowserUrl")]
|
||||
public string? BrowserUrl { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
public enum PointsDisplay
|
||||
{
|
||||
CurrentAndMax,
|
||||
Remaining
|
||||
Remaining,
|
||||
Percentage
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ public static class ProjectConfiguration
|
||||
services.AddScoped<IGuildwarsMemoryReader, GuildwarsMemoryReader>();
|
||||
services.AddScoped<IMemoryScanner, MemoryScanner>();
|
||||
services.AddScoped<IExperienceCalculator, ExperienceCalculator>();
|
||||
services.AddScoped<IAttributePointCalculator, AttributePointCalculator>();
|
||||
}
|
||||
|
||||
public static void RegisterViews(IViewProducer viewProducer)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Visibility="Visible" Opacity="0.1" />
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="50" d:DesignWidth="50">
|
||||
<Grid>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
xmlns:behaviors="clr-namespace:Daybreak.Behaviors"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
@@ -20,13 +21,12 @@
|
||||
FontStretch="{Binding ElementName=_this, Path=FontStretch, Mode=OneWay}"
|
||||
FontWeight="{Binding ElementName=_this, Path=FontWeight, Mode=OneWay}"
|
||||
FontStyle="{Binding ElementName=_this, Path=FontStyle, Mode=OneWay}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"></TextBlock>
|
||||
VerticalAlignment="{Binding ElementName=_this, Path=TextVerticalAlignment, Mode=OneWay}"
|
||||
HorizontalAlignment="{Binding ElementName=_this, Path=TextHorizontalAlignment, Mode=OneWay}"></TextBlock>
|
||||
<Rectangle Fill="{Binding ElementName=_this, Path=Highlight, Mode=OneWay}"
|
||||
Opacity="{Binding ElementName=_this, Path=HighlightOpacity, Mode=OneWay}"
|
||||
Visibility="{Binding ElementName=_this, Path=HighlightVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></Rectangle>
|
||||
<Rectangle MouseEnter="Rectangle_MouseEnter" MouseLeave="Rectangle_MouseLeave"
|
||||
MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Fill="Transparent"
|
||||
Cursor="Hand"></Rectangle>
|
||||
MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Fill="Transparent"></Rectangle>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -26,6 +26,10 @@ public partial class OpaqueButton : UserControl
|
||||
public double highlightOpacity;
|
||||
[GenerateDependencyProperty]
|
||||
public bool highlightVisible;
|
||||
[GenerateDependencyProperty(InitialValue = VerticalAlignment.Center)]
|
||||
public VerticalAlignment textVerticalAlignment;
|
||||
[GenerateDependencyProperty(InitialValue = HorizontalAlignment.Center)]
|
||||
public HorizontalAlignment textHorizontalAlignment;
|
||||
|
||||
public OpaqueButton()
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
xmlns:behaviors="clr-namespace:Daybreak.Behaviors"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<StackPanel Margin="10">
|
||||
<local:OpaqueButton Text="Load build template" Foreground="White" Background="#F0202020" BackgroundOpacity="0.4"
|
||||
<local:OpaqueButton Text="Load build template" Foreground="White" Background="#F0212121" BackgroundOpacity="0.4"
|
||||
Clicked="LoadBuildTemplateButton_Click" FontSize="16" Height="40" Width="200"></local:OpaqueButton>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
@@ -33,7 +33,7 @@
|
||||
</Grid.RowDefinitions>
|
||||
<wv2:WebView2 x:Name="WebBrowser" Source="{Binding ElementName=_this, Path=Address, Mode=TwoWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"></wv2:WebView2>
|
||||
<Grid Grid.Row="1" Background="#80808080" IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
<Grid Grid.Row="1" Background="#F0212121" IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Visibility="{Binding ElementName=_this, Path=ControlsEnabled, Mode=OneWay, Converter={StaticResource ReverseBooleanToVisibilityConverter}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<UserControl x:Class="Daybreak.Controls.ResourceBar"
|
||||
<UserControl x:Class="Daybreak.Controls.HorizontalResourceBar"
|
||||
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"
|
||||
@@ -13,16 +13,16 @@
|
||||
<Rectangle
|
||||
Fill="{Binding ElementName=_this, Path=BarColor, Mode=OneWay}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Left"
|
||||
HorizontalAlignment="{Binding ElementName=_this, Path=FillAlignment, Mode=OneWay}"
|
||||
Width="{Binding ElementName=_this, Path=MaxResourceValue, Mode=TwoWay}"></Rectangle>
|
||||
<Rectangle
|
||||
Fill="#A0202020"
|
||||
Fill="#F0202020"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"></Rectangle>
|
||||
<Rectangle
|
||||
Fill="{Binding ElementName=_this, Path=BarColor, Mode=OneWay}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Left"
|
||||
HorizontalAlignment="{Binding ElementName=_this, Path=FillAlignment, Mode=OneWay}"
|
||||
Width="{Binding ElementName=_this, Path=CurrentResourceValue, Mode=TwoWay}"></Rectangle>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for ResourceBar.xaml
|
||||
/// </summary>
|
||||
public partial class HorizontalResourceBar : UserControl
|
||||
{
|
||||
[GenerateDependencyProperty]
|
||||
private double currentResourceValue;
|
||||
[GenerateDependencyProperty]
|
||||
private double maxResourceValue;
|
||||
[GenerateDependencyProperty]
|
||||
private Brush barColor;
|
||||
[GenerateDependencyProperty]
|
||||
private string text;
|
||||
[GenerateDependencyProperty(InitialValue = HorizontalAlignment.Left)]
|
||||
private HorizontalAlignment fillAlignment;
|
||||
|
||||
public HorizontalResourceBar()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.MaxResourceValue = 1;
|
||||
this.CurrentResourceValue = 0;
|
||||
this.barColor = Brushes.Transparent;
|
||||
this.text = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="GameCompanionButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:GoldenArrowGlyph Foreground="White"
|
||||
@@ -22,6 +23,7 @@
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="ManageBuildsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:FireballGlyph Foreground="White"
|
||||
@@ -32,6 +34,7 @@
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="AccountSettingsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:AvatarGlyph Foreground="White"
|
||||
@@ -42,6 +45,7 @@
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="GuildwarsSettingsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:FileGlyph Foreground="White"
|
||||
@@ -52,6 +56,7 @@
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="LauncherSettingsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:CogGlyph Foreground="White"
|
||||
@@ -63,6 +68,7 @@
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="ExperimentalSettingsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:ExperimentGlyph Foreground="White"
|
||||
@@ -73,6 +79,7 @@
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="VersionManagementButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:StaticGlyph Foreground="White"
|
||||
@@ -83,6 +90,7 @@
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="LogsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:LogsGlyph Foreground="White"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using System;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -16,7 +18,9 @@ public partial class AttributeTemplate : UserControl
|
||||
{
|
||||
public event EventHandler<AttributeEntry>? HelpClicked;
|
||||
public event EventHandler<AttributeEntry>? AttributeChanged;
|
||||
|
||||
|
||||
private IAttributePointCalculator? attributePointCalculator;
|
||||
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
private bool canAdd;
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
@@ -27,6 +31,23 @@ public partial class AttributeTemplate : UserControl
|
||||
this.InitializeComponent();
|
||||
this.DataContextChanged += this.AttributeTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
public void InitializeAttributeTemplate(
|
||||
int attributePoints,
|
||||
IAttributePointCalculator attributePointCalculator)
|
||||
{
|
||||
this.attributePointCalculator = attributePointCalculator.ThrowIfNull();
|
||||
var remainingPoints = attributePoints;
|
||||
var requiredPointsForNextLevel = this.attributePointCalculator?.GetPointsRequiredToIncreaseRank(this.DataContext.As<AttributeEntry>().Points) ?? 0;
|
||||
if (remainingPoints < requiredPointsForNextLevel)
|
||||
{
|
||||
this.CanAdd = false;
|
||||
}
|
||||
else if (this.DataContext.As<AttributeEntry>().Points < 12)
|
||||
{
|
||||
this.CanAdd = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void AttributeTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
x:Name="_this"
|
||||
Unloaded="BuildTemplate_Unloaded"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="Transparent" MouseLeftButtonDown="Grid_MouseLeftButtonDown">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
@@ -30,20 +33,15 @@
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Primary Profession: " FontSize="16" Foreground="White" Grid.Column="1"></TextBlock>
|
||||
<ListView FontSize="16" Foreground="White" Grid.Column="2" BorderThickness="0"
|
||||
Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Professions, Mode=OneWay}"
|
||||
SelectedItem="{Binding ElementName=_this, Path=PrimaryProfession, Mode=TwoWay}" Height="30"
|
||||
SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
PreviewMouseWheel="ListView_NavigateWithMouseWheel">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name, Mode=OneWay}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<behaviors:ScrollIntoView></behaviors:ScrollIntoView>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ListView>
|
||||
<local:OpaqueButton Grid.Column="2"
|
||||
Text="{Binding ElementName=_this, Path=BuildEntry.Primary.Name, Mode=OneWay}"
|
||||
Foreground="White"
|
||||
Highlight="White"
|
||||
HighlightOpacity="0.4"
|
||||
FontSize="16"
|
||||
TextHorizontalAlignment="Left"
|
||||
Margin="0, 0, 10, 0"
|
||||
Clicked="PrimaryProfessionButton_Clicked"></local:OpaqueButton>
|
||||
<local:HelpButton Grid.Column="0" Foreground="White" Width="20" Height="20" Margin="3"
|
||||
Clicked="HelpButtonPrimary_Clicked" Cursor="Hand"></local:HelpButton>
|
||||
</Grid>
|
||||
@@ -54,29 +52,26 @@
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Secondary Profession: " FontSize="16" Foreground="White" Grid.Column="1"></TextBlock>
|
||||
<ListView FontSize="16" Foreground="White" Grid.Column="2" BorderThickness="0"
|
||||
Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Professions, Mode=OneWay}"
|
||||
SelectedItem="{Binding ElementName=_this, Path=SecondaryProfession, Mode=TwoWay}" Height="30"
|
||||
SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
PreviewMouseWheel="ListView_NavigateWithMouseWheel">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name, Mode=OneWay}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<behaviors:ScrollIntoView></behaviors:ScrollIntoView>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ListView>
|
||||
<local:OpaqueButton Grid.Column="2"
|
||||
Text="{Binding ElementName=_this, Path=BuildEntry.Secondary.Name, Mode=OneWay}"
|
||||
Foreground="White"
|
||||
Highlight="White"
|
||||
HighlightOpacity="0.4"
|
||||
FontSize="16"
|
||||
TextHorizontalAlignment="Left"
|
||||
Margin="0, 0, 10, 0"
|
||||
Clicked="SecondaryProfessionButton_Clicked"></local:OpaqueButton>
|
||||
<local:HelpButton Grid.Column="0" Foreground="White" Width="20" Height="20" Margin="3"
|
||||
Clicked="HelpButtonSecondary_Clicked" Cursor="Hand"></local:HelpButton>
|
||||
</Grid>
|
||||
<Grid Grid.Row="3">
|
||||
<ListBox Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Attributes, Mode=OneWay}"
|
||||
<ListBox Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=BuildEntry.Attributes, Mode=OneWay}"
|
||||
HorizontalContentAlignment="Stretch" BorderThickness="0">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<local:AttributeTemplate HelpClicked="AttributeTemplate_HelpClicked" AttributeChanged="AttributeTemplate_AttributeChanged"></local:AttributeTemplate>
|
||||
<local:AttributeTemplate HelpClicked="AttributeTemplate_HelpClicked"
|
||||
AttributeChanged="AttributeTemplate_AttributeChanged"
|
||||
Loaded="AttributeTemplate_Loaded"></local:AttributeTemplate>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
@@ -98,60 +93,60 @@
|
||||
</Grid.RowDefinitions>
|
||||
<local:SkillTemplate Grid.Column="0" x:Name="SkillTemplate0"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill0, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.FirstSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="1" x:Name="SkillTemplate1"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill1, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.SecondSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="2" x:Name="SkillTemplate2"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill2, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.ThirdSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="3" x:Name="SkillTemplate3"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill3, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.FourthSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="4" x:Name="SkillTemplate4"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill4, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.FifthSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="5" x:Name="SkillTemplate5"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill5, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.SixthSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="6" x:Name="SkillTemplate6"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill6, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.SeventhSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="7" x:Name="SkillTemplate7"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill7, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.EigthSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<TextBlock Grid.Column="0" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill0.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.FirstSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="1" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill1.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.SecondSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="2" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill2.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.ThirdSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="3" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill3.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.FourthSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="4" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill4.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.FifthSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="5" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill5.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.SixthSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="6" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill6.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.SeventhSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="7" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill7.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.EigthSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Grid.RowSpan="6">
|
||||
<local:ChromiumBrowserWrapper x:Name="SkillBrowser" ControlsEnabled="False" Width="0" AddressBarReadonly="True" CanNavigate="True"></local:ChromiumBrowserWrapper>
|
||||
@@ -170,10 +165,11 @@
|
||||
<ListView x:Name="SkillsListView"
|
||||
Grid.Row="1"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Hidden"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Background="Transparent"
|
||||
ScrollViewer.CanContentScroll="False"
|
||||
ItemsSource="{Binding ElementName=_this, Path=AvailableSkills, Mode=OneWay}"
|
||||
MouseDoubleClick="ListView_MouseDoubleClick">
|
||||
MouseDoubleClick="SkillListView_MouseDoubleClick">
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel>
|
||||
@@ -188,5 +184,28 @@
|
||||
</ListView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Grid.RowSpan="6">
|
||||
<ListView x:Name="ProfessionListView"
|
||||
Width="0"
|
||||
HorizontalAlignment="Right"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Background="Transparent"
|
||||
ScrollViewer.CanContentScroll="False"
|
||||
ItemsSource="{Binding ElementName=_this, Path=Professions, Mode=OneWay}"
|
||||
MouseDoubleClick="ProfessionListView_MouseDoubleClick">
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel>
|
||||
</VirtualizingStackPanel>
|
||||
</ItemsPanelTemplate>
|
||||
</ListView.ItemsPanel>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock FontSize="16" Foreground="White" TextWrapping="Wrap" Text="{Binding Name}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
@@ -30,11 +31,13 @@ public partial class BuildTemplate : UserControl
|
||||
private const string InfoNamePlaceholder = "[NAME]";
|
||||
private const string BaseAddress = $"https://wiki.guildwars.com/wiki/{InfoNamePlaceholder}";
|
||||
|
||||
private bool suppressBuildChanged = false;
|
||||
private bool loadedProperties = false;
|
||||
private bool showingSkillList = false;
|
||||
private bool replacingSecondaryProfession;
|
||||
private bool replacingPrimaryProfession;
|
||||
private IIconBrowser? iconBrowser;
|
||||
private BuildEntry? loadedBuild;
|
||||
private IAttributePointCalculator? attributePointCalculator;
|
||||
private SkillTemplate? selectingSkillTemplate;
|
||||
private List<Skill>? skillListCache;
|
||||
private CancellationTokenSource? cancellationTokenSource = new();
|
||||
|
||||
public event EventHandler? BuildChanged;
|
||||
@@ -42,25 +45,10 @@ public partial class BuildTemplate : UserControl
|
||||
[GenerateDependencyProperty]
|
||||
private string skillSearchText = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private Profession primaryProfession = default!;
|
||||
private BuildEntry buildEntry;
|
||||
[GenerateDependencyProperty]
|
||||
private Profession secondaryProfession = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill0 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill1 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill2 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill3 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill4 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill5 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill6 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill7 = default!;
|
||||
private int attributePoints;
|
||||
|
||||
public ObservableCollection<Skill> AvailableSkills { get; } = new ObservableCollection<Skill>();
|
||||
public ObservableCollection<AttributeEntry> Attributes { get; } = new ObservableCollection<AttributeEntry>();
|
||||
public ObservableCollection<Profession> Professions { get; } = new ObservableCollection<Profession>(Profession.Professions);
|
||||
@@ -68,17 +56,19 @@ public partial class BuildTemplate : UserControl
|
||||
public BuildTemplate()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.InitializeProperties();
|
||||
this.buildEntry = new BuildEntry();
|
||||
this.DataContextChanged += this.BuildTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
public async void InitializeTemplate(
|
||||
IAttributePointCalculator attributePointCalculator,
|
||||
IIconCache iconRetriever,
|
||||
IIconBrowser iconBrowser,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
ILogger<ChromiumBrowserWrapper> logger)
|
||||
{
|
||||
this.attributePointCalculator = attributePointCalculator.ThrowIfNull();
|
||||
this.iconBrowser = iconBrowser.ThrowIfNull();
|
||||
await this.SkillBrowser.InitializeDefaultBrowser(liveOptions, buildTemplateManager, logger);
|
||||
this.SkillTemplate0.InitializeSkillTemplate(iconRetriever);
|
||||
@@ -94,200 +84,35 @@ public partial class BuildTemplate : UserControl
|
||||
this.HideInfoBrowser();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (this.loadedProperties is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Property == PrimaryProfessionProperty || e.Property == SecondaryProfessionProperty)
|
||||
{
|
||||
if (e.Property == PrimaryProfessionProperty)
|
||||
{
|
||||
this.loadedBuild!.Build!.Primary = this.PrimaryProfession;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.loadedBuild!.Build!.Secondary = this.SecondaryProfession;
|
||||
}
|
||||
|
||||
this.LoadSkills();
|
||||
this.LoadAttributes();
|
||||
if (this.suppressBuildChanged is false)
|
||||
{
|
||||
this.BuildChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
if (e.Property == Skill0Property ||
|
||||
e.Property == Skill1Property ||
|
||||
e.Property == Skill2Property ||
|
||||
e.Property == Skill3Property ||
|
||||
e.Property == Skill4Property ||
|
||||
e.Property == Skill5Property ||
|
||||
e.Property == Skill6Property ||
|
||||
e.Property == Skill7Property)
|
||||
{
|
||||
if (this.suppressBuildChanged is false)
|
||||
{
|
||||
this.loadedBuild!.Build!.Skills[0] = this.Skill0;
|
||||
this.loadedBuild!.Build!.Skills[1] = this.Skill1;
|
||||
this.loadedBuild!.Build!.Skills[2] = this.Skill2;
|
||||
this.loadedBuild!.Build!.Skills[3] = this.Skill3;
|
||||
this.loadedBuild!.Build!.Skills[4] = this.Skill4;
|
||||
this.loadedBuild!.Build!.Skills[5] = this.Skill5;
|
||||
this.loadedBuild!.Build!.Skills[6] = this.Skill6;
|
||||
this.loadedBuild!.Build!.Skills[7] = this.Skill7;
|
||||
this.BuildChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildTemplate_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
}
|
||||
|
||||
private void InitializeProperties()
|
||||
{
|
||||
this.PrimaryProfession = Profession.None;
|
||||
this.SecondaryProfession = Profession.None;
|
||||
this.Skill0 = Skill.NoSkill;
|
||||
this.Skill1 = Skill.NoSkill;
|
||||
this.Skill2 = Skill.NoSkill;
|
||||
this.Skill3 = Skill.NoSkill;
|
||||
this.Skill4 = Skill.NoSkill;
|
||||
this.Skill5 = Skill.NoSkill;
|
||||
this.Skill6 = Skill.NoSkill;
|
||||
this.Skill7 = Skill.NoSkill;
|
||||
this.loadedProperties = true;
|
||||
}
|
||||
|
||||
private void BuildTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if(e.NewValue is BuildEntry)
|
||||
if(e.NewValue is BuildEntry buildEntry)
|
||||
{
|
||||
this.LoadBuild();
|
||||
this.LoadSkills();
|
||||
this.LoadAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
private void Grid_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
this.HideSkillListView();
|
||||
this.HideInfoBrowser();
|
||||
}
|
||||
|
||||
private void LoadAttributes()
|
||||
{
|
||||
var possibleAttributes = new List<AttributeEntry>();
|
||||
if (this.PrimaryProfession != Profession.None)
|
||||
{
|
||||
possibleAttributes.Add(new AttributeEntry { Attribute = this.PrimaryProfession.PrimaryAttribute });
|
||||
possibleAttributes.AddRange(this.PrimaryProfession.Attributes!.Select(a => new AttributeEntry { Attribute = a }));
|
||||
}
|
||||
|
||||
if (this.SecondaryProfession != Profession.None && this.SecondaryProfession != this.PrimaryProfession)
|
||||
{
|
||||
possibleAttributes.AddRange(this.SecondaryProfession.Attributes!.Select(a => new AttributeEntry { Attribute = a }));
|
||||
}
|
||||
|
||||
this.Attributes.ClearAnd().AddRange(possibleAttributes.Select(entry =>
|
||||
{
|
||||
var maybePresentAttribute = this.loadedBuild!.Build!.Attributes.Where(buildEntry => entry.Attribute == buildEntry.Attribute).FirstOrDefault();
|
||||
if (maybePresentAttribute is null)
|
||||
if (this.BuildEntry is not null)
|
||||
{
|
||||
return entry;
|
||||
this.BuildEntry.PropertyChanged -= this.BuildEntry_Changed;
|
||||
}
|
||||
|
||||
this.BuildEntry = buildEntry;
|
||||
this.BuildEntry.PropertyChanged += this.BuildEntry_Changed;
|
||||
this.AttributePoints = this.attributePointCalculator!.GetRemainingFreePoints(this.BuildEntry.Build!);
|
||||
}
|
||||
}
|
||||
|
||||
entry.Points = maybePresentAttribute.Points;
|
||||
return entry;
|
||||
}));
|
||||
|
||||
this.loadedBuild!.Build!.Attributes = this.Attributes.ToList();
|
||||
private void BuildEntry_Changed(object? sender, PropertyChangedEventArgs propertyChangedEventArgs)
|
||||
{
|
||||
this.LoadSkills();
|
||||
}
|
||||
|
||||
private async void LoadSkills()
|
||||
{
|
||||
if (this.Skill0.Profession != this.PrimaryProfession &&
|
||||
this.Skill0.Profession != this.SecondaryProfession &&
|
||||
this.Skill0.Profession != Profession.None)
|
||||
{
|
||||
this.Skill0 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill1.Profession != this.PrimaryProfession &&
|
||||
this.Skill1.Profession != this.SecondaryProfession &&
|
||||
this.Skill1.Profession != Profession.None)
|
||||
{
|
||||
this.Skill1 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill2.Profession != this.PrimaryProfession &&
|
||||
this.Skill2.Profession != this.SecondaryProfession &&
|
||||
this.Skill2.Profession != Profession.None)
|
||||
{
|
||||
this.Skill2 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill3.Profession != this.PrimaryProfession &&
|
||||
this.Skill3.Profession != this.SecondaryProfession &&
|
||||
this.Skill3.Profession != Profession.None)
|
||||
{
|
||||
this.Skill3 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill4.Profession != this.PrimaryProfession &&
|
||||
this.Skill4.Profession != this.SecondaryProfession &&
|
||||
this.Skill4.Profession != Profession.None)
|
||||
{
|
||||
this.Skill4 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill5.Profession != this.PrimaryProfession &&
|
||||
this.Skill5.Profession != this.SecondaryProfession &&
|
||||
this.Skill5.Profession != Profession.None)
|
||||
{
|
||||
this.Skill5 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill6.Profession != this.PrimaryProfession &&
|
||||
this.Skill6.Profession != this.SecondaryProfession &&
|
||||
this.Skill6.Profession != Profession.None)
|
||||
{
|
||||
this.Skill6 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill7.Profession != this.PrimaryProfession &&
|
||||
this.Skill7.Profession != this.SecondaryProfession &&
|
||||
this.Skill7.Profession != Profession.None)
|
||||
{
|
||||
this.Skill7 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
var filteredSkills = await this.FilterSkills(this.SkillSearchText).ToListAsync().ConfigureAwait(true);
|
||||
this.AvailableSkills.ClearAnd().AddRange(filteredSkills);
|
||||
}
|
||||
|
||||
private void LoadBuild()
|
||||
{
|
||||
this.suppressBuildChanged = true;
|
||||
var build = this.DataContext.As<BuildEntry>();
|
||||
this.loadedBuild = build;
|
||||
this.PrimaryProfession = build.Build!.Primary;
|
||||
this.SecondaryProfession = build.Build.Secondary;
|
||||
this.Skill0 = build.Build.Skills[0];
|
||||
this.Skill1 = build.Build.Skills[1];
|
||||
this.Skill2 = build.Build.Skills[2];
|
||||
this.Skill3 = build.Build.Skills[3];
|
||||
this.Skill4 = build.Build.Skills[4];
|
||||
this.Skill5 = build.Build.Skills[5];
|
||||
this.Skill6 = build.Build.Skills[6];
|
||||
this.Skill7 = build.Build.Skills[7];
|
||||
this.suppressBuildChanged = false;
|
||||
this.PrepareSkillListCache(filteredSkills);
|
||||
}
|
||||
|
||||
private void BrowseToInfo(string infoName)
|
||||
@@ -301,8 +126,9 @@ public partial class BuildTemplate : UserControl
|
||||
{
|
||||
if (this.SkillBrowser.BrowserSupported is true)
|
||||
{
|
||||
this.HideSkillListView();
|
||||
this.HideProfessionListView();
|
||||
this.SkillBrowser.Width = 400;
|
||||
this.SkillListContainer.Width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,23 +142,103 @@ public partial class BuildTemplate : UserControl
|
||||
|
||||
private void ShowSkillListView()
|
||||
{
|
||||
this.SkillBrowser.Width = 0;
|
||||
this.HideInfoBrowser();
|
||||
this.HideProfessionListView();
|
||||
this.SkillListContainer.Width = 400;
|
||||
}
|
||||
|
||||
private void HideSkillListView()
|
||||
{
|
||||
this.SkillListContainer.Width = 0;
|
||||
}
|
||||
|
||||
private void HelpButtonPrimary_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.PrimaryProfession == Profession.None)
|
||||
this.SkillListContainer.Visibility = Visibility.Visible;
|
||||
this.showingSkillList = true;
|
||||
if (this.skillListCache?.Except(this.AvailableSkills).None() is true &&
|
||||
this.skillListCache.Count == this.AvailableSkills.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.BrowseToInfo(this.PrimaryProfession.Name!);
|
||||
this.AvailableSkills.ClearAnd().AddRange(this.skillListCache);
|
||||
}
|
||||
|
||||
private void HideSkillListView()
|
||||
{
|
||||
this.SkillListContainer.Visibility = Visibility.Hidden;
|
||||
this.SkillListContainer.Width = 0;
|
||||
this.showingSkillList = false;
|
||||
}
|
||||
|
||||
private void ShowProfessionListView()
|
||||
{
|
||||
this.HideInfoBrowser();
|
||||
this.HideSkillListView();
|
||||
this.ProfessionListView.Width = 400;
|
||||
this.ProfessionListView.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideProfessionListView()
|
||||
{
|
||||
this.ProfessionListView.Visibility = Visibility.Hidden;
|
||||
this.ProfessionListView.Width = 0;
|
||||
}
|
||||
|
||||
private void PrepareSkillListCache(List<Skill> skills)
|
||||
{
|
||||
/*
|
||||
* To improve application performance, only load the skill list when it is showing.
|
||||
* Otherwise, defer the loading to when the skill list will show.
|
||||
*/
|
||||
|
||||
this.skillListCache = skills;
|
||||
if (this.showingSkillList)
|
||||
{
|
||||
this.ShowSkillListView();
|
||||
}
|
||||
}
|
||||
|
||||
private async IAsyncEnumerable<Skill> FilterSkills(string searchTerm)
|
||||
{
|
||||
// Replace symbols to ease search
|
||||
searchTerm = searchTerm?.Replace("\"", "").Replace("!", "")!;
|
||||
|
||||
foreach (var skill in Skill.Skills)
|
||||
{
|
||||
if (skill == Skill.NoSkill)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skill.Profession != this.BuildEntry!.Primary &&
|
||||
skill.Profession != this.BuildEntry!.Secondary &&
|
||||
skill.Profession != Profession.None)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (searchTerm.IsNullOrWhiteSpace())
|
||||
{
|
||||
yield return skill;
|
||||
continue;
|
||||
}
|
||||
|
||||
var matchesName = await Task.Run(() => StringUtils.MatchesSearchString(skill.Name!.Replace("\"", "").Replace("!", ""), searchTerm!));
|
||||
if (matchesName)
|
||||
{
|
||||
yield return skill;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Grid_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
this.HideSkillListView();
|
||||
this.HideInfoBrowser();
|
||||
}
|
||||
|
||||
private void HelpButtonPrimary_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.BuildEntry!.Primary == Profession.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.BrowseToInfo(this.BuildEntry.Primary.Name!);
|
||||
if (e is RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
routedEventArgs.Handled = true;
|
||||
@@ -341,12 +247,12 @@ public partial class BuildTemplate : UserControl
|
||||
|
||||
private void HelpButtonSecondary_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.SecondaryProfession == Profession.None)
|
||||
if (this.BuildEntry!.Secondary == Profession.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.BrowseToInfo(this.SecondaryProfession.Name!);
|
||||
this.BrowseToInfo(this.BuildEntry.Secondary.Name!);
|
||||
if (e is RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
routedEventArgs.Handled = true;
|
||||
@@ -362,6 +268,7 @@ public partial class BuildTemplate : UserControl
|
||||
{
|
||||
e.ThrowIfNull();
|
||||
this.BuildChanged?.Invoke(this, new EventArgs());
|
||||
this.AttributePoints = this.attributePointCalculator!.GetRemainingFreePoints(this.BuildEntry.Build!);
|
||||
}
|
||||
|
||||
private void SkillTemplate_Clicked(object sender, RoutedEventArgs e)
|
||||
@@ -389,10 +296,41 @@ public partial class BuildTemplate : UserControl
|
||||
|
||||
private void SkillTemplate_RemoveClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
sender.As<SkillTemplate>().DataContext = Skill.NoSkill;
|
||||
if (sender == this.SkillTemplate0)
|
||||
{
|
||||
this.BuildEntry.FirstSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate1)
|
||||
{
|
||||
this.BuildEntry.SecondSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate2)
|
||||
{
|
||||
this.BuildEntry.ThirdSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate3)
|
||||
{
|
||||
this.BuildEntry.FourthSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate4)
|
||||
{
|
||||
this.BuildEntry.FifthSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate5)
|
||||
{
|
||||
this.BuildEntry.SixthSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate6)
|
||||
{
|
||||
this.BuildEntry.SeventhSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate7)
|
||||
{
|
||||
this.BuildEntry.EigthSkill = Skill.NoSkill;
|
||||
}
|
||||
}
|
||||
|
||||
private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
private void SkillListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.selectingSkillTemplate is null)
|
||||
{
|
||||
@@ -400,16 +338,56 @@ public partial class BuildTemplate : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectingSkillTemplate.DataContext = sender.As<ListView>().SelectedItem;
|
||||
var selectedSkilll = sender.As<ListView>().SelectedItem.As<Skill>();
|
||||
if (this.selectingSkillTemplate == this.SkillTemplate0)
|
||||
{
|
||||
this.BuildEntry.FirstSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate1)
|
||||
{
|
||||
this.BuildEntry.SecondSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate2)
|
||||
{
|
||||
this.BuildEntry.ThirdSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate3)
|
||||
{
|
||||
this.BuildEntry.FourthSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate4)
|
||||
{
|
||||
this.BuildEntry.FifthSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate5)
|
||||
{
|
||||
this.BuildEntry.SixthSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate6)
|
||||
{
|
||||
this.BuildEntry.SeventhSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate7)
|
||||
{
|
||||
this.BuildEntry.EigthSkill = selectedSkilll;
|
||||
}
|
||||
|
||||
this.HideSkillListView();
|
||||
this.loadedBuild!.Build!.Skills[0] = this.Skill0;
|
||||
this.loadedBuild!.Build!.Skills[1] = this.Skill1;
|
||||
this.loadedBuild!.Build!.Skills[2] = this.Skill2;
|
||||
this.loadedBuild!.Build!.Skills[3] = this.Skill3;
|
||||
this.loadedBuild!.Build!.Skills[4] = this.Skill4;
|
||||
this.loadedBuild!.Build!.Skills[5] = this.Skill5;
|
||||
this.loadedBuild!.Build!.Skills[6] = this.Skill6;
|
||||
this.loadedBuild!.Build!.Skills[7] = this.Skill7;
|
||||
}
|
||||
|
||||
private void ProfessionListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
var selected = sender.As<ListView>().SelectedItem.As<Profession>();
|
||||
if (this.replacingPrimaryProfession)
|
||||
{
|
||||
this.BuildEntry!.Primary = selected;
|
||||
}
|
||||
else if (this.replacingSecondaryProfession)
|
||||
{
|
||||
this.BuildEntry!.Secondary = selected;
|
||||
}
|
||||
|
||||
this.HideProfessionListView();
|
||||
}
|
||||
|
||||
private void ListView_NavigateWithMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
|
||||
@@ -440,37 +418,24 @@ public partial class BuildTemplate : UserControl
|
||||
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
|
||||
}
|
||||
|
||||
private async IAsyncEnumerable<Skill> FilterSkills(string searchTerm)
|
||||
private void SecondaryProfessionButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
// Replace symbols to ease search
|
||||
searchTerm = searchTerm?.Replace("\"", "").Replace("!", "")!;
|
||||
|
||||
foreach (var skill in Skill.Skills)
|
||||
{
|
||||
if (skill == Skill.NoSkill)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
this.replacingPrimaryProfession = false;
|
||||
this.replacingSecondaryProfession = true;
|
||||
this.Professions.ClearAnd().AddRange(Profession.Professions.Where(p => p != this.BuildEntry?.Secondary));
|
||||
this.ShowProfessionListView();
|
||||
}
|
||||
|
||||
if (skill.Profession != this.PrimaryProfession &&
|
||||
skill.Profession != this.SecondaryProfession &&
|
||||
skill.Profession != Profession.None)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
private void PrimaryProfessionButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.replacingPrimaryProfession = true;
|
||||
this.replacingSecondaryProfession = false;
|
||||
this.Professions.ClearAnd().AddRange(Profession.Professions.Where(p => p != this.BuildEntry?.Primary));
|
||||
this.ShowProfessionListView();
|
||||
}
|
||||
|
||||
if (searchTerm.IsNullOrWhiteSpace())
|
||||
{
|
||||
yield return skill;
|
||||
continue;
|
||||
}
|
||||
|
||||
var matchesName = await Task.Run(() => StringUtils.MatchesSearchString(skill.Name!.Replace("\"", "").Replace("!", ""), searchTerm!));
|
||||
if (matchesName)
|
||||
{
|
||||
yield return skill;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
private void AttributeTemplate_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
sender.As<AttributeTemplate>().InitializeAttributeTemplate(this.AttributePoints, this.attributePointCalculator!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Daybreak.Controls.Templates;
|
||||
@@ -60,36 +61,22 @@ public partial class QuestLogTemplate : UserControl
|
||||
foreach(var grouping in this.questLogCache)
|
||||
{
|
||||
var location = grouping.Key;
|
||||
var locationTextBlock = new TextBlock
|
||||
var locationTextBlock = new OpaqueButton
|
||||
{
|
||||
Text = grouping.Key?.Name ?? UncategorizedQuestsString,
|
||||
FontSize = 18,
|
||||
Margin = new Thickness(5),
|
||||
Cursor = grouping.Key is null ? Cursors.Arrow : Cursors.Hand,
|
||||
HorizontalAlignment = HorizontalAlignment.Left
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
TextHorizontalAlignment = HorizontalAlignment.Left,
|
||||
Highlight = Brushes.White,
|
||||
HighlightOpacity = grouping.Key is null ? 0 : 0.6
|
||||
};
|
||||
|
||||
locationTextBlock.MouseLeftButtonDown += (_, _) => this.OnMapClicked(location);
|
||||
this.ItemStackPanel.Children.Add(locationTextBlock);
|
||||
foreach(var questMetadata in grouping)
|
||||
{
|
||||
var quest = questMetadata.Quest;
|
||||
var questTextBlock = new TextBlock
|
||||
{
|
||||
Text = quest?.Name,
|
||||
FontSize = 20,
|
||||
Cursor = Cursors.Hand,
|
||||
HorizontalAlignment = HorizontalAlignment.Left
|
||||
};
|
||||
|
||||
questTextBlock.MouseLeftButtonDown += (_, _) => this.OnQuestClicked(quest);
|
||||
this.ItemStackPanel.Children.Add(questTextBlock);
|
||||
}
|
||||
|
||||
var rectangle = new Rectangle
|
||||
{
|
||||
Height = 1,
|
||||
Margin = new Thickness(0, 0, 0, 10)
|
||||
};
|
||||
|
||||
var rectangleForegroundBinding = new Binding("Foreground")
|
||||
@@ -99,6 +86,30 @@ public partial class QuestLogTemplate : UserControl
|
||||
|
||||
rectangle.SetBinding(Rectangle.FillProperty, rectangleForegroundBinding);
|
||||
this.ItemStackPanel.Children.Add(rectangle);
|
||||
foreach (var questMetadata in grouping)
|
||||
{
|
||||
var quest = questMetadata.Quest;
|
||||
var questTextBlock = new OpaqueButton
|
||||
{
|
||||
Text = quest?.Name,
|
||||
FontSize = 20,
|
||||
Cursor = Cursors.Hand,
|
||||
Highlight = Brushes.White,
|
||||
HighlightOpacity = 0.6,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
TextHorizontalAlignment = HorizontalAlignment.Left
|
||||
};
|
||||
|
||||
questTextBlock.MouseLeftButtonDown += (_, _) => this.OnQuestClicked(quest);
|
||||
this.ItemStackPanel.Children.Add(questTextBlock);
|
||||
}
|
||||
|
||||
this.ItemStackPanel.Children.Add(new Rectangle
|
||||
{
|
||||
Fill = Brushes.Transparent,
|
||||
Height = 10,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<UserControl x:Class="Daybreak.Controls.VerticalResourceBar"
|
||||
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:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Viewbox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Stretch="Fill">
|
||||
<Grid Width="1">
|
||||
<Rectangle
|
||||
Fill="{Binding ElementName=_this, Path=BarColor, Mode=OneWay}"
|
||||
VerticalAlignment="{Binding ElementName=_this, Path=FillAlignment, Mode=OneWay}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Height="{Binding ElementName=_this, Path=MaxResourceValue, Mode=TwoWay}"></Rectangle>
|
||||
<Rectangle
|
||||
Fill="#F0212121"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"></Rectangle>
|
||||
<Rectangle
|
||||
Fill="{Binding ElementName=_this, Path=BarColor, Mode=OneWay}"
|
||||
VerticalAlignment="{Binding ElementName=_this, Path=FillAlignment, Mode=OneWay}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Height="{Binding ElementName=_this, Path=CurrentResourceValue, Mode=TwoWay}"></Rectangle>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
FontSize="{Binding ElementName=_this, Path=FontSize, Mode=OneWay}"
|
||||
FontFamily="{Binding ElementName=_this, Path=FontFamily, Mode=OneWay}"
|
||||
Text="{Binding ElementName=_this, Path=Text, Mode=OneWay}"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"></TextBlock>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
+4
-2
@@ -8,7 +8,7 @@ namespace Daybreak.Controls;
|
||||
/// <summary>
|
||||
/// Interaction logic for ResourceBar.xaml
|
||||
/// </summary>
|
||||
public partial class ResourceBar : UserControl
|
||||
public partial class VerticalResourceBar : UserControl
|
||||
{
|
||||
[GenerateDependencyProperty]
|
||||
private double currentResourceValue;
|
||||
@@ -18,8 +18,10 @@ public partial class ResourceBar : UserControl
|
||||
private Brush barColor;
|
||||
[GenerateDependencyProperty]
|
||||
private string text;
|
||||
[GenerateDependencyProperty(InitialValue = VerticalAlignment.Bottom)]
|
||||
private VerticalAlignment fillAlignment;
|
||||
|
||||
public ResourceBar()
|
||||
public VerticalResourceBar()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.MaxResourceValue = 1;
|
||||
@@ -13,7 +13,7 @@
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
|
||||
<IncludePackageReferencesDuringMarkupCompilation>true</IncludePackageReferencesDuringMarkupCompilation>
|
||||
<Version>0.9.8.2</Version>
|
||||
<Version>0.9.8.7</Version>
|
||||
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||
<UserSecretsId>cfb2a489-db80-448d-a969-80270f314c46</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
@@ -72,6 +72,9 @@
|
||||
<Compile Update="Controls\Buttons\CancelButton.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\VerticalResourceBar.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Views\IconDownloadView.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Grid>
|
||||
<Grid Cursor="Hand">
|
||||
<Rectangle x:Name="OverlayRect" Fill="{TemplateBinding Background}" Opacity="0"></Rectangle>
|
||||
<controls:ThreeDotsGlyph Margin="13"></controls:ThreeDotsGlyph>
|
||||
</Grid>
|
||||
@@ -33,7 +33,7 @@
|
||||
<Condition Property="IsMouseOver" Value="True"></Condition>
|
||||
</MultiTrigger.Conditions>
|
||||
<MultiTrigger.Setters>
|
||||
<Setter Property="Opacity" TargetName="OverlayRect" Value="0.5"></Setter>
|
||||
<Setter Property="Opacity" TargetName="OverlayRect" Value="1"></Setter>
|
||||
</MultiTrigger.Setters>
|
||||
</MultiTrigger>
|
||||
<MultiTrigger>
|
||||
@@ -118,7 +118,7 @@
|
||||
Grid.RowSpan="2"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Left"
|
||||
Background="#A0202020">
|
||||
Background="#F0212121">
|
||||
<controls:MenuList Margin="0, 30, 0, 0"/>
|
||||
</Grid>
|
||||
<ToggleButton x:Name="OpeningSettingsButton"
|
||||
@@ -126,6 +126,7 @@
|
||||
Width="50"
|
||||
Height="30"
|
||||
HorizontalAlignment="Left"
|
||||
Background="#F0212121"
|
||||
Margin="0, 0, 0, 0"
|
||||
Grid.ColumnSpan="2"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
@@ -138,6 +139,7 @@
|
||||
Margin="0, 0, 0, 0"
|
||||
Grid.ColumnSpan="2"
|
||||
Foreground="White"
|
||||
Background="#F09E9E9E"
|
||||
Visibility="{Binding ElementName=_this, Path=IsShowingDropdown, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Click="SettingsButton_Clicked"></ToggleButton>
|
||||
<wcl:Border OnResize="Border_OnResize" Grid.RowSpan="2" Grid.ColumnSpan="2" Active="True"></wcl:Border>
|
||||
@@ -146,8 +148,9 @@
|
||||
HorizontalAlignment="Center"
|
||||
Visibility="Visible"
|
||||
ControlsEnabled="False"
|
||||
CanNavigate="False"
|
||||
CanNavigate="True"
|
||||
CanDownloadBuild="False"
|
||||
Grid.Row="1"></controls:ChromiumBrowserWrapper>
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"></controls:ChromiumBrowserWrapper>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Models.Builds;
|
||||
|
||||
@@ -28,4 +32,170 @@ public sealed class BuildEntry : INotifyPropertyChanged
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Build)));
|
||||
}
|
||||
}
|
||||
public Profession Primary
|
||||
{
|
||||
get => this.Build!.Primary;
|
||||
set
|
||||
{
|
||||
this.Build!.Primary = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Primary)));
|
||||
this.UpdateAttributes();
|
||||
}
|
||||
}
|
||||
public Profession Secondary
|
||||
{
|
||||
get => this.Build!.Secondary;
|
||||
set
|
||||
{
|
||||
this.Build!.Secondary = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Secondary)));
|
||||
this.UpdateAttributes();
|
||||
}
|
||||
}
|
||||
public List<AttributeEntry> Attributes
|
||||
{
|
||||
get => this.Build!.Attributes;
|
||||
set
|
||||
{
|
||||
this.Build!.Attributes = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Attributes)));
|
||||
this.UpdateSkills();
|
||||
}
|
||||
}
|
||||
public Skill FirstSkill
|
||||
{
|
||||
get => this.Build!.Skills[0];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[0] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.FirstSkill)));
|
||||
}
|
||||
}
|
||||
public Skill SecondSkill
|
||||
{
|
||||
get => this.Build!.Skills[1];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[1] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.SecondSkill)));
|
||||
}
|
||||
}
|
||||
public Skill ThirdSkill
|
||||
{
|
||||
get => this.Build!.Skills[2];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[2] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.ThirdSkill)));
|
||||
}
|
||||
}
|
||||
public Skill FourthSkill
|
||||
{
|
||||
get => this.Build!.Skills[3];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[3] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.FourthSkill)));
|
||||
}
|
||||
}
|
||||
public Skill FifthSkill
|
||||
{
|
||||
get => this.Build!.Skills[4];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[4] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.FifthSkill)));
|
||||
}
|
||||
}
|
||||
public Skill SixthSkill
|
||||
{
|
||||
get => this.Build!.Skills[5];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[5] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.SixthSkill)));
|
||||
}
|
||||
}
|
||||
public Skill SeventhSkill
|
||||
{
|
||||
get => this.Build!.Skills[6];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[6] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.SeventhSkill)));
|
||||
}
|
||||
}
|
||||
public Skill EigthSkill
|
||||
{
|
||||
get => this.Build!.Skills[7];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[7] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.EigthSkill)));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAttributes()
|
||||
{
|
||||
var attributesToAdd = new List<Attribute>();
|
||||
if (this.Primary.PrimaryAttribute is not null)
|
||||
{
|
||||
attributesToAdd.Add(this.Primary.PrimaryAttribute);
|
||||
}
|
||||
|
||||
attributesToAdd.AddRange(this.Primary.Attributes);
|
||||
attributesToAdd.AddRange(this.Secondary.Attributes);
|
||||
this.Attributes = attributesToAdd.Distinct().Select(attribute =>
|
||||
{
|
||||
if (this.Attributes.FirstOrDefault(attributeEntry => attributeEntry.Attribute == attribute) is AttributeEntry attributeEntry)
|
||||
{
|
||||
return attributeEntry;
|
||||
}
|
||||
|
||||
return new AttributeEntry { Attribute = attribute };
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private void UpdateSkills()
|
||||
{
|
||||
if (this.FirstSkill.Profession != this.Primary && this.FirstSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.FirstSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.SecondSkill.Profession != this.Primary && this.SecondSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.SecondSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.ThirdSkill.Profession != this.Primary && this.ThirdSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.ThirdSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.FourthSkill.Profession != this.Primary && this.FourthSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.FourthSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.FifthSkill.Profession != this.Primary && this.FifthSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.FifthSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.SixthSkill.Profession != this.Primary && this.SixthSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.SixthSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.SeventhSkill.Profession != this.Primary && this.SeventhSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.SeventhSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.EigthSkill.Profession != this.Primary && this.EigthSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.EigthSkill = Skill.NoSkill;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,48 +6,48 @@ namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public sealed class Attribute
|
||||
{
|
||||
public static Attribute FastCasting { get; } = new() { Name = "Fast Casting", Id = 0 };
|
||||
public static Attribute IllusionMagic { get; } = new() { Name = "Illusion Magic", Id = 1 };
|
||||
public static Attribute DominationMagic { get; } = new() { Name = "Domination Magic", Id = 2 };
|
||||
public static Attribute InspirationMagic { get; } = new() { Name = "Inspiration Magic", Id = 3 };
|
||||
public static Attribute BloodMagic { get; } = new() { Name = "Blood Magic", Id = 4 };
|
||||
public static Attribute DeathMagic { get; } = new() { Name = "Death Magic", Id = 5 };
|
||||
public static Attribute SoulReaping { get; } = new() { Name = "Soul Reaping", Id = 6 };
|
||||
public static Attribute Curses { get; } = new() { Name = "Curses", Id = 7 };
|
||||
public static Attribute AirMagic { get; } = new() { Name = "Air Magic", Id = 8 };
|
||||
public static Attribute EarthMagic { get; } = new() { Name = "Earth Magic", Id = 9 };
|
||||
public static Attribute FireMagic { get; } = new() { Name = "Fire Magic", Id = 10 };
|
||||
public static Attribute WaterMagic { get; } = new() { Name = "Water Magic", Id = 11 };
|
||||
public static Attribute EnergyStorage { get; } = new() { Name = "Energy Storage", Id = 12 };
|
||||
public static Attribute HealingPrayers { get; } = new() { Name = "Healing Prayers", Id = 13 };
|
||||
public static Attribute SmitingPrayers { get; } = new() { Name = "Smiting Prayers", Id = 14 };
|
||||
public static Attribute ProtectionPrayers { get; } = new() { Name = "Protection Prayers", Id = 15 };
|
||||
public static Attribute DivineFavor { get; } = new() { Name = "Divine Favor", Id = 16 };
|
||||
public static Attribute Strength { get; } = new() { Name = "Strength", Id = 17 };
|
||||
public static Attribute AxeMastery { get; } = new() { Name = "Axe Mastery", Id = 18 };
|
||||
public static Attribute HammerMastery { get; } = new() { Name = "Hammer Mastery", Id = 19 };
|
||||
public static Attribute Swordsmanship { get; } = new() { Name = "Swordsmanship", Id = 20};
|
||||
public static Attribute Tactics { get; } = new() { Name = "Tactics", Id = 21 };
|
||||
public static Attribute BeastMastery { get; } = new() { Name = "Beast Mastery", Id = 22 };
|
||||
public static Attribute Expertise { get; } = new() { Name = "Expertise", Id = 23 };
|
||||
public static Attribute WildernessSurvival { get; } = new() { Name = "Wilderness Survival", Id = 24 };
|
||||
public static Attribute Marksmanship { get; } = new() { Name = "Marksmanship", Id = 25 };
|
||||
public static Attribute DaggerMastery { get; } = new() { Name = "Dagger Mastery", Id = 29 };
|
||||
public static Attribute DeadlyArts { get; } = new() { Name = "Deadly Arts", Id = 30 };
|
||||
public static Attribute ShadowArts { get; } = new() { Name = "Shadow Arts", Id = 31 };
|
||||
public static Attribute Communing { get; } = new() { Name = "Communing", Id = 32 };
|
||||
public static Attribute RestorationMagic { get; } = new() { Name = "Restoration Magic", Id = 33 };
|
||||
public static Attribute ChannelingMagic { get; } = new() { Name = "Channeling Magic", Id = 34 };
|
||||
public static Attribute CriticalStrikes { get; } = new() { Name = "Critical Strikes", Id = 35 };
|
||||
public static Attribute SpawningPower { get; } = new() { Name = "Spawning Power", Id = 36 };
|
||||
public static Attribute SpearMastery { get; } = new() { Name = "Spear Mastery", Id = 37 };
|
||||
public static Attribute Command { get; } = new() { Name = "Command", Id = 38 };
|
||||
public static Attribute Motivation { get; } = new() { Name = "Motivation", Id = 39 };
|
||||
public static Attribute Leadership { get; } = new() { Name = "Leadership", Id = 40 };
|
||||
public static Attribute ScytheMastery { get; } = new() { Name = "Scythe Mastery", Id = 41 };
|
||||
public static Attribute WindPrayers { get; } = new() { Name = "Wind Prayers", Id = 42 };
|
||||
public static Attribute EarthPrayers { get; } = new() { Name = "Earth Prayers", Id = 43 };
|
||||
public static Attribute Mysticism { get; } = new() { Name = "Mysticism", Id = 44 };
|
||||
public static Attribute FastCasting { get; } = new() { Name = "Fast Casting", Id = 0, Profession = Profession.Mesmer };
|
||||
public static Attribute IllusionMagic { get; } = new() { Name = "Illusion Magic", Id = 1, Profession = Profession.Mesmer };
|
||||
public static Attribute DominationMagic { get; } = new() { Name = "Domination Magic", Id = 2, Profession = Profession.Mesmer };
|
||||
public static Attribute InspirationMagic { get; } = new() { Name = "Inspiration Magic", Id = 3, Profession = Profession.Mesmer };
|
||||
public static Attribute BloodMagic { get; } = new() { Name = "Blood Magic", Id = 4, Profession = Profession.Necromancer };
|
||||
public static Attribute DeathMagic { get; } = new() { Name = "Death Magic", Id = 5, Profession = Profession.Necromancer };
|
||||
public static Attribute SoulReaping { get; } = new() { Name = "Soul Reaping", Id = 6, Profession = Profession.Necromancer };
|
||||
public static Attribute Curses { get; } = new() { Name = "Curses", Id = 7, Profession = Profession.Necromancer };
|
||||
public static Attribute AirMagic { get; } = new() { Name = "Air Magic", Id = 8, Profession = Profession.Elementalist };
|
||||
public static Attribute EarthMagic { get; } = new() { Name = "Earth Magic", Id = 9, Profession = Profession.Elementalist };
|
||||
public static Attribute FireMagic { get; } = new() { Name = "Fire Magic", Id = 10, Profession = Profession.Elementalist };
|
||||
public static Attribute WaterMagic { get; } = new() { Name = "Water Magic", Id = 11, Profession = Profession.Elementalist };
|
||||
public static Attribute EnergyStorage { get; } = new() { Name = "Energy Storage", Id = 12, Profession = Profession.Elementalist };
|
||||
public static Attribute HealingPrayers { get; } = new() { Name = "Healing Prayers", Id = 13, Profession = Profession.Monk };
|
||||
public static Attribute SmitingPrayers { get; } = new() { Name = "Smiting Prayers", Id = 14, Profession = Profession.Monk };
|
||||
public static Attribute ProtectionPrayers { get; } = new() { Name = "Protection Prayers", Id = 15, Profession = Profession.Monk };
|
||||
public static Attribute DivineFavor { get; } = new() { Name = "Divine Favor", Id = 16, Profession = Profession.Monk };
|
||||
public static Attribute Strength { get; } = new() { Name = "Strength", Id = 17, Profession = Profession.Warrior };
|
||||
public static Attribute AxeMastery { get; } = new() { Name = "Axe Mastery", Id = 18, Profession = Profession.Warrior };
|
||||
public static Attribute HammerMastery { get; } = new() { Name = "Hammer Mastery", Id = 19, Profession = Profession.Warrior };
|
||||
public static Attribute Swordsmanship { get; } = new() { Name = "Swordsmanship", Id = 20, Profession = Profession.Warrior };
|
||||
public static Attribute Tactics { get; } = new() { Name = "Tactics", Id = 21, Profession = Profession.Warrior };
|
||||
public static Attribute BeastMastery { get; } = new() { Name = "Beast Mastery", Id = 22, Profession = Profession.Ranger };
|
||||
public static Attribute Expertise { get; } = new() { Name = "Expertise", Id = 23, Profession = Profession.Ranger };
|
||||
public static Attribute WildernessSurvival { get; } = new() { Name = "Wilderness Survival", Id = 24, Profession = Profession.Ranger };
|
||||
public static Attribute Marksmanship { get; } = new() { Name = "Marksmanship", Id = 25, Profession = Profession.Ranger };
|
||||
public static Attribute DaggerMastery { get; } = new() { Name = "Dagger Mastery", Id = 29, Profession = Profession.Assassin };
|
||||
public static Attribute DeadlyArts { get; } = new() { Name = "Deadly Arts", Id = 30, Profession = Profession.Assassin };
|
||||
public static Attribute ShadowArts { get; } = new() { Name = "Shadow Arts", Id = 31, Profession = Profession.Assassin };
|
||||
public static Attribute Communing { get; } = new() { Name = "Communing", Id = 32, Profession = Profession.Ritualist };
|
||||
public static Attribute RestorationMagic { get; } = new() { Name = "Restoration Magic", Id = 33, Profession = Profession.Ritualist };
|
||||
public static Attribute ChannelingMagic { get; } = new() { Name = "Channeling Magic", Id = 34, Profession = Profession.Ritualist };
|
||||
public static Attribute CriticalStrikes { get; } = new() { Name = "Critical Strikes", Id = 35, Profession = Profession.Assassin };
|
||||
public static Attribute SpawningPower { get; } = new() { Name = "Spawning Power", Id = 36, Profession = Profession.Ritualist };
|
||||
public static Attribute SpearMastery { get; } = new() { Name = "Spear Mastery", Id = 37, Profession = Profession.Paragon };
|
||||
public static Attribute Command { get; } = new() { Name = "Command", Id = 38, Profession = Profession.Paragon };
|
||||
public static Attribute Motivation { get; } = new() { Name = "Motivation", Id = 39, Profession = Profession.Paragon };
|
||||
public static Attribute Leadership { get; } = new() { Name = "Leadership", Id = 40, Profession = Profession.Paragon };
|
||||
public static Attribute ScytheMastery { get; } = new() { Name = "Scythe Mastery", Id = 41, Profession = Profession.Dervish };
|
||||
public static Attribute WindPrayers { get; } = new() { Name = "Wind Prayers", Id = 42, Profession = Profession.Dervish };
|
||||
public static Attribute EarthPrayers { get; } = new() { Name = "Earth Prayers", Id = 43, Profession = Profession.Dervish };
|
||||
public static Attribute Mysticism { get; } = new() { Name = "Mysticism", Id = 44, Profession = Profession.Dervish };
|
||||
public static IEnumerable<Attribute> Attributes { get; } = new List<Attribute>
|
||||
{
|
||||
FastCasting,
|
||||
@@ -136,6 +136,7 @@ public sealed class Attribute
|
||||
|
||||
public int Id { get; private set; }
|
||||
public string? Name { get; private set; }
|
||||
public Profession? Profession { get; private set; }
|
||||
private Attribute()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -9,4 +9,5 @@ public sealed class GameData
|
||||
public List<PlayerInformation>? Party { get; init; }
|
||||
public UserInformation? User { get; init; }
|
||||
public SessionInformation? Session { get; init; }
|
||||
public List<WorldPlayerInformation>? WorldPlayers { get; init; }
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public sealed class MainPlayerInformation : PlayerInformation
|
||||
public sealed class MainPlayerInformation : WorldPlayerInformation
|
||||
{
|
||||
public string? Name { get; init; }
|
||||
public bool HardModeUnlocked { get; init; }
|
||||
public uint Experience { get; init; }
|
||||
public uint Level { get; init; }
|
||||
|
||||
@@ -627,68 +627,68 @@ public sealed class Map
|
||||
public static readonly Map KilroysPunchoutTournament = new() { Id = 726, Name = "Plains of Jarin", WikiUrl = "https://wiki.guildwars.com/wiki/Plains_of_Jarin" };
|
||||
public static readonly Map SpecialOpsFlameTempleCorridor = new() { Id = 727, Name = "Plains of Jarin", WikiUrl = "https://wiki.guildwars.com/wiki/Plains_of_Jarin" };
|
||||
public static readonly Map SpecialOpsDragonsGullet = new() { Id = 728, Name = "(crash)", WikiUrl = "" };
|
||||
public static readonly Map SpecialOpsGrendichCourthouse = new() { Id = 729, Name = " Special Ops Grendich Courthouse", WikiUrl = "https://wiki.guildwars.com/wiki/Grendich_Courthouse" };
|
||||
public static readonly Map TheTenguAccords = new() { Id = 730, Name = " The Tengu Accords", WikiUrl = "https://wiki.guildwars.com/wiki/_The_Tengu_Accords" };
|
||||
public static readonly Map TheBattleofJahai = new() { Id = 731, Name = " The Battle of Jahai", WikiUrl = "https://wiki.guildwars.com/wiki/The_Battle_of_Jahai" };
|
||||
public static readonly Map TheFlightNorth = new() { Id = 732, Name = " The Flight North", WikiUrl = "https://wiki.guildwars.com/wiki/_The_Flight_North" };
|
||||
public static readonly Map TheRiseoftheWhiteMantle = new() { Id = 733, Name = " The Rise of the White Mantle", WikiUrl = "https://wiki.guildwars.com/wiki/The_Rise_of_the_White_Mantle" };
|
||||
public static readonly Map FindingtheBloodstoneMission = new() { Id = 734, Name = " Finding the Bloodstone Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Finding_the_Bloodstone" };
|
||||
public static readonly Map GeniusOperatedLivingEnchantedManifestationMission = new() { Id = 760, Name = " Genius Operated Living Enchanted Manifestation Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Genius_Operated_Living_Enchanted_Manifestation" };
|
||||
public static readonly Map AgainsttheCharrMission = new() { Id = 761, Name = " Against the Charr Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Against_the_Charr" };
|
||||
public static readonly Map WarbandofbrothersMission = new() { Id = 762, Name = " Warband of brothers Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Warband_of_Brothers" };
|
||||
public static readonly Map AssaultontheStrongholdMission = new() { Id = 763, Name = " Assault on the Stronghold Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Assault_on_the_Stronghold" };
|
||||
public static readonly Map DestructionsDepthsMission = new() { Id = 764, Name = " Destructions Depths Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Destruction's_Depths" };
|
||||
public static readonly Map ATimeforHeroesMission = new() { Id = 765, Name = " A Time for Heroes Mission", WikiUrl = "https://wiki.guildwars.com/wiki/A_Time_for_Heroes" };
|
||||
public static readonly Map CurseoftheNornbearMission = new() { Id = 766, Name = " Curse of the Nornbear Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Curse_of_the_Nornbear" };
|
||||
public static readonly Map BloodWashesBloodMission = new() { Id = 767, Name = " Blood Washes Blood Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Blood_Washes_Blood" };
|
||||
public static readonly Map AGateTooFarMission = new() { Id = 768, Name = " A Gate Too Far Mission", WikiUrl = "https://wiki.guildwars.com/wiki/A_Gate_Too_Far" };
|
||||
public static readonly Map TheElusiveGolemancerMission = new() { Id = 769, Name = " The Elusive Golemancer Mission", WikiUrl = "https://wiki.guildwars.com/wiki/The_Elusive_Golemancer" };
|
||||
public static readonly Map SecretLairoftheSnowmen2 = new() { Id = 770, Name = " Secret Lair of the Snowmen2", WikiUrl = "https://wiki.guildwars.com/wiki/Secret_Lair_of_the_Snowmen" };
|
||||
public static readonly Map SecretLairoftheSnowmen3 = new() { Id = 782, Name = " Secret Lair of the Snowmen3", WikiUrl = "https://wiki.guildwars.com/wiki/Secret_Lair_of_the_Snowmen" };
|
||||
public static readonly Map DroknarsForgecinematic = new() { Id = 783, Name = " Droknars Forge (cinematic)", WikiUrl = "https://wiki.guildwars.com/wiki/Droknar's_Forge" };
|
||||
public static readonly Map IsleoftheNamelessPvP = new() { Id = 784, Name = " Isle of the Nameless PvP", WikiUrl = "https://wiki.guildwars.com/wiki/Isle_of_the_Nameless_(PvP)" };
|
||||
public static readonly Map TempleoftheAgesROX = new() { Id = 785, Name = " Temple of the Ages ROX", WikiUrl = "https://wiki.guildwars.com/wiki/Deactivating_R.O.X." };
|
||||
public static readonly Map WajjunBazaarPOX = new() { Id = 789, Name = " Wajjun Bazaar POX", WikiUrl = "https://wiki.guildwars.com/wiki/Deactivating_P.O.X." };
|
||||
public static readonly Map BokkaAmphitheatreNOX = new() { Id = 790, Name = " Bokka Amphitheatre NOX", WikiUrl = "https://wiki.guildwars.com/wiki/Deactivating_N.O.X." };
|
||||
public static readonly Map SecretUndergroundLair = new() { Id = 791, Name = " Secret Underground Lair", WikiUrl = "https://wiki.guildwars.com/wiki/_Secret_Underground_Lair" };
|
||||
public static readonly Map GolemTutorialSimulation = new() { Id = 792, Name = " Golem Tutorial Simulation", WikiUrl = "https://wiki.guildwars.com/wiki/_Golem_Tutorial_Simulation" };
|
||||
public static readonly Map SnowballDominance = new() { Id = 793, Name = " Snowball Dominance", WikiUrl = "https://wiki.guildwars.com/wiki/_Snowball_Dominance" };
|
||||
public static readonly Map ZaishenMenagerieGrounds = new() { Id = 794, Name = " Zaishen Menagerie Grounds", WikiUrl = "https://wiki.guildwars.com/wiki/_Zaishen_Menagerie_Grounds" };
|
||||
public static readonly Map ZaishenMenagerieOutpost = new() { Id = 795, Name = " Zaishen Menagerie (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Zaishen_Menagerie_(outpost)" };
|
||||
public static readonly Map CodexArenaOutpost = new() { Id = 796, Name = " Codex Arena (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Codex_Arena_(outpost)" };
|
||||
public static readonly Map TheUnderworldSomethingWickedThisWayComes = new() { Id = 797, Name = " The Underworld Something Wicked This Way Comes", WikiUrl = "https://wiki.guildwars.com/wiki/Something_Wicked_This_Way_Comes" };
|
||||
public static readonly Map TheUnderworldDontFeartheReapers = new() { Id = 807, Name = " The Underworld Don't Fear the Reapers", WikiUrl = "https://wiki.guildwars.com/wiki/Don't_Fear_the_Reapers" };
|
||||
public static readonly Map LionsArchHalloweenOutpost = new() { Id = 808, Name = " Lions Arch Halloween (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch_(Halloween)" };
|
||||
public static readonly Map LionsArchWintersdayOutpost = new() { Id = 809, Name = " Lions Arch Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch_(Wintersday)" };
|
||||
public static readonly Map LionsArchCanthanNewYearOutpost = new() { Id = 810, Name = " Lions Arch Canthan New Year (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch" };
|
||||
public static readonly Map AscalonCityWintersdayOutpost = new() { Id = 811, Name = " Ascalon City Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Ascalon_City_(Wintersday)" };
|
||||
public static readonly Map DroknarsForgeHalloweenOutpost = new() { Id = 812, Name = " Droknars Forge Halloween (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Droknar's_Forge_(Halloween)" };
|
||||
public static readonly Map DroknarsForgeWintersdayOutpost = new() { Id = 813, Name = " Droknars Forge Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Droknar's_Forge_(Halloween)" };
|
||||
public static readonly Map TombofthePrimevalKingsHalloweenOutpost = new() { Id = 814, Name = " Tomb of the Primeval Kings Halloween (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Tomb_of_the_Primeval_Kings_(Halloween)" };
|
||||
public static readonly Map ShingJeaMonasteryDragonFestivalOutpost = new() { Id = 815, Name = " Shing Jea Monastery Dragon Festival (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Shing_Jea_Monastery" };
|
||||
public static readonly Map ShingJeaMonasteryCanthanNewYearOutpost = new() { Id = 816, Name = " Shing Jea Monastery Canthan New Year (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Shing_Jea_Monastery" };
|
||||
public static readonly Map KainengCenterCanthanNewYearOutpost = new() { Id = 817, Name = " Kaineng Center Canthan New Year (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Kaineng_Center" };
|
||||
public static readonly Map KamadanJewelofIstanHalloweenOutpost = new() { Id = 818, Name = " Kamadan Jewel of Istan Halloween (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Kamadan,_Jewel_of_Istan_(Halloween)" };
|
||||
public static readonly Map KamadanJewelofIstanWintersdayOutpost = new() { Id = 819, Name = " Kamadan Jewel of Istan Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Kamadan,_Jewel_of_Istan_(Wintersday)" };
|
||||
public static readonly Map KamadanJewelofIstanCanthanNewYearOutpost = new() { Id = 820, Name = " Kamadan Jewel of Istan Canthan New Year (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Kamadan,_Jewel_of_Istan" };
|
||||
public static readonly Map EyeoftheNorthOutpostWintersdayOutpost = new() { Id = 821, Name = " Eyeofthe North Outpost Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Eye_of_the_North_(outpost)_(Wintersday)" };
|
||||
public static readonly Map WarinKrytaTalmarkWilderness = new() { Id = 822, Name = " War in Kryta Talmark Wilderness", WikiUrl = "https://wiki.guildwars.com/wiki/Talmark_Wilderness_(War_in_Kryta)" };
|
||||
public static readonly Map WarinKrytaTrialofZinn = new() { Id = 838, Name = " War in Kryta Trialof Zinn", WikiUrl = "https://wiki.guildwars.com/wiki/Trial_of_Zinn" };
|
||||
public static readonly Map WarinKrytaDivinityCoast = new() { Id = 839, Name = " War in Kryta Divinity Coast", WikiUrl = "https://wiki.guildwars.com/wiki/Divinity_Coast_(explorable_area)" };
|
||||
public static readonly Map WarinKrytaLionsArchKeep = new() { Id = 840, Name = " War in Kryta Lions Arch Keep", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch_(War_in_Kryta)" };
|
||||
public static readonly Map WarinKrytaDAlessioSeaboard = new() { Id = 841, Name = " War in Kryta D'Alessio Seaboard", WikiUrl = "https://wiki.guildwars.com/wiki/D'Alessio_Seaboard_(explorable_area)" };
|
||||
public static readonly Map WarinKrytaTheBattleforLionsArch = new() { Id = 842, Name = " War in Kryta The Battle for Lions Arch", WikiUrl = "https://wiki.guildwars.com/wiki/The_Battle_for_Lion's_Arch" };
|
||||
public static readonly Map WarinKrytaRiversideProvince = new() { Id = 843, Name = " War in Kryta Riverside Province", WikiUrl = "https://wiki.guildwars.com/wiki/Riverside_Province_(explorable_area)" };
|
||||
public static readonly Map WarinKrytaLionsArch = new() { Id = 844, Name = " War in Kryta Lions Arch", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch_(War_in_Kryta)" };
|
||||
public static readonly Map WarinKrytaTheMausoleum = new() { Id = 845, Name = " War in Kryta The Mausoleum", WikiUrl = "https://wiki.guildwars.com/wiki/The_Mausoleum" };
|
||||
public static readonly Map WarinKrytaRise = new() { Id = 846, Name = " War in Kryta Rise", WikiUrl = "https://wiki.guildwars.com/wiki/Rise" };
|
||||
public static readonly Map WarinKrytaShadowsintheJungle = new() { Id = 847, Name = " War in Kryta Shadows in the Jungle", WikiUrl = "https://wiki.guildwars.com/wiki/Shadows_in_the_Jungle" };
|
||||
public static readonly Map WarinKrytaAVengeanceofBlades = new() { Id = 848, Name = " War in Kryta A Vengeance of Blades", WikiUrl = "https://wiki.guildwars.com/wiki/A_Vengeance_of_Blades" };
|
||||
public static readonly Map WarinKrytaAuspiciousBeginnings = new() { Id = 849, Name = " War in Kryta Auspicious Beginnings", WikiUrl = "https://wiki.guildwars.com/wiki/Auspicious_Beginnings" };
|
||||
public static readonly Map Olafsteadcinematic = new() { Id = 850, Name = " Olafstead (cinematic)", WikiUrl = "https://wiki.guildwars.com/wiki/Olafstead" };
|
||||
public static readonly Map TheGreatSnowballFightoftheGodsOperationCrushSpirits = new() { Id = 855, Name = " The Great Snowball Fight of the Gods Operation Crush Spirits", WikiUrl = "https://wiki.guildwars.com/wiki/The_Great_Snowball_Fight_of_the_Gods_(outpost)" };
|
||||
public static readonly Map TheGreatSnowballFightoftheGodsFightinginaWinterWonderland = new() { Id = 856, Name = " The Great Snowball Fight of the Gods Fighting in a Winter Wonderland", WikiUrl = "https://wiki.guildwars.com/wiki/The_Great_Snowball_Fight_of_the_Gods" };
|
||||
public static readonly Map EmbarkBeach = new() { Id = 857, Name = " Embark Beach", WikiUrl = "https://wiki.guildwars.com/wiki/_Embark_Beach" };
|
||||
public static readonly Map SpecialOpsGrendichCourthouse = new() { Id = 729, Name = "Special Ops Grendich Courthouse", WikiUrl = "https://wiki.guildwars.com/wiki/Grendich_Courthouse" };
|
||||
public static readonly Map TheTenguAccords = new() { Id = 730, Name = "The Tengu Accords", WikiUrl = "https://wiki.guildwars.com/wiki/_The_Tengu_Accords" };
|
||||
public static readonly Map TheBattleofJahai = new() { Id = 731, Name = "The Battle of Jahai", WikiUrl = "https://wiki.guildwars.com/wiki/The_Battle_of_Jahai" };
|
||||
public static readonly Map TheFlightNorth = new() { Id = 732, Name = "The Flight North", WikiUrl = "https://wiki.guildwars.com/wiki/_The_Flight_North" };
|
||||
public static readonly Map TheRiseoftheWhiteMantle = new() { Id = 733, Name = "The Rise of the White Mantle", WikiUrl = "https://wiki.guildwars.com/wiki/The_Rise_of_the_White_Mantle" };
|
||||
public static readonly Map FindingtheBloodstoneMission = new() { Id = 734, Name = "Finding the Bloodstone Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Finding_the_Bloodstone" };
|
||||
public static readonly Map GeniusOperatedLivingEnchantedManifestationMission = new() { Id = 760, Name = "Genius Operated Living Enchanted Manifestation Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Genius_Operated_Living_Enchanted_Manifestation" };
|
||||
public static readonly Map AgainsttheCharrMission = new() { Id = 761, Name = "Against the Charr Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Against_the_Charr" };
|
||||
public static readonly Map WarbandofbrothersMission = new() { Id = 762, Name = "Warband of brothers Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Warband_of_Brothers" };
|
||||
public static readonly Map AssaultontheStrongholdMission = new() { Id = 763, Name = "Assault on the Stronghold Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Assault_on_the_Stronghold" };
|
||||
public static readonly Map DestructionsDepthsMission = new() { Id = 764, Name = "Destructions Depths Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Destruction's_Depths" };
|
||||
public static readonly Map ATimeforHeroesMission = new() { Id = 765, Name = "A Time for Heroes Mission", WikiUrl = "https://wiki.guildwars.com/wiki/A_Time_for_Heroes" };
|
||||
public static readonly Map CurseoftheNornbearMission = new() { Id = 766, Name = "Curse of the Nornbear Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Curse_of_the_Nornbear" };
|
||||
public static readonly Map BloodWashesBloodMission = new() { Id = 767, Name = "Blood Washes Blood Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Blood_Washes_Blood" };
|
||||
public static readonly Map AGateTooFarMission = new() { Id = 768, Name = "A Gate Too Far Mission", WikiUrl = "https://wiki.guildwars.com/wiki/A_Gate_Too_Far" };
|
||||
public static readonly Map TheElusiveGolemancerMission = new() { Id = 769, Name = "The Elusive Golemancer Mission", WikiUrl = "https://wiki.guildwars.com/wiki/The_Elusive_Golemancer" };
|
||||
public static readonly Map SecretLairoftheSnowmen2 = new() { Id = 770, Name = "Secret Lair of the Snowmen2", WikiUrl = "https://wiki.guildwars.com/wiki/Secret_Lair_of_the_Snowmen" };
|
||||
public static readonly Map SecretLairoftheSnowmen3 = new() { Id = 782, Name = "Secret Lair of the Snowmen3", WikiUrl = "https://wiki.guildwars.com/wiki/Secret_Lair_of_the_Snowmen" };
|
||||
public static readonly Map DroknarsForgecinematic = new() { Id = 783, Name = "Droknars Forge (cinematic)", WikiUrl = "https://wiki.guildwars.com/wiki/Droknar's_Forge" };
|
||||
public static readonly Map IsleoftheNamelessPvP = new() { Id = 784, Name = "Isle of the Nameless PvP", WikiUrl = "https://wiki.guildwars.com/wiki/Isle_of_the_Nameless_(PvP)" };
|
||||
public static readonly Map TempleoftheAgesROX = new() { Id = 785, Name = "Temple of the Ages ROX", WikiUrl = "https://wiki.guildwars.com/wiki/Deactivating_R.O.X." };
|
||||
public static readonly Map WajjunBazaarPOX = new() { Id = 789, Name = "Wajjun Bazaar POX", WikiUrl = "https://wiki.guildwars.com/wiki/Deactivating_P.O.X." };
|
||||
public static readonly Map BokkaAmphitheatreNOX = new() { Id = 790, Name = "Bokka Amphitheatre NOX", WikiUrl = "https://wiki.guildwars.com/wiki/Deactivating_N.O.X." };
|
||||
public static readonly Map SecretUndergroundLair = new() { Id = 791, Name = "Secret Underground Lair", WikiUrl = "https://wiki.guildwars.com/wiki/_Secret_Underground_Lair" };
|
||||
public static readonly Map GolemTutorialSimulation = new() { Id = 792, Name = "Golem Tutorial Simulation", WikiUrl = "https://wiki.guildwars.com/wiki/_Golem_Tutorial_Simulation" };
|
||||
public static readonly Map SnowballDominance = new() { Id = 793, Name = "Snowball Dominance", WikiUrl = "https://wiki.guildwars.com/wiki/_Snowball_Dominance" };
|
||||
public static readonly Map ZaishenMenagerieGrounds = new() { Id = 794, Name = "Zaishen Menagerie Grounds", WikiUrl = "https://wiki.guildwars.com/wiki/_Zaishen_Menagerie_Grounds" };
|
||||
public static readonly Map ZaishenMenagerieOutpost = new() { Id = 795, Name = "Zaishen Menagerie (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Zaishen_Menagerie_(outpost)" };
|
||||
public static readonly Map CodexArenaOutpost = new() { Id = 796, Name = "Codex Arena (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Codex_Arena_(outpost)" };
|
||||
public static readonly Map TheUnderworldSomethingWickedThisWayComes = new() { Id = 797, Name = "The Underworld Something Wicked This Way Comes", WikiUrl = "https://wiki.guildwars.com/wiki/Something_Wicked_This_Way_Comes" };
|
||||
public static readonly Map TheUnderworldDontFeartheReapers = new() { Id = 807, Name = "The Underworld Don't Fear the Reapers", WikiUrl = "https://wiki.guildwars.com/wiki/Don't_Fear_the_Reapers" };
|
||||
public static readonly Map LionsArchHalloweenOutpost = new() { Id = 808, Name = "Lions Arch Halloween (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch_(Halloween)" };
|
||||
public static readonly Map LionsArchWintersdayOutpost = new() { Id = 809, Name = "Lions Arch Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch_(Wintersday)" };
|
||||
public static readonly Map LionsArchCanthanNewYearOutpost = new() { Id = 810, Name = "Lions Arch Canthan New Year (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch" };
|
||||
public static readonly Map AscalonCityWintersdayOutpost = new() { Id = 811, Name = "Ascalon City Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Ascalon_City_(Wintersday)" };
|
||||
public static readonly Map DroknarsForgeHalloweenOutpost = new() { Id = 812, Name = "Droknars Forge Halloween (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Droknar's_Forge_(Halloween)" };
|
||||
public static readonly Map DroknarsForgeWintersdayOutpost = new() { Id = 813, Name = "Droknars Forge Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Droknar's_Forge_(Halloween)" };
|
||||
public static readonly Map TombofthePrimevalKingsHalloweenOutpost = new() { Id = 814, Name = "Tomb of the Primeval Kings Halloween (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Tomb_of_the_Primeval_Kings_(Halloween)" };
|
||||
public static readonly Map ShingJeaMonasteryDragonFestivalOutpost = new() { Id = 815, Name = "Shing Jea Monastery Dragon Festival (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Shing_Jea_Monastery" };
|
||||
public static readonly Map ShingJeaMonasteryCanthanNewYearOutpost = new() { Id = 816, Name = "Shing Jea Monastery Canthan New Year (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Shing_Jea_Monastery" };
|
||||
public static readonly Map KainengCenterCanthanNewYearOutpost = new() { Id = 817, Name = "Kaineng Center Canthan New Year (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Kaineng_Center" };
|
||||
public static readonly Map KamadanJewelofIstanHalloweenOutpost = new() { Id = 818, Name = "Kamadan Jewel of Istan Halloween (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Kamadan,_Jewel_of_Istan_(Halloween)" };
|
||||
public static readonly Map KamadanJewelofIstanWintersdayOutpost = new() { Id = 819, Name = "Kamadan Jewel of Istan Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Kamadan,_Jewel_of_Istan_(Wintersday)" };
|
||||
public static readonly Map KamadanJewelofIstanCanthanNewYearOutpost = new() { Id = 820, Name = "Kamadan Jewel of Istan Canthan New Year (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Kamadan,_Jewel_of_Istan" };
|
||||
public static readonly Map EyeoftheNorthOutpostWintersdayOutpost = new() { Id = 821, Name = "Eyeofthe North Outpost Wintersday (Outpost)", WikiUrl = "https://wiki.guildwars.com/wiki/Eye_of_the_North_(outpost)_(Wintersday)" };
|
||||
public static readonly Map WarinKrytaTalmarkWilderness = new() { Id = 822, Name = "War in Kryta Talmark Wilderness", WikiUrl = "https://wiki.guildwars.com/wiki/Talmark_Wilderness_(War_in_Kryta)" };
|
||||
public static readonly Map WarinKrytaTrialofZinn = new() { Id = 838, Name = "War in Kryta Trialof Zinn", WikiUrl = "https://wiki.guildwars.com/wiki/Trial_of_Zinn" };
|
||||
public static readonly Map WarinKrytaDivinityCoast = new() { Id = 839, Name = "War in Kryta Divinity Coast", WikiUrl = "https://wiki.guildwars.com/wiki/Divinity_Coast_(explorable_area)" };
|
||||
public static readonly Map WarinKrytaLionsArchKeep = new() { Id = 840, Name = "War in Kryta Lions Arch Keep", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch_(War_in_Kryta)" };
|
||||
public static readonly Map WarinKrytaDAlessioSeaboard = new() { Id = 841, Name = "War in Kryta D'Alessio Seaboard", WikiUrl = "https://wiki.guildwars.com/wiki/D'Alessio_Seaboard_(explorable_area)" };
|
||||
public static readonly Map WarinKrytaTheBattleforLionsArch = new() { Id = 842, Name = "War in Kryta The Battle for Lions Arch", WikiUrl = "https://wiki.guildwars.com/wiki/The_Battle_for_Lion's_Arch" };
|
||||
public static readonly Map WarinKrytaRiversideProvince = new() { Id = 843, Name = "War in Kryta Riverside Province", WikiUrl = "https://wiki.guildwars.com/wiki/Riverside_Province_(explorable_area)" };
|
||||
public static readonly Map WarinKrytaLionsArch = new() { Id = 844, Name = "War in Kryta Lions Arch", WikiUrl = "https://wiki.guildwars.com/wiki/Lion's_Arch_(War_in_Kryta)" };
|
||||
public static readonly Map WarinKrytaTheMausoleum = new() { Id = 845, Name = "War in Kryta The Mausoleum", WikiUrl = "https://wiki.guildwars.com/wiki/The_Mausoleum" };
|
||||
public static readonly Map WarinKrytaRise = new() { Id = 846, Name = "War in Kryta Rise", WikiUrl = "https://wiki.guildwars.com/wiki/Rise" };
|
||||
public static readonly Map WarinKrytaShadowsintheJungle = new() { Id = 847, Name = "War in Kryta Shadows in the Jungle", WikiUrl = "https://wiki.guildwars.com/wiki/Shadows_in_the_Jungle" };
|
||||
public static readonly Map WarinKrytaAVengeanceofBlades = new() { Id = 848, Name = "War in Kryta A Vengeance of Blades", WikiUrl = "https://wiki.guildwars.com/wiki/A_Vengeance_of_Blades" };
|
||||
public static readonly Map WarinKrytaAuspiciousBeginnings = new() { Id = 849, Name = "War in Kryta Auspicious Beginnings", WikiUrl = "https://wiki.guildwars.com/wiki/Auspicious_Beginnings" };
|
||||
public static readonly Map Olafsteadcinematic = new() { Id = 850, Name = "Olafstead (cinematic)", WikiUrl = "https://wiki.guildwars.com/wiki/Olafstead" };
|
||||
public static readonly Map TheGreatSnowballFightoftheGodsOperationCrushSpirits = new() { Id = 855, Name = "The Great Snowball Fight of the Gods Operation Crush Spirits", WikiUrl = "https://wiki.guildwars.com/wiki/The_Great_Snowball_Fight_of_the_Gods_(outpost)" };
|
||||
public static readonly Map TheGreatSnowballFightoftheGodsFightinginaWinterWonderland = new() { Id = 856, Name = "The Great Snowball Fight of the Gods Fighting in a Winter Wonderland", WikiUrl = "https://wiki.guildwars.com/wiki/The_Great_Snowball_Fight_of_the_Gods" };
|
||||
public static readonly Map EmbarkBeach = new() { Id = 857, Name = "Embark Beach", WikiUrl = "https://wiki.guildwars.com/wiki/_Embark_Beach" };
|
||||
public static readonly Map DragonsThroatareaWhatWaitsinShadow = new() { Id = 858, Name = "What Waits in Shadow", WikiUrl = "https://wiki.guildwars.com/wiki/What_Waits_in_Shadow" };
|
||||
public static readonly Map KainengCenterWindsofChangeAChanceEncounter = new() { Id = 861, Name = "Winds of Change A Chance Encounter", WikiUrl = "https://wiki.guildwars.com/wiki/A_Chance_Encounter" };
|
||||
public static readonly Map TheMarketplaceareaTrackingtheCorruption = new() { Id = 862, Name = "Tracking The Corruption", WikiUrl = "https://wiki.guildwars.com/wiki/Tracking_the_Corruption" };
|
||||
@@ -697,7 +697,7 @@ public sealed class Map
|
||||
public static readonly Map SeitungHarborareaDeadlyCargo = new() { Id = 865, Name = "Deadly Cargo", WikiUrl = "https://wiki.guildwars.com/wiki/Deadly_Cargo" };
|
||||
public static readonly Map TahnnakaiTempleWindsofChangeTheRescueAttempt = new() { Id = 866, Name = "The Rescue Attempt", WikiUrl = "https://wiki.guildwars.com/wiki/The_Rescue_Attempt" };
|
||||
public static readonly Map WajjunBazaarWindsofChangeViolenceintheStreets = new() { Id = 867, Name = "Violence in the Streets", WikiUrl = "https://wiki.guildwars.com/wiki/Violence_in_the_Streets" };
|
||||
public static readonly Map ScarredPsycheMission = new() { Id = 868, Name = " Scarred Psyche Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Scarred_Psyche" };
|
||||
public static readonly Map ScarredPsycheMission = new() { Id = 868, Name = "Scarred Psyche Mission", WikiUrl = "https://wiki.guildwars.com/wiki/Scarred_Psyche" };
|
||||
public static readonly Map ShadowsPassageWindsofChangeCallingAllThugs = new() { Id = 869, Name = "Calling All Thugs", WikiUrl = "https://wiki.guildwars.com/wiki/Calling_All_Thugs" };
|
||||
public static readonly Map AltrummRuinsFindingJinnai = new() { Id = 870, Name = "Finding Jinnai", WikiUrl = "https://wiki.guildwars.com/wiki/Finding_Jinnai" };
|
||||
public static readonly Map ShingJeaMonasteryRaidonShingJeaMonastery = new() { Id = 871, Name = "Raid on Shing Jea Monastery", WikiUrl = "https://wiki.guildwars.com/wiki/Raid_on_Shing_Jea_Monastery" };
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public sealed class Profession
|
||||
{
|
||||
public static Profession None { get; } = new() { Name = "None", Id = 0, };
|
||||
public static Profession None { get; } = new() { Name = "None", Id = 0 };
|
||||
public static Profession Warrior { get; } = new() { Name = "Warrior", Id = 1, PrimaryAttribute = Attribute.Strength, Attributes = new List<Attribute> { Attribute.AxeMastery, Attribute.HammerMastery, Attribute.Swordsmanship, Attribute.Tactics } };
|
||||
public static Profession Ranger { get; } = new() { Name = "Ranger", Id = 2, PrimaryAttribute = Attribute.Expertise, Attributes = new List<Attribute> { Attribute.BeastMastery, Attribute.Marksmanship, Attribute.WildernessSurvival } };
|
||||
public static Profession Monk { get; } = new() { Name = "Monk", Id = 3, PrimaryAttribute = Attribute.DivineFavor, Attributes = new List<Attribute> { Attribute.HealingPrayers, Attribute.SmitingPrayers, Attribute.ProtectionPrayers } };
|
||||
@@ -73,7 +73,7 @@ public sealed class Profession
|
||||
public string? Name { get; private set; }
|
||||
public int Id { get; set; }
|
||||
public Attribute? PrimaryAttribute { get; private set; }
|
||||
public List<Attribute>? Attributes { get; private set; }
|
||||
public List<Attribute> Attributes { get; private set; } = new List<Attribute>();
|
||||
private Profession()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@ public sealed class SessionInformation
|
||||
{
|
||||
public uint FoesKilled { get; init; }
|
||||
public uint FoesToKill { get; init; }
|
||||
public Map? CurrentMap { get; init; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public class WorldPlayerInformation : PlayerInformation
|
||||
{
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
@@ -11,29 +11,4 @@ public readonly struct EntityContext
|
||||
|
||||
[FieldOffset(0x9C)]
|
||||
public readonly EntityType Type;
|
||||
|
||||
// From here, all fields are only valid for living entities.
|
||||
[FieldOffset(0xC4)]
|
||||
public readonly uint OwnerId;
|
||||
|
||||
[FieldOffset(0x114)]
|
||||
public readonly float EnergyRegen;
|
||||
|
||||
[FieldOffset(0x11C)]
|
||||
public readonly float Energy;
|
||||
|
||||
[FieldOffset(0x120)]
|
||||
public readonly uint MaxEnergy;
|
||||
|
||||
[FieldOffset(0x128)]
|
||||
public readonly float HealthRegen;
|
||||
|
||||
[FieldOffset(0x130)]
|
||||
public readonly float Health;
|
||||
|
||||
[FieldOffset(0x134)]
|
||||
public readonly uint MaxHealth;
|
||||
|
||||
[FieldOffset(0x1BC)]
|
||||
public readonly ushort H01BC;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,11 @@ namespace Daybreak.Models.Interop;
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct GlobalContext
|
||||
{
|
||||
[FieldOffset(0x0008)]
|
||||
public readonly IntPtr InstanceContext;
|
||||
|
||||
[FieldOffset(0x002C)]
|
||||
public readonly IntPtr CharacterContext;
|
||||
public readonly IntPtr GameContext;
|
||||
|
||||
[FieldOffset(0x0044)]
|
||||
public readonly IntPtr UserContext;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Daybreak.Models.Interop;
|
||||
|
||||
public readonly struct InstanceContext
|
||||
{
|
||||
public const int BaseOffset = 0x01AC;
|
||||
|
||||
/// <summary>
|
||||
/// Milliseconds since the instance was joined.
|
||||
/// </summary>
|
||||
public readonly uint Timer;
|
||||
}
|
||||
@@ -9,14 +9,23 @@ public readonly struct MapEntityContext
|
||||
public readonly float CurrentEnergy;
|
||||
[FieldOffset(0x04)]
|
||||
public readonly float MaxEnergy;
|
||||
/// <summary>
|
||||
/// Amount of regen in one second.
|
||||
/// </summary>
|
||||
[FieldOffset(0x08)]
|
||||
public readonly float EnergyRegen;
|
||||
/// <summary>
|
||||
/// Milliseconds since the last information update from the server.
|
||||
/// </summary>
|
||||
[FieldOffset(0x0C)]
|
||||
public readonly int SkillTimestamp;
|
||||
[FieldOffset(0x20)]
|
||||
public readonly float CurrentHealth;
|
||||
[FieldOffset(0x24)]
|
||||
public readonly float MaxHealth;
|
||||
/// <summary>
|
||||
/// Amount of regen in one second.
|
||||
/// </summary>
|
||||
[FieldOffset(0x28)]
|
||||
public readonly float HealthRegen;
|
||||
/// <summary>
|
||||
|
||||
@@ -11,6 +11,9 @@ public readonly struct UserContext
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x28)]
|
||||
public readonly byte[] PlayerNameBytes;
|
||||
|
||||
[FieldOffset(0x0124)]
|
||||
public readonly uint MapId;
|
||||
|
||||
[FieldOffset(0x01B0)]
|
||||
public readonly int Language;
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Services.BuildTemplates;
|
||||
|
||||
/// <summary>
|
||||
/// Attribute point calculator.
|
||||
/// Based on https://wiki.guildwars.com/wiki/Attribute_point.
|
||||
/// </summary>
|
||||
public sealed class AttributePointCalculator : IAttributePointCalculator
|
||||
{
|
||||
private const int MaxRank = 12;
|
||||
private const int MinRank = 0;
|
||||
|
||||
private static readonly List<int> PointsRequiredToIncreaseRankMapping = new()
|
||||
{
|
||||
1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, int.MaxValue
|
||||
};
|
||||
|
||||
public int MaximumAttributePoints => 200;
|
||||
|
||||
public int GetPointsRequiredToIncreaseRank(int currentRank)
|
||||
{
|
||||
if (currentRank < MinRank ||
|
||||
currentRank > MaxRank)
|
||||
{
|
||||
throw new ArgumentException($"Current rank must be between {MinRank} and {MaxRank}");
|
||||
}
|
||||
|
||||
return PointsRequiredToIncreaseRankMapping[currentRank];
|
||||
}
|
||||
|
||||
public int GetRemainingFreePoints(Build build)
|
||||
{
|
||||
return this.MaximumAttributePoints - this.GetUsedPoints(build);
|
||||
}
|
||||
|
||||
public int GetUsedPoints(Build build)
|
||||
{
|
||||
var totalPoints = 0;
|
||||
foreach(var attribute in build.Attributes)
|
||||
{
|
||||
for(var i = 0; i < attribute.Points; i++)
|
||||
{
|
||||
totalPoints += this.GetPointsRequiredToIncreaseRank(i);
|
||||
}
|
||||
}
|
||||
|
||||
return totalPoints;
|
||||
}
|
||||
}
|
||||
@@ -190,15 +190,31 @@ public sealed class BuildTemplateManager : IBuildTemplateManager
|
||||
}
|
||||
|
||||
build.Secondary = secondaryProfession;
|
||||
/*
|
||||
* Prepopulate the attributes first and then populate the attribute points based on ids.
|
||||
*/
|
||||
|
||||
if (primaryProfession != Profession.None)
|
||||
{
|
||||
build.Attributes.Add(new AttributeEntry { Attribute = primaryProfession.PrimaryAttribute });
|
||||
build.Attributes.AddRange(primaryProfession.Attributes!.Select(a => new AttributeEntry { Attribute = a }));
|
||||
}
|
||||
|
||||
if (secondaryProfession != Profession.None)
|
||||
{
|
||||
build.Attributes.AddRange(secondaryProfession.Attributes!.Select(a => new AttributeEntry { Attribute = a }));
|
||||
}
|
||||
|
||||
for(int i = 0; i < buildMetadata.AttributeCount; i++)
|
||||
{
|
||||
if (Daybreak.Models.Guildwars.Attribute.TryParse(buildMetadata.AttributesIds[i], out var attribute) is false)
|
||||
var attributeId = buildMetadata.AttributesIds[i];
|
||||
var maybeAttribute = build.Attributes.FirstOrDefault(a => a.Attribute!.Id == attributeId);
|
||||
if (maybeAttribute is null)
|
||||
{
|
||||
this.logger.LogError($"Failed to parse attribute with id {buildMetadata.AttributesIds[i]}");
|
||||
return new InvalidOperationException($"Failed to parse template");
|
||||
this.logger.LogError($"Failed to parse attribute with id {attributeId} for professions {primaryProfession.Name}/{secondaryProfession.Name}");
|
||||
}
|
||||
|
||||
build.Attributes.Add(new AttributeEntry { Attribute = attribute, Points = buildMetadata.AttributePoints[i] });
|
||||
maybeAttribute!.Points = buildMetadata.AttributePoints[i];
|
||||
}
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
|
||||
namespace Daybreak.Services.BuildTemplates;
|
||||
|
||||
public interface IAttributePointCalculator
|
||||
{
|
||||
int MaximumAttributePoints { get; }
|
||||
|
||||
int GetPointsRequiredToIncreaseRank(int currentRank);
|
||||
|
||||
int GetRemainingFreePoints(Build build);
|
||||
|
||||
int GetUsedPoints(Build build);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public sealed class ExperienceCalculator : IExperienceCalculator
|
||||
var previousLevelExperience = 0U;
|
||||
foreach (var threshold in ExperienceThreshold)
|
||||
{
|
||||
if (currentTotalExperience >= threshold)
|
||||
if (threshold >= currentTotalExperience)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -96,6 +96,7 @@ public sealed class ExperienceCalculator : IExperienceCalculator
|
||||
if (currentTotalExperience < ExperienceCalculationThreshold)
|
||||
{
|
||||
var totalXpForNextLevel = 0U;
|
||||
var totalXpForPreviousLevel = 0U;
|
||||
foreach (var threshold in ExperienceThreshold)
|
||||
{
|
||||
if (currentTotalExperience < threshold)
|
||||
@@ -103,9 +104,11 @@ public sealed class ExperienceCalculator : IExperienceCalculator
|
||||
totalXpForNextLevel = threshold;
|
||||
break;
|
||||
}
|
||||
|
||||
totalXpForPreviousLevel = threshold;
|
||||
}
|
||||
|
||||
return totalXpForNextLevel;
|
||||
return totalXpForNextLevel - totalXpForPreviousLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -108,6 +108,7 @@ public sealed class IconBrowser : IIconBrowser
|
||||
logger.LogInformation($"Looking for icon at {skillIconUrl}");
|
||||
|
||||
this.browserWrapper.Address = skillIconUrl;
|
||||
this.browserWrapper.WebBrowser.CoreWebView2.Navigate(skillIconUrl);
|
||||
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
|
||||
@@ -49,25 +49,14 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
scoppedLogger.LogInformation($"Initializing {nameof(GuildwarsMemoryReader)}");
|
||||
if (this.memoryScanner.Process?.MainModule?.FileName != process?.MainModule?.FileName)
|
||||
try
|
||||
{
|
||||
if (this.memoryScanner.Scanning)
|
||||
{
|
||||
scoppedLogger.LogInformation("Scanner is already scanning a different process. Restart scanner and target the new process");
|
||||
this.memoryScanner.EndScanner();
|
||||
}
|
||||
|
||||
await this.ResilientBeginScanner(scoppedLogger, process!);
|
||||
await this.InitializeSafe(process, scoppedLogger);
|
||||
}
|
||||
|
||||
if (!this.memoryScanner.Scanning)
|
||||
catch(Exception e)
|
||||
{
|
||||
await this.ResilientBeginScanner(scoppedLogger, process!);
|
||||
scoppedLogger.LogError(e, "Encountered exception during initialization");
|
||||
}
|
||||
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
this.PeriodicallyReadGuildwarsMemory();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
@@ -77,6 +66,31 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
}
|
||||
|
||||
private async Task InitializeSafe(Process process, ScopedLogger<GuildwarsMemoryReader> scopedLogger)
|
||||
{
|
||||
scopedLogger.LogInformation($"Initializing {nameof(GuildwarsMemoryReader)}");
|
||||
if (this.memoryScanner.Process is null ||
|
||||
this.memoryScanner.Process.HasExited ||
|
||||
this.memoryScanner.Process.MainModule?.FileName != process?.MainModule?.FileName)
|
||||
{
|
||||
if (this.memoryScanner.Scanning)
|
||||
{
|
||||
scopedLogger.LogInformation("Scanner is already scanning a different process. Restart scanner and target the new process");
|
||||
this.memoryScanner.EndScanner();
|
||||
}
|
||||
|
||||
await this.ResilientBeginScanner(scopedLogger, process!);
|
||||
}
|
||||
|
||||
if (!this.memoryScanner.Scanning)
|
||||
{
|
||||
await this.ResilientBeginScanner(scopedLogger, process!);
|
||||
}
|
||||
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
this.PeriodicallyReadGuildwarsMemory();
|
||||
}
|
||||
|
||||
private async Task ResilientBeginScanner(ScopedLogger<GuildwarsMemoryReader> scopedLogger, Process process)
|
||||
{
|
||||
for (var i = 0; i < RetryInitializationCount; i++)
|
||||
@@ -99,7 +113,19 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
{
|
||||
var cancellationTokenSource = new CancellationTokenSource();
|
||||
this.cancellationTokenSource = cancellationTokenSource;
|
||||
System.Extensions.TaskExtensions.RunPeriodicAsync(() => this.ReadGameMemory(cancellationTokenSource.Token), TimeSpan.Zero, TimeSpan.FromSeconds(1), cancellationTokenSource.Token);
|
||||
System.Extensions.TaskExtensions.RunPeriodicAsync(() => this.SafeReadGameMemory(cancellationTokenSource.Token), TimeSpan.Zero, TimeSpan.FromSeconds(1), cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
private void SafeReadGameMemory(CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.ReadGameMemory(cancellationToken);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
this.logger.LogError(e, "Exception encountered when reading game memory");
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadGameMemory(CancellationToken cancellationToken)
|
||||
@@ -121,9 +147,12 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
var globalContext = this.memoryScanner.ReadPtrChain<GlobalContext>(this.memoryScanner.ModuleStartAddress, finalPointerOffset: 0x0, 0x00629244, 0xC, 0xC);
|
||||
|
||||
// GameContext struct is offset by 0x07C due to the memory layout of the structure.
|
||||
var gameContext = this.memoryScanner.Read<GameContext>(globalContext.CharacterContext + GameContext.BaseOffset);
|
||||
var gameContext = this.memoryScanner.Read<GameContext>(globalContext.GameContext + GameContext.BaseOffset);
|
||||
// UserContext struct is offset by 0x074 due to the memory layout of the structure.
|
||||
var userContext = this.memoryScanner.Read<UserContext>(globalContext.UserContext + UserContext.BaseOffset);
|
||||
// InstanceContext struct is offset by 0x01AC due to memory layout of the structure.
|
||||
var instanceContext = this.memoryScanner.Read<InstanceContext>(globalContext.InstanceContext + InstanceContext.BaseOffset);
|
||||
|
||||
var mapEntities = this.memoryScanner.ReadArray<MapEntityContext>(gameContext.MapEntities);
|
||||
var professions = this.memoryScanner.ReadArray<ProfessionsContext>(gameContext.Professions);
|
||||
var players = this.memoryScanner.ReadArray<PlayerContext>(gameContext.Players);
|
||||
@@ -134,10 +163,7 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
//var entityArray = this.memoryScanner.ReadPtrChain<GuildwarsArray>(this.GetEntityArrayPointer(), 0x0, 0x0);
|
||||
//var entities = this.memoryScanner.ReadArray<EntityContext>(entityArray);
|
||||
|
||||
var email = ParseAndCleanWCharArray(userContext.PlayerEmailBytes);
|
||||
var name = ParseAndCleanWCharArray(userContext.PlayerNameBytes);
|
||||
|
||||
this.GameData = AggregateGameData(gameContext, mapEntities, professions, quests, email, name, playerEntityId);
|
||||
this.GameData = this.AggregateGameData(gameContext, instanceContext, mapEntities, players, professions, quests, userContext, playerEntityId);
|
||||
}
|
||||
|
||||
private IntPtr GetPlayerIdPointer()
|
||||
@@ -160,22 +186,33 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
return this.entityArrayPointer;
|
||||
}
|
||||
|
||||
private static GameData AggregateGameData(
|
||||
private GameData AggregateGameData(
|
||||
GameContext gameContext,
|
||||
InstanceContext instanceContext,
|
||||
MapEntityContext[] entities,
|
||||
PlayerContext[] players,
|
||||
ProfessionsContext[] professions,
|
||||
QuestContext[] quests,
|
||||
string email,
|
||||
string name,
|
||||
UserContext userContext,
|
||||
int mainPlayerEntityId)
|
||||
{
|
||||
var email = ParseAndCleanWCharArray(userContext.PlayerEmailBytes);
|
||||
var name = ParseAndCleanWCharArray(userContext.PlayerNameBytes);
|
||||
_ = Map.TryParse((int)userContext.MapId, out var currentMap);
|
||||
var partyMembers = professions
|
||||
.Where(p => p.AgentId != mainPlayerEntityId)
|
||||
.Select(p => GetPlayerInformation((int)p.AgentId, entities, professions))
|
||||
.Select(p => GetPlayerInformation((int)p.AgentId, instanceContext, entities, professions))
|
||||
.ToList();
|
||||
|
||||
var mainPlayer = GetMainPlayerInformation(mainPlayerEntityId, name, gameContext, entities, professions, quests);
|
||||
var mainPlayer = GetMainPlayerInformation(mainPlayerEntityId, name, gameContext, instanceContext, entities, professions, quests);
|
||||
|
||||
var worldPlayers = players
|
||||
.Where(p => p.AgentId != mainPlayerEntityId)
|
||||
.Select(p => GetWorldPlayerInformation(p, this.memoryScanner.ReadWString(p.NamePointer, 0x40), instanceContext, entities, professions))
|
||||
.ToList();
|
||||
|
||||
|
||||
|
||||
var userInformation = new UserInformation
|
||||
{
|
||||
Email = email,
|
||||
@@ -198,7 +235,8 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
var sessionInformation = new SessionInformation
|
||||
{
|
||||
FoesKilled = gameContext.FoesKilled,
|
||||
FoesToKill = gameContext.FoesToKill
|
||||
FoesToKill = gameContext.FoesToKill,
|
||||
CurrentMap = currentMap
|
||||
};
|
||||
|
||||
return new GameData
|
||||
@@ -206,7 +244,8 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
Party = partyMembers,
|
||||
MainPlayer = mainPlayer,
|
||||
Session = sessionInformation,
|
||||
User = userInformation
|
||||
User = userInformation,
|
||||
WorldPlayers = worldPlayers
|
||||
};
|
||||
}
|
||||
|
||||
@@ -214,11 +253,12 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
int mainPlayerId,
|
||||
string name,
|
||||
GameContext gameContext,
|
||||
InstanceContext instanceContext,
|
||||
MapEntityContext[] entities,
|
||||
ProfessionsContext[] professions,
|
||||
QuestContext[] quests)
|
||||
{
|
||||
var playerInformation = GetPlayerInformation(mainPlayerId, entities, professions);
|
||||
var playerInformation = GetPlayerInformation(mainPlayerId, instanceContext, entities, professions);
|
||||
_ = Quest.TryParse((int)gameContext.QuestId, out var quest);
|
||||
var questLog = quests
|
||||
.Select(q =>
|
||||
@@ -252,8 +292,32 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
};
|
||||
}
|
||||
|
||||
private static WorldPlayerInformation GetWorldPlayerInformation(
|
||||
PlayerContext playerContext,
|
||||
string name,
|
||||
InstanceContext instanceContext,
|
||||
MapEntityContext[] entities,
|
||||
ProfessionsContext[] professions)
|
||||
{
|
||||
var playerInformation = GetPlayerInformation(playerContext.AgentId, instanceContext, entities, professions);
|
||||
return new WorldPlayerInformation
|
||||
{
|
||||
PrimaryProfession = playerInformation.PrimaryProfession,
|
||||
SecondaryProfession = playerInformation.SecondaryProfession,
|
||||
UnlockedProfession = playerInformation.UnlockedProfession,
|
||||
CurrentEnergy = playerInformation.CurrentEnergy,
|
||||
CurrentHealth = playerInformation.CurrentHealth,
|
||||
MaxEnergy = playerInformation.MaxEnergy,
|
||||
MaxHealth = playerInformation.MaxHealth,
|
||||
EnergyRegen = playerInformation.EnergyRegen,
|
||||
HealthRegen = playerInformation.HealthRegen,
|
||||
Name = name,
|
||||
};
|
||||
}
|
||||
|
||||
private static PlayerInformation GetPlayerInformation(
|
||||
int playerId,
|
||||
InstanceContext instanceContext,
|
||||
MapEntityContext[] entities,
|
||||
ProfessionsContext[] professions)
|
||||
{
|
||||
@@ -264,16 +328,17 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
var unlockedProfessions = Profession.Professions
|
||||
.Where(p => professionContext.ProfessionUnlocked(p.Id))
|
||||
.Append(primaryProfession)
|
||||
.Where(p => p != Profession.None)
|
||||
.Where(p => p is not null && p != Profession.None)
|
||||
.OrderBy(p => p.Id)
|
||||
.ToList();
|
||||
(var currentHp, var currentEnergy) = ApplyEnergyAndHealthRegen(instanceContext, entityContext);
|
||||
return new PlayerInformation
|
||||
{
|
||||
PrimaryProfession = primaryProfession,
|
||||
SecondaryProfession = secondaryProfession,
|
||||
UnlockedProfession = unlockedProfessions,
|
||||
CurrentHealth = entityContext.CurrentHealth,
|
||||
CurrentEnergy = entityContext.CurrentEnergy,
|
||||
CurrentHealth = currentHp,
|
||||
CurrentEnergy = currentEnergy,
|
||||
MaxHealth = entityContext.MaxHealth,
|
||||
MaxEnergy = entityContext.MaxEnergy,
|
||||
HealthRegen = entityContext.HealthRegen,
|
||||
@@ -281,6 +346,20 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
|
||||
};
|
||||
}
|
||||
|
||||
private static (float CurrentHp, float CurrentEnergy) ApplyEnergyAndHealthRegen(InstanceContext instanceContext, MapEntityContext entityContext)
|
||||
{
|
||||
var lastKnownHp = entityContext.CurrentHealth;
|
||||
var lastKnownEnergy = entityContext.CurrentEnergy;
|
||||
var hpRegen = entityContext.HealthRegen;
|
||||
var energyRegen = entityContext.EnergyRegen;
|
||||
var millisSinceLastKnownInformation = instanceContext.Timer - (uint)entityContext.SkillTimestamp;
|
||||
var currentHp = lastKnownHp + (hpRegen * ((float)millisSinceLastKnownInformation / 1000));
|
||||
var currentEnergy = lastKnownEnergy + (energyRegen * ((float)millisSinceLastKnownInformation / 1000));
|
||||
return (
|
||||
currentHp > entityContext.MaxHealth ? entityContext.MaxHealth : currentHp,
|
||||
currentEnergy > entityContext.MaxEnergy ? entityContext.MaxEnergy : currentEnergy);
|
||||
}
|
||||
|
||||
private static string ParseAndCleanWCharArray(byte[] bytes)
|
||||
{
|
||||
var str = Encoding.Unicode.GetString(bytes);
|
||||
|
||||
@@ -99,6 +99,7 @@ public sealed class MemoryScanner : IMemoryScanner
|
||||
this.Memory = default;
|
||||
this.Size = default;
|
||||
this.ModuleStartAddress = default;
|
||||
this.Scanning = false;
|
||||
Monitor.Exit(LockObject);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="#A0202020">
|
||||
<Grid Background="#F0212121">
|
||||
<TextBlock HorizontalAlignment="Center" Text="Accounts settings" FontSize="22" Foreground="White"></TextBlock>
|
||||
<controls:AddButton Foreground="White" Height="30" Width="30" Grid.Column="0" HorizontalAlignment="Right" Margin="5, 5, 45, 5"
|
||||
Clicked="AddButton_Clicked" VerticalAlignment="Top"></controls:AddButton>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using Daybreak.Controls;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Credentials;
|
||||
using Daybreak.Services.Navigation;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
@@ -15,14 +17,17 @@ namespace Daybreak.Views;
|
||||
/// </summary>
|
||||
public partial class AccountsView : UserControl
|
||||
{
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly ICredentialManager credentialManager;
|
||||
|
||||
public ObservableCollection<LoginCredentials> Accounts { get; } = new();
|
||||
|
||||
public AccountsView(
|
||||
IViewManager viewManager,
|
||||
ICredentialManager credentialManager)
|
||||
{
|
||||
this.credentialManager = credentialManager.ThrowIfNull(nameof(credentialManager));
|
||||
this.viewManager = viewManager.ThrowIfNull();
|
||||
this.credentialManager = credentialManager.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
this.GetCredentials();
|
||||
}
|
||||
@@ -46,6 +51,7 @@ public partial class AccountsView : UserControl
|
||||
private async void SaveButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
await this.credentialManager.StoreCredentials(this.Accounts.ToList()).ConfigureAwait(true);
|
||||
this.viewManager.ShowView<LauncherView>();
|
||||
}
|
||||
|
||||
private void AccountTemplate_RemoveClicked(object sender, EventArgs e)
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Width="400" Height="200"
|
||||
Background="White">
|
||||
Background="#F0212121">
|
||||
<StackPanel VerticalAlignment="Center" Orientation="Vertical">
|
||||
<TextBlock Text="An update has been detected. Do you want to download the update?" HorizontalAlignment="Center"
|
||||
FontSize="16" Foreground="Black" Margin="10, 0, 10, 10" TextWrapping="Wrap"></TextBlock>
|
||||
FontSize="16" Foreground="White" Margin="10, 0, 10, 10" TextWrapping="Wrap"></TextBlock>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:OpaqueButton Text="Yes" BackgroundOpacity="0.2" TransparentBackground="Gray" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
|
||||
Clicked="YesButton_Clicked" Foreground="Black" FontSize="16"></controls:OpaqueButton>
|
||||
<controls:OpaqueButton Text="No" BackgroundOpacity="0.2" TransparentBackground="Gray" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
|
||||
Clicked="NoButton_Clicked" Foreground="Black" Grid.Column="1" FontSize="16"></controls:OpaqueButton>
|
||||
<controls:OpaqueButton Text="Yes" BackgroundOpacity="0.2" TransparentBackground="Gray" Highlight="White" HighlightOpacity="0.6" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
|
||||
Clicked="YesButton_Clicked" Foreground="White" FontSize="16" Cursor="Hand"></controls:OpaqueButton>
|
||||
<controls:OpaqueButton Text="No" BackgroundOpacity="0.2" TransparentBackground="Gray" Highlight="White" HighlightOpacity="0.6" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
|
||||
Clicked="NoButton_Clicked" Foreground="White" Grid.Column="1" FontSize="16" Cursor="Hand"></controls:OpaqueButton>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="#A0202020">
|
||||
<Grid Background="#F0212121">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
@@ -40,10 +40,15 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Code: " Foreground="White" Background="Transparent" FontSize="16"></TextBlock>
|
||||
<TextBox Grid.Column="1" Foreground="White" Background="Transparent" FontSize="16"
|
||||
Text="{Binding ElementName=_this, Path=CurrentBuildCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
|
||||
<TextBlock Grid.Column="2" Text="Points: " Foreground="White" Background="Transparent" FontSize="16" Margin="10, 0, 0, 0"></TextBlock>
|
||||
<TextBox Grid.Column="3" Foreground="White" Background="Transparent" FontSize="16"
|
||||
Text="{Binding ElementName=_this, Path=AttributePoints, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
|
||||
</Grid>
|
||||
<controls:BuildTemplate x:Name="BuildTemplate" Grid.Row="2" DataContext="{Binding ElementName=_this, Path=CurrentBuild, Mode=OneWay}"
|
||||
BuildChanged="BuildTemplate_BuildChanged">
|
||||
|
||||
@@ -8,6 +8,7 @@ using Daybreak.Services.Navigation;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
@@ -23,10 +24,9 @@ public partial class BuildTemplateView : UserControl
|
||||
{
|
||||
private const string DisallowedChars = "\r\n/.";
|
||||
|
||||
private bool supressDecode = false;
|
||||
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IBuildTemplateManager buildTemplateManager;
|
||||
private readonly IAttributePointCalculator attributePointCalculator;
|
||||
private readonly ILogger<BuildTemplateView> logger;
|
||||
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
@@ -35,28 +35,33 @@ public partial class BuildTemplateView : UserControl
|
||||
private BuildEntry currentBuild = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private string currentBuildCode = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private int attributePoints;
|
||||
|
||||
public BuildTemplateView(
|
||||
IViewManager viewManager,
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
IIconCache iconRetriever,
|
||||
IIconBrowser iconBrowser,
|
||||
IAttributePointCalculator attributePointCalculator,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
ILogger<ChromiumBrowserWrapper> chromiumLogger,
|
||||
ILogger<BuildTemplateView> logger)
|
||||
{
|
||||
this.buildTemplateManager = buildTemplateManager.ThrowIfNull(nameof(buildTemplateManager));
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.buildTemplateManager = buildTemplateManager.ThrowIfNull();
|
||||
this.logger = logger.ThrowIfNull();
|
||||
this.viewManager = viewManager.ThrowIfNull();
|
||||
this.attributePointCalculator = attributePointCalculator.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
this.BuildTemplate.InitializeTemplate(iconRetriever, iconBrowser, liveOptions, buildTemplateManager, chromiumLogger);
|
||||
this.BuildTemplate.InitializeTemplate(attributePointCalculator, iconRetriever, iconBrowser, liveOptions, buildTemplateManager, chromiumLogger);
|
||||
this.DataContextChanged += (sender, contextArgs) =>
|
||||
{
|
||||
if (contextArgs.NewValue is BuildEntry)
|
||||
if (contextArgs.NewValue is BuildEntry buildEntry)
|
||||
{
|
||||
this.logger.LogInformation("Received data context. Setting current build");
|
||||
this.CurrentBuild = contextArgs.NewValue.As<BuildEntry>();
|
||||
this.CurrentBuild = buildEntry;
|
||||
this.CurrentBuildCode = this.buildTemplateManager.EncodeTemplate(this.CurrentBuild.Build!);
|
||||
this.AttributePoints = this.attributePointCalculator.GetRemainingFreePoints(this.CurrentBuild.Build!);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -64,7 +69,7 @@ public partial class BuildTemplateView : UserControl
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (e.Property == CurrentBuildCodeProperty && this.supressDecode is false)
|
||||
if (e.Property == CurrentBuildCodeProperty)
|
||||
{
|
||||
this.logger.LogInformation($"Attempting to decode provided template {this.CurrentBuildCode}");
|
||||
try
|
||||
@@ -88,6 +93,8 @@ public partial class BuildTemplateView : UserControl
|
||||
Build = new Build()
|
||||
};
|
||||
}
|
||||
|
||||
this.AttributePoints = this.attributePointCalculator.GetRemainingFreePoints(this.CurrentBuild.Build!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,12 +102,11 @@ public partial class BuildTemplateView : UserControl
|
||||
{
|
||||
try
|
||||
{
|
||||
this.supressDecode = true;
|
||||
this.CurrentBuildCode = this.buildTemplateManager.EncodeTemplate(this.CurrentBuild.Build!);
|
||||
this.AttributePoints = this.attributePointCalculator.GetRemainingFreePoints(this.CurrentBuild.Build!);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.supressDecode = false;
|
||||
}
|
||||
}
|
||||
private void BackButton_Clicked(object sender, EventArgs e)
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="#A0202020">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="#F0212121">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
@@ -30,5 +33,9 @@
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<controls:CircularLoadingWidget Grid.RowSpan="3"
|
||||
Width="100"
|
||||
Height="100"
|
||||
Visibility="{Binding ElementName=_this, Path=Loading, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></controls:CircularLoadingWidget>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Views;
|
||||
|
||||
@@ -21,6 +22,9 @@ public partial class BuildsListView : UserControl
|
||||
|
||||
private IEnumerable<BuildEntry>? buildEntries;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool loading;
|
||||
|
||||
public ObservableCollection<BuildEntry> BuildEntries { get; } = new ObservableCollection<BuildEntry>();
|
||||
|
||||
public BuildsListView(
|
||||
@@ -35,8 +39,10 @@ public partial class BuildsListView : UserControl
|
||||
|
||||
private async void LoadBuilds()
|
||||
{
|
||||
this.Loading = true;
|
||||
this.buildEntries = await this.buildTemplateManager.GetBuilds().ToListAsync();
|
||||
this.BuildEntries.ClearAnd().AddRange(this.buildEntries.OrderBy(b => b.Name));
|
||||
this.Loading = false;
|
||||
}
|
||||
|
||||
private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<BooleanToVisibilityConverter x:Key="BaseBooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid
|
||||
Background="#A0202020">
|
||||
Background="#F0212121">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
@@ -174,7 +174,7 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Grid.RowSpan="3"
|
||||
Background="#A0202020"
|
||||
Background="#F0212121"
|
||||
Visibility="{Binding ElementName=_this, Path=ShowLoading, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<controls:CircularLoadingWidget MaxWidth="200"
|
||||
MaxHeight="200"/>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="#A0202020">
|
||||
<Grid Background="#F0212121">
|
||||
<TextBlock HorizontalAlignment="Center" Text="Executables settings" FontSize="22" Foreground="White"></TextBlock>
|
||||
<controls:AddButton Foreground="White" Height="30" Width="30" Grid.Column="0" HorizontalAlignment="Right" Margin="5, 5, 45, 5"
|
||||
Clicked="AddButton_Clicked" VerticalAlignment="Top"></controls:AddButton>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Controls;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Navigation;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
@@ -16,13 +18,16 @@ namespace Daybreak.Views;
|
||||
/// </summary>
|
||||
public partial class ExecutablesView : UserControl
|
||||
{
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions;
|
||||
public ObservableCollection<GuildwarsPath> Paths { get; } = new();
|
||||
|
||||
public ExecutablesView(
|
||||
IViewManager viewManager,
|
||||
ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions)
|
||||
{
|
||||
this.liveUpdateableOptions = liveUpdateableOptions.ThrowIfNull(nameof(liveUpdateableOptions));
|
||||
this.viewManager = viewManager.ThrowIfNull();
|
||||
this.liveUpdateableOptions = liveUpdateableOptions.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
this.GetPaths();
|
||||
}
|
||||
@@ -46,6 +51,7 @@ public partial class ExecutablesView : UserControl
|
||||
{
|
||||
this.liveUpdateableOptions.Value.GuildwarsPaths = this.Paths.ToList();
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
this.viewManager.ShowView<LauncherView>();
|
||||
}
|
||||
|
||||
private void GuildwarsPathTemplate_DefaultClicked(object sender, EventArgs e)
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="#A0202020">
|
||||
<Grid Background="#F0212121">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Navigation;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
@@ -14,6 +16,8 @@ namespace Daybreak.Views;
|
||||
/// </summary>
|
||||
public partial class ExperimentalSettingsView : UserControl
|
||||
{
|
||||
private readonly IViewManager viewManager;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool launchAsCurrentUser;
|
||||
[GenerateDependencyProperty]
|
||||
@@ -32,9 +36,11 @@ public partial class ExperimentalSettingsView : UserControl
|
||||
private readonly ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions;
|
||||
|
||||
public ExperimentalSettingsView(
|
||||
IViewManager viewManager,
|
||||
ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions)
|
||||
{
|
||||
this.liveUpdateableOptions = liveUpdateableOptions.ThrowIfNull(nameof(liveUpdateableOptions));
|
||||
this.viewManager = viewManager.ThrowIfNull();
|
||||
this.liveUpdateableOptions = liveUpdateableOptions.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
this.LoadExperimentalSettings();
|
||||
}
|
||||
@@ -66,6 +72,7 @@ public partial class ExperimentalSettingsView : UserControl
|
||||
}
|
||||
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
this.viewManager.ShowView<LauncherView>();
|
||||
}
|
||||
|
||||
private void SaveButton_Clicked(object sender, EventArgs e)
|
||||
|
||||
+255
-87
@@ -7,6 +7,7 @@
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
xmlns:templates="clr-namespace:Daybreak.Controls.Templates"
|
||||
mc:Ignorable="d"
|
||||
Foreground="White"
|
||||
Loaded="FocusView_Loaded"
|
||||
Unloaded="FocusView_Unloaded"
|
||||
x:Name="_this"
|
||||
@@ -16,123 +17,291 @@
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.1*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="0.01*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="0.1*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="0.01*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="0.1*"></RowDefinition>
|
||||
<RowDefinition Height="0.6*"></RowDefinition>
|
||||
<RowDefinition Height="0.2*"></RowDefinition>
|
||||
<RowDefinition Height="0.1*"></RowDefinition>
|
||||
<RowDefinition Height="0*"></RowDefinition>
|
||||
<RowDefinition Height="1*"></RowDefinition>
|
||||
<RowDefinition Height="118"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<controls:ResourceBar
|
||||
<Grid
|
||||
Margin="0, 2, 0, 0"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
Grid.RowSpan="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="0.1*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="0.3*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="0.1*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:VerticalResourceBar
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
Height="30"
|
||||
Grid.ColumnSpan="3"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=CurrentExperienceInLevel, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=NextLevelExperienceThreshold, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Center"
|
||||
BarColor="#a026ff00"
|
||||
Text="{Binding ElementName=_this,Path=ExperienceBarText, Mode=OneWay}"
|
||||
BarColor="#6076FF03"
|
||||
Foreground="White"
|
||||
FontSize="22"
|
||||
Height="113"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=ExperienceBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="ExperienceBar_MouseLeftButtonDown"></controls:ResourceBar>
|
||||
<controls:ResourceBar
|
||||
Grid.Column="1"
|
||||
MouseLeftButtonDown="ExperienceBar_MouseLeftButtonDown">
|
||||
<controls:VerticalResourceBar.OpacityMask>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<GeometryDrawing Brush="#FFFFFFFF">
|
||||
<GeometryDrawing.Geometry>
|
||||
<PathGeometry>
|
||||
<PathGeometry.Figures>
|
||||
<PathFigure IsClosed="True" StartPoint="5, 1">
|
||||
<PathSegmentCollection>
|
||||
<LineSegment Point="1, 5"></LineSegment>
|
||||
<LineSegment Point="5, 9"></LineSegment>
|
||||
<LineSegment Point="15, 9"></LineSegment>
|
||||
<LineSegment Point="19, 5"></LineSegment>
|
||||
<LineSegment Point="15, 1"></LineSegment>
|
||||
</PathSegmentCollection>
|
||||
</PathFigure>
|
||||
</PathGeometry.Figures>
|
||||
</PathGeometry>
|
||||
</GeometryDrawing.Geometry>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</controls:VerticalResourceBar.OpacityMask>
|
||||
</controls:VerticalResourceBar>
|
||||
<StackPanel
|
||||
VerticalAlignment="Center"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
Margin="0, 0, 20, 80"
|
||||
Height="30"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.User.CurrentKurzickPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.User.TotalKurzickPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#a00b00ff"
|
||||
Foreground="White"
|
||||
FontSize="22"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=KurzickBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="KurzickBar_MouseLeftButtonDown"></controls:ResourceBar>
|
||||
<controls:ResourceBar
|
||||
Grid.Column="1"
|
||||
Grid.RowSpan="2">
|
||||
<StackPanel.OpacityMask>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<GeometryDrawing Brush="#FFFFFFFF">
|
||||
<GeometryDrawing.Geometry>
|
||||
<PathGeometry>
|
||||
<PathGeometry.Figures>
|
||||
<PathFigure IsClosed="True" StartPoint="1, 1">
|
||||
<PathSegmentCollection>
|
||||
<LineSegment Point="1, 9"></LineSegment>
|
||||
<LineSegment Point="21, 9"></LineSegment>
|
||||
<LineSegment Point="19, 5"></LineSegment>
|
||||
<LineSegment Point="21, 1"></LineSegment>
|
||||
</PathSegmentCollection>
|
||||
</PathFigure>
|
||||
</PathGeometry.Figures>
|
||||
</PathGeometry>
|
||||
</GeometryDrawing.Geometry>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</StackPanel.OpacityMask>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Height="{Binding ElementName=_this, Path=LeftSideBarSize, Mode=OneWay}"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.User.CurrentKurzickPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.User.MaxKurzickPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#603D5AFE"
|
||||
Foreground="White"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=KurzickBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="KurzickBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Height="{Binding ElementName=_this, Path=LeftSideBarSize, Mode=OneWay}"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.User.CurrentLuxonPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.User.MaxLuxonPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#60FF9100"
|
||||
Foreground="White"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=LuxonBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="LuxonBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Height="{Binding ElementName=_this, Path=LeftSideBarSize, Mode=OneWay}"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.User.CurrentImperialPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.User.MaxImperialPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#60651FFF"
|
||||
Foreground="White"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=ImperialBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="ImperialBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Height="{Binding ElementName=_this, Path=LeftSideBarSize, Mode=OneWay}"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.User.CurrentBalthazarPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.User.MaxBalthazarPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#60FFEA00"
|
||||
Foreground="White"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=BalthazarBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="BalthazarBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
VerticalAlignment="Center"
|
||||
Grid.Column="3"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
Margin="0, 0, 20, 40"
|
||||
Height="30"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.User.CurrentLuxonPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.User.TotalLuxonPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#a0ff3400"
|
||||
Foreground="White"
|
||||
FontSize="22"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=LuxonBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="LuxonBar_MouseLeftButtonDown"></controls:ResourceBar>
|
||||
<controls:ResourceBar
|
||||
Grid.Column="2"
|
||||
Grid.Row="2"
|
||||
Margin="20, 0, 0, 80"
|
||||
Height="30"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.User.CurrentImperialPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.User.TotalImperialPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#a0a800ff"
|
||||
Foreground="White"
|
||||
FontSize="22"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=ImperialBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="ImperialBar_MouseLeftButtonDown"></controls:ResourceBar>
|
||||
<controls:ResourceBar
|
||||
Grid.Column="2"
|
||||
Grid.Row="2"
|
||||
Margin="20, 0, 0, 40"
|
||||
Height="30"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.User.CurrentBalthazarPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.User.TotalBalthazarPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#a0ffb200"
|
||||
Foreground="White"
|
||||
FontSize="22"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=BalthazarBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="BalthazarBar_MouseLeftButtonDown"></controls:ResourceBar>
|
||||
Grid.RowSpan="2">
|
||||
<StackPanel.OpacityMask>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<GeometryDrawing Brush="#FFFFFFFF">
|
||||
<GeometryDrawing.Geometry>
|
||||
<PathGeometry>
|
||||
<PathGeometry.Figures>
|
||||
<PathFigure IsClosed="True" StartPoint="1, 1">
|
||||
<PathSegmentCollection>
|
||||
<LineSegment Point="3, 5"></LineSegment>
|
||||
<LineSegment Point="1, 9"></LineSegment>
|
||||
<LineSegment Point="21, 9"></LineSegment>
|
||||
<LineSegment Point="21, 1"></LineSegment>
|
||||
</PathSegmentCollection>
|
||||
</PathFigure>
|
||||
</PathGeometry.Figures>
|
||||
</PathGeometry>
|
||||
</GeometryDrawing.Geometry>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</StackPanel.OpacityMask>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Height="{Binding ElementName=_this, Path=RightSideBarSize, Mode=OneWay}"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.Session.FoesKilled, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=TotalFoes, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#60DD2C00"
|
||||
Foreground="White"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=VanquishingText, Mode=OneWay}"
|
||||
FillAlignment="Right"
|
||||
Visibility="{Binding ElementName=_this, Path=Vanquishing, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
MouseLeftButtonDown="VanquishingBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Height="{Binding ElementName=_this, Path=RightSideBarSize, Mode=OneWay}"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.MainPlayer.CurrentHealth, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.MainPlayer.MaxHealth, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#60D50000"
|
||||
Foreground="White"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=HealthBarText, Mode=OneWay}"
|
||||
FillAlignment="Right"
|
||||
MouseLeftButtonDown="HealthBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Height="{Binding ElementName=_this, Path=RightSideBarSize, Mode=OneWay}"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=GameData.MainPlayer.CurrentEnergy, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=GameData.MainPlayer.MaxEnergy, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="#6018FFFF"
|
||||
Foreground="White"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=EnergyBarText, Mode=OneWay}"
|
||||
FillAlignment="Right"
|
||||
MouseLeftButtonDown="EnergyBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="10"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="10"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel
|
||||
Background="#F0212121"
|
||||
Grid.Row="0"
|
||||
Margin="0, 0, 10, 0">
|
||||
Margin="0, 0, 5, 0">
|
||||
<TextBlock
|
||||
FontSize="18"
|
||||
Margin="5"
|
||||
Text="Current Quest"></TextBlock>
|
||||
<TextBlock
|
||||
Text="{Binding ElementName=_this, Path=GameData.MainPlayer.Quest.Name, Mode=OneWay}"
|
||||
Cursor="Hand"
|
||||
FontSize="20"
|
||||
MouseLeftButtonDown="CurrentQuest_MouseLeftButtonDown"></TextBlock>
|
||||
Margin="10"
|
||||
Text="Current Map"></TextBlock>
|
||||
<Rectangle
|
||||
Height="1"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Rectangle>
|
||||
<controls:OpaqueButton
|
||||
Text="{Binding ElementName=_this, Path=GameData.Session.CurrentMap.Name, Mode=OneWay}"
|
||||
Highlight="White"
|
||||
HighlightOpacity="0.6"
|
||||
HorizontalAlignment="Stretch"
|
||||
TextHorizontalAlignment="Left"
|
||||
Cursor="Hand"
|
||||
FontSize="20"
|
||||
MouseLeftButtonDown="CurrentMap_MouseLeftButtonDown"></controls:OpaqueButton>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Background="#F0212121"
|
||||
Grid.Row="2"
|
||||
Margin="0, 0, 5, 0">
|
||||
<TextBlock
|
||||
FontSize="18"
|
||||
Margin="5"
|
||||
Text="Quest Log"></TextBlock>
|
||||
Margin="10"
|
||||
Text="Current Quest"></TextBlock>
|
||||
<Rectangle
|
||||
Height="1"
|
||||
Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Rectangle>
|
||||
<controls:OpaqueButton
|
||||
Text="{Binding ElementName=_this, Path=GameData.MainPlayer.Quest.Name, Mode=OneWay}"
|
||||
Highlight="White"
|
||||
HighlightOpacity="0.6"
|
||||
HorizontalAlignment="Stretch"
|
||||
TextHorizontalAlignment="Left"
|
||||
Cursor="Hand"
|
||||
FontSize="20"
|
||||
MouseLeftButtonDown="CurrentQuest_MouseLeftButtonDown"></controls:OpaqueButton>
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Background="#F0212121"
|
||||
Grid.Row="4"
|
||||
FontSize="18"
|
||||
Margin="0, 0, 5, 0"
|
||||
Padding="10"
|
||||
Text="Quest Log"></TextBlock>
|
||||
<ScrollViewer
|
||||
Background="#F0212121"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
Grid.Row="1">
|
||||
Grid.Row="5"
|
||||
Margin="0, 0, 5, 0">
|
||||
<templates:QuestLogTemplate
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Quests="{Binding ElementName=_this,Path=GameData.MainPlayer.QuestLog, Mode=OneWay}"
|
||||
@@ -141,12 +310,11 @@
|
||||
</templates:QuestLogTemplate>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
<controls:ChromiumBrowserWrapper
|
||||
x:Name="Browser"
|
||||
Grid.Column="2"
|
||||
Grid.Row="1"
|
||||
Margin="10, 0, 0, 0"
|
||||
Margin="5, 0, 0, 0"
|
||||
ControlsEnabled="True"
|
||||
AddressBarReadonly="False"
|
||||
CanNavigate="True"
|
||||
|
||||
@@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Drawing.Printing;
|
||||
using System.Extensions;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
@@ -22,6 +23,8 @@ namespace Daybreak.Views;
|
||||
/// </summary>
|
||||
public partial class FocusView : UserControl
|
||||
{
|
||||
private const double BarsTotalSize = 116; // Size of the bars on one side of the screen.
|
||||
|
||||
private readonly IApplicationLauncher applicationLauncher;
|
||||
private readonly IGuildwarsMemoryReader guildwarsMemoryReader;
|
||||
private readonly IExperienceCalculator experienceCalculator;
|
||||
@@ -38,7 +41,6 @@ public partial class FocusView : UserControl
|
||||
private double nextLevelExperienceThreshold;
|
||||
[GenerateDependencyProperty]
|
||||
private string experienceBarText = string.Empty;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private string luxonBarText = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
@@ -48,6 +50,23 @@ public partial class FocusView : UserControl
|
||||
[GenerateDependencyProperty]
|
||||
private string balthazarBarText = string.Empty;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private string healthBarText = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private string energyBarText = string.Empty;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool vanquishing;
|
||||
[GenerateDependencyProperty]
|
||||
private uint totalFoes;
|
||||
[GenerateDependencyProperty]
|
||||
private string vanquishingText = string.Empty;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private double leftSideBarSize;
|
||||
[GenerateDependencyProperty]
|
||||
private double rightSideBarSize;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private string browserAddress = string.Empty;
|
||||
|
||||
@@ -72,6 +91,7 @@ public partial class FocusView : UserControl
|
||||
|
||||
this.InitializeComponent();
|
||||
|
||||
this.LeftSideBarSize = 25;
|
||||
this.InitializeBrowser();
|
||||
}
|
||||
|
||||
@@ -84,6 +104,11 @@ public partial class FocusView : UserControl
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.BrowserUrl = this.BrowserAddress;
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
}
|
||||
else if (e.Property == VanquishingProperty &&
|
||||
e.OldValue != e.NewValue)
|
||||
{
|
||||
this.UpdateRightSideBarsLayout();
|
||||
}
|
||||
|
||||
base.OnPropertyChanged(e);
|
||||
}
|
||||
@@ -101,42 +126,68 @@ public partial class FocusView : UserControl
|
||||
this.viewManager.ShowView<LauncherView>();
|
||||
}
|
||||
|
||||
if (this.guildwarsMemoryReader.Running is false)
|
||||
{
|
||||
this.guildwarsMemoryReader.Initialize(this.applicationLauncher.RunningGuildwarsProcess!);
|
||||
}
|
||||
|
||||
this.Dispatcher.Invoke(() =>
|
||||
{
|
||||
this.GameData = this.guildwarsMemoryReader.GameData;
|
||||
if (this.GameData?.MainPlayer is null)
|
||||
if (this.GameData?.MainPlayer is null ||
|
||||
this.GameData?.User is null ||
|
||||
this.GameData?.Session is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.CurrentExperienceInLevel = this.experienceCalculator.GetExperienceForCurrentLevel(this.GameData.MainPlayer!.Experience);
|
||||
this.NextLevelExperienceThreshold = this.experienceCalculator.GetNextExperienceThreshold(this.GameData.MainPlayer!.Experience);
|
||||
this.TotalFoes = this.GameData.Session.FoesKilled + this.GameData.Session.FoesToKill;
|
||||
this.Vanquishing = this.GameData.Session.FoesToKill + this.GameData.Session.FoesKilled > 0U;
|
||||
this.UpdateExperienceText();
|
||||
this.UpdateLuxonText();
|
||||
this.UpdateKurzickText();
|
||||
this.UpdateImperialText();
|
||||
this.UpdateBalthazarText();
|
||||
this.UpdateVanquishingText();
|
||||
this.UpdateHealthText();
|
||||
this.UpdateEnergyText();
|
||||
},
|
||||
System.Windows.Threading.DispatcherPriority.ApplicationIdle);
|
||||
}
|
||||
|
||||
private void UpdateRightSideBarsLayout()
|
||||
{
|
||||
// If vanquishing, there's 3 bars, otherwise there's only 2 bars
|
||||
var bars = this.Vanquishing ? 3 : 2;
|
||||
var marginsTotalSize = 4 * bars;
|
||||
var finalBarSize = (BarsTotalSize - marginsTotalSize) / bars;
|
||||
this.RightSideBarSize = finalBarSize;
|
||||
}
|
||||
|
||||
private void UpdateExperienceText()
|
||||
{
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay)
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.ExperienceDisplay)
|
||||
{
|
||||
case Configuration.FocusView.EnergyDisplay.CurrentLevelCurrentAndCurrentLevelMax:
|
||||
case Configuration.FocusView.ExperienceDisplay.CurrentLevelCurrentAndCurrentLevelMax:
|
||||
var currentExperienceInLevel = this.experienceCalculator.GetExperienceForCurrentLevel(this.GameData.MainPlayer!.Experience);
|
||||
var nextLevelExperienceThreshold = this.experienceCalculator.GetNextExperienceThreshold(this.GameData.MainPlayer!.Experience);
|
||||
this.ExperienceBarText = $"{currentExperienceInLevel} / {nextLevelExperienceThreshold} XP";
|
||||
this.ExperienceBarText = $"{(int)currentExperienceInLevel} / {(int)nextLevelExperienceThreshold} XP";
|
||||
break;
|
||||
case Configuration.FocusView.EnergyDisplay.TotalCurretAndTotalMax:
|
||||
case Configuration.FocusView.ExperienceDisplay.TotalCurretAndTotalMax:
|
||||
var currentTotalExperience = this.GameData.MainPlayer!.Experience;
|
||||
var requiredTotalExperience = this.experienceCalculator.GetTotalExperienceForNextLevel(currentTotalExperience);
|
||||
this.ExperienceBarText = $"{currentTotalExperience} / {requiredTotalExperience} XP";
|
||||
this.ExperienceBarText = $"{(int)currentTotalExperience} / {(int)requiredTotalExperience} XP";
|
||||
break;
|
||||
case Configuration.FocusView.EnergyDisplay.RemainingUntilNextLevel:
|
||||
case Configuration.FocusView.ExperienceDisplay.RemainingUntilNextLevel:
|
||||
var remainingExperience = this.experienceCalculator.GetRemainingExperienceForNextLevel(this.GameData.MainPlayer!.Experience);
|
||||
this.ExperienceBarText = $"Remaining {remainingExperience} XP";
|
||||
this.ExperienceBarText = $"Remaining {(int)remainingExperience} XP";
|
||||
break;
|
||||
case Configuration.FocusView.ExperienceDisplay.Percentage:
|
||||
var currentExperienceInLevel2 = this.experienceCalculator.GetExperienceForCurrentLevel(this.GameData.MainPlayer!.Experience);
|
||||
var nextLevelExperienceThreshold2 = this.experienceCalculator.GetNextExperienceThreshold(this.GameData.MainPlayer!.Experience);
|
||||
this.ExperienceBarText = $"{(int)((double)currentExperienceInLevel2 / (double)nextLevelExperienceThreshold2 * 100)}% XP";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -146,10 +197,13 @@ public partial class FocusView : UserControl
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.LuxonPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.LuxonBarText = $"{this.GameData.User!.CurrentLuxonPoints} / {this.GameData.User!.MaxLuxonPoints} Luxon Points";
|
||||
this.LuxonBarText = $"{this.GameData.User!.CurrentLuxonPoints} / {this.GameData.User.MaxLuxonPoints} Luxon Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.LuxonBarText = $"Remaining {this.GameData.User!.MaxLuxonPoints - this.GameData.User!.CurrentLuxonPoints} Luxon Points";
|
||||
this.LuxonBarText = $"Remaining {this.GameData.User!.MaxLuxonPoints - this.GameData.User.CurrentLuxonPoints} Luxon Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.LuxonBarText = $"{(int)((double)this.GameData.User!.CurrentLuxonPoints / (double)this.GameData.User.MaxLuxonPoints * 100)}% Luxon Points";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -159,10 +213,13 @@ public partial class FocusView : UserControl
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.KurzickPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.KurzickBarText = $"{this.GameData.User!.CurrentKurzickPoints} / {this.GameData.User!.MaxKurzickPoints} Kurzick Points";
|
||||
this.KurzickBarText = $"{this.GameData.User!.CurrentKurzickPoints} / {this.GameData.User.MaxKurzickPoints} Kurzick Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.KurzickBarText = $"Remaining {this.GameData.User!.MaxKurzickPoints - this.GameData.User!.CurrentKurzickPoints} Kurzick Points";
|
||||
this.KurzickBarText = $"Remaining {this.GameData.User!.MaxKurzickPoints - this.GameData.User.CurrentKurzickPoints} Kurzick Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.KurzickBarText = $"{(int)((double)this.GameData.User!.CurrentKurzickPoints / (double)this.GameData.User.MaxKurzickPoints * 100)}% Kurzick Points";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -172,10 +229,13 @@ public partial class FocusView : UserControl
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.ImperialPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.ImperialBarText = $"{this.GameData.User!.CurrentImperialPoints} / {this.GameData.User!.MaxImperialPoints} Imperial Points";
|
||||
this.ImperialBarText = $"{this.GameData.User!.CurrentImperialPoints} / {this.GameData.User.MaxImperialPoints} Imperial Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.ImperialBarText = $"Remaining {this.GameData.User!.MaxImperialPoints - this.GameData.User!.CurrentImperialPoints} Imperial Points";
|
||||
this.ImperialBarText = $"Remaining {this.GameData.User!.MaxImperialPoints - this.GameData.User.CurrentImperialPoints} Imperial Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.ImperialBarText = $"{(int)((double)this.GameData.User!.CurrentImperialPoints / (double)this.GameData.User.MaxImperialPoints * 100)}% Imperial Points";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -185,28 +245,69 @@ public partial class FocusView : UserControl
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.BalthazarPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.BalthazarBarText = $"{this.GameData.User!.CurrentBalthazarPoints} / {this.GameData.User!.MaxBalthazarPoints} Balthazar Points";
|
||||
this.BalthazarBarText = $"{this.GameData.User!.CurrentBalthazarPoints} / {this.GameData.User.MaxBalthazarPoints} Balthazar Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.BalthazarBarText = $"Remaining {this.GameData.User!.MaxBalthazarPoints - this.GameData.User!.CurrentBalthazarPoints} Balthazar Points";
|
||||
this.BalthazarBarText = $"Remaining {this.GameData.User!.MaxBalthazarPoints - this.GameData.User.CurrentBalthazarPoints} Balthazar Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.BalthazarBarText = $"{(int)((double)this.GameData.User!.CurrentBalthazarPoints / (double)this.GameData.User.MaxBalthazarPoints * 100)}% Balthazar Points";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVanquishingText()
|
||||
{
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.VanquishingDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.VanquishingText = $"{this.GameData.Session!.FoesKilled} / {(int)this.TotalFoes} Foes Killed";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.VanquishingText = $"Remaining {this.GameData.Session!.FoesToKill} Foes";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.VanquishingText = $"{(int)((double)this.GameData.Session!.FoesKilled / (double)this.TotalFoes * 100)}% Foes Killed";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHealthText()
|
||||
{
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.HealthDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.HealthBarText = $"{(int)this.GameData.MainPlayer!.CurrentHealth} / {(int)this.GameData.MainPlayer.MaxHealth} Health";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.HealthBarText = $"Remaining {(int)this.GameData.MainPlayer!.CurrentHealth} Health";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.HealthBarText = $"{(int)(this.GameData.MainPlayer!.CurrentHealth / this.GameData.MainPlayer.MaxHealth * 100)}% Health";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEnergyText()
|
||||
{
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.EnergyBarText = $"{(int)this.GameData.MainPlayer!.CurrentEnergy} / {(int)this.GameData.MainPlayer.MaxEnergy} Energy";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.EnergyBarText = $"Remaining {(int)this.GameData.MainPlayer!.CurrentEnergy} Energy";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.EnergyBarText = $"{(int)(this.GameData.MainPlayer!.CurrentEnergy / this.GameData.MainPlayer.MaxEnergy * 100)}% Energy";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void FocusView_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.UpdateRightSideBarsLayout();
|
||||
this.BrowserAddress = this.liveUpdateableOptions.Value.FocusViewOptions.BrowserUrl;
|
||||
|
||||
if (!this.guildwarsMemoryReader.Running)
|
||||
{
|
||||
this.guildwarsMemoryReader.Initialize(this.applicationLauncher.RunningGuildwarsProcess!);
|
||||
}
|
||||
|
||||
if (this.guildwarsMemoryReader.TargetProcess?.MainModule?.FileName != this.applicationLauncher.RunningGuildwarsProcess?.MainModule?.FileName)
|
||||
{
|
||||
this.guildwarsMemoryReader.Initialize(this.applicationLauncher.RunningGuildwarsProcess!);
|
||||
}
|
||||
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
this.cancellationTokenSource = new CancellationTokenSource();
|
||||
TaskExtensions.RunPeriodicAsync(this.UpdateGameData, TimeSpan.Zero, TimeSpan.FromSeconds(1), this.cancellationTokenSource.Token);
|
||||
@@ -216,20 +317,24 @@ public partial class FocusView : UserControl
|
||||
{
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
this.cancellationTokenSource = null;
|
||||
this.guildwarsMemoryReader?.Stop();
|
||||
}
|
||||
|
||||
private void ExperienceBar_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay)
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.ExperienceDisplay)
|
||||
{
|
||||
case Configuration.FocusView.EnergyDisplay.CurrentLevelCurrentAndCurrentLevelMax:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay = Configuration.FocusView.EnergyDisplay.TotalCurretAndTotalMax;
|
||||
case Configuration.FocusView.ExperienceDisplay.CurrentLevelCurrentAndCurrentLevelMax:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.ExperienceDisplay = Configuration.FocusView.ExperienceDisplay.TotalCurretAndTotalMax;
|
||||
break;
|
||||
case Configuration.FocusView.EnergyDisplay.TotalCurretAndTotalMax:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay = Configuration.FocusView.EnergyDisplay.RemainingUntilNextLevel;
|
||||
case Configuration.FocusView.ExperienceDisplay.TotalCurretAndTotalMax:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.ExperienceDisplay = Configuration.FocusView.ExperienceDisplay.RemainingUntilNextLevel;
|
||||
break;
|
||||
case Configuration.FocusView.EnergyDisplay.RemainingUntilNextLevel:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay = Configuration.FocusView.EnergyDisplay.CurrentLevelCurrentAndCurrentLevelMax;
|
||||
case Configuration.FocusView.ExperienceDisplay.RemainingUntilNextLevel:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.ExperienceDisplay = Configuration.FocusView.ExperienceDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.ExperienceDisplay.Percentage:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.ExperienceDisplay = Configuration.FocusView.ExperienceDisplay.CurrentLevelCurrentAndCurrentLevelMax;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -245,6 +350,9 @@ public partial class FocusView : UserControl
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.LuxonPointsDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.LuxonPointsDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.LuxonPointsDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
@@ -261,6 +369,9 @@ public partial class FocusView : UserControl
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.KurzickPointsDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.KurzickPointsDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.KurzickPointsDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
@@ -277,6 +388,9 @@ public partial class FocusView : UserControl
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.ImperialPointsDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.ImperialPointsDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.ImperialPointsDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
@@ -293,6 +407,9 @@ public partial class FocusView : UserControl
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.BalthazarPointsDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.BalthazarPointsDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.BalthazarPointsDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
@@ -301,6 +418,63 @@ public partial class FocusView : UserControl
|
||||
this.UpdateBalthazarText();
|
||||
}
|
||||
|
||||
private void VanquishingBar_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.VanquishingDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.VanquishingDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.VanquishingDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.VanquishingDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
this.UpdateVanquishingText();
|
||||
}
|
||||
|
||||
private void HealthBar_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.HealthDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.HealthDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.HealthDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.HealthDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
this.UpdateHealthText();
|
||||
}
|
||||
|
||||
private void EnergyBar_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveUpdateableOptions.Value.FocusViewOptions.EnergyDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
this.UpdateEnergyText();
|
||||
}
|
||||
|
||||
private void CurrentQuest_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.GameData.MainPlayer?.Quest?.WikiUrl is string url)
|
||||
@@ -309,6 +483,14 @@ public partial class FocusView : UserControl
|
||||
}
|
||||
}
|
||||
|
||||
private void CurrentMap_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.GameData.Session?.CurrentMap?.WikiUrl is string url)
|
||||
{
|
||||
this.BrowserAddress = url;
|
||||
}
|
||||
}
|
||||
|
||||
private void Browser_MaximizeClicked(object sender, EventArgs e)
|
||||
{
|
||||
this.browserMaximized = !this.browserMaximized;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid
|
||||
Background="#A0202020">
|
||||
Background="#F0212121">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
|
||||
@@ -12,13 +12,14 @@
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="White" MinHeight="200" MinWidth="400">
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="#F0212121" MinHeight="200" MinWidth="400">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=Description, Mode=OneWay}" Margin="10, 0, 10, 0" Foreground="Black"
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=Description, Mode=OneWay}" Margin="10, 0, 10, 0" Foreground="White"
|
||||
TextWrapping="Wrap" HorizontalAlignment="Center" FontSize="16"></TextBlock>
|
||||
<ProgressBar Minimum="0" Maximum="100" Value="{Binding ElementName=_this, Path=ProgressValue, Mode=OneWay}" Width="300" Height="20"></ProgressBar>
|
||||
<controls:OpaqueButton Text="Continue" BackgroundOpacity="0.2" TransparentBackground="Gray" HorizontalAlignment="Center" Margin="10" Width="80" Height="25"
|
||||
Clicked="OpaqueButton_Clicked" Foreground="Black" FontSize="16"></controls:OpaqueButton>
|
||||
Clicked="OpaqueButton_Clicked" Foreground="White" Highlight="White" HighlightOpacity="0.6" FontSize="16"
|
||||
Cursor="Hand"></controls:OpaqueButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -24,20 +24,23 @@
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:OpaqueButton Text="Launch game" Highlight="White" TransparentBackground="Black" HighlightOpacity="0.3" BackgroundOpacity="0.2"
|
||||
<controls:OpaqueButton Text="Launch game" Highlight="White" TransparentBackground="#F0212121" HighlightOpacity="0.3" BackgroundOpacity="1"
|
||||
Foreground="White" FontSize="36" Width="250" Height="60" VerticalAlignment="Bottom"
|
||||
IsEnabled="{Binding ElementName=_this, Path=LaunchButtonEnabled, Mode=OneWay}"
|
||||
Clicked="LaunchButton_Clicked" Grid.Row="0" Grid.ColumnSpan="3"
|
||||
Cursor="Hand"
|
||||
Visibility="{Binding ElementName=_this, Path=ButtonsVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"></controls:OpaqueButton>
|
||||
<controls:OpaqueButton Text="Launch toolbox" Highlight="White" TransparentBackground="Black" HighlightOpacity="0.3" BackgroundOpacity="0.2"
|
||||
<controls:OpaqueButton Text="Launch toolbox" Highlight="White" TransparentBackground="#F0212121" HighlightOpacity="0.3" BackgroundOpacity="1"
|
||||
Foreground="White" FontSize="24" Width="200" Height="40" Margin="0, 10, 0, 10"
|
||||
IsEnabled="{Binding ElementName=_this, Path=LaunchToolboxButtonEnabled, Mode=OneWay}"
|
||||
Clicked="LaunchToolboxButton_Clicked" Grid.Row="1" Grid.ColumnSpan="2"
|
||||
Cursor="Hand"
|
||||
Visibility="{Binding ElementName=_this, Path=ButtonsVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"></controls:OpaqueButton>
|
||||
<controls:OpaqueButton Text="Launch texmod" Highlight="White" TransparentBackground="Black" HighlightOpacity="0.3" BackgroundOpacity="0.2"
|
||||
<controls:OpaqueButton Text="Launch texmod" Highlight="White" TransparentBackground="#F0212121" HighlightOpacity="0.3" BackgroundOpacity="1"
|
||||
Foreground="White" FontSize="24" Width="200" Height="40" Margin="0, 10, 0, 10"
|
||||
IsEnabled="{Binding ElementName=_this, Path=LaunchTexmodButtonEnabled, Mode=OneWay}"
|
||||
Clicked="LaunchTexmodButton_Clicked" Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="1"
|
||||
Cursor="Hand"
|
||||
Visibility="{Binding ElementName=_this, Path=ButtonsVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"></controls:OpaqueButton>
|
||||
<Grid Grid.Column="2" Margin="10" Visibility="{Binding ElementName=_this, Path=BrowsersEnabled, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}">
|
||||
<controls:ChromiumBrowserWrapper x:Name="RightWebBrowser"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="#A0202020">
|
||||
<Grid Background="#F0212121">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
x:Name="_this"
|
||||
DataContextChanged="UserControl_DataContextChanged"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="White" MinHeight="200" MinWidth="400">
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="#F0212121" MinHeight="200" MinWidth="400">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=Description, Mode=OneWay}" Margin="10, 0, 10, 0" Foreground="Black"
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=Description, Mode=OneWay}" Margin="10, 0, 10, 0" Foreground="White"
|
||||
TextWrapping="Wrap" HorizontalAlignment="Center" FontSize="16"></TextBlock>
|
||||
<controls:OpaqueButton Text="Ok" BackgroundOpacity="0.2" TransparentBackground="Gray" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
|
||||
Clicked="OpaqueButton_Clicked" Foreground="Black" FontSize="16"></controls:OpaqueButton>
|
||||
Clicked="OpaqueButton_Clicked" Foreground="White" Highlight="White" HighlightOpacity="0.6" FontSize="16" Cursor="Hand"></controls:OpaqueButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -7,21 +7,21 @@
|
||||
mc:Ignorable="d"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="White" MinHeight="200" MinWidth="400">
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="#F0212121" MinHeight="200" MinWidth="400">
|
||||
<StackPanel VerticalAlignment="Center" Orientation="Vertical">
|
||||
<TextBlock Text="{Binding MessageToUser}" Margin="10, 0, 10, 0" Foreground="Black"
|
||||
<TextBlock Text="{Binding MessageToUser}" Margin="10, 0, 10, 0" Foreground="White"
|
||||
TextWrapping="Wrap" HorizontalAlignment="Center" FontSize="16"></TextBlock>
|
||||
<TextBlock Text="Do you want to restart the application with administrator rights?" HorizontalAlignment="Center"
|
||||
FontSize="16" Foreground="Black" Margin="10, 0, 10, 10" TextWrapping="Wrap"></TextBlock>
|
||||
FontSize="16" Foreground="White" Margin="10, 0, 10, 10" TextWrapping="Wrap"></TextBlock>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:OpaqueButton Text="Yes" BackgroundOpacity="0.2" TransparentBackground="Gray" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
|
||||
Clicked="YesButton_Clicked" Foreground="Black" FontSize="16"></controls:OpaqueButton>
|
||||
Clicked="YesButton_Clicked" Foreground="White" Highlight="White" HighlightOpacity="0.6" FontSize="16" Cursor="Hand"></controls:OpaqueButton>
|
||||
<controls:OpaqueButton Text="No" BackgroundOpacity="0.2" TransparentBackground="Gray" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
|
||||
Clicked="NoButton_Clicked" Foreground="Black" Grid.Column="1" FontSize="16"></controls:OpaqueButton>
|
||||
Clicked="NoButton_Clicked" Foreground="White" Highlight="White" HighlightOpacity="0.6" Grid.Column="1" FontSize="16" Cursor="Hand"></controls:OpaqueButton>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="#A0202020">
|
||||
<Grid Background="#F0212121">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<Grid Background="#A0202020">
|
||||
<Grid Background="#F0212121">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
|
||||
@@ -86,6 +86,7 @@ public partial class SettingsView : System.Windows.Controls.UserControl
|
||||
currentConfig.PlaceShortcut = this.ShortcutPlaced;
|
||||
currentConfig.AutoCheckUpdate = this.AutoCheckUpdate;
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
this.viewManager.ShowView<LauncherView>();
|
||||
}
|
||||
|
||||
private void ToolboxFilePickerGlyph_Clicked(object sender, EventArgs e)
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="White" MinHeight="200" MinWidth="400">
|
||||
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="#F0212121" MinHeight="200" MinWidth="400">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=Description, Mode=OneWay}" Margin="10, 0, 10, 0" Foreground="Black"
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=Description, Mode=OneWay}" Margin="10, 0, 10, 0" Foreground="White"
|
||||
TextWrapping="Wrap" HorizontalAlignment="Center" FontSize="16"></TextBlock>
|
||||
<ProgressBar Minimum="0" Maximum="100" Value="{Binding ElementName=_this, Path=ProgressValue, Mode=OneWay}" Width="300" Height="20"></ProgressBar>
|
||||
<controls:OpaqueButton Text="Ok" BackgroundOpacity="0.2" TransparentBackground="Gray" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
|
||||
Clicked="OpaqueButton_Clicked" Foreground="Black" FontSize="16"
|
||||
Clicked="OpaqueButton_Clicked" Foreground="White" FontSize="16" Highlight="White" HighlightOpacity="0.6"
|
||||
Visibility="{Binding ElementName=_this, Path=ContinueButtonEnabled, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></controls:OpaqueButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="#A0202020">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="#F0212121">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
@@ -40,5 +43,9 @@
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<controls:CircularLoadingWidget Grid.RowSpan="4"
|
||||
Width="100"
|
||||
Height="100"
|
||||
Visibility="{Binding ElementName=_this, Path=Loading, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></controls:CircularLoadingWidget>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -25,6 +25,9 @@ public partial class VersionManagementView : UserControl
|
||||
[GenerateDependencyProperty]
|
||||
private Version currentVersion;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool loading;
|
||||
|
||||
public ObservableCollection<Version> Versions { get; } = new();
|
||||
|
||||
public VersionManagementView(
|
||||
@@ -41,7 +44,9 @@ public partial class VersionManagementView : UserControl
|
||||
|
||||
private async void LoadVersionList()
|
||||
{
|
||||
this.Loading = true;
|
||||
this.Versions.ClearAnd().AddRange((await this.applicationUpdater.GetVersions()).Reverse());
|
||||
this.Loading = false;
|
||||
}
|
||||
|
||||
private void CurrentVersion_Clicked(object sender, EventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user