Skip to content

Commit

Permalink
Add opponent deck input (HearthSim#4316)
Browse files Browse the repository at this point in the history
* WIP

* Add basic opponent deck tracking

* Add Opponent Upload Framework

* Add Upload to OverlayWindow

* Add passing in to Player

* Control when to show upload opponent deck

* Add hovering control

* Position uploader

* Control when uploader is shown

* Update opponent state text

* Adjust opponent upload to the right

* Cleanup Code

* Update UI

* Add state for updated ui

* Fix deck import error reporting

* Control auto showing the panel

* Cleanup code

* Control message visibility

* Fix panel visibility flickering

* Adjust panel position

* Pass error out

* Fix link button

* Fix state updating

* Fix DescriptorVisibility

* Add localizations for hyperlink

* Cleanup code

* Revert "Fix panel visibility flickering"

This reverts commit 50e6742.

# Conflicts:
#	Hearthstone Deck Tracker/Windows/OverlayWindow.MouseOverDetection.cs
#	Hearthstone Deck Tracker/Windows/OverlayWindow.xaml.cs

* Fix panel flickering

* Pass where the show or hide originated

* Correct ui behavior

* Reset error message on panel hide

* Localize error message

* Persist detailed message on first non interacted session

* Add config for showing panel in non friendly matches

* Fix margin
  • Loading branch information
Jonysegal authored Jul 6, 2021
1 parent fdc1936 commit a75411a
Show file tree
Hide file tree
Showing 18 changed files with 440 additions and 25 deletions.
6 changes: 6 additions & 0 deletions Hearthstone Deck Tracker/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,9 @@ public class Config
[DefaultValue(false)]
public bool HighlightDiscarded = false;

[DefaultValue(false)]
public bool EnableLinkOpponentDeckInNonFriendly = false;

[DefaultValue(true)]
public bool HighlightLastDrawn = true;

Expand Down Expand Up @@ -812,6 +815,9 @@ public class Config
[DefaultValue(false)]
public bool BobsBuddyAverageDamageInfoClosed = false;

[DefaultValue(false)]
public bool InteractedWithLinkOpponentDeck = false;

[DefaultValue(false)]
public bool ShowCapturableOverlay = false;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<UserControl x:Class="Hearthstone_Deck_Tracker.Controls.Overlay.LinkOpponentDeckPanel"
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"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
lex:LocalizeDictionary.DesignCulture="en"
lex:ResxLocalizationProvider.DefaultAssembly="HearthstoneDeckTracker"
lex:ResxLocalizationProvider.DefaultDictionary="Strings"
mc:Ignorable="d">
<Border Background="#23272A" BorderBrush="#141617" BorderThickness="1" CornerRadius="3" Margin="0,5,0,0" Visibility="{Binding LinkOpponentDeckVisibility}" MaxWidth="352" MouseEnter="Border_MouseEnter" MouseLeave="Border_MouseLeave">
<Grid>
<StackPanel Margin="10">
<TextBlock Text="{lex:Loc LinkOpponentDeck_Panel_Title}" Foreground="White" FontSize="14" FontWeight="Bold"/>

<TextBlock Foreground="White" FontSize="14" TextWrapping="Wrap" Visibility="{Binding DescriptorVisibility, Mode=OneWay}" Margin="0 3 0 0" Opacity=".7">
<Run Text="{lex:Loc LinkOpponentDeck_Panel_Description}"/>
</TextBlock>

<Button Content="{lex:Loc LinkOpponentDeck_Panel_LinkDeckButton}" Margin="0 6 0 0"
Click="LinkOpponentDeck_Click" DockPanel.Dock="Right" />

<TextBlock FontSize="14" TextWrapping="Wrap" Margin="0 10 0 0" Visibility="{Binding LinkMessageVisibility}" Opacity=".7" HorizontalAlignment="Center">
<Hyperlink Foreground="White">
<Run Text="{Binding LinkMessage, Mode=OneWay}" MouseDown="Hyperlink_MouseDown"/>
</Hyperlink>
</TextBlock>

<TextBlock Foreground="Red" FontSize="14" TextWrapping="Wrap" Visibility="{Binding ErrorMessageVisibility}" Margin="0 10 0 0" >
<Run Text="{Binding ErrorMessage, Mode=OneWay}"/>
</TextBlock>

</StackPanel>
</Grid>
</Border>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
using Hearthstone_Deck_Tracker.Annotations;
using Hearthstone_Deck_Tracker.Hearthstone;
using Hearthstone_Deck_Tracker.Importing;
using Hearthstone_Deck_Tracker.Utility;
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace Hearthstone_Deck_Tracker.Controls.Overlay
{
public partial class LinkOpponentDeckPanel : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

private LinkOpponentDeckState _linkOpponentDeckState;

private Visibility _linkOpponentDeckVisibility = Visibility.Hidden;
public Visibility LinkOpponentDeckVisibility
{
get => _linkOpponentDeckVisibility;
set
{
_linkOpponentDeckVisibility = value;
OnPropertyChanged();
}
}

public Visibility DescriptorVisibility => !Config.Instance.InteractedWithLinkOpponentDeck || !_sessionStartHasInteracted ? Visibility.Visible : Visibility.Collapsed;

private string _errorMessage;
public string ErrorMessage
{
get => _errorMessage;
set
{
_errorMessage = value;
OnPropertyChanged();
}
}

public bool AutoShown = false;

public bool IsFriendlyMatch = false;

private bool _shownByOpponentStack = false;

private bool _mouseIsOver = false;

private bool _hasLinkedDeck = false;

private bool _sessionStartHasInteracted = false;

public string LinkMessage => LinkOpponentDeckStateConverter.GetLinkMessage(_linkOpponentDeckState);

public Visibility LinkMessageVisibility => (AutoShown && !Config.Instance.InteractedWithLinkOpponentDeck) || _hasLinkedDeck ? Visibility.Visible : Visibility.Collapsed;

public Visibility ErrorMessageVisibility => !string.IsNullOrEmpty(ErrorMessage) ? Visibility.Visible : Visibility.Collapsed;

[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public LinkOpponentDeckPanel()
{
_sessionStartHasInteracted = Config.Instance.InteractedWithLinkOpponentDeck;
InitializeComponent();
}

private async void LinkOpponentDeck_Click(object sender, RoutedEventArgs e)
{
Config.Instance.InteractedWithLinkOpponentDeck = true;
Config.Save();
OnPropertyChanged(nameof(DescriptorVisibility));
try
{
var deck = await ClipboardImporter.Import(true);
if(deck != null)
{
Player.KnownOpponentDeck = deck;
e.Handled = true;
Core.UpdateOpponentCards();
_linkOpponentDeckState = LinkOpponentDeckState.InKnownDeckMode;
_hasLinkedDeck = true;
ErrorMessage = "";
}
else
_linkOpponentDeckState = LinkOpponentDeckState.Error;
}
catch
{
_linkOpponentDeckState = LinkOpponentDeckState.Error;
ErrorMessage = LocUtil.Get("LinkOpponentDeck_NoValidDeckOnClipboardMessage");
}

OnPropertyChanged(nameof(ErrorMessage));
OnPropertyChanged(nameof(ErrorMessageVisibility));
OnPropertyChanged(nameof(LinkMessage));
OnPropertyChanged(nameof(LinkMessageVisibility));
}

public void HideByOpponentStack()
{
_shownByOpponentStack = false;
Hide(false);
}

public void Hide(bool force = false)
{
if(force || !_mouseIsOver)
{
LinkOpponentDeckVisibility = Visibility.Hidden;
}
AutoShown = false;
ErrorMessage = "";
OnPropertyChanged(nameof(ErrorMessage));
OnPropertyChanged(nameof(ErrorMessageVisibility));
}

public void ShowByOpponentStack()
{
_shownByOpponentStack = true;
Show();
}

public void Show()
{
if(IsFriendlyMatch || Config.Instance.EnableLinkOpponentDeckInNonFriendly)
{
LinkOpponentDeckVisibility = Visibility.Visible;
OnPropertyChanged(nameof(LinkMessageVisibility));
}
}

private void Border_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
_mouseIsOver = true;
}

private void Border_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
_mouseIsOver = false;
if(!_shownByOpponentStack)
Hide();
}

private void Hyperlink_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if(!Config.Instance.InteractedWithLinkOpponentDeck)
{
Config.Instance.InteractedWithLinkOpponentDeck = true;
Config.Save();
OnPropertyChanged(nameof(LinkMessageVisibility));
OnPropertyChanged(nameof(DescriptorVisibility));
Hide(true);
}
else
{
Player.KnownOpponentDeck = null;
Core.UpdateOpponentCards();
_linkOpponentDeckState = LinkOpponentDeckState.Initial;
_hasLinkedDeck = false;
OnPropertyChanged(nameof(LinkMessage));
OnPropertyChanged(nameof(LinkMessageVisibility));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,14 @@
Unchecked="CheckboxIncludeCreated_Unchecked" />
<CheckBox x:Name="CheckboxHighlightDiscarded"
Content="{lex:LocText Options_Overlay_Opponent_CheckBox_DiscardedCards}" HorizontalAlignment="Left"
Margin="10,5,0,10" VerticalAlignment="Top"
Margin="10,5,0,0" VerticalAlignment="Top"
Checked="CheckboxHighlightDiscarded_Checked"
Unchecked="CheckboxHighlightDiscarded_Unchecked" />
<CheckBox x:Name="CheckboxEnableLinkOpponentDeckInNonFriendly"
Content="{lex:LocText Options_Overlay_Opponent_CheckBox_LinkOpponentDeck}" HorizontalAlignment="Left"
Margin="10,5,0,10" VerticalAlignment="Top"
Checked="CheckboxEnableLinkOpponentDeckInNonFriendly_Checked"
Unchecked="CheckboxEnableLinkOpponentDeckInNonFriendly_Unchecked" />
<hearthstoneDeckTracker:ElementSorter x:Name="ElementSorterOpponent" Margin="10,5,10,10"
Height="auto" />
</StackPanel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,22 @@ private void CheckboxHighlightDiscarded_Unchecked(object sender, RoutedEventArgs
SaveConfig(true);
}

private void CheckboxEnableLinkOpponentDeckInNonFriendly_Checked(object sender, RoutedEventArgs e)
{
if(!_initialized)
return;
Config.Instance.EnableLinkOpponentDeckInNonFriendly = true;
SaveConfig(true);
}

private void CheckboxEnableLinkOpponentDeckInNonFriendly_Unchecked(object sender, RoutedEventArgs e)
{
if(!_initialized)
return;
Config.Instance.EnableLinkOpponentDeckInNonFriendly = false;
SaveConfig(true);
}

private void SliderOpponentOpacity_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if(!_initialized)
Expand Down
5 changes: 5 additions & 0 deletions Hearthstone Deck Tracker/GameEventHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -452,8 +452,13 @@ public void HandleGameStart(DateTime timestamp)
GameEvents.OnGameStart.Execute();
LiveDataManager.WatchBoardState();

Core.Overlay.LinkOpponentDeckDisplay.IsFriendlyMatch = _game.IsFriendlyMatch;

if(_game.IsBattlegroundsMatch && _game.CurrentGameMode == GameMode.Spectator)
Core.Overlay.ShowBgsTopBar();
if(_game.IsFriendlyMatch)
if(!Config.Instance.InteractedWithLinkOpponentDeck)
Core.Overlay.ShowLinkOpponentDeckDisplay();
}

private void HandleAdventureRestart()
Expand Down
9 changes: 9 additions & 0 deletions Hearthstone Deck Tracker/Hearthstone Deck Tracker.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@
<Compile Include="Controls\Overlay\BattlegroundsCardsGroup.xaml.cs">
<DependentUpon>BattlegroundsCardsGroup.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\Overlay\LinkOpponentDeckPanel.xaml.cs">
<DependentUpon>LinkOpponentDeckPanel.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\Overlay\MulliganPanel.xaml.cs">
<DependentUpon>MulliganPanel.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -352,6 +355,7 @@
<Compile Include="OpponentDeadForTracker.cs" />
<Compile Include="Utility\Assets\AssetDownloader.cs" />
<Compile Include="Utility\Assets\AssetDownloaders.cs" />
<Compile Include="Utility\LinkOpponentDeckState.cs" />
<Compile Include="Utility\ComboBoxHelper.cs" />
<Compile Include="Utility\DataLoader.cs" />
<Compile Include="Utility\DelayedMouseOver.cs" />
Expand Down Expand Up @@ -402,6 +406,7 @@
<Compile Include="Utility\Shell32.cs" />
<Compile Include="Utility\Singleton.cs" />
<Compile Include="Utility\ScheduledTaskRunner.cs" />
<Compile Include="Utility\LinkOpponentDeckStateConverter.cs" />
<Compile Include="Utility\Toasts\ToastControls\BattlegroundsToast.xaml.cs">
<DependentUpon>BattlegroundsToast.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -1038,6 +1043,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\Overlay\LinkOpponentDeckPanel.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Controls\Overlay\MulliganPanel.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
Expand Down
1 change: 1 addition & 0 deletions Hearthstone Deck Tracker/Hearthstone/GameV2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ public bool IsOpponentMinionInPlay
public bool IsConstructedMatch => CurrentGameType == GameType.GT_RANKED
|| CurrentGameType == GameType.GT_CASUAL
|| CurrentGameType == GameType.GT_VS_FRIEND;
public bool IsFriendlyMatch => CurrentGameType == GameType.GT_VS_FRIEND;

public Mode CurrentMode
{
Expand Down
Loading

0 comments on commit a75411a

Please sign in to comment.