public static void UpdateDungeonRunDeck(DungeonInfo info, bool isPVPDR) { if (!Config.Instance.DungeonAutoImport) { return; } var isNewPVPDR = isPVPDR && !info.RunActive && info.SelectedLoadoutTreasureDbId > 0; Log.Info($"Found dungeon run deck Set={(CardSet)info.CardSet}, PVPDR={isPVPDR} (new={isNewPVPDR})"); var allCards = info.DbfIds?.ToList() ?? new List <int>(); // New PVPDR runs have all non-loadout cards in the DbfIds. We still add the picked loadout below. // So we don't want to replace allCards with baseDeck, as backDeck is empty, and we don't want to add // any loot or treasure, as these will be the ones from a previous run, if they exist. if (!isNewPVPDR) { var baseDeck = info.SelectedDeck ?? new List <int>(); if (baseDeck.All(x => allCards.Contains(x))) { if (info.PlayerChosenLoot > 0) { var loot = new[] { info.LootA, info.LootB, info.LootC }; var chosen = loot[info.PlayerChosenLoot - 1]; for (var i = 1; i < chosen.Count; i++) { allCards.Add(chosen[i]); } } if (info.PlayerChosenTreasure > 0) { allCards.Add(info.Treasure[info.PlayerChosenTreasure - 1]); } } else { allCards = baseDeck; } } var cards = allCards.GroupBy(x => x).Select(x => { var card = Database.GetCardFromDbfId(x.Key, false); if (card == null) { return(null); } card.Count = x.Count(); return(card); }).Where(x => x != null).ToList(); var loadoutCardId = info.LoadoutCardId; var loadout = loadoutCardId != null?Database.GetCardFromId(loadoutCardId) : null; if (loadout != null && !allCards.Contains(loadout.DbfIf)) { cards.Add(loadout); } if (!Config.Instance.DungeonRunIncludePassiveCards) { cards.RemoveAll(c => !c.Collectible && c.HideStats); } var cardSet = (CardSet)info.CardSet; string playerClass = null; if (cardSet == CardSet.ULDUM && loadout != null) { playerClass = DungeonRun.GetUldumHeroPlayerClass(loadout.PlayerClass); } else if (isPVPDR) { playerClass = HearthDbConverter.ConvertClass((CardClass)(info.HeroClass != 0 ? info.HeroClass : info.HeroCardClass)); } else { if (allCards.Count == 10) { playerClass = allCards.Select(x => Database.GetCardFromDbfId(x).PlayerClass).FirstOrDefault(x => x != null)?.ToUpperInvariant(); } if (playerClass == null) { playerClass = ((CardClass)info.HeroCardClass).ToString().ToUpperInvariant(); } } var deck = DeckList.Instance.Decks.FirstOrDefault(x => (!isPVPDR && x.IsDungeonDeck || isPVPDR && x.IsDuelsDeck) && x.Class.ToUpperInvariant() == playerClass.ToUpperInvariant() && x.Cards.All(e => cards.Any(c => c.Id == e.Id && c.Count >= e.Count)) && !(x.IsDungeonRunCompleted ?? false) && !(x.IsDuelsRunCompleted ?? false)); var baseDbfids = isPVPDR ? info.DbfIds : info.SelectedDeck; if (deck == null && (deck = CreateDungeonDeck(playerClass, cardSet, isPVPDR, baseDbfids, loadout)) == null) { Log.Info($"No existing deck - can't find default deck for {playerClass}"); return; } if (!info.RunActive && (cardSet == CardSet.ULDUM || cardSet == CardSet.DALARAN)) { Log.Info($"Inactive run for Set={cardSet.ToString()} - this is a new run"); return; } if (cards.All(c => deck.Cards.Any(e => c.Id == e.Id && c.Count == e.Count))) { Log.Info("No new cards"); return; } deck.Cards.Clear(); Helper.SortCardCollection(cards, false); foreach (var card in cards) { deck.Cards.Add(card); } deck.LastEdited = DateTime.Now; DeckList.Save(); Core.UpdatePlayerCards(true); Log.Info("Updated dungeon run deck"); }
public static Deck Import(string cards, bool localizedNames = false) { CardClass[] AvailableClasses(Card x) { var card = HearthDb.Cards.GetFromDbfId(x.DbfIf); switch ((MultiClassGroup)card.Entity.GetTag(GameTag.MULTI_CLASS_GROUP)) { case MultiClassGroup.GRIMY_GOONS: return(new[] { CardClass.WARRIOR, CardClass.HUNTER, CardClass.PALADIN }); case MultiClassGroup.JADE_LOTUS: return(new[] { CardClass.ROGUE, CardClass.DRUID, CardClass.SHAMAN }); case MultiClassGroup.KABAL: return(new[] { CardClass.MAGE, CardClass.PRIEST, CardClass.WARLOCK }); case MultiClassGroup.PALADIN_PRIEST: return(new[] { CardClass.PALADIN, CardClass.PRIEST }); case MultiClassGroup.PRIEST_WARLOCK: return(new[] { CardClass.PRIEST, CardClass.WARLOCK }); case MultiClassGroup.WARLOCK_DEMONHUNTER: return(new[] { CardClass.WARLOCK, CardClass.DEMONHUNTER }); case MultiClassGroup.HUNTER_DEMONHUNTER: return(new[] { CardClass.HUNTER, CardClass.DEMONHUNTER }); case MultiClassGroup.DRUID_HUNTER: return(new[] { CardClass.DRUID, CardClass.HUNTER }); case MultiClassGroup.DRUID_SHAMAN: return(new[] { CardClass.DRUID, CardClass.SHAMAN }); case MultiClassGroup.MAGE_SHAMAN: return(new[] { CardClass.MAGE, CardClass.SHAMAN }); case MultiClassGroup.MAGE_ROGUE: return(new[] { CardClass.MAGE, CardClass.ROGUE }); case MultiClassGroup.ROGUE_WARRIOR: return(new[] { CardClass.ROGUE, CardClass.WARRIOR }); case MultiClassGroup.PALADIN_WARRIOR: return(new[] { CardClass.PALADIN, CardClass.WARRIOR }); default: return(new[] { card.Class }); } } try { var deck = new Deck(); var lines = cards.Split(Separators, StringSplitOptions.RemoveEmptyEntries); 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); } if (match != null) { var tmpCount = match.Groups["count"]; if (tmpCount.Success) { count = int.Parse(tmpCount.Value); } cardName = match.Groups["cardname"].Value.Trim(); } var card = Database.GetCardFromName(cardName.Replace("’", "'"), localizedNames); if (string.IsNullOrEmpty(card?.Name) || card.Id == Database.UnknownCardId) { continue; } card.Count = count; 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); } } var deckClass = deck.Cards .Where(x => x.DbfIf != 0) .Select(AvailableClasses) .Where(x => x.Length > 1 || x[0] != CardClass.NEUTRAL) .Aggregate((a, b) => a.Concat(b).GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key).ToArray()); if (deckClass.Length > 1) { Log.Warn("Could not identify a class for this deck. Found multiple potential classes: " + string.Join(", ", deckClass.Select(HearthDbConverter.ConvertClass))); return(null); } else if (deckClass.Length == 0) { Log.Warn("Could not identify a class for this deck. Found conflicting classes."); return(null); } else { deck.Class = HearthDbConverter.ConvertClass(deckClass[0]); return(deck); } } catch (Exception ex) { Log.Error(ex); return(null); } }