diff --git a/Daybreak.GWCA/CMakeLists.txt b/Daybreak.GWCA/CMakeLists.txt index 7ecfa714..a43c64d6 100644 --- a/Daybreak.GWCA/CMakeLists.txt +++ b/Daybreak.GWCA/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(VERSION_MAJOR 0) set(VERSION_MINOR 9) set(VERSION_PATCH 9) -set(VERSION_TWEAK 6) +set(VERSION_TWEAK 10) set(VERSION_RC "${CMAKE_CURRENT_BINARY_DIR}/version.rc") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in" "${VERSION_RC}" @ONLY) diff --git a/Daybreak.GWCA/header/payloads/Camera.h b/Daybreak.GWCA/header/payloads/Camera.h new file mode 100644 index 00000000..5e1ac8d6 --- /dev/null +++ b/Daybreak.GWCA/header/payloads/Camera.h @@ -0,0 +1,14 @@ +#pragma once +#include +#include + +using json = nlohmann::json; + +namespace Daybreak { + struct Camera { + float Yaw; + float Pitch; + }; + + void to_json(json& j, const Camera& p); +} \ No newline at end of file diff --git a/Daybreak.GWCA/header/payloads/GameStatePayload.h b/Daybreak.GWCA/header/payloads/GameStatePayload.h index f47bc20c..7c951316 100644 --- a/Daybreak.GWCA/header/payloads/GameStatePayload.h +++ b/Daybreak.GWCA/header/payloads/GameStatePayload.h @@ -2,11 +2,13 @@ #include #include #include +#include using json = nlohmann::json; namespace Daybreak { struct GameStatePayload { + Camera Camera; std::list States; }; diff --git a/Daybreak.GWCA/source/GameStateModule.cpp b/Daybreak.GWCA/source/GameStateModule.cpp index a4e9e014..017b2920 100644 --- a/Daybreak.GWCA/source/GameStateModule.cpp +++ b/Daybreak.GWCA/source/GameStateModule.cpp @@ -2,7 +2,9 @@ #include "GameStateModule.h" #include #include +#include #include +#include #include #include #include @@ -64,6 +66,12 @@ namespace Daybreak::Modules::GameStateModule { auto states = GetStates(agents); gamePayload.States = states; + + auto camera = GW::CameraMgr::GetCamera(); + Daybreak::Camera cameraPayload{}; + cameraPayload.Pitch = camera->pitch; + cameraPayload.Yaw = camera->yaw; + gamePayload.Camera = cameraPayload; return gamePayload; } diff --git a/Daybreak.GWCA/source/payloads/Camera.cpp b/Daybreak.GWCA/source/payloads/Camera.cpp new file mode 100644 index 00000000..c765e8ea --- /dev/null +++ b/Daybreak.GWCA/source/payloads/Camera.cpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include +#include + +using json = nlohmann::json; + +namespace Daybreak { + void to_json(json& j, const Camera& p) { + j = json + { + {"Yaw", p.Yaw}, + {"Pitch", p.Pitch} + }; + } +} \ No newline at end of file diff --git a/Daybreak.GWCA/source/payloads/GameStatePayload.cpp b/Daybreak.GWCA/source/payloads/GameStatePayload.cpp index a6b10bd3..12462926 100644 --- a/Daybreak.GWCA/source/payloads/GameStatePayload.cpp +++ b/Daybreak.GWCA/source/payloads/GameStatePayload.cpp @@ -8,6 +8,7 @@ namespace Daybreak { void to_json(json& j, const GameStatePayload& p) { j = json { + {"Camera", p.Camera}, {"States", p.States}, }; } diff --git a/Daybreak/Configuration/Options/FocusViewOptions.cs b/Daybreak/Configuration/Options/FocusViewOptions.cs index 44f9357e..0275d36d 100644 --- a/Daybreak/Configuration/Options/FocusViewOptions.cs +++ b/Daybreak/Configuration/Options/FocusViewOptions.cs @@ -50,6 +50,10 @@ public sealed class FocusViewOptions [OptionName(Name = "Energy Display Mode", Description = "Sets how should the energy display show the information")] public PointsDisplay EnergyDisplay { get; set; } + [JsonProperty(nameof(MinimapRotationEnabled))] + [OptionName(Name = "Minimap Rotation", Description = "When enabled, the minimap will rotate according to the player camera")] + public bool MinimapRotationEnabled { get; set; } = true; + [JsonProperty(nameof(BrowserHistory))] [OptionIgnore] public BrowserHistory BrowserHistory { get; set; } = new(); diff --git a/Daybreak/Controls/Minimap/GuildwarsMinimap.xaml b/Daybreak/Controls/Minimap/GuildwarsMinimap.xaml index d55e3a17..81129436 100644 --- a/Daybreak/Controls/Minimap/GuildwarsMinimap.xaml +++ b/Daybreak/Controls/Minimap/GuildwarsMinimap.xaml @@ -68,8 +68,13 @@ - - + + + + + + + - - - - - diff --git a/Daybreak/Controls/Minimap/GuildwarsMinimap.xaml.cs b/Daybreak/Controls/Minimap/GuildwarsMinimap.xaml.cs index 00eca147..f92fd298 100644 --- a/Daybreak/Controls/Minimap/GuildwarsMinimap.xaml.cs +++ b/Daybreak/Controls/Minimap/GuildwarsMinimap.xaml.cs @@ -24,6 +24,7 @@ using System.Diagnostics; using Daybreak.Models.FocusView; using Daybreak.Models.LaunchConfigurations; +using System.Configuration; namespace Daybreak.Controls.Minimap; @@ -78,6 +79,10 @@ public partial class GuildwarsMinimap : UserControl [GenerateDependencyProperty] private bool controlsVisible; [GenerateDependencyProperty] + private bool canRotate; + [GenerateDependencyProperty] + private double angle; + [GenerateDependencyProperty] private int targetEntityId; [GenerateDependencyProperty] private int targetEntityModelId; @@ -187,6 +192,8 @@ this.GameData is null || entity.Health = state?.Health ?? 0; entity.Energy = state?.Energy ?? 0; } + + this.Angle = this.CanRotate ? (this.GameState.Camera.Yaw - (Math.PI / 2)) * (180 / Math.PI) : 0; } private void UpdateGameData() diff --git a/Daybreak/Daybreak.csproj b/Daybreak/Daybreak.csproj index 12ea3da1..cd5001d2 100644 --- a/Daybreak/Daybreak.csproj +++ b/Daybreak/Daybreak.csproj @@ -11,7 +11,7 @@ preview Daybreak.ico true - 0.9.9.9 + 0.9.9.10 true cfb2a489-db80-448d-a969-80270f314c46 True diff --git a/Daybreak/Models/Guildwars/Camera.cs b/Daybreak/Models/Guildwars/Camera.cs new file mode 100644 index 00000000..e3a3b3cc --- /dev/null +++ b/Daybreak/Models/Guildwars/Camera.cs @@ -0,0 +1,7 @@ +namespace Daybreak.Models.Guildwars; + +public sealed class Camera +{ + public float Yaw { get; set; } + public float Pitch { get; set; } +} diff --git a/Daybreak/Models/Guildwars/GameState.cs b/Daybreak/Models/Guildwars/GameState.cs index 29ec91fb..cbb0f784 100644 --- a/Daybreak/Models/Guildwars/GameState.cs +++ b/Daybreak/Models/Guildwars/GameState.cs @@ -3,5 +3,6 @@ namespace Daybreak.Models.Guildwars; public sealed class GameState { + public Camera Camera { get; init; } public List? States { get; init; } } diff --git a/Daybreak/Services/Scanner/GWCAMemoryReader.cs b/Daybreak/Services/Scanner/GWCAMemoryReader.cs index 41967611..38b621c5 100644 --- a/Daybreak/Services/Scanner/GWCAMemoryReader.cs +++ b/Daybreak/Services/Scanner/GWCAMemoryReader.cs @@ -581,7 +581,7 @@ public async Task EnsureInitialized(uint processId, CancellationToken cancellati }; }).ToList(); - return new GameState { States = states }; + return new GameState { States = states, Camera = new Camera { Pitch = gameStatePayload.Camera?.Pitch ?? 0, Yaw = gameStatePayload.Camera?.Yaw ?? 0 }, }; } catch (Exception ex) { diff --git a/Daybreak/Services/Scanner/Models/CameraPayload.cs b/Daybreak/Services/Scanner/Models/CameraPayload.cs new file mode 100644 index 00000000..24b9907d --- /dev/null +++ b/Daybreak/Services/Scanner/Models/CameraPayload.cs @@ -0,0 +1,6 @@ +namespace Daybreak.Services.Scanner.Models; +internal sealed class CameraPayload +{ + public float Yaw { get; set; } + public float Pitch { get; set; } +} diff --git a/Daybreak/Services/Scanner/Models/GameStatePayload.cs b/Daybreak/Services/Scanner/Models/GameStatePayload.cs index d1de34f6..45a5c6fb 100644 --- a/Daybreak/Services/Scanner/Models/GameStatePayload.cs +++ b/Daybreak/Services/Scanner/Models/GameStatePayload.cs @@ -3,5 +3,6 @@ namespace Daybreak.Services.Scanner.Models; internal sealed class GameStatePayload { + public CameraPayload? Camera { get; set; } public List? States { get; set; } } diff --git a/Daybreak/Views/FocusView.xaml b/Daybreak/Views/FocusView.xaml index 8248b7a9..cbbf7a5a 100644 --- a/Daybreak/Views/FocusView.xaml +++ b/Daybreak/Views/FocusView.xaml @@ -104,6 +104,7 @@ GameData="{Binding ElementName=_this, Path=GameData, Mode=OneWay}" GameState="{Binding ElementName=_this, Path=GameState, Mode=OneWay}" PathingData="{Binding ElementName=_this, Path=PathingData, Mode=OneWay}" + CanRotate="{Binding ElementName=_this, Path=CanRotateMinimap, Mode=OneWay}" Zoom="0.04" ControlsVisible="True" MaximizeClicked="GuildwarsMinimap_MaximizeClicked" diff --git a/Daybreak/Views/FocusView.xaml.cs b/Daybreak/Views/FocusView.xaml.cs index 86b5e2cc..7469620a 100644 --- a/Daybreak/Views/FocusView.xaml.cs +++ b/Daybreak/Views/FocusView.xaml.cs @@ -15,7 +15,6 @@ using System.Core.Extensions; using System.Extensions; using System.Linq; -using System.Logging; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -76,6 +75,9 @@ public partial class FocusView : UserControl [GenerateDependencyProperty] private bool minimapVisible; + [GenerateDependencyProperty] + private bool canRotateMinimap; + private bool browserMaximized = false; private bool minimapMaximized = false; private bool inventoryMaximized = false; @@ -239,6 +241,7 @@ await Task.WhenAll( } this.GameState = maybeGameState; + this.CanRotateMinimap = this.liveUpdateableOptions.Value.MinimapRotationEnabled; } catch (InvalidOperationException ex) { diff --git a/Daybreak/Views/LauncherView.xaml.cs b/Daybreak/Views/LauncherView.xaml.cs index 48030bd6..e16b897b 100644 --- a/Daybreak/Views/LauncherView.xaml.cs +++ b/Daybreak/Views/LauncherView.xaml.cs @@ -40,6 +40,8 @@ public partial class LauncherView : UserControl private readonly ILiveOptions focusViewOptions; private readonly CancellationTokenSource cancellationTokenSource = new(); + private bool launching; + [GenerateDependencyProperty] private LauncherViewContext latestConfiguration = default!; @@ -97,7 +99,11 @@ private async void PeriodicallyCheckSelectedConfigState() { while (!this.cancellationTokenSource.IsCancellationRequested) { - await this.Dispatcher.InvokeAsync(() => this.CanLaunch = this.LatestConfiguration?.CanLaunch ?? false); + if (!this.launching) + { + await this.Dispatcher.InvokeAsync(() => this.CanLaunch = this.LatestConfiguration?.CanLaunch ?? false); + } + await Task.Delay(TimeSpan.FromSeconds(1), this.cancellationTokenSource.Token); } } @@ -139,14 +145,8 @@ private async void DropDownButton_SelectionChanged(object _, object e) private async void DropDownButton_Clicked(object _, object e) { - await this.Dispatcher.InvokeAsync(() => this.CanLaunch = true); - if (this.LatestConfiguration is null || - this.LatestConfiguration.CanLaunch is false) - { - await this.Dispatcher.InvokeAsync(() => this.CanLaunch = false); - return; - } - + this.launching = true; + await this.Dispatcher.InvokeAsync(() => this.CanLaunch = false); var launchingTask = await new TaskFactory().StartNew(async () => { var latestConfig = await this.Dispatcher.InvokeAsync(() => this.LatestConfiguration); @@ -186,7 +186,14 @@ private async void DropDownButton_Clicked(object _, object e) } }, TaskCreationOptions.LongRunning); - await launchingTask; - await this.Dispatcher.InvokeAsync(() => this.CanLaunch = false); + try + { + await launchingTask; + } + catch + { + } + + this.launching = false; } }