From 77198e4062df1ab5dca04fbaf525e113e3ed9413 Mon Sep 17 00:00:00 2001 From: Alexander Zeier Date: Tue, 12 Oct 2021 18:08:32 -0700 Subject: [PATCH] Add initial support for Mercenaries --- Hearthstone Deck Tracker/Config.cs | 3 + .../Controls/CardImage.xaml | 12 ++-- .../Controls/CardImage.xaml.cs | 1 + Hearthstone Deck Tracker/Enums/GameMode.cs | 2 + .../Enums/Hearthstone/Mode.cs | 12 +++- .../Options/HSReplay/HSReplayReplays.xaml | 1 + Hearthstone Deck Tracker/GameEventHandler.cs | 19 ++++++- .../Hearthstone/Entities/Entity.cs | 8 ++- .../Hearthstone/GameV2.cs | 18 +++++- .../Hearthstone/HearthDbConverter.cs | 16 ++++++ .../HsReplay/UploadMetaDataGenerator.cs | 11 +++- .../Handlers/LoadingScreenHandler.cs | 3 + Hearthstone Deck Tracker/Stats/GameStats.cs | 28 ++++++++-- .../Utility/ConfigWrapper.cs | 10 ++++ .../Utility/RemoteConfig.cs | 15 +++++ .../OverlayWindow.MouseOverDetection.cs | 55 +++++++++++++++++-- .../Windows/OverlayWindow.Update.cs | 13 +++-- .../Windows/OverlayWindow.xaml | 5 ++ ResourceGenerator/Program.cs | 2 +- 19 files changed, 204 insertions(+), 30 deletions(-) diff --git a/Hearthstone Deck Tracker/Config.cs b/Hearthstone Deck Tracker/Config.cs index 71e18387ec..423b8b0b95 100644 --- a/Hearthstone Deck Tracker/Config.cs +++ b/Hearthstone Deck Tracker/Config.cs @@ -509,6 +509,9 @@ public class Config [DefaultValue(true)] public bool HsReplayUploadDuels = true; + [DefaultValue(true)] + public bool HsReplayUploadMercenaries = true; + [DefaultValue(null)] public bool? HsReplayUploadPacks = null; diff --git a/Hearthstone Deck Tracker/Controls/CardImage.xaml b/Hearthstone Deck Tracker/Controls/CardImage.xaml index 2bcfc6b8b8..8eacc985e0 100644 --- a/Hearthstone Deck Tracker/Controls/CardImage.xaml +++ b/Hearthstone Deck Tracker/Controls/CardImage.xaml @@ -16,20 +16,20 @@ + MaxWidth="{Binding Path=CardImageConfigs.CardImageSize, Source={StaticResource ConfigWrapper}, Converter={StaticResource CardImageSizeConverter}, ConverterParameter={x:Static controls:CardImageSizeType.Width}}" + MaxHeight="{Binding Path=CardImageConfigs.CardImageSize, Source={StaticResource ConfigWrapper}, Converter={StaticResource CardImageSizeConverter}, ConverterParameter={x:Static controls:CardImageSizeType.Height}}"> diff --git a/Hearthstone Deck Tracker/Controls/CardImage.xaml.cs b/Hearthstone Deck Tracker/Controls/CardImage.xaml.cs index 4df177103d..55dc377da8 100644 --- a/Hearthstone Deck Tracker/Controls/CardImage.xaml.cs +++ b/Hearthstone Deck Tracker/Controls/CardImage.xaml.cs @@ -131,6 +131,7 @@ public async void SetCardIdFromCard(Hearthstone.Card card) try { CardImagePath = AssetDownloaders.cardImageDownloader.StoragePathFor(card); + LoadingImageSource = null; if (hasAsset) ExpandAnimation?.Begin(); } diff --git a/Hearthstone Deck Tracker/Enums/GameMode.cs b/Hearthstone Deck Tracker/Enums/GameMode.cs index acd88bebcf..42b84e47ad 100644 --- a/Hearthstone Deck Tracker/Enums/GameMode.cs +++ b/Hearthstone Deck Tracker/Enums/GameMode.cs @@ -22,6 +22,8 @@ public enum GameMode Spectator, [LocDescription("Enum_GameMode_Duels")] Duels, + [LocDescription("Enum_GameMode_Mercenaries")] + Mercenaries, [LocDescription("Enum_GameMode_None")] None } diff --git a/Hearthstone Deck Tracker/Enums/Hearthstone/Mode.cs b/Hearthstone Deck Tracker/Enums/Hearthstone/Mode.cs index 33557e7cf9..55f93fdb4b 100644 --- a/Hearthstone Deck Tracker/Enums/Hearthstone/Mode.cs +++ b/Hearthstone Deck Tracker/Enums/Hearthstone/Mode.cs @@ -20,6 +20,16 @@ public enum Mode FIRESIDE_GATHERING, BACON, GAME_MODE, - PVP_DUNGEON_RUN + PVP_DUNGEON_RUN, + BACON_COLLECTION, + LETTUCE_VILLAGE, + LETTUCE_BOUNTY_BOARD, + LETTUCE_MAP, + LETTUCE_PLAY, + LETTUCE_COLLECTION, + LETTUCE_COOP, + LETTUCE_FRIENDLY, + LETTUCE_BOUNTY_TEAM_SELECT, + LETTUCE_PACK_OPENING } } diff --git a/Hearthstone Deck Tracker/FlyoutControls/Options/HSReplay/HSReplayReplays.xaml b/Hearthstone Deck Tracker/FlyoutControls/Options/HSReplay/HSReplayReplays.xaml index 06dbd1cfd3..dbfb6f19d2 100644 --- a/Hearthstone Deck Tracker/FlyoutControls/Options/HSReplay/HSReplayReplays.xaml +++ b/Hearthstone Deck Tracker/FlyoutControls/Options/HSReplay/HSReplayReplays.xaml @@ -16,6 +16,7 @@ + diff --git a/Hearthstone Deck Tracker/GameEventHandler.cs b/Hearthstone Deck Tracker/GameEventHandler.cs index 6224a96ef1..1604d68616 100644 --- a/Hearthstone Deck Tracker/GameEventHandler.cs +++ b/Hearthstone Deck Tracker/GameEventHandler.cs @@ -70,7 +70,8 @@ public GameEventHandler(GameV2 game) || _game.CurrentGameMode == Casual && Config.Instance.HsReplayUploadCasual || _game.CurrentGameMode == Spectator && Config.Instance.HsReplayUploadSpectator || _game.IsBattlegroundsMatch && Config.Instance.HsReplayUploadBattlegrounds - || _game.CurrentGameMode == Duels && Config.Instance.HsReplayUploadDuels; + || _game.CurrentGameMode == Duels && Config.Instance.HsReplayUploadDuels + || _game.IsMercenariesMatch && Config.Instance.HsReplayUploadMercenaries; public void HandleInMenu() { @@ -563,6 +564,13 @@ public async void HandleGameEnd(bool stateComplete) { _game.CurrentGameStats.BattlegroundsRating = _game.BattlegroundsRatingInfo.Rating; } + else if (_game.IsMercenariesMatch) + { + if(_game.IsMercenariesPvpMatch && _game.MercenariesRatingInfo != null) + _game.CurrentGameStats.MercenariesRating = _game.MercenariesRatingInfo.Rating; + if(_game.IsMercenariesPveMatch) + _game.CurrentGameStats.MercenariesBountyRunId = _game.MercenariesMapInfo?.Seed.ToString(); + } _game.CurrentGameStats.GameType = _game.CurrentGameType; _game.CurrentGameStats.ServerInfo = _game.MetaData.ServerInfo; _game.CurrentGameStats.PlayerCardbackId = _game.MatchInfo?.LocalPlayer.CardBackId ?? 0; @@ -669,8 +677,13 @@ public async void HandleGameEnd(bool stateComplete) { try { - DefaultDeckStats.Instance.GetDeckStats(_game.Player.Class).AddGameResult(_game.CurrentGameStats); - Log.Info($"Assigned current deck to default {_game.Player.Class} deck."); + if(!string.IsNullOrEmpty(_game.Player.Class)) + { + DefaultDeckStats.Instance.GetDeckStats(_game.Player.Class).AddGameResult(_game.CurrentGameStats); + Log.Info($"Assigned current deck to default {_game.Player.Class} deck."); + } + else + Log.Debug("Not assigning a deck, no player class found."); } catch(Exception ex) { diff --git a/Hearthstone Deck Tracker/Hearthstone/Entities/Entity.cs b/Hearthstone Deck Tracker/Hearthstone/Entities/Entity.cs index 8929a892ba..18f491e045 100644 --- a/Hearthstone Deck Tracker/Hearthstone/Entities/Entity.cs +++ b/Hearthstone Deck Tracker/Hearthstone/Entities/Entity.cs @@ -135,7 +135,13 @@ public Entity Clone() public bool IsInZone(Zone zone) => HasTag(GameTag.ZONE) && GetTag(GameTag.ZONE) == (int)zone; - public bool IsControlledBy(int controllerId) => HasTag(GameTag.CONTROLLER) && GetTag(GameTag.CONTROLLER) == controllerId; + public bool IsControlledBy(int controllerId) + { + var lettuceController = GetTag(GameTag.LETTUCE_CONTROLLER); + if(lettuceController > 0) + return lettuceController == controllerId; + return HasTag(GameTag.CONTROLLER) && GetTag(GameTag.CONTROLLER) == controllerId; + } public bool IsAttachedTo(int entityId) => GetTag(GameTag.ATTACHED) == entityId; diff --git a/Hearthstone Deck Tracker/Hearthstone/GameV2.cs b/Hearthstone Deck Tracker/Hearthstone/GameV2.cs index d11fb635c4..d869eab63b 100644 --- a/Hearthstone Deck Tracker/Hearthstone/GameV2.cs +++ b/Hearthstone Deck Tracker/Hearthstone/GameV2.cs @@ -32,6 +32,7 @@ public class GameV2 : IGame private Mode _currentMode; private BrawlInfo _brawlInfo; private BattlegroundRatingInfo _battlegroundsRatingInfo; + private MercenariesRatingInfo _mercenariesRatingInfo; private BattlegroundsBoardState _battlegroundsBoardState; Regex BattlegroundsHeroRegex = new Regex(@"(TB_BaconShop_HERO_\d\d)|(BG20_HERO_\d\d)"); @@ -110,6 +111,11 @@ public bool IsOpponentMinionInPlay : CurrentGameType == GameType.GT_VS_AI && DungeonRun.IsDungeonBoss(CurrentGameStats.OpponentHeroCardId); public bool IsBattlegroundsMatch => CurrentGameType == GameType.GT_BATTLEGROUNDS || CurrentGameType == GameType.GT_BATTLEGROUNDS_FRIENDLY; + public bool IsMercenariesMatch => CurrentGameType == GameType.GT_MERCENARIES_AI_VS_AI || CurrentGameType == GameType.GT_MERCENARIES_FRIENDLY + || CurrentGameType == GameType.GT_MERCENARIES_PVE || CurrentGameType == GameType.GT_MERCENARIES_PVP + || CurrentGameType == GameType.GT_MERCENARIES_PVE_COOP; + public bool IsMercenariesPvpMatch => CurrentGameType == GameType.GT_MERCENARIES_PVP; + public bool IsMercenariesPveMatch => CurrentGameType == GameType.GT_MERCENARIES_PVE || CurrentGameType == GameType.GT_MERCENARIES_PVE_COOP; public bool IsConstructedMatch => CurrentGameType == GameType.GT_RANKED || CurrentGameType == GameType.GT_CASUAL || CurrentGameType == GameType.GT_VS_FRIEND; @@ -185,10 +191,14 @@ public GameMode CurrentGameMode public BattlegroundRatingInfo BattlegroundsRatingInfo => _battlegroundsRatingInfo ?? (_battlegroundsRatingInfo = HearthMirror.Reflection.GetBattlegroundRatingInfo()); - private bool IsValidPlayerInfo(MatchInfo.Player playerInfo) + public MercenariesRatingInfo MercenariesRatingInfo => _mercenariesRatingInfo ?? (_mercenariesRatingInfo = HearthMirror.Reflection.GetMercenariesRatingInfo()); + + public MercenariesMapInfo MercenariesMapInfo => HearthMirror.Reflection.GetMercenariesMapInfo(); + + private bool IsValidPlayerInfo(MatchInfo.Player playerInfo, bool allowMissing = true) { var name = playerInfo?.Name ?? playerInfo?.BattleTag?.Name; - var valid = name != null; + var valid = allowMissing || name != null; Log.Debug($"valid={valid}, gameMode={CurrentGameMode}, player={name}, starLevel={playerInfo?.Standard?.StarLevel}"); return valid; } @@ -198,7 +208,7 @@ internal async void CacheMatchInfo() if(!_matchInfoCacheInvalid) return; MatchInfo matchInfo; - while((matchInfo = HearthMirror.Reflection.GetMatchInfo()) == null || !IsValidPlayerInfo(matchInfo.LocalPlayer) || !IsValidPlayerInfo(matchInfo.OpposingPlayer)) + while((matchInfo = HearthMirror.Reflection.GetMatchInfo()) == null || !IsValidPlayerInfo(matchInfo.LocalPlayer) || !IsValidPlayerInfo(matchInfo.OpposingPlayer, IsMercenariesMatch)) { Log.Info($"Waiting for matchInfo... (matchInfo={matchInfo}, localPlayer={matchInfo?.LocalPlayer?.Name}, opposingPlayer={matchInfo?.OpposingPlayer?.Name})"); await Task.Delay(1000); @@ -235,6 +245,8 @@ internal async void CacheGameType() internal void CacheBattlegroundRatingInfo() => _battlegroundsRatingInfo = HearthMirror.Reflection.GetBattlegroundRatingInfo(); + internal void CacheMercenariesRatingInfo() => _mercenariesRatingInfo = HearthMirror.Reflection.GetMercenariesRatingInfo(); + internal void InvalidateMatchInfoCache() => _matchInfoCacheInvalid = true; public void Reset(bool resetStats = true) diff --git a/Hearthstone Deck Tracker/Hearthstone/HearthDbConverter.cs b/Hearthstone Deck Tracker/Hearthstone/HearthDbConverter.cs index b779200d83..498aca9919 100644 --- a/Hearthstone Deck Tracker/Hearthstone/HearthDbConverter.cs +++ b/Hearthstone Deck Tracker/Hearthstone/HearthDbConverter.cs @@ -128,6 +128,12 @@ public static GameMode GetGameMode(GameType gameType) return GameMode.Duels; case GameType.GT_PVPDR_PAID: return GameMode.Duels; + case GameType.GT_MERCENARIES_AI_VS_AI: + case GameType.GT_MERCENARIES_FRIENDLY: + case GameType.GT_MERCENARIES_PVE: + case GameType.GT_MERCENARIES_PVP: + case GameType.GT_MERCENARIES_PVE_COOP: + return GameMode.Mercenaries; default: return GameMode.None; } @@ -206,6 +212,16 @@ public static BnetGameType GetBnetGameType(GameType gameType, Format? format) return BGT_PVPDR; case GameType.GT_PVPDR_PAID: return BGT_PVPDR_PAID; + case GameType.GT_MERCENARIES_AI_VS_AI: + return BGT_UNKNOWN; // Does not exist in BGT + case GameType.GT_MERCENARIES_FRIENDLY: + return BGT_MERCENARIES_FRIENDLY; + case GameType.GT_MERCENARIES_PVE: + return BGT_MERCENARIES_PVE; + case GameType.GT_MERCENARIES_PVP: + return BGT_MERCENARIES_PVP; + case GameType.GT_MERCENARIES_PVE_COOP: + return BGT_MERCENARIES_PVE_COOP; default: return BGT_UNKNOWN; } diff --git a/Hearthstone Deck Tracker/HsReplay/UploadMetaDataGenerator.cs b/Hearthstone Deck Tracker/HsReplay/UploadMetaDataGenerator.cs index f8c8eb0ac8..47323dc04f 100644 --- a/Hearthstone Deck Tracker/HsReplay/UploadMetaDataGenerator.cs +++ b/Hearthstone Deck Tracker/HsReplay/UploadMetaDataGenerator.cs @@ -18,7 +18,7 @@ public static UploadMetaData Generate(GameMetaData gameMetaData, GameStats game) var players = GetPlayerInfo(game); if (players != null) { - if (game.GameMode == GameMode.Battlegrounds) + if (game.GameMode == GameMode.Battlegrounds || game.GameMode == GameMode.Mercenaries) metaData.Players = players; else { @@ -122,6 +122,15 @@ public static UploadMetaData Generate(GameMetaData gameMetaData, GameStats game) if(game.BattlegroundsRatingAfter > 0) friendly.BattlegroundsRatingAfter = game.BattlegroundsRatingAfter; } + else if(game.GameMode == GameMode.Mercenaries) + { + if(game.MercenariesRating > 0) + friendly.MercenariesRating = game.MercenariesRating; + if(game.MercenariesRatingAfter > 0) + friendly.MercenariesRatingAfter = game.MercenariesRatingAfter; + if(!string.IsNullOrEmpty(game.MercenariesBountyRunId)) + friendly.MercenariesBountyRunId = game.MercenariesBountyRunId; + } else if(game.PlayerCards.Sum(x => x.Count) == 30 || game.IsPVPDungeonMatch || game.IsDungeonMatch == true && game.DeckId != Guid.Empty) { friendly.DeckList = game.PlayerCards.Where(x => x.Id != Database.UnknownCardId).SelectMany(x => Enumerable.Repeat(x.Id, x.Count)).ToArray(); diff --git a/Hearthstone Deck Tracker/LogReader/Handlers/LoadingScreenHandler.cs b/Hearthstone Deck Tracker/LogReader/Handlers/LoadingScreenHandler.cs index b152aec2b4..fbe2c40f3a 100644 --- a/Hearthstone Deck Tracker/LogReader/Handlers/LoadingScreenHandler.cs +++ b/Hearthstone Deck Tracker/LogReader/Handlers/LoadingScreenHandler.cs @@ -84,6 +84,9 @@ public void Handle(LogLine logLine, IHsGameState gameState, IGame game) if(game.CurrentMode == Mode.BACON) Core.Game.CacheBattlegroundRatingInfo(); + if(game.CurrentMode == Mode.LETTUCE_PLAY) + Core.Game.CacheMercenariesRatingInfo(); + if(game.CurrentMode == Mode.ADVENTURE || game.PreviousMode == Mode.ADVENTURE && game.CurrentMode == Mode.GAMEPLAY) Watchers.DungeonRunWatcher.Run(); else diff --git a/Hearthstone Deck Tracker/Stats/GameStats.cs b/Hearthstone Deck Tracker/Stats/GameStats.cs index ef206cbdd5..552b81d9e7 100644 --- a/Hearthstone Deck Tracker/Stats/GameStats.cs +++ b/Hearthstone Deck Tracker/Stats/GameStats.cs @@ -47,6 +47,7 @@ public class GameStats : INotifyPropertyChanged private int _rank; private int _starLevel; private int _battlegroundsRating; + private int _mercenariesRating; private int _stars; private int _legendRank; private Region _region; @@ -136,7 +137,7 @@ public string Note get { return _note; } set { - _note = value; + _note = value; OnPropertyChanged(); } } @@ -220,6 +221,20 @@ public int BattlegroundsRating public int BattlegroundsRatingAfter { get; set; } + public int MercenariesRating + { + get { return _mercenariesRating; } + set + { + _mercenariesRating = value; + OnPropertyChanged(); + } + } + + public int MercenariesRatingAfter { get; set; } + + public string MercenariesBountyRunId { get; set; } + public HashSet BattlegroundsRaces { get; set; } public int OpponentLegendRank @@ -242,7 +257,7 @@ public int OpponentLegendRank public int StarMultiplier { get; set; } public int? HearthstoneBuild { get; set; } - + public int PlayerCardbackId { get; set; } public int OpponentCardbackId { get; set; } @@ -329,7 +344,7 @@ public string DeckNameAndVersion { get { - if (!string.IsNullOrEmpty(_deckNameAndVersion)) + if(!string.IsNullOrEmpty(_deckNameAndVersion)) return _deckNameAndVersion; var deck = DeckList.Instance.Decks.FirstOrDefault(d => d.DeckId == DeckId)?.GetVersion(PlayerDeckVersion); _deckNameAndVersion = deck?.NameAndVersion ?? "none"; @@ -380,7 +395,7 @@ public SolidColorBrush ResultTextColor public string PlayerDeckVersionString => PlayerDeckVersion != null ? PlayerDeckVersion.ToString("v{M}.{m}") : SerializableVersion.Default.ToString("v{M}.{m}"); [XmlIgnore] - public ToolTip ResultToolTip => new ToolTip {Content = "conceded", Visibility = (WasConceded ? Visibility.Visible : Visibility.Hidden)}; + public ToolTip ResultToolTip => new ToolTip { Content = "conceded", Visibility = (WasConceded ? Visibility.Visible : Visibility.Hidden) }; [XmlIgnore] public bool HasReplayFile => ReplayFile != null && File.Exists(Path.Combine(Config.Instance.ReplayDir, ReplayFile)); @@ -486,7 +501,7 @@ public void GameEnd() public void SetPlayerCards(HearthMirror.Objects.Deck deck, List revealedCards) { - var cards = deck?.Cards.Select(c => new Card {Id = c.Id, Count = c.Count}); + var cards = deck?.Cards.Select(c => new Card { Id = c.Id, Count = c.Count }); SetPlayerCards(cards, revealedCards); } @@ -561,6 +576,9 @@ public void SetOpponentCards(List revealedCards) public bool ShouldSerializeBrawlLosses() => BrawlLosses > 0; public bool ShouldSerializeBattlegroundsRating() => BattlegroundsRating > 0; public bool ShouldSerializeBattlegroundsRatingAfter() => BattlegroundsRatingAfter > 0; + public bool ShouldSerializeMercenariesRating() => MercenariesRating > 0; + public bool ShouldSerializeMercenariesRatingAfter() => MercenariesRatingAfter > 0; + public bool ShouldSerializeMercenariesBountyRunId() => !string.IsNullOrEmpty(MercenariesBountyRunId); public bool ShouldSerializeStarLevel() => StarLevel > 0; public bool ShouldSerializeStarLevelAfter() => StarLevelAfter > 0; public bool ShouldSerializeOpponentStarLevel() => OpponentStarLevel > 0; diff --git a/Hearthstone Deck Tracker/Utility/ConfigWrapper.cs b/Hearthstone Deck Tracker/Utility/ConfigWrapper.cs index fbe42aff1c..45c8bc45bf 100644 --- a/Hearthstone Deck Tracker/Utility/ConfigWrapper.cs +++ b/Hearthstone Deck Tracker/Utility/ConfigWrapper.cs @@ -303,6 +303,16 @@ public static bool HsReplayUploadDuels } } + public static bool HsReplayUploadMercenaries + { + get { return Config.Instance.HsReplayUploadMercenaries; } + set + { + Config.Instance.HsReplayUploadMercenaries = value; + Config.Save(); + } + } + public static Visibility ShowDateOnDeckVisibility => Config.Instance.ShowDateOnDeck ? Visibility.Visible : Visibility.Collapsed; public static Visibility UseButtonVisiblity => Config.Instance.AutoUseDeck ? Visibility.Collapsed : Visibility.Visible; diff --git a/Hearthstone Deck Tracker/Utility/RemoteConfig.cs b/Hearthstone Deck Tracker/Utility/RemoteConfig.cs index 88d876f5ed..ea88981600 100644 --- a/Hearthstone Deck Tracker/Utility/RemoteConfig.cs +++ b/Hearthstone Deck Tracker/Utility/RemoteConfig.cs @@ -44,6 +44,9 @@ internal class ConfigData [JsonProperty("update_info")] public UpdateData UpdateInfo { get; set; } + [JsonProperty("mercenary_abilities")] + public List MercenaryAbilities { get; set; } + internal class NewsData { [JsonProperty("id")] @@ -147,6 +150,18 @@ internal class UpdateData [JsonProperty("image_update_hearthstone_version")] public int Version { get; set; } } + + internal class Mercenary + { + [JsonProperty("card_id")] + public string CardId { get; set; } + + [JsonProperty("skins")] + public List Skins { get; set; } + + [JsonProperty("abilities")] + public List Abilities { get; set; } + } } } } diff --git a/Hearthstone Deck Tracker/Windows/OverlayWindow.MouseOverDetection.cs b/Hearthstone Deck Tracker/Windows/OverlayWindow.MouseOverDetection.cs index 66d1d40f03..9ef079aadf 100644 --- a/Hearthstone Deck Tracker/Windows/OverlayWindow.MouseOverDetection.cs +++ b/Hearthstone Deck Tracker/Windows/OverlayWindow.MouseOverDetection.cs @@ -14,7 +14,7 @@ using Hearthstone_Deck_Tracker.Controls; using Hearthstone_Deck_Tracker.Utility; using System.Threading.Tasks; -using System.Windows.Input; +using Hearthstone_Deck_Tracker.Hearthstone; #endregion @@ -29,6 +29,7 @@ public partial class OverlayWindow public double MinionWidth => Width * 0.63 / 7 * ScreenRatio; public double CardWidth => Height * 0.125; public double CardHeight => Height * 0.189; + public double MercAbilityHeight => Height * 0.3; //Adjusts OpponentDeadFor textblocks left by this amount depending on what position they represent on the leaderboard. const double LeftAdjust = .00075; //Adjusts the OpponentDeadFor textblock of the next oponent by this to the right so it aligns correctly with the hero portrait. @@ -47,7 +48,7 @@ public Thickness MinionMargin { get { - var side = Width * ScreenRatio * 0.0029; + var side = Width * ScreenRatio * (_game.IsMercenariesMatch ? 0.01 : 0.0029); return new Thickness(side, 0, side, 0); } } @@ -174,28 +175,68 @@ private Point GetCursorPos() } } + private void ShowMercHover(Entity entity) + { + var id = entity?.Card?.Id; + if(string.IsNullOrEmpty(id)) + { + MercAbility1.SetCardIdFromCard(null); + MercAbility2.SetCardIdFromCard(null); + MercAbility3.SetCardIdFromCard(null); + } + else + { + var abilities = RemoteConfig.Instance.Data?.MercenaryAbilities?.FirstOrDefault(x => x.CardId == id || x.Skins.Contains(id))?.Abilities ?? new List(); + if(abilities.Count == 3) + { + MercAbility1.SetCardIdFromCard(Database.GetCardFromId(abilities.ElementAt(0))); + MercAbility2.SetCardIdFromCard(Database.GetCardFromId(abilities.ElementAt(1))); + MercAbility3.SetCardIdFromCard(Database.GetCardFromId(abilities.ElementAt(2))); + } + } + } + private void DetectMouseOver(List playerBoard, List oppBoard) { - if(playerBoard.Count == 0 && oppBoard.Count == 0 && _game.Player.HandCount == 0 || IsGameOver) + if(!_game.IsMercenariesMatch && (playerBoard.Count == 0 && oppBoard.Count == 0 && _game.Player.HandCount == 0 || IsGameOver)) { FlavorTextVisibility = Visibility.Collapsed; return; } + if(_game.IsMercenariesMatch && _entityMouseOver.HasCurrent && _game.GameEntity.GetTag(GameTag.STEP) == (int)Step.MAIN_COMBAT) + { + _entityMouseOver.Clear(); + ShowMercHover(null); + return; + } var relativeCanvas = GetCursorPos(); if(relativeCanvas.X == -1 && relativeCanvas.Y == -1) return; + + var isOverOpponent = false; for(var i = 0; i < 7; i++) { if(oppBoard.Count > i && EllipseContains(_oppBoard[i], relativeCanvas)) { + isOverOpponent = true; var entity = oppBoard[i]; _entityMouseOver.DelayedMouseOverDetection(oppBoard[i], () => { - SetFlavorTextEntity(entity); + if(_game.IsMercenariesMatch) + { + if(_game.GameEntity.GetTag(GameTag.STEP) != (int)Step.MAIN_COMBAT) + ShowMercHover(entity); + } + else + SetFlavorTextEntity(entity); GameEvents.OnOpponentMinionMouseOver.Execute(entity.Card); - }, () => FlavorTextVisibility = Visibility.Collapsed); + }, () => { + FlavorTextVisibility = Visibility.Collapsed; + ShowMercHover(null); + }); return; } + if(playerBoard.Count > i && EllipseContains(_playerBoard[i], relativeCanvas)) { var entity = playerBoard[i]; @@ -207,6 +248,10 @@ private void DetectMouseOver(List playerBoard, List oppBoard) return; } } + + if(_game.IsMercenariesMatch && _entityMouseOver.HasCurrent && !isOverOpponent) + ShowMercHover(null); + var handCount = Math.Min(_game.Player.HandCount, MaxHandSize); for(var i = handCount - 1; i >= 0; i--) { diff --git a/Hearthstone Deck Tracker/Windows/OverlayWindow.Update.cs b/Hearthstone Deck Tracker/Windows/OverlayWindow.Update.cs index 4de209f374..bb713a88d9 100644 --- a/Hearthstone Deck Tracker/Windows/OverlayWindow.Update.cs +++ b/Hearthstone Deck Tracker/Windows/OverlayWindow.Update.cs @@ -101,10 +101,11 @@ public void Update(bool refresh) _cardMarks[i].Visibility = Collapsed; } + var foo = Core.Game.Entities; var oppBoard = Core.Game.Opponent.Board.Where(x => x.IsMinion).OrderBy(x => x.GetTag(ZONE_POSITION)).ToList(); var playerBoard = Core.Game.Player.Board.Where(x => x.IsMinion).OrderBy(x => x.GetTag(ZONE_POSITION)).ToList(); UpdateMouseOverDetectionRegions(oppBoard, playerBoard); - if(!_game.IsInMenu && (_game.IsMulliganDone || _game.IsBattlegroundsMatch) && User32.IsHearthstoneInForeground() && IsVisible) + if(!_game.IsInMenu && (_game.IsMulliganDone || _game.IsBattlegroundsMatch || _game.IsMercenariesMatch) && User32.IsHearthstoneInForeground() && IsVisible) DetectMouseOver(playerBoard, oppBoard); else FlavorTextVisibility = Collapsed; @@ -117,7 +118,8 @@ public void Update(bool refresh) Opacity = Config.Instance.OverlayOpacity / 100; var inBattlegrounds = _game.IsBattlegroundsMatch; - var hideDeck = Config.Instance.HideDecksInOverlay || inBattlegrounds || (Config.Instance.HideInMenu && _game.IsInMenu); + var inMercenaries = _game.IsMercenariesMatch; + var hideDeck = Config.Instance.HideDecksInOverlay || inBattlegrounds || inMercenaries || (Config.Instance.HideInMenu && _game.IsInMenu); if (!_playerCardsHidden) { @@ -279,12 +281,14 @@ public void UpdatePosition() if (Height != prevHeight) { OnPropertyChanged(nameof(BoardHeight)); - OnPropertyChanged(nameof(MinionMargin)); OnPropertyChanged(nameof(MinionWidth)); OnPropertyChanged(nameof(CardWidth)); OnPropertyChanged(nameof(CardHeight)); + OnPropertyChanged(nameof(MercAbilityHeight)); } + OnPropertyChanged(nameof(MinionMargin)); + UpdateElementSizes(); ApplyAutoScaling(); UpdateElementPositions(); @@ -352,7 +356,8 @@ private void UpdateElementPositions() Canvas.SetLeft(IconBoardAttackPlayer, Helper.GetScaledXPos(Config.Instance.AttackIconPlayerHorizontalPosition / 100, (int)Width, ScreenRatio)); Canvas.SetTop(IconBoardAttackOpponent, Height * Config.Instance.AttackIconOpponentVerticalPosition / 100); Canvas.SetLeft(IconBoardAttackOpponent, Helper.GetScaledXPos(Config.Instance.AttackIconOpponentHorizontalPosition / 100, (int)Width, ScreenRatio)); - Canvas.SetTop(GridOpponentBoard, Height / 2 - GridOpponentBoard.ActualHeight - Height * 0.045); + var opponentBoardOffset = _game.IsMercenariesMatch && !(_game.GameEntity?.HasTag(LETTUCE_SHOW_OPPOSING_FAKE_HAND) ?? false) ? Height * 0.142 : Height * 0.045; + Canvas.SetTop(GridOpponentBoard, Height / 2 - GridOpponentBoard.ActualHeight - opponentBoardOffset); Canvas.SetTop(GridPlayerBoard, Height / 2 - Height * 0.03); Canvas.SetLeft(LinkOpponentDeckDisplay, Width * Config.Instance.OpponentDeckLeft / 100); diff --git a/Hearthstone Deck Tracker/Windows/OverlayWindow.xaml b/Hearthstone Deck Tracker/Windows/OverlayWindow.xaml index 0b25211bb4..88864cae28 100644 --- a/Hearthstone Deck Tracker/Windows/OverlayWindow.xaml +++ b/Hearthstone Deck Tracker/Windows/OverlayWindow.xaml @@ -99,6 +99,11 @@ + + + + + diff --git a/ResourceGenerator/Program.cs b/ResourceGenerator/Program.cs index 48200c7ee0..6223ede2e9 100644 --- a/ResourceGenerator/Program.cs +++ b/ResourceGenerator/Program.cs @@ -68,7 +68,7 @@ private static void GenerateTiles(string[] args) foreach(var card in Cards.All) { - if(card.Value.Set == CardSet.CHEAT || card.Value.Set == CardSet.SLUSH) + if(card.Value.Set == CardSet.CHEAT || card.Value.Set == CardSet.SLUSH || card.Value.Set == CardSet.LETTUCE || card.Value.Set == CardSet.MERCENARIES_DEV) continue; var key = card.Value.Set + (card.Value.Collectible ? "" : "_NC"); if(!dict.ContainsKey(key))