Skip to content

Commit

Permalink
Fix scaling of the mulligan overlay, add setting and w/r to the card …
Browse files Browse the repository at this point in the history
…list
  • Loading branch information
fmoraes74 committed Feb 29, 2024
1 parent 6358116 commit 6579789
Show file tree
Hide file tree
Showing 32 changed files with 688 additions and 260 deletions.
21 changes: 21 additions & 0 deletions HSTracker/Assets/Assets.xcassets/eye.imageset/Contents.json
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "eye.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions HSTracker/Assets/Assets.xcassets/eye_slash.imageset/Contents.json
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "eye_slash.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 19 additions & 4 deletions HSTracker/Core/Extensions/Array.swift
Expand Up @@ -16,13 +16,28 @@ extension Dictionary {
}
}

enum CardListSorting: Int {
case cost, mulliganWr
}

extension Array where Element: Card {
func sortCardList() -> [Card] {
func sortCardList(_ sorting: CardListSorting = .cost) -> [Card] {
if sorting == .cost {
return sorted {
if $0.cost == $1.cost {
return $0.name < $1.name
}
return $0.cost < $1.cost
}
}
return sorted {
if $0.cost == $1.cost {
return $0.name < $1.name
if $0.cardWinRates?.mulliganWinRate == $1.cardWinRates?.mulliganWinRate {
if $0.cost == $1.cost {
return $0.name < $1.name
}
return $0.cost < $1.cost
}
return $0.cost < $1.cost
return ($0.cardWinRates?.mulliganWinRate ?? 0.0) > ($1.cardWinRates?.mulliganWinRate ?? 0.0)
}
}

Expand Down
3 changes: 3 additions & 0 deletions HSTracker/Core/Settings.swift
Expand Up @@ -236,6 +236,8 @@ final class Settings {
static var showMulliganToast: Bool
@UserDefault(key: Settings.show_flavor_text, defaultValue: true)
static var showFlavorText: Bool
@UserDefault(key: Settings.enable_mulligan_guide, defaultValue: true)
static var enableMulliganGuide: Bool

// MARK: - Battlegrounds
@UserDefault(key: Settings.show_bobs_buddy, defaultValue: true)
Expand Down Expand Up @@ -571,6 +573,7 @@ extension Settings {
static let show_experience_counter = "show_experience_counter"
static let show_mulligan_toast = "show_mulligan_toast"
static let show_flavor_text = "show_flavor_text"
static let enable_mulligan_guide = "enable_mulligan_guide"

// MARK: Battlegrounds
static let show_bobs_buddy = "show_bobs_buddy"
Expand Down
11 changes: 11 additions & 0 deletions HSTracker/Database/Models/Card.swift
Expand Up @@ -9,6 +9,15 @@
import Foundation
//import HearthAssets

class CardWinrates: Equatable {
static func == (lhs: CardWinrates, rhs: CardWinrates) -> Bool {
return lhs.mulliganWinRate == rhs.mulliganWinRate && lhs.baseWinrate == rhs.baseWinrate
}

var mulliganWinRate = 0.0
var baseWinrate: Double?
}

final class Card {
// MARK: - Card data
var id = ""
Expand Down Expand Up @@ -45,6 +54,8 @@ final class Card {
var deckListIndex = 0
var battlegroundsSkinParentId = 0
var battlegroundsArmorTier = 0
var isMulliganOption = false
var cardWinRates: CardWinrates?

static let multiClassGroups: [MultiClassGroup: [CardClass]] = [
.grimy_goons: [ .hunter, .paladin, .warrior ],
Expand Down
58 changes: 50 additions & 8 deletions HSTracker/Logging/Game.swift
Expand Up @@ -71,10 +71,12 @@ class Game: NSObject, PowerEventHandler {
DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(1), execute: { [weak self] in
self?.updateTrackers()
self?.updateBattlegroundsOverlays()
self?.updateConstructedMulliganOverlays()
})
} else {
self.updateTrackers()
self.updateBattlegroundsOverlays()
self.updateConstructedMulliganOverlays()
}
}
}
Expand Down Expand Up @@ -564,6 +566,23 @@ class Game: NSObject, PowerEventHandler {
}
}

func updateConstructedMulliganOverlays() {
DispatchQueue.main.async {
let hsActive = self.hearthstoneRunState.isActive

if self.windowManager.constructedMulliganGuide.viewModel.visibility {
if hsActive {
self.windowManager.show(controller: self.windowManager.constructedMulliganGuide, show: true, frame: SizeHelper.hearthstoneWindow.frame, overlay: true)
DispatchQueue.main.async {
self.windowManager.constructedMulliganGuide.updateScaling()
}
} else {
self.windowManager.show(controller: self.windowManager.constructedMulliganGuide, show: false)
}
}
}
}

func updateBattlegroundsOverlays() {
DispatchQueue.main.async {
let hsActive = self.hearthstoneRunState.isActive
Expand Down Expand Up @@ -810,7 +829,7 @@ class Game: NSObject, PowerEventHandler {
self.windowManager.show(controller: playerBoardDamage, show: false)
}

if Settings.opponentBoardDamage && self.shouldShowGUIElement && (self.currentGameMode != .battlegrounds && self.currentGameMode != .mercenaries) {
if Settings.opponentBoardDamage && self.shouldShowGUIElement && (self.currentGameMode != .battlegrounds && self.currentGameMode != .mercenaries) && self.isMulliganDone() {
if !self.gameEnded {
var heroPowerDmg = 0
if let heroPower = board.opponent.heroPower {
Expand Down Expand Up @@ -1384,6 +1403,7 @@ class Game: NSObject, PowerEventHandler {
if rect != SizeHelper.hearthstoneWindow.frame {
self.updateAllTrackers()
self.updateBattlegroundsOverlays()
self.updateConstructedMulliganOverlays()
}
self.counter = 0
} else {
Expand Down Expand Up @@ -1890,6 +1910,13 @@ class Game: NSObject, PowerEventHandler {
windowManager.battlegroundsHeroPicking.viewModel.reset()
windowManager.battlegroundsQuestPicking.viewModel.reset()
}
if isConstructedMatch() {
// Core.Overlay.HideMulliganToast(false);
player.mulliganCardStats = nil
DispatchQueue.main.async {
self.hideMulliganGuideStats()
}
}

if let currentDeck = self.currentDeck {
var skip = false
Expand Down Expand Up @@ -2089,6 +2116,12 @@ class Game: NSObject, PowerEventHandler {
turnTimer.startTurn(for: player, timeout: timeout)

if player == .player && !isInMenu {
// Clear some state that should never be active at the start of a turn in case another hiding mechanism fails
DispatchQueue.main.async {
self.hideMulliganGuideStats()
}
self.player.mulliganCardStats = nil

if isBattlegroundsMatch() {
DispatchQueue.main.async { [self] in
self.windowManager.battlegroundsHeroPicking.viewModel.reset()
Expand Down Expand Up @@ -2984,6 +3017,11 @@ class Game: NSObject, PowerEventHandler {
windowManager.constructedMulliganGuide.viewModel.setMulliganData(stats: stats, maxRank: maxRank)
}

@MainActor
func hideMulliganGuideStats() {
windowManager.constructedMulliganGuide.viewModel.reset()
}

func handleBeginMulligan() {
if isBattlegroundsMatch() {
handleBattlegroundsStart()
Expand All @@ -3001,7 +3039,7 @@ class Game: NSObject, PowerEventHandler {
AppDelegate.instance().coreManager.toaster.hide()
let openingHand = snapshotOpeningHand()

if let mulliganCardStats /* TODO: enable mulligan guide */ {
if let mulliganCardStats, Settings.enableMulliganGuide {
let numSwappedCards = getMulliganSwappedCards()?.count ?? 0
if numSwappedCards > 0 {
// show the updated cards
Expand All @@ -3024,7 +3062,9 @@ class Game: NSObject, PowerEventHandler {
// Wait for the mulligan to be complete (component or animation)
for _ in 0..<16*60*60 { // 2 minutes
if isInMenu || (gameEntity?[.step] ?? 0) > Step.begin_mulligan.rawValue {
// TODO: hideMulliganGuideStats()
DispatchQueue.main.async {
self.hideMulliganGuideStats()
}
player.mulliganCardStats = nil
return
}
Expand All @@ -3033,7 +3073,9 @@ class Game: NSObject, PowerEventHandler {
}
Thread.sleep(forTimeInterval: 0.016)
}
// TODO: hideMulliganGuideStats
DispatchQueue.main.async {
self.hideMulliganGuideStats()
}
player.mulliganCardStats = nil
}
}
Expand All @@ -3059,9 +3101,9 @@ class Game: NSObject, PowerEventHandler {
@available(macOS 10.15.0, *)
private func internalHandleMulliganGuide(showToast: Bool, dbfIds: [Int]) async {
var mulliganGuideData: MulliganGuideData?
// TODO: if Settings.enableMulliganGuide {
mulliganGuideData = await getMulliganGuideData()
// }
if Settings.enableMulliganGuide {
mulliganGuideData = await getMulliganGuideData()
}
if let data = mulliganGuideData {
// Show mulligan guide with parameters as selected by the API
if showToast {
Expand Down Expand Up @@ -3113,7 +3155,7 @@ class Game: NSObject, PowerEventHandler {
_ = snapshotMulligan()

let showToast = Settings.showMulliganToast && !isArenaMatch
if showToast /* TODO: || Settings.enableMulliganGuide */ {
if showToast || Settings.enableMulliganGuide {
if let currentDeck = currentDeck {
// Show Mulligan Guide Elements (Overlay and/or Toast)
let shortId = currentDeck.shortid
Expand Down
31 changes: 26 additions & 5 deletions HSTracker/Logging/Player.swift
Expand Up @@ -330,18 +330,39 @@ final class Player {
return (revealedCards + createdInHand
+ knownCardsInDeck + getPredictedCardsInDeck(hidden: true)).sortCardList()
}
let sorting = game.isMulliganDone() ? CardListSorting.cost : CardListSorting.mulliganWr
let deckState = getDeckState()
let inDeck = deckState.remainingInDeck
let notInDeck = deckState.removedFromDeck.filter({ x in inDeck.all({ x.id != $0.id }) })
let predictedInDeck = getPredictedCardsInDeck(hidden: false).filter({ x in inDeck.all { c in x.id != c.id } })
if !Settings.removeCardsFromDeck {
return (inDeck + predictedInDeck + notInDeck + createdInHand).sortCardList()
return attachMulliganData(cards: (inDeck + predictedInDeck + notInDeck + createdInHand)).sortCardList(sorting)
}
if Settings.highlightCardsInHand {
return (inDeck + predictedInDeck + getHighlightedCardsInHand(cardsInDeck: inDeck)
+ createdInHand).sortCardList()
return attachMulliganData(cards: (inDeck + predictedInDeck + getHighlightedCardsInHand(cardsInDeck: inDeck)
+ createdInHand)).sortCardList(sorting)
}
return attachMulliganData(cards: (inDeck + predictedInDeck + createdInHand)).sortCardList(sorting)
}

private func attachMulliganData(cards: [Card]) -> [Card] {
guard let mulliganCardStats else {
return cards
}
return cards.compactMap { card in
guard let cardStats = mulliganCardStats.first(where: { x in x.dbf_id == card.dbfId }) else {
return card
}
let newCard = card.copy()
if let openingHandWinrate = cardStats.opening_hand_winrate {
let cardWinRates = CardWinrates()
cardWinRates.mulliganWinRate = openingHandWinrate
cardWinRates.baseWinrate = cardStats.baseWinRate
newCard.cardWinRates = cardWinRates
}
newCard.isMulliganOption = hand.any { x in x.card.dbfId == card.dbfId }
return newCard
}
return (inDeck + predictedInDeck + createdInHand).sortCardList()
}

var opponentCardList: [Card] {
Expand Down Expand Up @@ -867,7 +888,7 @@ final class Player {
}
set {
_mulliganCardStats = newValue
AppDelegate.instance().coreManager.game.updatePlayerTracker()
AppDelegate.instance().coreManager.game.updatePlayerTracker(reset: true)
}
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6579789

Please sign in to comment.