diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7409cd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.atom-build.yml \ No newline at end of file diff --git a/Graveyard.csproj b/Graveyard.csproj new file mode 100644 index 0000000..f338ab9 --- /dev/null +++ b/Graveyard.csproj @@ -0,0 +1,85 @@ + + + + Debug + x86 + {59c8cca4-7f9b-4592-87a8-a23aded7759e} + Library + Graveyard + Graveyard + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + lib\HearthDb.dll + + + lib\HearthstoneDeckTracker.exe + + + False + lib\MahApps.Metro.dll + + + + + + + + + + + + SettingsView.xaml + + + Designer + MSBuild:Compile + + + True + True + Settings.settings + + + PublicSettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec7561d --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# Graveyard +Graveyard is a plugin for the [Hearthstone Deck Tracker](https://github.com/HearthSim/Hearthstone-Deck-Tracker). + +Graveyard displays minions that have died this game. In addition Graveyard will display specialized views for decks containing certain cards. + +* **Anyfin Can Happen** +Displays Murlocs killed by both the player and opponent as well as a damage calculator (thanks to [AnyfinCalculator](https://github.com/ericBG/AnyfinCalculator)). + +* **N'Zoth the Corruptor** +Displays deathrattle minions. + +* **Resurect** or **Onix Bishop** +Displays resurect chance next to each minion that has died. + +## Installing +Extract `graveyard.dll` from the archive and move it to `%AppData%\HearthstoneDeckTracker\Plugins`. You will need to enable Graveyard in the Hearthstone Deck Tracker client under `Options > Tracker > Plugins > Graveyard`. diff --git a/lib/HearthDb.dll b/lib/HearthDb.dll new file mode 100644 index 0000000..7a7a423 Binary files /dev/null and b/lib/HearthDb.dll differ diff --git a/lib/HearthstoneDeckTracker.exe b/lib/HearthstoneDeckTracker.exe new file mode 100644 index 0000000..da11318 Binary files /dev/null and b/lib/HearthstoneDeckTracker.exe differ diff --git a/lib/MahApps.Metro.dll b/lib/MahApps.Metro.dll new file mode 100644 index 0000000..c71adf9 Binary files /dev/null and b/lib/MahApps.Metro.dll differ diff --git a/src/AnyfinCalculator.cs b/src/AnyfinCalculator.cs new file mode 100644 index 0000000..b7a12aa --- /dev/null +++ b/src/AnyfinCalculator.cs @@ -0,0 +1,246 @@ +/** + * Code originally from https://github.com/ericBG/AnyfinCalculator. + * Thank you ericBG for all the hard work! + * + * The MIT License (MIT) + * + * Copyright (c) 2016 ericBG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +using System.Runtime.CompilerServices; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System; +using HearthDb.Enums; +using Hearthstone_Deck_Tracker; +using Hearthstone_Deck_Tracker.Hearthstone; +using Hearthstone_Deck_Tracker.Hearthstone.Entities; +using Hearthstone_Deck_Tracker.Utility.Logging; + +namespace HDT.Plugins.Graveyard +{ + public class MurlocInfo + { + public enum State + { + Dead, + OnBoard, + OnOpponentsBoard + } + + public State BoardState { get; set; } + public bool CanAttack { get; set; } + public bool IsSilenced { get; set; } + public bool AreBuffsApplied { get; set; } + public int Attack { get; set; } + public Card Murloc { get; set; } + } + + public class Range where T : IComparable + { + public T Minimum { get; set; } + public T Maximum { get; set; } + } + + public class AnyfinCalculator + { + public static Range CalculateDamageDealt(List Graveyard) + { + var DeadMurlocs = new List(); + foreach (var card in Graveyard) { + for (var i = 0; i < card.Count; i++) { + var c = card.Clone() as Card; + c.Count = 1; + DeadMurlocs.Add(c); + } + } + + if (Core.Game.PlayerMinionCount >= 7) return new Range() {Maximum = 0, Minimum = 0}; + if (DeadMurlocs.Count() + Core.Game.PlayerMinionCount <= 7) + { + var damage = CalculateDamageInternal(DeadMurlocs, Core.Game.Player.Board, + Core.Game.Opponent.Board); + return new Range {Maximum = damage, Minimum = damage}; + } + var sw = Stopwatch.StartNew(); + var board = Core.Game.Player.Board.ToList(); + var opponent = Core.Game.Opponent.Board.ToList(); + int? min = null, max = null; + foreach (var combination in Combinations(DeadMurlocs, 7 - Core.Game.PlayerMinionCount)) + { + var damage = CalculateDamageInternal(combination, board, opponent); + if (damage > max || !max.HasValue) max = damage; + if (damage < min || !min.HasValue) min = damage; + } + sw.Stop(); + Log.Debug($"Time to calculate the possibilities: {sw.Elapsed.ToString("ss\\:fff")}"); + return new Range {Maximum = max.Value, Minimum = min.Value}; + } + + private static int CalculateDamageInternal(IEnumerable graveyard, IEnumerable friendlyBoard, + IEnumerable opponentBoard) + { + var deadMurlocs = graveyard.ToList(); + var aliveMurlocs = friendlyBoard.Where(c => c.Card.IsMurloc()).ToList(); + var opponentMurlocs = opponentBoard.Where(c => c.Card.IsMurloc()).ToList(); + //compiles together into one big freaking list + var murlocs = + deadMurlocs.Select( + c => + new MurlocInfo + { + AreBuffsApplied = false, + Attack = c.Attack, + BoardState = MurlocInfo.State.Dead, + CanAttack = c.IsChargeMurloc(), + IsSilenced = false, + Murloc = c + }) + .Concat( + aliveMurlocs.Select( + ent => + new MurlocInfo + { + AreBuffsApplied = true, + Attack = ent.GetTag(GameTag.ATK), + BoardState = MurlocInfo.State.OnBoard, + CanAttack = CanAttack(ent), + IsSilenced = IsSilenced(ent), + Murloc = ent.Card + })) + .Concat( + opponentMurlocs.Select( + ent => + new MurlocInfo + { + AreBuffsApplied = false, + Attack = ent.Card.Attack, + BoardState = MurlocInfo.State.OnOpponentsBoard, + CanAttack = false, + IsSilenced = IsSilenced(ent), + Murloc = ent.Card + })).ToList(); + var nonSilencedWarleaders = + murlocs.Count(m => m.BoardState != MurlocInfo.State.Dead && m.Murloc.IsWarleader() && !m.IsSilenced); + var nonSilencedGrimscales = + murlocs.Count(m => m.BoardState != MurlocInfo.State.Dead && m.Murloc.IsGrimscale() && !m.IsSilenced); + var murlocsToBeSummoned = murlocs.Count(m => m.BoardState == MurlocInfo.State.Dead); + foreach (var murloc in murlocs.Where(t => t.AreBuffsApplied)) + { + murloc.AreBuffsApplied = false; + murloc.Attack -= nonSilencedGrimscales + (nonSilencedWarleaders*2); + if (murloc.IsSilenced) continue; + if (murloc.Murloc.IsGrimscale()) murloc.Attack += 1; + if (murloc.Murloc.IsWarleader()) murloc.Attack += 2; + if (murloc.Murloc.IsMurkEye()) murloc.Attack -= (murlocs.Count(m => m.BoardState != MurlocInfo.State.Dead) - 1); + } + nonSilencedWarleaders += murlocs.Count(m => m.BoardState == MurlocInfo.State.Dead && m.Murloc.IsWarleader()); + nonSilencedGrimscales += murlocs.Count(m => m.BoardState == MurlocInfo.State.Dead && m.Murloc.IsGrimscale()); + foreach (var murloc in murlocs) + { + murloc.AreBuffsApplied = true; + murloc.Attack += nonSilencedGrimscales + (nonSilencedWarleaders*2); + if (murloc.IsSilenced) continue; + if (murloc.Murloc.IsWarleader()) murloc.Attack -= 2; + if (murloc.Murloc.IsGrimscale()) murloc.Attack -= 1; + if (murloc.Murloc.IsMurkEye()) murloc.Attack += (murlocs.Count - 1); + if (murloc.Murloc.IsTidecaller()) murloc.Attack += murlocsToBeSummoned; + } + Log.Debug(murlocs.Aggregate("", + (s, m) => + s + $"{m.Murloc.Name}{(m.IsSilenced ? " (Silenced)" : "")}: {m.Attack} {(!m.CanAttack ? "(Can't Attack)" : "")}\n")); + return murlocs.Sum(m => m.CanAttack ? m.Attack : 0); + } + + private static bool IsSilenced(Entity entity) => entity.GetTag(GameTag.SILENCED) == 1; + + private static bool CanAttack(Entity entity) + { + if (entity.GetTag(GameTag.CANT_ATTACK) == 1 || entity.GetTag(GameTag.FROZEN) == 1) + return false; + if (entity.GetTag(GameTag.EXHAUSTED) == 1) + //from reading the HDT source, it seems like internally Charge minions still have summoning sickness + return entity.GetTag(GameTag.CHARGE) == 1 && + entity.GetTag(GameTag.NUM_ATTACKS_THIS_TURN) < MaxAttacks(entity); + return entity.GetTag(GameTag.NUM_ATTACKS_THIS_TURN) < MaxAttacks(entity); + } + + private static int MaxAttacks(Entity entity) + { + // GVG_111t == V-07-TR-0N (MegaWindfury, 4x attack) + if (entity.CardId == "GVG_111t") return 4; + // if it has windfury it can attack twice, else it can only attack once + return entity.GetTag(GameTag.WINDFURY) == 1 ? 2 : 1; + } + + public static IEnumerable> Combinations(IEnumerable elements, int k) + { + return k == 0 + ? new[] {new T[0]} + : elements.SelectMany((e, i) => + Combinations(elements.Skip(i + 1), k - 1).Select(c => (new[] {e}).Concat(c))); + } + } + + public static class Murlocs + { + static Murlocs() + { + BluegillWarrior = Database.GetCardFromId("CS2_173"); + GrimscaleOracle = Database.GetCardFromId("EX1_508"); + MurlocWarleader = Database.GetCardFromId("EX1_507"); + OldMurkEye = Database.GetCardFromId("EX1_062"); + MurlocTidecaller = Database.GetCardFromId("EX1_509"); + AnyfinCanHappen = Database.GetCardFromId("LOE_026"); + } + + public static Card BluegillWarrior { get; } + public static Card GrimscaleOracle { get; } + public static Card MurlocWarleader { get; } + public static Card OldMurkEye { get; } + public static Card MurlocTidecaller { get; } + public static Card AnyfinCanHappen { get; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsMurloc(this Card card) => card.Race == "Murloc"; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsChargeMurloc(this Card card) => card.Id == OldMurkEye.Id || card.Id == BluegillWarrior.Id; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsBluegill(this Card card) => card.Id == BluegillWarrior.Id; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsGrimscale(this Card card) => card.Id == GrimscaleOracle.Id; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsWarleader(this Card card) => card.Id == MurlocWarleader.Id; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsMurkEye(this Card card) => card.Id == OldMurkEye.Id; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsTidecaller(this Card card) => card.Id == MurlocTidecaller.Id; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsAnyfin(this Card card) => card.Id == AnyfinCanHappen.Id; + } +} diff --git a/src/AnyfinView.cs b/src/AnyfinView.cs new file mode 100644 index 0000000..e5c4f3c --- /dev/null +++ b/src/AnyfinView.cs @@ -0,0 +1,44 @@ +using System.Linq; +using System.Windows; +using Hearthstone_Deck_Tracker; +using Hearthstone_Deck_Tracker.Hearthstone; + +namespace HDT.Plugins.Graveyard +{ + public class AnyfinView : NormalView + { + private HearthstoneTextBlock _dmg; + + public static bool isValid () { + return Core.Game.Player.PlayerCardList.FindIndex(card => card.Id == "LOE_026") > -1; + } + + public AnyfinView () { + // Section Label + Label.Text = "Anyfin Can Happen"; + + // Damage Label + _dmg = new HearthstoneTextBlock(); + _dmg.FontSize = 24; + _dmg.TextAlignment = TextAlignment.Center; + _dmg.Text = "0"; + Children.Add(_dmg); + _dmg.Visibility = Visibility.Hidden; + } + + new public bool Update (Card card) { + if (card.Race != "Murloc" || !base.Update(card)) return false; + UpdateDamage(); + return true; + } + + public void UpdateDamage () { + // Update damage counter + Range damage = AnyfinCalculator.CalculateDamageDealt(Cards); + + _dmg.Text = damage.Minimum == damage.Maximum ? + damage.Maximum.ToString() : $"{damage.Minimum} - {damage.Maximum}"; + _dmg.Visibility = Cards.Count > 0 ? Visibility.Visible : Visibility.Hidden; + } + } +} diff --git a/src/Graveyard.cs b/src/Graveyard.cs new file mode 100644 index 0000000..357eb57 --- /dev/null +++ b/src/Graveyard.cs @@ -0,0 +1,107 @@ +using System; +using System.ComponentModel; +using System.Windows.Controls; +using System.Windows.Media; +using Hearthstone_Deck_Tracker; +using Hearthstone_Deck_Tracker.Utility.Logging; +using Hearthstone_Deck_Tracker.API; +using Core = Hearthstone_Deck_Tracker.API.Core; +using Card = Hearthstone_Deck_Tracker.Hearthstone.Card; + +namespace HDT.Plugins.Graveyard +{ + public class Graveyard + { + // The views + public NormalView Normal; + public ResurrectView Resurrect; + public AnyfinView Anyfin; + public NZothView NZoth; + + private StackPanel _vertical; + + public Graveyard () { + // Create container + _vertical = new StackPanel(); + _vertical.Orientation = Orientation.Vertical; + _vertical.RenderTransform = new ScaleTransform( + Config.Instance.OverlayPlayerScaling / 100, + Config.Instance.OverlayPlayerScaling / 100); + Core.OverlayCanvas.Children.Add(_vertical); + + // Stick to the left of the player panal + var border = Core.OverlayCanvas.FindName("BorderStackPanelPlayer") as Border; + DependencyPropertyDescriptor.FromProperty(Canvas.LeftProperty, typeof(Border)) + .AddValueChanged(border, Layout); + DependencyPropertyDescriptor.FromProperty(Canvas.TopProperty, typeof(Border)) + .AddValueChanged(border, Layout); + DependencyPropertyDescriptor.FromProperty(StackPanel.ActualWidthProperty, typeof(StackPanel)) + .AddValueChanged(_vertical, Layout); + + // Connect events + GameEvents.OnGameStart.Add(Reset); + DeckManagerEvents.OnDeckSelected.Add(d => Reset()); + GameEvents.OnPlayerPlayToGraveyard.Add(Update); + + GameEvents.OnOpponentPlayToGraveyard.Add(c => Anyfin?.Update(c)); + GameEvents.OnPlayerPlay.Add(c => Anyfin?.UpdateDamage()); + GameEvents.OnOpponentPlay.Add(c => Anyfin?.UpdateDamage()); + } + + public void Dispose () { + Core.OverlayCanvas.Children.Remove(_vertical); + var border = Core.OverlayCanvas.FindName("BorderStackPanelPlayer") as Border; + DependencyPropertyDescriptor.FromProperty(Canvas.LeftProperty, typeof(Border)) + .RemoveValueChanged(border, Layout); + DependencyPropertyDescriptor.FromProperty(Canvas.TopProperty, typeof(Border)) + .RemoveValueChanged(border, Layout); + DependencyPropertyDescriptor.FromProperty(StackPanel.ActualWidthProperty, typeof(StackPanel)) + .RemoveValueChanged(_vertical, Layout); + } + + private void Layout (object obj, EventArgs e) { + var border = Core.OverlayCanvas.FindName("BorderStackPanelPlayer") as Border; + Canvas.SetLeft(_vertical, Canvas.GetLeft(border) - _vertical.ActualWidth * Config.Instance.OverlayPlayerScaling / 100 - 10); + Canvas.SetTop(_vertical, Canvas.GetTop(border)); + } + + /** + * Clear then recreate all Views. + */ + public void Reset () { + _vertical.Children.Clear(); + + if (Settings.Default.ResurrectEnabled && ResurrectView.isValid()) { + Resurrect = new ResurrectView(); + _vertical.Children.Add(Resurrect); + Normal = null; + } else if (Settings.Default.NormalEnabled) { + Normal = new NormalView(); + _vertical.Children.Add(Normal); + Resurrect = null; + } + + if (Settings.Default.AnyfinEnabled && AnyfinView.isValid()) { + Anyfin = new AnyfinView(); + _vertical.Children.Add(Anyfin); + } else { + Anyfin = null; + } + + if (Settings.Default.NZothEnabled && NZothView.isValid()) { + NZoth = new NZothView(); + _vertical.Children.Add(NZoth); + } else { + NZoth = null; + } + } + + public void Update (Card card) { + var a = Anyfin?.Update(card) ?? false; + var b = NZoth?.Update(card) ?? false; + var c = Resurrect?.Update(card) ?? false; + if (!(a || b || c)) + Normal?.Update(card); + } + } +} diff --git a/src/GraveyardPlugin.cs b/src/GraveyardPlugin.cs new file mode 100644 index 0000000..e51d6ef --- /dev/null +++ b/src/GraveyardPlugin.cs @@ -0,0 +1,59 @@ +using System; +using System.Windows.Controls; +using Hearthstone_Deck_Tracker.Plugins; + +namespace HDT.Plugins.Graveyard +{ + public class GraveyardPlugin : IPlugin + { + public Graveyard GraveyardInstance; + + public string Author + { + get { return "RedHatter"; } + } + + public string ButtonText + { + get { return "Settings"; } + } + + public string Description + { + get { return "Displays minions that have died this game. Includes specialized displays: deathrattle minions for N'Zoth decks, resurect chance for Resurect Priest, and Murloc minions with a damage calculator for Anyfin Can Happen."; } + } + + public MenuItem MenuItem + { + get { return null; } + } + + public string Name + { + get { return "Graveyard"; } + } + + public void OnButtonPress() + { + SettingsView.Flyout.IsOpen = true; + } + + public void OnLoad() + { + GraveyardInstance = new Graveyard (); + } + + public void OnUnload() + { + GraveyardInstance.Dispose(); + GraveyardInstance = null; + } + + public void OnUpdate() {} + + public Version Version + { + get { return new Version(1, 0, 0); } + } + } +} diff --git a/src/NZothView.cs b/src/NZothView.cs new file mode 100644 index 0000000..ff509ac --- /dev/null +++ b/src/NZothView.cs @@ -0,0 +1,24 @@ +using System.Linq; +using System.Windows; +using Hearthstone_Deck_Tracker; +using Hearthstone_Deck_Tracker.Utility.Logging; +using Hearthstone_Deck_Tracker.Hearthstone; + +namespace HDT.Plugins.Graveyard +{ + public class NZothView : NormalView + { + public static bool isValid () { + return Core.Game.Player.PlayerCardList.FindIndex(card => card.Id == "OG_133") > -1; + } + + public NZothView () { + // Section Label + Label.Text = "N'Zoth, the Corruptor"; + } + + new public bool Update (Card card) { + return card.Mechanics.Contains("Deathrattle") && base.Update(card); + } + } +} diff --git a/src/NormalView.cs b/src/NormalView.cs new file mode 100644 index 0000000..b1422ab --- /dev/null +++ b/src/NormalView.cs @@ -0,0 +1,59 @@ +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Collections.Generic; +using Hearthstone_Deck_Tracker; +using Hearthstone_Deck_Tracker.Utility.Logging; +using Hearthstone_Deck_Tracker.Controls; +using Card = Hearthstone_Deck_Tracker.Hearthstone.Card; + +namespace HDT.Plugins.Graveyard +{ + public class NormalView : StackPanel + { + public List Cards; + public HearthstoneTextBlock Label; + public AnimatedCardList View; + + public NormalView () { + Orientation = Orientation.Vertical; + + // Section Label + Label = new HearthstoneTextBlock(); + Label.FontSize = 16; + Label.TextAlignment = TextAlignment.Center; + Label.Text = "Graveyard"; + var margin = Label.Margin; + margin.Top = 20; + Label.Margin = margin; + Children.Add(Label); + Label.Visibility = Visibility.Hidden; + + // Card View + View = new AnimatedCardList(); + Children.Add(View); + Cards = new List(); + } + + public bool Update (Card card) { + if (card.Type != "Minion") + return false; + + // Increment + var match = Cards.FirstOrDefault(c => c.Name == card.Name); + if (match != null) { + Cards.Remove(match); + card = match.Clone() as Card; + card.Count++; + } + + // Update View + Cards.Add(card); + View.Update(Cards, false); + + Label.Visibility = Visibility.Visible; + + return true; + } + } +} diff --git a/src/ResurrectView.cs b/src/ResurrectView.cs new file mode 100644 index 0000000..8362717 --- /dev/null +++ b/src/ResurrectView.cs @@ -0,0 +1,51 @@ +using System; +using System.Linq; +using System.Windows; +using System.Windows.Shapes; +using System.Windows.Controls; +using System.Collections.Generic; +using Hearthstone_Deck_Tracker; +using Hearthstone_Deck_Tracker.Hearthstone; + +namespace HDT.Plugins.Graveyard +{ + public class ResurrectView : NormalView + { + private Dictionary _chances; + + public static bool isValid () { + return Core.Game.Player.PlayerCardList.FindIndex(card => + card.Id == "BRM_017" || card.Id == "KAR_204") > -1; + } + + public ResurrectView () { + // Section Label + Label.Text = "Resurrect"; + + _chances = new Dictionary(); + } + + new public bool Update (Card card) { + if (!base.Update(card)) return false; + + var count = (double) Cards.Aggregate(0, (total, c) => total + c.Count); + for (var i = 0; i < Cards.Count(); i++) { + if (!_chances.ContainsKey(Cards[i])) { + var chance = new HearthstoneTextBlock(); + chance.FontSize = 18; + chance.TextAlignment = TextAlignment.Left; + var grid = (View.Items.GetItemAt(i) as UserControl).Content as Grid; + grid.Width = 260; + (grid.Children[0] as Rectangle).HorizontalAlignment = HorizontalAlignment.Right; + (grid.Children[1] as Rectangle).Width = 260; + grid.Children.Add(chance); + _chances.Add(Cards[i], chance); + } + + _chances[Cards[i]].Text = $"{Math.Round(Cards[i].Count / count * 100)}%"; + } + + return true; + } + } +} diff --git a/src/Settings.Designer.cs b/src/Settings.Designer.cs new file mode 100644 index 0000000..6cb9be7 --- /dev/null +++ b/src/Settings.Designer.cs @@ -0,0 +1,65 @@ +namespace HDT.Plugins.Graveyard { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool NormalEnabled { + get { + return ((bool)(this["NormalEnabled"])); + } + set { + this["NormalEnabled"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool ResurrectEnabled { + get { + return ((bool)(this["ResurrectEnabled"])); + } + set { + this["ResurrectEnabled"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool AnyfinEnabled { + get { + return ((bool)(this["AnyfinEnabled"])); + } + set { + this["AnyfinEnabled"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool NZothEnabled { + get { + return ((bool)(this["NZothEnabled"])); + } + set { + this["NZothEnabled"] = value; + } + } + + } +} diff --git a/src/Settings.settings b/src/Settings.settings new file mode 100644 index 0000000..a2fbdab --- /dev/null +++ b/src/Settings.settings @@ -0,0 +1,18 @@ + + + + + + True + + + True + + + True + + + True + + + diff --git a/src/SettingsView.xaml b/src/SettingsView.xaml new file mode 100644 index 0000000..4717f5e --- /dev/null +++ b/src/SettingsView.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/src/SettingsView.xaml.cs b/src/SettingsView.xaml.cs new file mode 100644 index 0000000..ea4a4ec --- /dev/null +++ b/src/SettingsView.xaml.cs @@ -0,0 +1,35 @@ +using System.Windows.Controls; +using MahApps.Metro.Controls; +using Hearthstone_Deck_Tracker; + +namespace HDT.Plugins.Graveyard +{ + public partial class SettingsView : StackPanel + { + private static Flyout _flyout; + public static Flyout Flyout { + get { + if (_flyout == null) + _flyout = CreateSettingsFlyout(); + + return _flyout; + } + } + + private static Flyout CreateSettingsFlyout() + { + var settings = new Flyout(); + settings.Position = Position.Left; + Panel.SetZIndex(settings, 100); + settings.Header = "Graveyard Settings"; + settings.Content = new SettingsView(); + Core.MainWindow.Flyouts.Items.Add(settings); + return settings; + } + + public SettingsView() { + InitializeComponent(); + Settings.Default.PropertyChanged += (sender, e) => Settings.Default.Save(); + } + } +}