public static void Update() { // Don't do anything if not in a game if (API.Game.IsInMenu || !API.Game.IsRunning) { return; } System.Windows.Point firstCardInHand = new System.Windows.Point(0.0d, 0.0d); firstCardInHand = Hearthstone_Deck_Tracker.Windows.OverlayWindow.GetPlayerCardPosition(1, 1); int count = API.Game.Entities.Count; int[] playerMinionPositions = { 0, 0, 0, 0, 0, 0, 0 }; for (int i = 0; i < count; i++) { if (API.Game.Entities[0].IsPlayer) { } } // Compare with old value and update with new value simultaneously // Print to debug log if changed and if program is in debug mode if (playerHandCount != (playerHandCount = API.Game.Player.HandCount) && debug) { Logger.WriteLine("Player now has " + playerHandCount + " in hand."); } if (playerMinionCount != (playerMinionCount = API.Game.PlayerMinionCount) && debug) { Logger.WriteLine("Player now has " + playerMinionCount + " minions."); } if (opponentHandCount != (opponentHandCount = API.Game.Opponent.HandCount) && debug) { Logger.WriteLine("Opponent now has " + opponentHandCount + " in hand."); } if (opponentMinionCount != (opponentMinionCount = API.Game.OpponentMinionCount) && debug) { Logger.WriteLine("Opponent now has " + opponentMinionCount + " minions."); } /* * TODO * - * * NOTES * - if player.goingFirst mulligancards = 4 * - else mulligancards = 3 */ }
private static async Task <Deck> ImportHearthstoneheroes(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck { Name = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//header[@class='panel-heading']/h1[@class='panel-title']").InnerText) .Trim() }; var nodes = doc.DocumentNode.SelectNodes("//table[@class='table table-bordered table-hover table-db']/tbody/tr"); foreach (var cardNode in nodes) { var name = HttpUtility.HtmlDecode(cardNode.SelectSingleNode(".//a").Attributes[3].Value); var temp = HttpUtility.HtmlDecode(cardNode.SelectSingleNode(".//a/small").InnerText[0].ToString()); var count = int.Parse(temp); var card = Game.GetCardFromName(name); card.Count = count; deck.Cards.Add(card); if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } } return(deck); } catch (Exception e) { Logger.WriteLine(e.ToString(), "DeckImporter"); return(null); } }
private static async Task <Deck> ImportHearthArena(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck { Name = "Arena " + DateTime.Now.ToString("dd-MM HH:mm"), IsArenaDeck = true }; var cardNodes = doc.DocumentNode.SelectSingleNode(".//ul[@class='deckList']"); var nameNodes = cardNodes.SelectNodes(".//span[@class='name']"); var countNodes = cardNodes.SelectNodes(".//span[@class='quantity']"); var numberOfCards = nameNodes.Count; for (var i = 0; i < numberOfCards; i++) { var nameRaw = nameNodes.ElementAt(i).InnerText; var name = HttpUtility.HtmlDecode(nameRaw); var card = Game.GetCardFromName(name); card.Count = int.Parse(countNodes.ElementAt(i).InnerText); deck.Cards.Add(card); if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } } if (DeckList.Instance.AllTags.Contains("Arena")) { deck.Tags.Add("Arena"); } return(deck); } catch (Exception e) { Logger.WriteLine(e.ToString(), "DeckImporter"); return(null); } }
private static async Task <Deck> ImportHsTopdeck(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck(); var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//*[@id='center']/div[1]/div[1]").InnerText).Split('-')[1].Trim(); deck.Name = deckName; var cardNodes = doc.DocumentNode.SelectNodes("//*[@class='cardname']"); foreach (var cardNode in cardNodes) { var text = HttpUtility.HtmlDecode(cardNode.InnerText).Split(' '); var count = int.Parse(text[0].Trim()); var name = string.Join(" ", text.Skip(1)).Trim(); var card = Game.GetCardFromName(name); card.Count = count; deck.Cards.Add(card); if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } } return(deck); } catch (Exception e) { Logger.WriteLine(e.ToString(), "DeckImporter"); return(null); } }
private static async Task<Deck> ImportHearthBuilder(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck(); var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//div[contains(@class, 'single-deck-title-wrap')]/h2").InnerText); deck.Name = deckName; var cardNodes = doc.DocumentNode.SelectNodes("//div[@data-card-load]"); foreach(var cardNode in cardNodes) { var nameString = HttpUtility.HtmlDecode(cardNode.InnerText); var match = Regex.Match(nameString, @"^\s*(.*)\s*(x 2)?\s*$"); if(match.Success) { var name = match.Groups[1].Value; var count = match.Groups[2].Value; var card = GameV2.GetCardFromName(name); card.Count = String.IsNullOrEmpty(count) ? 1 : 2; deck.Cards.Add(card); if(string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") deck.Class = card.PlayerClass; } } return deck; } catch(Exception e) { Logger.WriteLine(e.ToString(), "DeckImporter"); return null; } }
private static async Task <Deck> ImportEliteDecks(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck(); var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//h2[contains(@class, 'dname')]").InnerText); deck.Name = deckName; var cardNodes = doc.DocumentNode.SelectNodes("//ul[@class='vminionslist' or @class='vspellslist']/li"); foreach (var cardNode in cardNodes) { var count = int.Parse(cardNode.SelectSingleNode(".//span[@class='cantidad']").InnerText); var name = HttpUtility.HtmlDecode( cardNode.SelectSingleNode( ".//span[@class='nombreCarta rarity_legendary' or @class='nombreCarta rarity_epic' or @class='nombreCarta rarity_rare' or @class='nombreCarta rarity_common' or @class='nombreCarta rarity_basic']") .InnerText); var card = Game.GetCardFromName(name); card.Count = count; deck.Cards.Add(card); if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } } return(deck); } catch (Exception e) { Logger.WriteLine(e.ToString(), "DeckImporter"); return(null); } }
private async void BtnClipboardNames_OnClick(object sender, RoutedEventArgs e) { var deck = DeckList.Instance.ActiveDeckVersion; if (deck == null) { return; } var english = true; if (Config.Instance.SelectedLanguage != "enUS") { try { english = await this.ShowMessageAsync("Select language", "", MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings { AffirmativeButtonText = Helper.LanguageDict.First(x => x.Value == "enUS").Key, NegativeButtonText = Helper.LanguageDict.First(x => x.Value == Config.Instance.SelectedLanguage).Key }) == MessageDialogResult.Affirmative; } catch (Exception ex) { Logger.WriteLine(ex.ToString()); } } var names = deck.GetSelectedDeckVersion() .Cards.Select(c => (english ? c.Name : c.LocalizedName) + (c.Count > 1 ? " x " + c.Count : "")) .Aggregate((c, n) => c + Environment.NewLine + n); Clipboard.SetText(names); this.ShowMessage("", "copied names to clipboard"); Logger.WriteLine("Copied " + deck.GetDeckInfo() + " names to clipboard", "Export"); }
private static async Task SetDeckName(string name, double ratio, int width, int height, IntPtr hsHandle) { Logger.WriteLine("Setting deck name...", "DeckExporter"); var nameDeckPos = new Point((int)GetXPos(Config.Instance.ExportNameDeckX, width, ratio), (int)(Config.Instance.ExportNameDeckY * height)); await ClickOnPoint(hsHandle, nameDeckPos); //send enter and second click to make sure the current name gets selected SendKeys.SendWait("{ENTER}"); await ClickOnPoint(hsHandle, nameDeckPos); if (Config.Instance.ExportPasteClipboard) { Clipboard.SetText(name); SendKeys.SendWait("^v"); } else { SendKeys.SendWait(name); } SendKeys.SendWait("{ENTER}"); }
private static async Task <Deck> ImportHearthStats(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck(); var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//h1[contains(@class,'page-title')]").FirstChild.InnerText); deck.Name = deckName; var cardNameNodes = doc.DocumentNode.SelectNodes("//div[contains(@class,'name')]"); var cardCountNodes = doc.DocumentNode.SelectNodes("//div[contains(@class,'qty')]"); var cardNames = cardNameNodes.Select(cardNameNode => HttpUtility.HtmlDecode(cardNameNode.InnerText)); var cardCosts = cardCountNodes.Select(countNode => int.Parse(countNode.InnerText)); var cardInfo = cardNames.Zip(cardCosts, (n, c) => new { Name = n, Count = c }); foreach (var info in cardInfo) { var card = Game.GetCardFromName(info.Name); card.Count = info.Count; deck.Cards.Add(card); if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } } return(deck); } catch (Exception e) { Logger.WriteLine(e.ToString(), "DeckImporter"); return(null); } }
private async void BtnScreenhot_Click(object sender, RoutedEventArgs e) { if (DeckPickerList.SelectedDeck == null) { return; } Logger.WriteLine("Creating screenshot of " + DeckPickerList.SelectedDeck.GetDeckInfo(), "Screenshot"); var screenShotWindow = new PlayerWindow(Config.Instance, DeckPickerList.SelectedDeck.Cards, true); screenShotWindow.Show(); screenShotWindow.Top = 0; screenShotWindow.Left = 0; await Task.Delay(100); var source = PresentationSource.FromVisual(screenShotWindow); if (source == null) { return; } var dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11; var dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22; var fileName = Helper.ScreenshotDeck(screenShotWindow.ListViewPlayer, dpiX, dpiY, DeckPickerList.SelectedDeck.Name); screenShotWindow.Shutdown(); if (fileName == null) { await this.ShowMessageAsync("", "Error saving screenshot"); } else { await ShowSavedFileMessage(fileName, "Screenshots"); } }
private static async Task <Deck> ImportHearthNewsFr(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck(); var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//span[contains(@class, 'deckName')]").InnerText).Trim(); deck.Name = deckName; var cardNodes = doc.DocumentNode.SelectNodes("//table[@class='deck_card_list']/tbody/tr/td[3]/a"); foreach (var cardNode in cardNodes) { var id = cardNode.Attributes["real_id"].Value; var count = int.Parse(cardNode.Attributes["nb_card"].Value); var card = Game.GetCardFromId(id); card.Count = count; deck.Cards.Add(card); if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } } return(deck); } catch (Exception e) { Logger.WriteLine(e.Message + "\n" + e.StackTrace); return(null); } }
public static async Task <Version> CheckForUpdates(bool beta) { var betaString = beta ? "BETA" : "LIVE"; Logger.WriteLine("Checking for " + betaString + " updates...", "Helper"); var versionXmlUrl = beta ? @"https://raw.githubusercontent.com/Epix37/HDT-Data/master/beta-version" : @"https://raw.githubusercontent.com/Epix37/HDT-Data/master/live-version"; var currentVersion = GetCurrentVersion(); if (currentVersion == null) { return(null); } try { Logger.WriteLine("Current version: " + currentVersion, "Helper"); string xml; using (var wc = new WebClient()) xml = await wc.DownloadStringTaskAsync(versionXmlUrl); var newVersion = new Version(XmlManager <SerializableVersion> .LoadFromString(xml).ToString()); Logger.WriteLine("Latest " + betaString + " version: " + newVersion, "Helper"); if (newVersion > currentVersion) { return(newVersion); } } catch (Exception e) { MessageBox.Show("Error checking for new " + betaString + " version.\n\n" + e.Message + "\n\n" + e.InnerException); } return(null); }
private static async Task <Deck> ImportHsTopdeck_s(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck(); var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//header[@class='entry-header']/h1[@class='entry-title']").InnerText); deck.Name = deckName; var cardNodes = doc.DocumentNode.SelectNodes("//ul[@id='classes' or @id='neutral']/li"); foreach (var cardNode in cardNodes) { var name = HttpUtility.HtmlDecode(cardNode.SelectSingleNode(".//a").InnerText); var count = int.Parse(cardNode.InnerText[0].ToString()); var card = Game.GetCardFromName(name); card.Count = count; deck.Cards.Add(card); if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } } return(deck); } catch (Exception e) { Logger.WriteLine(e.ToString(), "DeckImporter"); return(null); } }
public void HandleGameStart() { if (DateTime.Now - _lastGameStart < new TimeSpan(0, 0, 0, 5)) //game already started { return; } _handledGameEnd = false; _handledGameResult = false; _lastGameStart = DateTime.Now; Logger.WriteLine("Game start", "GameEventHandler"); if (Config.Instance.FlashHsOnTurnStart) { User32.FlashHs(); } if (Config.Instance.BringHsToForeground) { User32.BringHsToForeground(); } if (Config.Instance.KeyPressOnGameStart != "None" && Helper.MainWindow.EventKeys.Contains(Config.Instance.KeyPressOnGameStart)) { SendKeys.SendWait("{" + Config.Instance.KeyPressOnGameStart + "}"); Logger.WriteLine("Sent keypress: " + Config.Instance.KeyPressOnGameStart, "GameEventHandler"); } _showedNoteDialog = false; _game.IsInMenu = false; _game.Reset(); var selectedDeck = DeckList.Instance.ActiveDeckVersion; if (selectedDeck != null) { _game.SetPremadeDeck((Deck)selectedDeck.Clone()); } GameEvents.OnGameStart.Execute(); }
private static async Task <Deck> ImportTempostorm(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck(); var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//*[@id='main']/h1").InnerText); deck.Name = deckName; var cardNodes = doc.DocumentNode.SelectNodes("//*[@class='card card-over']"); foreach (var cardNode in cardNodes) { var nameRaw = cardNode.SelectSingleNode(".//span[@class='card-name']").InnerText; var name = HttpUtility.HtmlDecode(nameRaw); var count = cardNode.SelectSingleNode(".//div").Attributes[0].Value.EndsWith("2") ? 2 : 1; var card = Game.GetCardFromName(name); card.Count = count; deck.Cards.Add(card); if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } } return(deck); } catch (Exception e) { Logger.WriteLine(e.Message + "\n" + e.StackTrace); return(null); } }
public static async Task<Deck> Import(string url) { Logger.WriteLine("Importing deck from " + url, "DeckImporter"); if(url.Contains("hearthstats") || url.Contains("hss.io")) return await ImportHearthStats(url); if(url.Contains("hearthpwn")) return await ImportHearthPwn(url); if(url.Contains("hearthhead")) return await ImportHearthHead(url); if(url.Contains("hearthstoneplayers")) return await ImportHearthstonePlayers(url); if(url.Contains("tempostorm")) return await ImportTempostorm(url); if(url.Contains("hearthstonetopdecks")) return await ImportHsTopdeck_s(url); if(url.Contains("hearthstonetopdeck.")) return await ImportHsTopdeck(url); if(url.Contains("hearthnews.fr")) return await ImportHearthNewsFr(url); if(url.Contains("arenavalue")) return await ImportArenaValue(url); if(url.Contains("hearthstone-decks")) return await ImportHearthstoneDecks(url); if(url.Contains("heartharena")) return await ImportHearthArena(url); if(url.Contains("hearthstoneheroes")) return await ImportHearthstoneheroes(url); if(url.Contains("elitedecks")) return await ImportEliteDecks(url); if(url.Contains("icy-veins")) return await ImportIcyVeins(url); if(url.Contains("hearthbuilder")) return await ImportHearthBuilder(url); Logger.WriteLine("invalid url", "DeckImporter"); return null; }
private static async Task<Deck> ImportHearthHead(string url) { try { if(!url.Contains("http://www.")) url = "http://www." + url.Split('.').Skip(1).Aggregate((c, n) => c + "." + n); var doc = await GetHtmlDocJs(url); var deck = new Deck(); var deckName = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//*[@id='deckguide-name']").InnerText); deck.Name = deckName; var cardNodes = doc.DocumentNode.SelectNodes("//*[contains(@class,'deckguide-cards-type')]//ul//li"); foreach(var cardNode in cardNodes) { var nameRaw = cardNode.SelectSingleNode(".//a").InnerText; var name = HttpUtility.HtmlDecode(nameRaw); var count = cardNode.InnerText.Remove(0, nameRaw.Length - 1).Contains("2") ? 2 : 1; var card = GameV2.GetCardFromName(name); card.Count = count; deck.Cards.Add(card); if(string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") deck.Class = card.PlayerClass; } return deck; } catch(Exception e) { Logger.WriteLine(e.ToString(), "DeckImporter"); return null; } }
private static async Task <Deck> ImportHearthstoneDecks(string url) { try { var doc = await GetHtmlDoc(url); var deck = new Deck { Name = HttpUtility.HtmlDecode(doc.DocumentNode.SelectSingleNode("//*[@id='content']/div[3]/h3").InnerText).Trim() }; var nodes = doc.DocumentNode.SelectNodes("//a[@real_id]"); foreach (var cardNode in nodes) { var id = cardNode.Attributes["real_id"].Value; var count = int.Parse(cardNode.Attributes["nb_card"].Value); var card = Game.GetCardFromId(id); card.Count = count; deck.Cards.Add(card); if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } } return(deck); } catch (Exception e) { Logger.WriteLine(e.ToString(), "DeckImporter"); return(null); } }
private async void BtnSaveDeck_Click(object sender, RoutedEventArgs e) { //NewDeck.Cards = // new ObservableCollection<Card>( // NewDeck.Cards.OrderBy(c => c.Cost).ThenByDescending(c => c.Type).ThenBy(c => c.Name).ToList()); //ListViewNewDeck.ItemsSource = NewDeck.Cards; var deckName = TextBoxDeckName.Text; if (EditingDeck) { var settings = new MetroDialogSettings { AffirmativeButtonText = "Overwrite", NegativeButtonText = "Save as new" }; var result = await this.ShowMessageAsync("Saving deck", "How do you wish to save the deck?", MessageDialogStyle.AffirmativeAndNegative, settings); if (result == MessageDialogResult.Affirmative) { SaveDeck(true); } else if (result == MessageDialogResult.Negative) { SaveDeck(false); } } else if (DeckList.DecksList.Any(d => d.Name == deckName)) { var settings = new MetroDialogSettings { AffirmativeButtonText = "Overwrite", NegativeButtonText = "Set new name" }; var result = await this.ShowMessageAsync("A deck with that name already exists", "Overwriting the deck can not be undone!", MessageDialogStyle.AffirmativeAndNegative, settings); if (result == MessageDialogResult.Affirmative) { Deck oldDeck; while ((oldDeck = DeckList.DecksList.FirstOrDefault(d => d.Name == deckName)) != null) { var deckStats = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.Name == oldDeck.Name); if (deckStats != null) { foreach (var game in deckStats.Games) { game.DeleteGameFile(); } DeckStatsList.Instance.DeckStats.Remove(deckStats); DeckStatsList.Save(); Logger.WriteLine("Deleted deckstats for deck: " + oldDeck.Name); } DeckList.DecksList.Remove(oldDeck); DeckPickerList.RemoveDeck(oldDeck); } SaveDeck(true); } else if (result == MessageDialogResult.Negative) { SaveDeck(false); } } else { SaveDeck(false); } editedDeckName = string.Empty; }
public async Task GetCardCounts(Deck deck) { var hsHandle = User32.GetHearthstoneWindow(); if (!User32.IsHearthstoneInForeground()) { //restore window and bring to foreground User32.ShowWindow(hsHandle, User32.SwRestore); User32.SetForegroundWindow(hsHandle); //wait it to actually be in foreground, else the rect might be wrong await Task.Delay(500); } if (!User32.IsHearthstoneInForeground()) { MessageBox.Show("Can't find Hearthstone window."); Logger.WriteLine("Can't find Hearthstone window.", "ArenaImport"); return; } await Task.Delay(1000); Overlay.ForceHidden = true; Overlay.UpdatePosition(); const double xScale = 0.013; const double yScale = 0.017; const int targetHue = 53; const int hueMargin = 3; const int numVisibleCards = 21; var hsRect = User32.GetHearthstoneRect(false); var ratio = (4.0 / 3.0) / ((double)hsRect.Width / hsRect.Height); var posX = (int)DeckExporter.GetXPos(0.92, hsRect.Width, ratio); var startY = 71.0 / 768.0 * hsRect.Height; var strideY = 29.0 / 768.0 * hsRect.Height; int width = (int)Math.Round(hsRect.Width * xScale); int height = (int)Math.Round(hsRect.Height * yScale); for (var i = 0; i < Math.Min(numVisibleCards, deck.Cards.Count); i++) { var posY = (int)(startY + strideY * i); var capture = Helper.CaptureHearthstone(new System.Drawing.Point(posX, posY), width, height, hsHandle); if (capture != null) { var yellowPixels = 0; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var pixel = capture.GetPixel(x, y); if (Math.Abs(pixel.GetHue() - targetHue) < hueMargin) { yellowPixels++; } } } //Console.WriteLine(yellowPixels + " of " + width * height + " - " + yellowPixels / (double)(width * height)); //capture.Save("arenadeckimages/" + i + ".png"); var yellowPixelRatio = yellowPixels / (double)(width * height); if (yellowPixelRatio > 0.25 && yellowPixelRatio < 50) { deck.Cards[i].Count = 2; } } } if (deck.Cards.Count > numVisibleCards) { const int scrollClicksPerCard = 4; const int scrollDistance = 120; var clientPoint = new System.Drawing.Point(posX, (int)startY); var previousPos = System.Windows.Forms.Cursor.Position; User32.ClientToScreen(hsHandle, ref clientPoint); System.Windows.Forms.Cursor.Position = new System.Drawing.Point(clientPoint.X, clientPoint.Y); for (int j = 0; j < scrollClicksPerCard * (deck.Cards.Count - numVisibleCards); j++) { User32.mouse_event((uint)User32.MouseEventFlags.Wheel, 0, 0, -scrollDistance, UIntPtr.Zero); await Task.Delay(30); } System.Windows.Forms.Cursor.Position = previousPos; await Task.Delay(100); var remainingCards = deck.Cards.Count - numVisibleCards; startY = 76.0 / 768.0 * hsRect.Height + (numVisibleCards - remainingCards) * strideY; for (int i = 0; i < remainingCards; i++) { var posY = (int)(startY + strideY * i); var capture = Helper.CaptureHearthstone(new System.Drawing.Point(posX, posY), width, height, hsHandle); if (capture != null) { var yellowPixels = 0; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var pixel = capture.GetPixel(x, y); if (Math.Abs(pixel.GetHue() - targetHue) < hueMargin) { yellowPixels++; } } } //Console.WriteLine(yellowPixels + " of " + width * height + " - " + yellowPixels / (double)(width * height)); //capture.Save("arenadeckimages/" + i + 21 + ".png"); var yellowPixelRatio = yellowPixels / (double)(width * height); if (yellowPixelRatio > 0.25 && yellowPixelRatio < 50) { deck.Cards[numVisibleCards + i].Count = 2; } } } System.Windows.Forms.Cursor.Position = new System.Drawing.Point(clientPoint.X, clientPoint.Y); for (int j = 0; j < scrollClicksPerCard * (deck.Cards.Count - 21); j++) { User32.mouse_event((uint)User32.MouseEventFlags.Wheel, 0, 0, scrollDistance, UIntPtr.Zero); await Task.Delay(30); } System.Windows.Forms.Cursor.Position = previousPos; } Overlay.ForceHidden = false; Overlay.UpdatePosition(); ActivateWindow(); }
private async void SaveDeck(bool overwrite) { var deckName = TextBoxDeckName.Text; if (string.IsNullOrEmpty(deckName)) { var settings = new MetroDialogSettings { AffirmativeButtonText = "Set", DefaultText = deckName }; var name = await this.ShowInputAsync("No name set", "Please set a name for the deck", settings); if (String.IsNullOrEmpty(name)) { return; } deckName = name; TextBoxDeckName.Text = name; } while (DeckList.DecksList.Any(d => d.Name == deckName) && (!EditingDeck || !overwrite)) { var settings = new MetroDialogSettings { AffirmativeButtonText = "Set", DefaultText = deckName }; var name = await this.ShowInputAsync("Name already exists", "You already have a deck with that name, please select a different one.", settings); if (String.IsNullOrEmpty(name)) { return; } deckName = name; TextBoxDeckName.Text = name; } if (_newDeck.Cards.Sum(c => c.Count) != 30) { var settings = new MetroDialogSettings { AffirmativeButtonText = "Yes", NegativeButtonText = "No" }; var result = await this.ShowMessageAsync("Not 30 cards", string.Format("Deck contains {0} cards. Is this what you want to save anyway?", _newDeck.Cards.Sum(c => c.Count)), MessageDialogStyle.AffirmativeAndNegative, settings); if (result != MessageDialogResult.Affirmative) { return; } } if (EditingDeck && overwrite) { DeckList.DecksList.Remove(_newDeck); DeckPickerList.RemoveDeck(_newDeck); } var oldDeckName = _newDeck.Name; _newDeck.Name = deckName; _newDeck.Tags = TagControlEdit.GetTags(); var newDeckClone = (Deck)_newDeck.Clone(); DeckList.DecksList.Add(newDeckClone); newDeckClone.LastEdited = DateTime.Now; WriteDecks(); Logger.WriteLine("Saved Decks"); if (EditingDeck) { TagControlEdit.SetSelectedTags(new List <string>()); if (deckName != oldDeckName) { var statsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(d => d.Name == oldDeckName); if (statsEntry != null) { if (overwrite) { statsEntry.Name = deckName; Logger.WriteLine("Deck has new name, updated deckstats"); } else { var newStatsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(d => d.Name == deckName); if (newStatsEntry == null) { newStatsEntry = new DeckStats(deckName); DeckStatsList.Instance.DeckStats.Add(newStatsEntry); } foreach (var game in statsEntry.Games) { newStatsEntry.AddGameResult(game.CloneWithNewId()); } Logger.WriteLine("cloned gamestats for \"Set as new\""); } DeckStatsList.Save(); } } } //after cloning the stats, otherwise new stats will be generated DeckPickerList.AddAndSelectDeck(newDeckClone); EditingDeck = false; foreach (var tag in _newDeck.Tags) { SortFilterDecksFlyout.AddSelectedTag(tag); } DeckPickerList.UpdateList(); DeckPickerList.SelectDeck(newDeckClone); CloseNewDeck(); ClearNewDeckSection(); }
public static void Load() { var foundConfig = false; try { if (File.Exists("config.xml")) { _config = XmlManager <Config> .Load("config.xml"); foundConfig = true; } else if (File.Exists(Instance.AppDataPath + @"\config.xml")) { _config = XmlManager <Config> .Load(Instance.AppDataPath + @"\config.xml"); foundConfig = true; } else if (!Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData))) { //save locally if appdata doesn't exist (when e.g. not on C) Instance.SaveConfigInAppData = false; } } catch (Exception e) { MessageBox.Show( e.Message + "\n\n" + e.InnerException + "\n\n If you don't know how to fix this, please delete " + Instance.ConfigPath, "Error loading config.xml"); Application.Current.Shutdown(); } if (!foundConfig) { if (Instance.ConfigDir != string.Empty) { Directory.CreateDirectory(Instance.ConfigDir); } using (var sr = new StreamWriter(Instance.ConfigPath, false)) sr.WriteLine("<Config></Config>"); } else if (Instance.SaveConfigInAppData != null) { if (Instance.SaveConfigInAppData.Value) //check if config needs to be moved { if (File.Exists("config.xml")) { Directory.CreateDirectory(Instance.ConfigDir); SaveBackup(true); //backup in case the file already exists File.Move("config.xml", Instance.ConfigPath); Logger.WriteLine("Moved config to appdata"); } } else if (File.Exists(Instance.AppDataPath + @"\config.xml")) { SaveBackup(true); //backup in case the file already exists File.Move(Instance.AppDataPath + @"\config.xml", Instance.ConfigPath); Logger.WriteLine("Moved config to local"); } } }
private Deck ParseCardString(string cards, bool localizedNames = false) { try { var deck = new Deck(); var lines = cards.Split('\n'); foreach (var line in lines) { var count = 1; var cardName = line.Trim(); Match match = null; if (_cardLineRegexCountFirst.IsMatch(cardName)) { match = _cardLineRegexCountFirst.Match(cardName); } else if (_cardLineRegexCountLast.IsMatch(cardName)) { match = _cardLineRegexCountLast.Match(cardName); } else if (_cardLineRegexCountLast2.IsMatch(cardName)) { match = _cardLineRegexCountLast2.Match(cardName); } if (match != null) { var tmpCount = match.Groups["count"]; if (tmpCount.Success) { count = int.Parse(tmpCount.Value); } cardName = match.Groups["cardname"].Value.Trim(); } var card = Game.GetCardFromName(cardName, localizedNames); if (card == null || string.IsNullOrEmpty(card.Name)) { continue; } card.Count = count; if (string.IsNullOrEmpty(deck.Class) && card.PlayerClass != "Neutral") { deck.Class = card.PlayerClass; } if (deck.Cards.Contains(card)) { var deckCard = deck.Cards.First(c => c.Equals(card)); deck.Cards.Remove(deckCard); deckCard.Count += count; deck.Cards.Add(deckCard); } else { deck.Cards.Add(card); } } return(deck); } catch (Exception ex) { Logger.WriteLine("Error parsing card string: " + ex, "Import"); return(null); } }
public void PlayerSetAside(string id) { _game.SetAsideCards.Add(id); Logger.WriteLine("set aside: " + id, "GameEventHandler"); }
private async void DeleteGames(DataGrid dataGrid, bool overall) { MetroWindow window; if (Config.Instance.StatsInWindow) { window = Helper.MainWindow.StatsWindow; } else { window = Helper.MainWindow; } var count = dataGrid.SelectedItems.Count; if (count == 1) { var selectedGame = dataGrid.SelectedItem as GameStats; if (selectedGame == null) { return; } if (await window.ShowDeleteGameStatsMessage(selectedGame) != MessageDialogResult.Affirmative) { return; } if (!overall) { if (_deck.DeckStats.Games.Contains(selectedGame)) { selectedGame.DeleteGameFile(); _deck.DeckStats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game: " + selectedGame); DeckStatsList.Save(); } } else { var deck = Helper.MainWindow.DeckList.DecksList.FirstOrDefault(d => d.DeckStats.Games.Contains(selectedGame)); if (deck != null) { if (deck.DeckStats.Games.Contains(selectedGame)) { selectedGame.DeleteGameFile(); deck.DeckStats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game: " + selectedGame); DefaultDeckStats.Save(); } } else { var deckstats = DefaultDeckStats.Instance.DeckStats.FirstOrDefault(ds => ds.Games.Contains(selectedGame)); if (deckstats != null) { selectedGame.DeleteGameFile(); deckstats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game: " + selectedGame); DefaultDeckStats.Save(); } } } Helper.MainWindow.DeckPickerList.Items.Refresh(); Refresh(); } else if (count > 1) { if (await window.ShowDeleteMultipleGameStatsMessage(count) != MessageDialogResult.Affirmative) { return; } foreach (var selectedItem in dataGrid.SelectedItems) { var selectedGame = selectedItem as GameStats; if (selectedGame == null) { continue; } if (!overall) { if (_deck.DeckStats.Games.Contains(selectedGame)) { selectedGame.DeleteGameFile(); _deck.DeckStats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game: " + selectedGame); } } else { var deck = Helper.MainWindow.DeckList.DecksList.FirstOrDefault(d => d.DeckStats.Games.Contains(selectedGame)); if (deck != null) { if (deck.DeckStats.Games.Contains(selectedGame)) { selectedGame.DeleteGameFile(); deck.DeckStats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game: " + selectedGame); } } else { var deckstats = DefaultDeckStats.Instance.DeckStats.FirstOrDefault(ds => ds.Games.Contains(selectedGame)); if (deckstats != null) { selectedGame.DeleteGameFile(); deckstats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game: " + selectedGame); } } } } DeckStatsList.Save(); DefaultDeckStats.Save(); Logger.WriteLine("Deleted " + count + " games"); Helper.MainWindow.DeckPickerList.Items.Refresh(); Refresh(); } }
private void LogEvent(string type, string id = "", int turn = 0, int from = -1) { Logger.WriteLine(string.Format("{0} (id:{1} turn:{2} from:{3})", type, id, turn, from), "GameEventHandler"); }
#pragma warning disable 4014 public async void HandleGameEnd() { Helper.MainWindow.Overlay.HideTimers(); if (_game.CurrentGameStats == null || _handledGameEnd) { return; } if (_game.CurrentGameMode == GameMode.Spectator && !Config.Instance.RecordSpectator) { Logger.WriteLine("Game is in Spectator mode, discarded. (Record Spectator disabled)", "GameEventHandler"); _assignedDeck = null; return; } var player = _game.Entities.FirstOrDefault(e => e.Value.IsPlayer); var opponent = _game.Entities.FirstOrDefault(e => e.Value.HasTag(GAME_TAG.PLAYER_ID) && !e.Value.IsPlayer); if (player.Value != null) { _game.CurrentGameStats.PlayerName = player.Value.Name; } if (opponent.Value != null && CardIds.HeroIdDict.ContainsValue(_game.CurrentGameStats.OpponentHero)) { _game.CurrentGameStats.OpponentName = opponent.Value.Name; } else { _game.CurrentGameStats.OpponentName = _game.CurrentGameStats.OpponentHero; } _game.CurrentGameStats.Turns = HsLogReaderV2.Instance.GetTurnNumber(); if (Config.Instance.DiscardZeroTurnGame && _game.CurrentGameStats.Turns < 1) { Logger.WriteLine("Game has 0 turns, discarded. (DiscardZeroTurnGame)", "GameEventHandler"); _assignedDeck = null; GameEvents.OnGameEnd.Execute(); return; } _game.CurrentGameStats.GameEnd(); GameEvents.OnGameEnd.Execute(); var selectedDeck = DeckList.Instance.ActiveDeck; if (selectedDeck != null) { if (Config.Instance.DiscardGameIfIncorrectDeck && !_game.PlayerDrawn.All( c => c.IsStolen || selectedDeck.GetSelectedDeckVersion().Cards.Any(c2 => c.Id == c2.Id && c.Count <= c2.Count))) { if (Config.Instance.AskBeforeDiscardingGame) { var discardDialog = new DiscardGameDialog(_game.CurrentGameStats); discardDialog.Topmost = true; discardDialog.ShowDialog(); if (discardDialog.Result == DiscardGameDialogResult.Discard) { Logger.WriteLine("Assigned current game to NO deck - selected deck does not match cards played (dialogresult: discard)", "GameEventHandler"); _game.CurrentGameStats.DeleteGameFile(); _assignedDeck = null; return; } if (discardDialog.Result == DiscardGameDialogResult.MoveToOther) { var moveDialog = new MoveGameDialog(DeckList.Instance.Decks.Where(d => d.Class == _game.CurrentGameStats.PlayerHero)); moveDialog.Topmost = true; moveDialog.ShowDialog(); var targetDeck = moveDialog.SelectedDeck; if (targetDeck != null) { selectedDeck = targetDeck; _game.CurrentGameStats.PlayerDeckVersion = moveDialog.SelectedVersion; _game.CurrentGameStats.HearthStatsDeckVersionId = targetDeck.GetVersion(moveDialog.SelectedVersion).HearthStatsDeckVersionId; //...continue as normal } else { Logger.WriteLine("No deck selected in move game dialog after discard dialog, discarding game", "GameEventHandler"); _game.CurrentGameStats.DeleteGameFile(); _assignedDeck = null; return; } } } else { Logger.WriteLine("Assigned current game to NO deck - selected deck does not match cards played (no dialog)", "GameEventHandler"); _game.CurrentGameStats.DeleteGameFile(); _assignedDeck = null; return; } } else { _game.CurrentGameStats.PlayerDeckVersion = DeckList.Instance.ActiveDeckVersion.Version; _game.CurrentGameStats.HearthStatsDeckVersionId = DeckList.Instance.ActiveDeckVersion.HearthStatsDeckVersionId; } _lastGame = _game.CurrentGameStats; selectedDeck.DeckStats.AddGameResult(_lastGame); selectedDeck.StatsUpdated(); if (Config.Instance.ShowNoteDialogAfterGame && !Config.Instance.NoteDialogDelayed && !_showedNoteDialog) { _showedNoteDialog = true; new NoteDialog(_game.CurrentGameStats); } Logger.WriteLine("Assigned current game to deck: " + selectedDeck.Name, "GameStats"); _assignedDeck = selectedDeck; // Unarchive the active deck after we have played a game with it if (_assignedDeck.Archived) { Logger.WriteLine("Automatically unarchiving deck " + selectedDeck.Name + " after assigning current game", "GameEventHandler"); Helper.MainWindow.ArchiveDeck(_assignedDeck, false); } if (HearthStatsAPI.IsLoggedIn && Config.Instance.HearthStatsAutoUploadNewGames) { if (_game.CurrentGameMode == GameMode.None) { await GameModeDetection(300); //give the user 5 minutes to get out of the victory/defeat screen } if (_game.CurrentGameMode == GameMode.Casual) { await HsLogReaderV2.Instance.RankedDetection(); } if (_game.CurrentGameMode == GameMode.Ranked && !_lastGame.HasRank) { await RankDetection(5); } await GameModeSaved(15); if (_game.CurrentGameMode == GameMode.Arena) { HearthStatsManager.UploadArenaMatchAsync(_lastGame, selectedDeck, background: true); } if (_game.CurrentGameMode == GameMode.Brawl) { /* do nothing */ } else { HearthStatsManager.UploadMatchAsync(_lastGame, selectedDeck, background: true); } } _lastGame = null; } else { DefaultDeckStats.Instance.GetDeckStats(_game.PlayingAs).AddGameResult(_game.CurrentGameStats); Logger.WriteLine(string.Format("Assigned current deck to default {0} deck.", _game.PlayingAs), "GameStats"); _assignedDeck = null; } }
private async void DeleteGames(DataGrid dataGrid, bool overall) { MetroWindow window; if (Config.Instance.StatsInWindow) { window = Helper.MainWindow.StatsWindow; } else { window = Helper.MainWindow; } var count = dataGrid.SelectedItems.Count; if (count == 1) { var selectedGame = dataGrid.SelectedItem as GameStats; if (selectedGame == null) { return; } if (await window.ShowDeleteGameStatsMessage(selectedGame) != MessageDialogResult.Affirmative) { return; } if (!overall) { if (_deck.DeckStats.Games.Contains(selectedGame)) { selectedGame.DeleteGameFile(); _deck.DeckStats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game " + selectedGame + "(overall=" + overall + ")", "DeckStatsControl"); DeckStatsList.Save(); } } else { var deck = DeckList.Instance.Decks.FirstOrDefault(d => d.DeckStats.Games.Contains(selectedGame)); if (deck != null) { if (deck.DeckStats.Games.Contains(selectedGame)) { selectedGame.DeleteGameFile(); deck.DeckStats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game " + selectedGame + "(overall=" + overall + ")", "DeckStatsControl"); DefaultDeckStats.Save(); } } else { var deckstats = DefaultDeckStats.Instance.DeckStats.FirstOrDefault(ds => ds.Games.Contains(selectedGame)); if (deckstats != null) { selectedGame.DeleteGameFile(); deckstats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game " + selectedGame + "(overall=" + overall + ")", "DeckStatsControl"); DefaultDeckStats.Save(); } } } if (HearthStatsAPI.IsLoggedIn && selectedGame.HasHearthStatsId && await Helper.MainWindow.CheckHearthStatsMatchDeletion()) { HearthStatsManager.DeleteMatchesAsync(new List <GameStats> { selectedGame }); } //Helper.MainWindow.DeckPickerList.Items.Refresh(); Helper.MainWindow.DeckPickerList.UpdateDecks(); Refresh(); } else if (count > 1) { if (await window.ShowDeleteMultipleGameStatsMessage(count) != MessageDialogResult.Affirmative) { return; } var selectedGames = dataGrid.SelectedItems.Cast <GameStats>().Where(g => g != null).ToList(); foreach (var selectedGame in selectedGames) { if (!overall) { if (_deck.DeckStats.Games.Contains(selectedGame)) { selectedGame.DeleteGameFile(); _deck.DeckStats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game " + selectedGame + "(overall=" + overall + ")", "DeckStatsControl"); } } else { var deck = DeckList.Instance.Decks.FirstOrDefault(d => d.DeckStats.Games.Contains(selectedGame)); if (deck != null) { if (deck.DeckStats.Games.Contains(selectedGame)) { selectedGame.DeleteGameFile(); deck.DeckStats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game " + selectedGame + "(overall=" + overall + ")", "DeckStatsControl"); } } else { var deckstats = DefaultDeckStats.Instance.DeckStats.FirstOrDefault(ds => ds.Games.Contains(selectedGame)); if (deckstats != null) { selectedGame.DeleteGameFile(); deckstats.Games.Remove(selectedGame); Logger.WriteLine("Deleted game " + selectedGame + "(overall=" + overall + ")", "DeckStatsControl"); } } } } if (HearthStatsAPI.IsLoggedIn && selectedGames.Any(g => g.HasHearthStatsId) && await Helper.MainWindow.CheckHearthStatsMatchDeletion()) { HearthStatsManager.DeleteMatchesAsync(selectedGames); } DeckStatsList.Save(); DefaultDeckStats.Save(); Logger.WriteLine("Deleted " + count + " games", "DeckStatsControl"); Helper.MainWindow.DeckPickerList.UpdateDecks(); Refresh(); } }
public void SetPlayerHero(string hero) { try { if (!string.IsNullOrEmpty(hero)) { //_game.PlayingAs = hero; if (_game.CurrentGameStats != null) { _game.CurrentGameStats.PlayerHero = hero; } var selectedDeck = DeckList.Instance.ActiveDeckVersion; if (!_game.IsUsingPremade || !Config.Instance.AutoDeckDetection) { return; } if (selectedDeck == null || selectedDeck.Class != _game.PlayingAs) { var classDecks = DeckList.Instance.Decks.Where(d => d.Class == _game.PlayingAs && !d.Archived).ToList(); if (classDecks.Count == 0) { Logger.WriteLine("Found no deck to switch to", "HandleGameStart"); } else if (classDecks.Count == 1) { Helper.MainWindow.DeckPickerList.SelectDeck(classDecks[0]); Helper.MainWindow.DeckPickerList.RefreshDisplayedDecks(); Logger.WriteLine("Found deck to switch to: " + classDecks[0].Name, "HandleGameStart"); } else if (DeckList.Instance.LastDeckClass.Any(ldc => ldc.Class == _game.PlayingAs)) { var lastDeck = DeckList.Instance.LastDeckClass.First(ldc => ldc.Class == _game.PlayingAs); var deck = lastDeck.Id == Guid.Empty ? DeckList.Instance.Decks.FirstOrDefault(d => d.Name == lastDeck.Name) : DeckList.Instance.Decks.FirstOrDefault(d => d.DeckId == lastDeck.Id); if (deck != null && _game.PlayerDrawnIdsTotal.Distinct().All(id => deck.GetSelectedDeckVersion().Cards.Any(c => id == c.Id))) { Logger.WriteLine("Found more than 1 deck to switch to - last played: " + lastDeck.Name, "HandleGameStart"); if (deck.Archived) { Logger.WriteLine("Deck " + deck.Name + " is archived - waiting for deck selection dialog", "HandleGameStart"); return; } Helper.MainWindow.NeedToIncorrectDeckMessage = false; Helper.MainWindow.DeckPickerList.SelectDeck(deck); Helper.MainWindow.UpdateDeckList(deck); Helper.MainWindow.UseDeck(deck); Helper.MainWindow.DeckPickerList.RefreshDisplayedDecks(); } } } } } catch (Exception exception) { Logger.WriteLine("Error setting player hero: " + exception, "GameEventHandler"); } }
private void SetupDeckStatsFile() { if (Config.Instance.SaveDataInAppData == null) { return; } var appDataPath = Config.Instance.AppDataPath + @"\DeckStats.xml"; var appDataGamesDirPath = Config.Instance.AppDataPath + @"\Games"; const string localPath = "DeckStats.xml"; const string localGamesDirPath = "Games"; if (Config.Instance.SaveDataInAppData.Value) { if (File.Exists(localPath)) { if (File.Exists(appDataPath)) { //backup in case the file already exists var time = DateTime.Now.ToFileTime(); File.Move(appDataPath, appDataPath + time); if (Directory.Exists(appDataGamesDirPath)) { Helper.CopyFolder(appDataGamesDirPath, appDataGamesDirPath + time); Directory.Delete(appDataGamesDirPath, true); } Logger.WriteLine("Created backups of deckstats and games in appdata"); } File.Move(localPath, appDataPath); Logger.WriteLine("Moved DeckStats to appdata"); if (Directory.Exists(localGamesDirPath)) { Helper.CopyFolder(localGamesDirPath, appDataGamesDirPath); Directory.Delete(localGamesDirPath, true); } Logger.WriteLine("Moved Games to appdata"); } } else if (File.Exists(appDataPath)) { if (File.Exists(localPath)) { //backup in case the file already exists var time = DateTime.Now.ToFileTime(); File.Move(localPath, localPath + time); if (Directory.Exists(localGamesDirPath)) { Helper.CopyFolder(localGamesDirPath, localGamesDirPath + time); Directory.Delete(localGamesDirPath, true); } Logger.WriteLine("Created backups of deckstats and games locally"); } File.Move(appDataPath, localPath); Logger.WriteLine("Moved DeckStats to local"); if (Directory.Exists(appDataGamesDirPath)) { Helper.CopyFolder(appDataGamesDirPath, localGamesDirPath); Directory.Delete(appDataGamesDirPath, true); } Logger.WriteLine("Moved Games to appdata"); } var filePath = Config.Instance.DataDir + "DeckStats.xml"; //load saved decks if (!File.Exists(filePath)) { //avoid overwriting decks file with new releases. using (var sr = new StreamWriter(filePath, false)) sr.WriteLine("<DeckStatsList></DeckStatsList>"); } }