diff --git a/ArenaHelper.csproj b/ArenaHelper.csproj
index 4b00c8c..df08bfa 100644
--- a/ArenaHelper.csproj
+++ b/ArenaHelper.csproj
@@ -43,7 +43,6 @@
..\..\..\..\..\..\Software\Games\Hearthstone Deck Tracker\Hearthstone Deck Tracker.exe
False
- False
packages\MahApps.Metro.1.1.2.0\lib\net45\MahApps.Metro.dll
@@ -74,11 +73,18 @@
ArenaWindow.xaml
+
+ AdviceOverlay.xaml
+
Card.xaml
+
+ ValueOverlay.xaml
+
+
@@ -90,10 +96,18 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
diff --git a/ArenaHelper.sln b/ArenaHelper.sln
index 00e791b..5ce2d5c 100644
--- a/ArenaHelper.sln
+++ b/ArenaHelper.sln
@@ -1,10 +1,12 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2013 for Windows Desktop
-VisualStudioVersion = 12.0.30110.0
+VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArenaHelper", "ArenaHelper.csproj", "{57D6FEFC-CD63-40B5-B83E-EACA3E3B105E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestPlugin", "TestPlugin\TestPlugin.csproj", "{9DBE89DA-8673-4657-A0DC-EC1F26C70B8A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{57D6FEFC-CD63-40B5-B83E-EACA3E3B105E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{57D6FEFC-CD63-40B5-B83E-EACA3E3B105E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{57D6FEFC-CD63-40B5-B83E-EACA3E3B105E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9DBE89DA-8673-4657-A0DC-EC1F26C70B8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9DBE89DA-8673-4657-A0DC-EC1F26C70B8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9DBE89DA-8673-4657-A0DC-EC1F26C70B8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9DBE89DA-8673-4657-A0DC-EC1F26C70B8A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/ArenaWindow.xaml b/ArenaWindow.xaml
index 708fc44..169401d 100644
--- a/ArenaWindow.xaml
+++ b/ArenaWindow.xaml
@@ -6,6 +6,38 @@
xmlns:localcontrols="clr-namespace:ArenaHelper.Controls"
Title="Arena Helper" Height="255" MinHeight="255" MaxHeight="255" Width="400" MinWidth="400" MaxWidth="400"
Background="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}" Topmost="True" LocationChanged="MetroWindow_LocationChanged">
+
+
+
+
+
+
+
+
+
+
+
+
+ Manual card pickingPick a card in Hearthstone, afterwards, click the card in the Arena Helper window. Don't detect picks automatically.
+
+
+
+
+
+
@@ -25,13 +57,13 @@
-
-
+
+
-
+
text
@@ -47,21 +79,21 @@
-
+
-
+
-
+
@@ -76,9 +108,9 @@
-
-
-
+
+
+
diff --git a/ArenaWindow.xaml.cs b/ArenaWindow.xaml.cs
index 2e3a917..b8ffdaf 100644
--- a/ArenaWindow.xaml.cs
+++ b/ArenaWindow.xaml.cs
@@ -11,6 +11,7 @@
using Point = System.Drawing.Point;
using Hearthstone_Deck_Tracker.Hearthstone.Entities;
using Hearthstone_Deck_Tracker.Hearthstone;
+using MahApps.Metro.Controls.Dialogs;
#endregion
@@ -23,9 +24,20 @@ public partial class ArenaWindow
private Card _card2;
public delegate void OnEvent();
- public OnEvent onbutton1click = null;
- public OnEvent onbutton2click = null;
+ public OnEvent onbuttonnewarenaclick = null;
+ public OnEvent onbuttonsaveclick = null;
public OnEvent onwindowlocation = null;
+ public OnEvent onaboutclick = null;
+
+ public delegate void OnOverrideClick(int index);
+ public OnOverrideClick onheroclick = null;
+ public OnOverrideClick oncardclick = null;
+
+ public delegate void OnCheckbox(bool check);
+ public OnCheckbox oncheckboxoverlay = null;
+ public OnCheckbox oncheckboxmanual = null;
+
+ public bool initconfig = false;
public ArenaWindow()
{
@@ -67,27 +79,131 @@ public void Update()
DataContext = this;
}
- private void Button1_Click(object sender, RoutedEventArgs e)
+ private void MetroWindow_LocationChanged(object sender, EventArgs e)
{
- if (onbutton1click != null)
+ if (onwindowlocation != null)
{
- onbutton1click();
+ onwindowlocation();
}
}
- private void Button2_Click(object sender, RoutedEventArgs e)
+ public Thickness TitleBarMargin
+ {
+ get { return new Thickness(0, TitlebarHeight, 0, 0); }
+ }
+
+ private void ButtonOptions_Click(object sender, RoutedEventArgs e)
{
- if (onbutton2click != null)
+ FlyoutOptions.IsOpen = true;
+ }
+
+ private void ButtonAbout_Click(object sender, RoutedEventArgs e)
+ {
+ if (onaboutclick != null)
{
- onbutton2click();
+ onaboutclick();
}
}
- private void MetroWindow_LocationChanged(object sender, EventArgs e)
+ private void ButtonNewArena_Click(object sender, RoutedEventArgs e)
{
- if (onwindowlocation != null)
+ if (onbuttonnewarenaclick != null)
{
- onwindowlocation();
+ onbuttonnewarenaclick();
+ }
+ }
+
+ private void ButtonSave_Click(object sender, RoutedEventArgs e)
+ {
+ if (onbuttonsaveclick != null)
+ {
+ onbuttonsaveclick();
+ }
+ }
+
+ private void HeroBorder0_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ // Override mouse detection
+ if (onheroclick != null)
+ {
+ onheroclick(0);
+ }
+ }
+
+ private void HeroBorder1_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ // Override mouse detection
+ if (onheroclick != null)
+ {
+ onheroclick(1);
+ }
+ }
+
+ private void HeroBorder2_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ // Override mouse detection
+ if (onheroclick != null)
+ {
+ onheroclick(2);
+ }
+ }
+
+ private void CardControl0_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ // Override mouse detection
+ if (oncardclick != null)
+ {
+ oncardclick(0);
+ }
+ }
+
+ private void CardControl1_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ // Override mouse detection
+ if (oncardclick != null)
+ {
+ oncardclick(1);
+ }
+ }
+
+ private void CardControl2_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ // Override mouse detection
+ if (oncardclick != null)
+ {
+ oncardclick(2);
+ }
+ }
+
+ private void CheckBoxOverlay_Checked(object sender, RoutedEventArgs e)
+ {
+ if (oncheckboxoverlay != null)
+ {
+ oncheckboxoverlay(true);
+ }
+ }
+
+ private void CheckBoxOverlay_Unchecked(object sender, RoutedEventArgs e)
+ {
+ if (oncheckboxoverlay != null)
+ {
+ oncheckboxoverlay(false);
+ }
+ }
+
+ private void CheckBoxManual_Checked(object sender, RoutedEventArgs e)
+ {
+ if (oncheckboxmanual != null)
+ {
+ oncheckboxmanual(true);
+ }
+ }
+
+ private void CheckBoxManual_Unchecked(object sender, RoutedEventArgs e)
+ {
+ if (oncheckboxmanual != null)
+ {
+ oncheckboxmanual(false);
}
}
}
diff --git a/Controls/AdviceOverlay.xaml b/Controls/AdviceOverlay.xaml
new file mode 100644
index 0000000..c67c13b
--- /dev/null
+++ b/Controls/AdviceOverlay.xaml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/Controls/AdviceOverlay.xaml.cs b/Controls/AdviceOverlay.xaml.cs
new file mode 100644
index 0000000..f3f1a4e
--- /dev/null
+++ b/Controls/AdviceOverlay.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace ArenaHelper.Controls
+{
+ ///
+ /// Interaction logic for AdviceOverlay.xaml
+ ///
+ public partial class AdviceOverlay : UserControl
+ {
+ public AdviceOverlay()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Controls/ValueOverlay.xaml b/Controls/ValueOverlay.xaml
new file mode 100644
index 0000000..8389a65
--- /dev/null
+++ b/Controls/ValueOverlay.xaml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/Controls/ValueOverlay.xaml.cs b/Controls/ValueOverlay.xaml.cs
new file mode 100644
index 0000000..84413d7
--- /dev/null
+++ b/Controls/ValueOverlay.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace ArenaHelper.Controls
+{
+ ///
+ /// Interaction logic for ValueOverlay.xaml
+ ///
+ public partial class ValueOverlay : UserControl
+ {
+ public ValueOverlay()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Plugin.cs b/Plugin.cs
index bcbccd0..bed8734 100644
--- a/Plugin.cs
+++ b/Plugin.cs
@@ -28,12 +28,16 @@ public class ConfigData
{
public int windowx;
public int windowy;
+ public bool manualclicks;
+ public bool overlay;
public bool debug;
public ConfigData()
{
windowx = 100;
windowy = 100;
+ manualclicks = false;
+ overlay = true;
debug = false;
}
}
@@ -167,20 +171,23 @@ public static Point GetMousePos()
private const UInt16 VK_LBUTTON = 0x01; // left mouse button
private const UInt16 VK_RBUTTON = 0x02; // right mouse button
- enum PluginState { Idle, SearchArena, SearchHeroes, SearchBigHero, DetectedHeroes, SearchCards, DetectedCards, Done };
+ enum PluginState { Idle, SearchHeroes, SearchBigHero, DetectedHeroes, SearchCards, DetectedCards, Done };
private List detectedcards = new List();
private List detectedheroes = new List();
private List detectedbighero = new List();
- private PluginState prevstate;
private PluginState state;
private List mouseindex = new List();
private ArenaData arenadata = new ArenaData();
private string currentfilename = "";
private ConfigData configdata = new ConfigData();
+ private bool configinit = false;
+ private List valueoverlays = new List();
+ private ArenaHelper.Controls.AdviceOverlay adviceoverlay = null;
private HearthstoneTextBlock testtext = null;
private List testimages = new List();
+
private List cardlist = new List();
private List cardhashlist = new List();
private List herohashlist = new List();
@@ -231,6 +238,10 @@ enum PluginState { Idle, SearchArena, SearchHeroes, SearchBigHero, DetectedHeroe
private const string DoneMessage = "All cards are picked. You can start a new arena run or save the deck.";
private const string ConfigFile = "arenahelper.json";
+ // TODO: When AH window is open, and you start Hearthstone, sometimes the plugin takes too long and gets suspended.
+
+ private Plugins plugins = new Plugins();
+
private string DataDir
{
get { return Path.Combine(Config.Instance.DataDir, "ArenaHelper"); }
@@ -263,7 +274,7 @@ public string Author
public Version Version
{
- get { return new Version("0.1.2"); }
+ get { return new Version("0.2.0"); }
}
public MenuItem MenuItem
@@ -273,10 +284,12 @@ public MenuItem MenuItem
public void OnLoad()
{
- prevstate = PluginState.Idle;
+ plugins.LoadPlugins();
+
state = PluginState.Idle;
// Set hashes
+ herohashlist.Clear();
herohashlist.Add(new HeroHashData(0, "Warrior", 13776678289873991291, "warrior_small.png"));
herohashlist.Add(new HeroHashData(1, "Shaman", 18366959783178990451, "shaman_small.png"));
herohashlist.Add(new HeroHashData(2, "Rogue", 5643619427529904809, "rogue_small.png"));
@@ -291,7 +304,6 @@ public void OnLoad()
stopwatch = Stopwatch.StartNew();
- //AddElements();
LoadCards();
}
@@ -329,17 +341,26 @@ protected void InitializeMainWindow()
// Load config
LoadConfig();
-
AddElements();
+ ApplyConfig();
arenawindow.Closed += (sender, args) =>
{
+ SaveConfig();
RemoveElements();
arenawindow = null;
+ configinit = false;
};
- arenawindow.onbutton1click = new ArenaWindow.OnEvent(OnButton1Click);
- arenawindow.onbutton2click = new ArenaWindow.OnEvent(OnButton2Click);
+ arenawindow.onbuttonnewarenaclick = new ArenaWindow.OnEvent(OnButtonNewArenaClick);
+ arenawindow.onbuttonsaveclick = new ArenaWindow.OnEvent(OnButtonSaveClick);
arenawindow.onwindowlocation = new ArenaWindow.OnEvent(OnWindowLocation);
+ arenawindow.onaboutclick = new ArenaWindow.OnEvent(OnAboutClick);
+
+ arenawindow.onheroclick = new ArenaWindow.OnOverrideClick(OnHeroClick);
+ arenawindow.oncardclick = new ArenaWindow.OnOverrideClick(OnCardClick);
+
+ arenawindow.oncheckboxoverlay = new ArenaWindow.OnCheckbox(OnCheckboxOverlay);
+ arenawindow.oncheckboxmanual = new ArenaWindow.OnCheckbox(OnCheckboxManual);
// Get the latest arena data
string newestfilename = "";
@@ -366,7 +387,44 @@ private void LoadConfig()
// Set window position
arenawindow.Left = configdata.windowx;
arenawindow.Top = configdata.windowy;
+
+ // Set options
+ arenawindow.CheckBoxOverlay.IsChecked = configdata.overlay;
+ arenawindow.CheckBoxManual.IsChecked = configdata.manualclicks;
+ }
+
+ configinit = true;
+ }
+
+ private void ApplyConfig()
+ {
+ // Debug
+ if (configdata.debug)
+ {
+ testtext.Visibility = System.Windows.Visibility.Visible;
+ }
+ else
+ {
+ testtext.Visibility = System.Windows.Visibility.Hidden;
+ }
+
+ // Overlay
+ //ShowOverlay(configdata.overlay);
+ }
+
+ private void ShowOverlay(bool show)
+ {
+ System.Windows.Visibility vis = System.Windows.Visibility.Hidden;
+ if (show)
+ {
+ vis = System.Windows.Visibility.Visible;
+ }
+
+ foreach (var overlay in valueoverlays)
+ {
+ overlay.Visibility = vis;
}
+ adviceoverlay.Visibility = vis;
}
private void SaveConfig()
@@ -379,24 +437,100 @@ private void SaveConfig()
File.WriteAllText(filename, json);
}
- public void OnButton1Click()
+ public void OnButtonNewArenaClick()
{
NewArena();
SaveArenaData();
+ plugins.NewArena(arenadata);
}
- public void OnButton2Click()
+ public void OnAboutClick()
+ {
+ ShowDialog();
+ }
+
+ private async void ShowDialog()
+ {
+ var settings = new MetroDialogSettings { AffirmativeButtonText = "Yes", NegativeButtonText = "No" };
+ try
+ {
+ if (arenawindow != null)
+ {
+ var result = await arenawindow.ShowMessageAsync("About",
+ "Thank you for using my plugin! This plugin was made by Rembound. Do you want to visit my site?",
+ MessageDialogStyle.AffirmativeAndNegative, settings);
+
+ if (result == MessageDialogResult.Affirmative)
+ {
+ Process.Start(@"http://rembound.com");
+ }
+ }
+ }
+ catch
+ {
+
+ }
+ }
+
+ public void OnButtonSaveClick()
{
SaveDeck();
}
+ public void OnHeroClick(int index)
+ {
+ // Override detection
+ if (configdata.manualclicks)
+ {
+
+ }
+ }
+
+ public void OnCardClick(int index)
+ {
+ // Override detection
+ if (!configdata.manualclicks)
+ {
+ return;
+ }
+
+ if (state == PluginState.DetectedCards)
+ {
+ // Manually pick a card
+ PickCard(index);
+ }
+
+ }
+
+ public void OnCheckboxOverlay(bool check)
+ {
+ if (configinit)
+ {
+ configdata.overlay = check;
+ SaveConfig();
+ ApplyConfig();
+ SetState(state); // Set state to update overlay
+ }
+ }
+
+ public void OnCheckboxManual(bool check)
+ {
+ if (configinit)
+ {
+ configdata.manualclicks = check;
+ SaveConfig();
+ ApplyConfig();
+ }
+ }
+
public void OnWindowLocation()
{
// Set window location
configdata.windowx = (int)arenawindow.Left;
configdata.windowy = (int)arenawindow.Top;
- SaveConfig();
+ // Don't save yet
+ //SaveConfig();
}
private void SaveDeck()
@@ -545,13 +679,12 @@ private void NewArena()
inarena = false;
stablearena = false;
+ // Init state
+ SetState(PluginState.SearchHeroes);
+
UpdateTitle();
UpdateHero();
ResetHeroSize();
-
- // Init state
- SetState(PluginState.SearchHeroes);
- prevstate = state;
}
private void ClearDetected()
@@ -600,11 +733,20 @@ public void OnUpdate()
testtext.Text = "";
stopwatch.Restart();
+ // Size updates
+ UpdateSize();
+
// Capture the screen
var hsrect = Helper.GetHearthstoneRect(false);
if (hsrect.Width > 0 && hsrect.Height > 0)
{
- fullcapture = Helper.CaptureHearthstone(new Point(0, 0), hsrect.Width, hsrect.Height, default(IntPtr), true);
+ bool needsfocus = true;
+ if (configdata.manualclicks)
+ {
+ // With manual clicks, we don't need the focus
+ needsfocus = false;
+ }
+ fullcapture = Helper.CaptureHearthstone(new Point(0, 0), hsrect.Width, hsrect.Height, default(IntPtr), needsfocus);
}
else
{
@@ -620,13 +762,40 @@ public void OnUpdate()
// Invalidate arena
inarena = false;
stablearena = false;
- SetState(PluginState.SearchArena);
+ SetState(state);
}
testtext.Text += "\nElapsed: " + stopwatch.ElapsedMilliseconds;
}
}
+ private void UpdateSize()
+ {
+ //Helper.MainWindow.Overlay.Width;
+ //Helper.MainWindow.Overlay.Height;
+
+ var hsrect = Helper.GetHearthstoneRect(false);
+ if (hsrect.Width <= 0 || hsrect.Height <= 0)
+ {
+ return;
+ }
+
+ // Position card values
+ for (int i = 0; i < valueoverlays.Count; i++)
+ {
+ Point cardpos = GetHSPos(hsrect, i * cardwidth + cardrect.X, cardrect.Y, scalewidth, scaleheight);
+ Point cardsize = GetHSSize(hsrect, cardrect.Width, cardrect.Height - 8, scalewidth, scaleheight);
+
+ Canvas.SetLeft(valueoverlays[i], cardpos.X + cardsize.X / 2 - valueoverlays[i].RenderSize.Width/2);
+ Canvas.SetTop(valueoverlays[i], cardpos.Y + cardsize.Y);
+ }
+
+ Point advpos = GetHSPos(hsrect, cardrect.X, cardrect.Y + cardrect.Height - 8, scalewidth, scaleheight);
+ //Point advsize = GetHSSize(hsrect, cardrect.Width, cardrect.Height, scalewidth, scaleheight);
+ Canvas.SetLeft(adviceoverlay, advpos.X);
+ Canvas.SetTop(adviceoverlay, advpos.Y + 50);
+ }
+
// Check if there are plugin updates
// Code from: Hearthstone Collection Tracker Plugin
private async Task CheckUpdate()
@@ -651,7 +820,6 @@ private async Task CheckUpdate()
showingupdatemessage = true;
var settings = new MetroDialogSettings { AffirmativeButtonText = "Yes", NegativeButtonText = "Not now" };
-
try
{
await Task.Delay(TimeSpan.FromSeconds(5));
@@ -682,16 +850,11 @@ private async Task CheckUpdate()
private void SetState(PluginState newstate)
{
- if (state == newstate)
- {
- return;
- }
-
- prevstate = state;
state = newstate;
- if (newstate == PluginState.SearchArena)
+ if (!stablearena)
{
+ ShowOverlay(false);
SetDetectingText("Detecting arena...", DetectionWarning);
arenawindow.DetectingPanel.Visibility = System.Windows.Visibility.Visible;
arenawindow.HeroPanel.Visibility = System.Windows.Visibility.Hidden;
@@ -699,6 +862,7 @@ private void SetState(PluginState newstate)
}
else if (newstate == PluginState.SearchHeroes)
{
+ ShowOverlay(false);
SetDetectingText("Detecting heroes...", DetectionWarning);
arenawindow.DetectingPanel.Visibility = System.Windows.Visibility.Visible;
arenawindow.HeroPanel.Visibility = System.Windows.Visibility.Hidden;
@@ -706,6 +870,7 @@ private void SetState(PluginState newstate)
}
else if (newstate == PluginState.SearchBigHero)
{
+ ShowOverlay(false);
arenawindow.DetectedHeroesWarning.Text = "";
arenawindow.DetectingPanel.Visibility = System.Windows.Visibility.Hidden;
arenawindow.HeroPanel.Visibility = System.Windows.Visibility.Visible;
@@ -713,6 +878,7 @@ private void SetState(PluginState newstate)
}
else if (newstate == PluginState.DetectedHeroes)
{
+ ShowOverlay(false);
arenawindow.DetectedHeroesWarning.Text = "";
arenawindow.DetectingPanel.Visibility = System.Windows.Visibility.Hidden;
arenawindow.HeroPanel.Visibility = System.Windows.Visibility.Visible;
@@ -720,6 +886,7 @@ private void SetState(PluginState newstate)
}
else if (newstate == PluginState.SearchCards)
{
+ ShowOverlay(false);
ClearDetected();
SetDetectingText("Detecting cards...", DetectionWarning);
arenawindow.DetectingPanel.Visibility = System.Windows.Visibility.Visible;
@@ -728,12 +895,14 @@ private void SetState(PluginState newstate)
}
else if (newstate == PluginState.DetectedCards)
{
+ ShowOverlay(configdata.overlay);
arenawindow.DetectingPanel.Visibility = System.Windows.Visibility.Hidden;
arenawindow.HeroPanel.Visibility = System.Windows.Visibility.Hidden;
arenawindow.CardPanel.Visibility = System.Windows.Visibility.Visible;
}
else if (newstate == PluginState.Done)
{
+ ShowOverlay(false);
SetDetectingText("Done", DoneMessage);
arenawindow.DetectingPanel.Visibility = System.Windows.Visibility.Visible;
arenawindow.HeroPanel.Visibility = System.Windows.Visibility.Hidden;
@@ -751,8 +920,7 @@ private void Detect()
// Screen is darker when picking a hero
bool arenacheck2 = false;
- if ((state == PluginState.DetectedHeroes || state == PluginState.SearchBigHero) ||
- (state == PluginState.SearchArena && (prevstate == PluginState.DetectedHeroes || prevstate == PluginState.SearchBigHero)))
+ if (state == PluginState.DetectedHeroes || state == PluginState.SearchBigHero)
{
if (GetHashDistance(arenahash2, arenascreenhash) < 10)
{
@@ -779,10 +947,10 @@ private void Detect()
{
if (arenastopwatch.ElapsedMilliseconds > ArenaDetectionTime)
{
- // Stable arena, restore previous state
+ // Stable arena
arenastopwatch.Stop();
stablearena = true;
- SetState(prevstate);
+ SetState(state);
}
else
{
@@ -796,7 +964,7 @@ private void Detect()
// Invalidate arena
inarena = false;
stablearena = false;
- SetState(PluginState.SearchArena);
+ SetState(state);
return;
}
@@ -857,6 +1025,8 @@ private void SearchHeroes(List heroindices, List cardindices)
arenadata.detectedheroes.Add(hero2.name);
SaveArenaData();
+ plugins.HeroesDetected(arenadata, hero0.name, hero1.name, hero2.name);
+
// Show the heroes
UpdateDetectedHeroes();
@@ -943,11 +1113,12 @@ private void WaitHeroPick(List heroindices, List cardindices)
// No heroes detected, at least one card detected
// The player picked a hero
arenadata.pickedhero = herohashlist[detectedbighero[0].index].name;
-
SaveArenaData();
UpdateHero();
+ plugins.HeroPicked(arenadata, arenadata.pickedhero);
+
// Show the card panel
SetState(PluginState.SearchCards);
}
@@ -967,16 +1138,58 @@ private void SearchCards(List cardindices)
if (ConfirmDetected(detectedcards, cardindices, CardConfirmations) == 3)
{
// All cards detected
+ List newcards = new List();
+ for (int i = 0; i < 3; i++)
+ {
+ newcards.Add(cardlist[detectedcards[i].index].card);
+ }
// Show the cards
- arenawindow.Card0 = cardlist[detectedcards[0].index].card;
- arenawindow.Card1 = cardlist[detectedcards[1].index].card;
- arenawindow.Card2 = cardlist[detectedcards[2].index].card;
+ arenawindow.Card0 = newcards[0];
+ arenawindow.Card1 = newcards[1];
+ arenawindow.Card2 = newcards[2];
+
+ // Add default values from the tierlist
+ List values = new List();
+ for (int i = 0; i < 3; i++)
+ {
+ values.Add(GetCardValue(newcards[i].Id));
+ }
+
+ // Get the plugin result
+ List pvalues = plugins.GetCardValues(arenadata, newcards, values);
+
+ // Override the values if the plugin has a result
+ string advice = "";
+ if (pvalues != null)
+ {
+ if (pvalues.Count >= 3)
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ values[i] = pvalues[i];
+ }
+ }
+
+ // Set advice text
+ if (pvalues.Count >= 4)
+ {
+ //adviceoverlay.AdviceText.Text = "Pick one! The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. dsf sThe quick brown fox jumps over the lazy dog.The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. dsf sThe quick brown fox jumps over the lazy dog.";
+ advice = pvalues[3];
+ }
+ }
// Show the card value
- arenawindow.Value0.Content = GetCardValue(cardlist[detectedcards[0].index].card.Id);
- arenawindow.Value1.Content = GetCardValue(cardlist[detectedcards[1].index].card.Id);
- arenawindow.Value2.Content = GetCardValue(cardlist[detectedcards[2].index].card.Id);
+ arenawindow.Value0.Content = values[0];
+ arenawindow.Value1.Content = values[1];
+ arenawindow.Value2.Content = values[2];
+
+ // Set value text
+ for (int i=0; i cardindices)
{
// All cards detected, wait for new pick
- // Get the click position
- CheckMouse();
-
- testtext.Text += "\nMouse: ";
- for (int i = 0; i < mouseindex.Count; i++)
- {
- testtext.Text += mouseindex[i] + " ";
- }
-
// Display detected cards
testtext.Text += "\nPicking card " + (arenadata.pickedcards.Count + 1) + "/" + MaxCardCount;
for (int i = 0; i < detectedcards.Count; i++)
@@ -1032,6 +1236,22 @@ private void WaitCardPick(List cardindices)
}
}
+ // Skip this if we only allow manual picking
+ if (configdata.manualclicks)
+ {
+ return;
+ }
+
+ // Get the click position
+ CheckMouse();
+
+ testtext.Text += "\nMouse: ";
+ for (int i = 0; i < mouseindex.Count; i++)
+ {
+ testtext.Text += mouseindex[i] + " ";
+ }
+
+
// Check if a new card was detected
bool newcard = false;
for (int i = 0; i < 3; i++) {
@@ -1049,35 +1269,54 @@ private void WaitCardPick(List cardindices)
if ((newcard || GetUndectectedCount(cardindices) == 3) && mouseindex.Count >= 1)
{
// New card or no cards detected, the player picked a card
- string cardid0 = cardlist[detectedcards[0].index].card.Id;
- string cardid1 = cardlist[detectedcards[1].index].card.Id;
- string cardid2 = cardlist[detectedcards[2].index].card.Id;
- arenadata.detectedcards.Add(new Tuple(cardid0, cardid1, cardid2));
-
- arenadata.pickedcards.Add(cardlist[detectedcards[mouseindex[mouseindex.Count-1]].index].card.Id);
- SaveArenaData();
-
- if (arenawindow != null)
- {
- arenawindow.Update();
- }
-
- if (arenadata.pickedcards.Count == MaxCardCount)
- {
- SetState(PluginState.Done);
- }
- else
+ int pickindex = -1;
+ if (mouseindex.Count > 0)
{
- SetState(PluginState.SearchCards);
+ pickindex = mouseindex[mouseindex.Count - 1];
}
-
- UpdateTitle();
+ PickCard(pickindex);
// Clear the mouse data to avoid double detection of clicks
mouseindex.Clear();
}
}
+ private void PickCard(int pickindex)
+ {
+ string cardid0 = cardlist[detectedcards[0].index].card.Id;
+ string cardid1 = cardlist[detectedcards[1].index].card.Id;
+ string cardid2 = cardlist[detectedcards[2].index].card.Id;
+ arenadata.detectedcards.Add(new Tuple(cardid0, cardid1, cardid2));
+
+ // Add to pickedcards
+ string cardid = "";
+ if (pickindex >= 0)
+ {
+ cardid = cardlist[detectedcards[pickindex].index].card.Id;
+ }
+ arenadata.pickedcards.Add(cardid);
+ SaveArenaData();
+
+ plugins.CardPicked(arenadata, pickindex, cardid);
+
+ if (arenawindow != null)
+ {
+ arenawindow.Update();
+ }
+
+ if (arenadata.pickedcards.Count == MaxCardCount)
+ {
+ SetState(PluginState.Done);
+ plugins.Done(arenadata);
+ }
+ else
+ {
+ SetState(PluginState.SearchCards);
+ }
+
+ UpdateTitle();
+ }
+
private CardInfo GetCard(string id)
{
for (int i=0; i GetCardValues(ArenaHelper.Plugin.ArenaData arenadata, List newcards, List defaultvalues) { return null; }
+
+ // Called when a new arena is started
+ // arendata: As before
+ public virtual void NewArena(ArenaHelper.Plugin.ArenaData arenadata) { }
+
+ // Called when the heroes are detected
+ // arendata: As before
+ // heroname0: name of hero 0
+ // heroname1: name of hero 1
+ // heroname2: name of hero 2
+ public virtual void HeroesDetected(ArenaHelper.Plugin.ArenaData arenadata, string heroname0, string heroname1, string heroname2) { }
+
+ // Called when a hero is picked
+ // arendata: As before
+ // heroname: name of the hero
+ public virtual void HeroPicked(ArenaHelper.Plugin.ArenaData arenadata, string heroname) { }
+
+ // Called when a card is picked
+ // arendata: As before
+ // pickindex: index of the picked card in the range -1 to 2, if -1, no valid pick was detected
+ // cardid: id of the card like "CS2_029"
+ public virtual void CardPicked(ArenaHelper.Plugin.ArenaData arenadata, int pickindex, string cardid) { }
+
+ // Called when all cards are picked
+ // arendata: As before
+ public virtual void Done(ArenaHelper.Plugin.ArenaData arenadata) { }
+ }
+}
+
+namespace ArenaHelper
+{
+ class Plugins
+ {
+ List plugins = new List();
+
+ public Plugins()
+ {
+ }
+
+ public void LoadPlugins()
+ {
+ plugins.Clear();
+
+ // Find dlls
+ string assemblylocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ string pluginpath = Path.Combine(assemblylocation, "plugins");
+
+ string[] dllFileNames = null;
+ if (Directory.Exists(pluginpath))
+ {
+ dllFileNames = Directory.GetFiles(pluginpath, "*.dll");
+ }
+ else
+ {
+ return;
+ }
+
+ if (dllFileNames.Length <= 0)
+ {
+ return;
+ }
+
+ // Load assemblies
+ ICollection assemblies = new List(dllFileNames.Length);
+ foreach (string dllFile in dllFileNames)
+ {
+ //Logger.WriteLine("Loading plugin: " + dllFile);
+ AssemblyName an = AssemblyName.GetAssemblyName(dllFile);
+ Assembly assembly = Assembly.Load(an);
+ assemblies.Add(assembly);
+ }
+
+ // Find valid plugins
+ Type pluginType = typeof(AHPlugin);
+ ICollection pluginTypes = new List();
+ foreach (Assembly assembly in assemblies)
+ {
+ if (assembly != null)
+ {
+ Type[] types = assembly.GetTypes();
+ foreach (Type type in types)
+ {
+ if (type.IsInterface || type.IsAbstract)
+ {
+ continue;
+ }
+ else
+ {
+ if (type.IsSubclassOf(pluginType))
+ {
+ pluginTypes.Add(type);
+ }
+ }
+ }
+ }
+ }
+
+ // Create instances
+ foreach (Type type in pluginTypes)
+ {
+ AHPlugin plugin = (AHPlugin)Activator.CreateInstance(type);
+ plugins.Add(plugin);
+ Logger.WriteLine("Found: " + plugin.Name);
+ }
+ }
+
+ public List GetCardValues(ArenaHelper.Plugin.ArenaData arenadata, List newcards, List defaultvalues)
+ {
+ foreach (var plugin in plugins)
+ {
+ return plugin.GetCardValues(arenadata, newcards, defaultvalues);
+ }
+ return null;
+ }
+
+ public void NewArena(ArenaHelper.Plugin.ArenaData arenadata)
+ {
+ foreach (var plugin in plugins)
+ {
+ plugin.NewArena(arenadata);
+ return;
+ }
+ }
+
+ public void HeroesDetected(ArenaHelper.Plugin.ArenaData arenadata, string heroname0, string heroname1, string heroname2)
+ {
+ foreach (var plugin in plugins)
+ {
+ plugin.HeroesDetected(arenadata, heroname0, heroname1, heroname2);
+ return;
+ }
+ }
+
+ public void HeroPicked(ArenaHelper.Plugin.ArenaData arenadata, string heroname)
+ {
+ foreach (var plugin in plugins)
+ {
+ plugin.HeroPicked(arenadata, heroname);
+ return;
+ }
+ }
+
+ public void CardPicked(ArenaHelper.Plugin.ArenaData arenadata, int pickindex, string cardid)
+ {
+ foreach (var plugin in plugins)
+ {
+ plugin.CardPicked(arenadata, pickindex, cardid);
+ return;
+ }
+ }
+
+ public void Done(ArenaHelper.Plugin.ArenaData arenadata)
+ {
+ foreach (var plugin in plugins)
+ {
+ plugin.Done(arenadata);
+ return;
+ }
+ }
+ }
+}
diff --git a/TestPlugin/Properties/AssemblyInfo.cs b/TestPlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..556bd20
--- /dev/null
+++ b/TestPlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TestPlugin")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("TestPlugin")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("832a29d4-aa2b-41f7-ae22-e6d36fcd0a01")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TestPlugin/TestPlugin.cs b/TestPlugin/TestPlugin.cs
new file mode 100644
index 0000000..0a22e9d
--- /dev/null
+++ b/TestPlugin/TestPlugin.cs
@@ -0,0 +1,104 @@
+using AHPlugins;
+using Hearthstone_Deck_Tracker;
+using Hearthstone_Deck_Tracker.Hearthstone;
+using System;
+using System.Collections.Generic;
+
+// A test plugin that does something when cards are detected
+// Reference ArenaHelper.dll and Hearthstone Deck Tracker
+// Place the dll in ArenaHelper/plugins/ in the HDT plugins directory
+// Only one plugin can be activated at a time
+namespace TestPlugin
+{
+ public class TestPlugin : AHPlugin
+ {
+ public override string Name
+ {
+ get { return "TestPlugin"; }
+ }
+
+ public override string Author
+ {
+ get { return "Rembound.com"; }
+ }
+
+ public override Version Version
+ {
+ get { return new Version("0.0.1"); }
+ }
+
+ public TestPlugin()
+ {
+ // Plugin constructor
+ // Setup stuff
+ Logger.WriteLine("TestPlugin constructor");
+ }
+
+ // Called when three new cards are detected
+ // arenadata: The previously detected cards, picked cards and heroes
+ // newcards: List of 3 detected cards
+ // defaultvalues: List of 3 tier values for the detected cards
+ // Return a list of 3 card values and an optional 4th advice value
+ public override List GetCardValues(ArenaHelper.Plugin.ArenaData arenadata, List newcards, List defaultvalues)
+ {
+ List values = new List();
+
+ // Add the three card values
+ for (int i = 0; i < 3; i++)
+ {
+ values.Add("p" + i.ToString() + " " + defaultvalues[i]);
+ }
+
+ // Optionally add an advice as a 4th list element
+ values.Add("I don't know, pick one!");
+
+ return values;
+ }
+
+ // Called when a new arena is started
+ // arendata: As before
+ public override void NewArena(ArenaHelper.Plugin.ArenaData arenadata)
+ {
+ // Do something with the information
+ Logger.WriteLine("New Arena: " + arenadata.deckname);
+ }
+
+ // Called when the heroes are detected
+ // arendata: As before
+ // heroname0: name of hero 0
+ // heroname1: name of hero 1
+ // heroname2: name of hero 2
+ public override void HeroesDetected(ArenaHelper.Plugin.ArenaData arenadata, string heroname0, string heroname1, string heroname2)
+ {
+ // Do something with the information
+ Logger.WriteLine("Heroes Detected: " + heroname0 + ", " + heroname1 + ", " + heroname2);
+ }
+
+ // Called when a hero is picked
+ // arendata: As before
+ // heroname: name of the hero
+ public override void HeroPicked(ArenaHelper.Plugin.ArenaData arenadata, string heroname)
+ {
+ // Do something with the information
+ Logger.WriteLine("Hero Picked: " + heroname);
+ }
+
+ // Called when a card is picked
+ // arendata: As before
+ // pickindex: index of the picked card in the range -1 to 2, if -1, no valid pick was detected
+ // cardid: id of the card like "CS2_029"
+ public override void CardPicked(ArenaHelper.Plugin.ArenaData arenadata, int pickindex, string cardid)
+ {
+ // Do something with the information
+ Logger.WriteLine("Card Picked: " + cardid);
+ }
+
+ // Called when all cards are picked
+ // arendata: As before
+ public override void Done(ArenaHelper.Plugin.ArenaData arenadata)
+ {
+ // Do something with the information
+ Logger.WriteLine("Done");
+ }
+ }
+}
\ No newline at end of file
diff --git a/TestPlugin/TestPlugin.csproj b/TestPlugin/TestPlugin.csproj
new file mode 100644
index 0000000..7f4dfd9
--- /dev/null
+++ b/TestPlugin/TestPlugin.csproj
@@ -0,0 +1,61 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {9DBE89DA-8673-4657-A0DC-EC1F26C70B8A}
+ Library
+ Properties
+ TestPlugin
+ TestPlugin
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\..\..\..\Software\Games\Hearthstone Deck Tracker\Plugins\ArenaHelper\ArenaHelper.dll
+ False
+
+
+ ..\..\..\..\..\..\..\Software\Games\Hearthstone Deck Tracker\Hearthstone Deck Tracker.exe
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file