@firestone-hs/simulate-bgs-battle 1.1.765 → 1.1.767
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/board-entity.d.ts +1 -0
- package/dist/board-entity.js.map +1 -1
- package/dist/cards/card.interface.d.ts +7 -3
- package/dist/cards/card.interface.js +4 -2
- package/dist/cards/card.interface.js.map +1 -1
- package/dist/cards/impl/_card-mappings.js +6 -0
- package/dist/cards/impl/_card-mappings.js.map +1 -1
- package/dist/cards/impl/bg-spell/boon-of-beetles.js +3 -2
- package/dist/cards/impl/bg-spell/boon-of-beetles.js.map +1 -1
- package/dist/cards/impl/enchantments/booming.d.ts +2 -0
- package/dist/cards/impl/enchantments/booming.js +44 -0
- package/dist/cards/impl/enchantments/booming.js.map +1 -0
- package/dist/cards/impl/enchantments/golemancy.js +1 -1
- package/dist/cards/impl/enchantments/golemancy.js.map +1 -1
- package/dist/cards/impl/enchantments/set-sail.d.ts +2 -0
- package/dist/cards/impl/enchantments/set-sail.js +39 -0
- package/dist/cards/impl/enchantments/set-sail.js.map +1 -0
- package/dist/cards/impl/enchantments/spell-siphon.js +5 -7
- package/dist/cards/impl/enchantments/spell-siphon.js.map +1 -1
- package/dist/cards/impl/hero-power/mechgyver.d.ts +2 -0
- package/dist/cards/impl/hero-power/mechgyver.js +27 -0
- package/dist/cards/impl/hero-power/mechgyver.js.map +1 -0
- package/dist/cards/impl/minion/cthun.js.map +1 -1
- package/dist/cards/impl/minion/diremuck-forager.js +4 -1
- package/dist/cards/impl/minion/diremuck-forager.js.map +1 -1
- package/dist/cards/impl/minion/expert-aviator.js +3 -1
- package/dist/cards/impl/minion/expert-aviator.js.map +1 -1
- package/dist/cards/impl/minion/faceless-converter.d.ts +2 -2
- package/dist/cards/impl/minion/faceless-converter.js +38 -5
- package/dist/cards/impl/minion/faceless-converter.js.map +1 -1
- package/dist/cards/impl/minion/hopebringer.js +10 -6
- package/dist/cards/impl/minion/hopebringer.js.map +1 -1
- package/dist/cards/impl/minion/jailbird-juggernaut.js +7 -14
- package/dist/cards/impl/minion/jailbird-juggernaut.js.map +1 -1
- package/dist/cards/impl/minion/sinrunner-blanchy.d.ts +1 -1
- package/dist/cards/impl/minion/sinrunner-blanchy.js +3 -1
- package/dist/cards/impl/minion/sinrunner-blanchy.js.map +1 -1
- package/dist/cards/impl/minion/wildfire-elemental.js +1 -1
- package/dist/cards/impl/minion/wildfire-elemental.js.map +1 -1
- package/dist/cards/impl/minion/yshaarj.js +6 -4
- package/dist/cards/impl/minion/yshaarj.js.map +1 -1
- package/dist/cards/impl/trinket/artisanal-urn.js +3 -2
- package/dist/cards/impl/trinket/artisanal-urn.js.map +1 -1
- package/dist/cards/impl/trinket/blood-golem-sticker.d.ts +2 -2
- package/dist/cards/impl/trinket/blood-golem-sticker.js +2 -2
- package/dist/cards/impl/trinket/blood-golem-sticker.js.map +1 -1
- package/dist/cards/impl/trinket/miniature-ship.js +21 -1
- package/dist/cards/impl/trinket/miniature-ship.js.map +1 -1
- package/dist/cards/impl/trinket/soul-fermenter.js +4 -1
- package/dist/cards/impl/trinket/soul-fermenter.js.map +1 -1
- package/dist/input-clone.js +8 -2
- package/dist/input-clone.js.map +1 -1
- package/dist/mechanics/tavern-spell-repeat.js +4 -4
- package/dist/mechanics/tavern-spell-repeat.js.map +1 -1
- package/dist/simulation/add-minion-to-board.js +5 -2
- package/dist/simulation/add-minion-to-board.js.map +1 -1
- package/dist/simulation/attack.js +8 -1
- package/dist/simulation/attack.js.map +1 -1
- package/dist/simulation/auras.js +8 -5
- package/dist/simulation/auras.js.map +1 -1
- package/dist/simulation/death-effects.js +21 -4
- package/dist/simulation/death-effects.js.map +1 -1
- package/dist/simulation/deathrattle-effects.js +8 -1
- package/dist/simulation/deathrattle-effects.js.map +1 -1
- package/dist/simulation/deathrattle-orchestration.js +2 -6
- package/dist/simulation/deathrattle-orchestration.js.map +1 -1
- package/dist/simulation/deathrattle-spawns.d.ts +3 -1
- package/dist/simulation/deathrattle-spawns.js +32 -2
- package/dist/simulation/deathrattle-spawns.js.map +1 -1
- package/dist/simulation/deity.d.ts +6 -1
- package/dist/simulation/deity.js +23 -13
- package/dist/simulation/deity.js.map +1 -1
- package/dist/simulation/reborn.d.ts +10 -0
- package/dist/simulation/reborn.js +75 -8
- package/dist/simulation/reborn.js.map +1 -1
- package/dist/simulation/shared-state.d.ts +1 -0
- package/dist/simulation/shared-state.js +1 -0
- package/dist/simulation/shared-state.js.map +1 -1
- package/dist/simulation/start-of-combat/soc-illidan-hero-power.js +5 -2
- package/dist/simulation/start-of-combat/soc-illidan-hero-power.js.map +1 -1
- package/dist/simulation/start-of-combat/soc-minion.js +1 -1
- package/dist/simulation/start-of-combat/soc-minion.js.map +1 -1
- package/dist/simulation/start-of-combat/soc-trinket.js +35 -17
- package/dist/simulation/start-of-combat/soc-trinket.js.map +1 -1
- package/dist/simulation/start-of-combat/start-of-combat.js.map +1 -1
- package/dist/simulation/stats.js +8 -6
- package/dist/simulation/stats.js.map +1 -1
- package/dist/simulation/summon-when-space.js +13 -1
- package/dist/simulation/summon-when-space.js.map +1 -1
- package/package.json +10 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deity.js","sourceRoot":"","sources":["../../src/simulation/deity.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Deity / BG_OldGod secret.\r\n * After 3 friendly Aberrations die each combat, awaken C'Thun or Y'Shaarj with stored stats.\r\n * scriptDataNum1 = deaths remaining, tags BACON_OLD_GOD_ATTACK/HEALTH = atk/hp, scriptDataNum6 = deity dbfId.\r\n */\r\nimport { AllCardsService, GameTag, Race } from '@firestone-hs/reference-data';\r\nimport { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { BoardSecret } from '../board-secret';\r\nimport { hasOnAwaken } from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { getPlayerState, hasCorrectTribe, hasEntityMechanic, hasMechanic } from '../utils';\r\nimport { spawnEntities } from './deathrattle-spawns';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { modifyStats } from './stats';\r\n\r\nconst numberOfFriendlyAberrationsToAwakenDeity = 4;\r\n\r\nexport const isDeityCard = (cardId: string, allCards: AllCardsService): boolean => {\r\n\treturn hasMechanic(allCards.getCard(cardId), GameTag.BACON_OLD_GOD);\r\n};\r\n\r\nexport const isAberration = (entity: BoardEntity, hero: BgsPlayerEntity, gameState: FullGameState): boolean => {\r\n\treturn hasCorrectTribe(entity, hero, Race.ABERRATION, gameState.anomalies, gameState.allCards);\r\n};\r\n\r\nexport const getDeitySecret = (hero: BgsPlayerEntity): BoardSecret | undefined => {\r\n\treturn hero.secrets?.find((s) => s.cardId === CardIds.SecretDeityDnt_BG_OldGod);\r\n};\r\n\r\nexport const getOnBoardDeity = (board: BoardEntity[], allCards: AllCardsService): BoardEntity | undefined => {\r\n\treturn board.find(\r\n\t\t(e) => hasEntityMechanic(e, GameTag.BACON_OLD_GOD, allCards) && e.health > 0 && !e.definitelyDead,\r\n\t);\r\n};\r\n\r\nconst awakeningSecrets = new WeakSet<BoardSecret>();\r\n/** Entities whose attack/health were just set to the stored aura. The next aura pass must not add them again. */\r\nconst deityBaseStatsAssigned = new WeakSet<BoardEntity>();\r\n\r\nconst readSecretAttack = (secret: BoardSecret): number => {\r\n\treturn secret.tags?.[GameTag.BACON_OLD_GOD_ATTACK] ?? secret.scriptDataNum2 ?? 1;\r\n};\r\n\r\nconst readSecretHealth = (secret: BoardSecret): number => {\r\n\treturn secret.tags?.[GameTag.BACON_OLD_GOD_HEALTH] ?? secret.scriptDataNum3 ?? 1;\r\n};\r\n\r\nconst writeSecretStats = (secret: BoardSecret, attack: number, health: number): void => {\r\n\tsecret.scriptDataNum2 = attack;\r\n\tsecret.scriptDataNum3 = health;\r\n\tsecret.tags = secret.tags ?? {};\r\n\tsecret.tags[GameTag.BACON_OLD_GOD_ATTACK] = attack;\r\n\tsecret.tags[GameTag.BACON_OLD_GOD_HEALTH] = health;\r\n};\r\n\r\nexport const getDeityBaseStats = (hero: BgsPlayerEntity, entity?: BoardEntity): { attack: number; health: number } => {\r\n\tconst secret = getDeitySecret(hero);\r\n\tconst attack =\r\n\t\tsecret?.tags?.[GameTag.BACON_OLD_GOD_ATTACK] ??\r\n\t\tentity?.tags?.[GameTag.BACON_OLD_GOD_ATTACK] ??\r\n\t\tsecret?.scriptDataNum2 ??\r\n\t\t1;\r\n\tconst health = Math.max(\r\n\t\t1,\r\n\t\tsecret?.tags?.[GameTag.BACON_OLD_GOD_HEALTH] ??\r\n\t\t\tentity?.tags?.[GameTag.BACON_OLD_GOD_HEALTH] ??\r\n\t\t\tsecret?.scriptDataNum3 ??\r\n\t\t\t1,\r\n\t);\r\n\treturn { attack, health };\r\n};\r\n\r\n/** Aura captured when this minion was summoned. Later secret growth is a separate buff. */\r\nexport const getDeityAuraSnapshot = (\r\n\tentity: BoardEntity,\r\n\thero: BgsPlayerEntity,\r\n): { attack: number; health: number } => {\r\n\tconst attack = entity.tags?.[GameTag.BACON_OLD_GOD_ATTACK];\r\n\tconst health = entity.tags?.[GameTag.BACON_OLD_GOD_HEALTH];\r\n\tif (attack != null && health != null) {\r\n\t\treturn { attack, health: Math.max(1, health) };\r\n\t}\r\n\treturn getDeityBaseStats(hero, entity);\r\n};\r\n\r\n/** Freeze the current secret onto a deity that is already in play, before combat buffs change it. */\r\nexport const stampOnBoardDeityAuras = (\r\n\tboard: BoardEntity[],\r\n\thero: BgsPlayerEntity,\r\n\tallCards: AllCardsService,\r\n): void => {\r\n\tfor (const entity of board) {\r\n\t\tif (!isDeityCard(entity.cardId, allCards)) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (\r\n\t\t\tentity.tags?.[GameTag.BACON_OLD_GOD_ATTACK] != null &&\r\n\t\t\tentity.tags?.[GameTag.BACON_OLD_GOD_HEALTH] != null\r\n\t\t) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst { attack, health } = getDeityBaseStats(hero, entity);\r\n\t\tentity.tags = entity.tags ?? {};\r\n\t\tentity.tags[GameTag.BACON_OLD_GOD_ATTACK] = attack;\r\n\t\tentity.tags[GameTag.BACON_OLD_GOD_HEALTH] = health;\r\n\t}\r\n};\r\n\r\nexport const applyDeityBaseStats = (entity: BoardEntity, hero: BgsPlayerEntity): void => {\r\n\tconst { attack, health } = getDeityBaseStats(hero, entity);\r\n\tentity.attack = attack;\r\n\tentity.maxAttack = attack;\r\n\tentity.health = health;\r\n\tentity.maxHealth = health;\r\n\tentity.tags = entity.tags ?? {};\r\n\tentity.tags[GameTag.BACON_OLD_GOD_ATTACK] = attack;\r\n\tentity.tags[GameTag.BACON_OLD_GOD_HEALTH] = health;\r\n\tdeityBaseStatsAssigned.add(entity);\r\n};\r\n\r\n/** True once, for the aura pass that follows a fresh stat assignment (awaken, reborn). */\r\nexport const consumeDeityBaseStatsAssignment = (entity: BoardEntity): boolean => {\r\n\tif (!deityBaseStatsAssigned.has(entity)) {\r\n\t\treturn false;\r\n\t}\r\n\tdeityBaseStatsAssigned.delete(entity);\r\n\treturn true;\r\n};\r\n\r\nexport const buffYourDeity = (\r\n\thero: BgsPlayerEntity,\r\n\tboard: BoardEntity[],\r\n\tsource: BoardEntity | BoardSecret | BgsPlayerEntity,\r\n\tattack: number,\r\n\thealth: number,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst onBoard = getOnBoardDeity(board, gameState.allCards);\r\n\tif (onBoard) {\r\n\t\tmodifyStats(onBoard, source as BoardEntity, attack, health, board, hero, gameState);\r\n\t}\r\n\tincrementDeitySecretStats(hero, attack, health);\r\n};\r\n\r\nexport const incrementDeitySecretStats = (hero: BgsPlayerEntity, attack: number, health: number): void => {\r\n\tconst secret = getDeitySecret(hero);\r\n\tif (secret) {\r\n\t\twriteSecretStats(secret, readSecretAttack(secret) + attack, readSecretHealth(secret) + health);\r\n\t}\r\n};\r\n\r\nexport const buffTeamDeities = (\r\n\thero: BgsPlayerEntity,\r\n\tboard: BoardEntity[],\r\n\tsource: BoardEntity,\r\n\tattack: number,\r\n\thealth: number,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tbuffYourDeity(hero, board, source, attack, health, gameState);\r\n\tconst playerState = getPlayerState(gameState.gameState, hero);\r\n\tconst teammate = playerState?.teammate;\r\n\tif (teammate?.player) {\r\n\t\tbuffYourDeity(teammate.player, teammate.board ?? [], source, attack, health, gameState);\r\n\t}\r\n};\r\n\r\nconst resolveDeityCardId = (secret: BoardSecret, gameState: FullGameState): string => {\r\n\tconst dbfId = secret.scriptDataNum6 ?? secret.tags?.[GameTag.BACON_GLOBAL_OLD_GOD_DBID];\r\n\tif (dbfId) {\r\n\t\tconst fromDbf = gameState.allCards.getCardFromDbfId(dbfId);\r\n\t\tif (fromDbf?.id) {\r\n\t\t\treturn fromDbf.id;\r\n\t\t}\r\n\t}\r\n\treturn CardIds.Cthun_BGFYM_000;\r\n};\r\n\r\nexport const onFriendlyAberrationDied = (\r\n\tdeadEntity: BoardEntity,\r\n\t_deadEntityIndexFromRight: number,\r\n\tboard: BoardEntity[],\r\n\thero: BgsPlayerEntity,\r\n\totherBoard: BoardEntity[],\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): BoardEntity[] => {\r\n\tif (!isAberration(deadEntity, hero, gameState)) {\r\n\t\treturn [];\r\n\t}\r\n\t// 2026-09-22: This seems to be an HS bug, but for now the deity doesn't spawn when facing the ghost\r\n\t// Looks like this is an intermittent bug\r\n\t// if (hero.hpLeft <= 0 || hero.cardId === CardIds.Kelthuzad_TB_BaconShop_HERO_KelThuzad) {\r\n\t// \treturn [];\r\n\t// }\r\n\tconst secret = getDeitySecret(hero);\r\n\tif (!secret || secret.triggered || awakeningSecrets.has(secret)) {\r\n\t\treturn [];\r\n\t}\r\n\tconst remaining = (secret.scriptDataNum1 || numberOfFriendlyAberrationsToAwakenDeity) - 1;\r\n\tsecret.scriptDataNum1 = remaining;\r\n\tif (remaining > 0) {\r\n\t\treturn [];\r\n\t}\r\n\t// A full board skips this awaken. The next friendly Aberration death tries again.\r\n\tif (board.length >= 7) {\r\n\t\tretryDeityAwakenOnNextAberrationDeath(hero);\r\n\t\treturn [];\r\n\t}\r\n\t// Keep the secret visible in the replay until the summon action is recorded.\r\n\tawakeningSecrets.add(secret);\r\n\tconst cardId = resolveDeityCardId(secret, gameState);\r\n\tconst spawns = spawnEntities(\r\n\t\tcardId,\r\n\t\t1,\r\n\t\tboard,\r\n\t\thero,\r\n\t\totherBoard,\r\n\t\totherHero,\r\n\t\tgameState,\r\n\t\tdeadEntity.friendly,\r\n\t\tfalse,\r\n\t\tfalse,\r\n\t\ttrue,\r\n\t);\r\n\tfor (const spawn of spawns) {\r\n\t\tapplyDeityBaseStats(spawn, hero);\r\n\t\tif (hero.trinkets?.some((t) => t.cardId === CardIds.EvilExperiment_BG36_MagicItem_416)) {\r\n\t\t\tspawn.reborn = true;\r\n\t\t}\r\n\t}\r\n\tif (spawns[0]) {\r\n\t\tgameState.spectator.registerPowerTarget(secret, spawns[0], board, hero, otherHero);\r\n\t}\r\n\tfor (const spawn of spawns) {\r\n\t\tconst impl = cardMappings[spawn.cardId];\r\n\t\tif (hasOnAwaken(impl)) {\r\n\t\t\timpl.onAwaken(spawn, {\r\n\t\t\t\thero,\r\n\t\t\t\tboard,\r\n\t\t\t\totherHero,\r\n\t\t\t\totherBoard,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tif (!spawns.length) {\r\n\t\tsecret.triggered = true;\r\n\t}\r\n\treturn [...spawns];\r\n};\r\n\r\nexport const markDeitySecretTriggered = (hero: BgsPlayerEntity): void => {\r\n\tconst secret = getDeitySecret(hero);\r\n\tif (secret) {\r\n\t\tsecret.triggered = true;\r\n\t}\r\n};\r\n\r\n/** Board was full, so this awaken did not happen. The next Aberration death starts the summon again. */\r\nexport const retryDeityAwakenOnNextAberrationDeath = (hero: BgsPlayerEntity): void => {\r\n\tconst secret = getDeitySecret(hero);\r\n\tif (!secret) {\r\n\t\treturn;\r\n\t}\r\n\tawakeningSecrets.delete(secret);\r\n\tsecret.triggered = false;\r\n\tsecret.scriptDataNum1 = 1;\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"deity.js","sourceRoot":"","sources":["../../src/simulation/deity.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Deity / BG_OldGod secret.\r\n * After 3 friendly Aberrations die each combat, awaken C'Thun or Y'Shaarj with stored stats.\r\n * scriptDataNum1 = deaths remaining, tags BACON_OLD_GOD_ATTACK/HEALTH = atk/hp, scriptDataNum6 = deity dbfId.\r\n */\r\nimport { AllCardsService, GameTag, Race } from '@firestone-hs/reference-data';\r\nimport { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { BoardSecret } from '../board-secret';\r\nimport { hasOnAwaken } from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { getPlayerState, hasCorrectTribe, hasEntityMechanic, hasMechanic } from '../utils';\r\nimport { spawnEntities } from './deathrattle-spawns';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { modifyStats } from './stats';\r\n\r\nconst numberOfFriendlyAberrationsToAwakenDeity = 4;\r\n\r\nexport const isDeityCard = (cardId: string, allCards: AllCardsService): boolean => {\r\n\treturn hasMechanic(allCards.getCard(cardId), GameTag.BACON_OLD_GOD);\r\n};\r\n\r\nexport const isAberration = (entity: BoardEntity, hero: BgsPlayerEntity, gameState: FullGameState): boolean => {\r\n\treturn hasCorrectTribe(entity, hero, Race.ABERRATION, gameState.anomalies, gameState.allCards);\r\n};\r\n\r\nexport const getDeitySecret = (hero: BgsPlayerEntity): BoardSecret | undefined => {\r\n\treturn hero.secrets?.find((s) => s.cardId === CardIds.SecretDeityDnt_BG_OldGod);\r\n};\r\n\r\nexport const getOnBoardDeity = (board: BoardEntity[], allCards: AllCardsService): BoardEntity | undefined => {\r\n\treturn board.find(\r\n\t\t(e) => hasEntityMechanic(e, GameTag.BACON_OLD_GOD, allCards) && e.health > 0 && !e.definitelyDead,\r\n\t);\r\n};\r\n\r\nconst awakeningSecrets = new WeakSet<BoardSecret>();\r\n/** Entities whose attack/health were just set to the stored aura. The next aura pass must not add them again. */\r\nconst deityBaseStatsAssigned = new WeakSet<BoardEntity>();\r\n\r\nconst readSecretAttack = (secret: BoardSecret): number => {\r\n\treturn secret.tags?.[GameTag.BACON_OLD_GOD_ATTACK] ?? secret.scriptDataNum2 ?? 1;\r\n};\r\n\r\nconst readSecretHealth = (secret: BoardSecret): number => {\r\n\treturn secret.tags?.[GameTag.BACON_OLD_GOD_HEALTH] ?? secret.scriptDataNum3 ?? 1;\r\n};\r\n\r\nconst writeSecretStats = (secret: BoardSecret, attack: number, health: number): void => {\r\n\tsecret.scriptDataNum2 = attack;\r\n\tsecret.scriptDataNum3 = health;\r\n\tsecret.tags = secret.tags ?? {};\r\n\tsecret.tags[GameTag.BACON_OLD_GOD_ATTACK] = attack;\r\n\tsecret.tags[GameTag.BACON_OLD_GOD_HEALTH] = health;\r\n};\r\n\r\nexport const getDeityBaseStats = (hero: BgsPlayerEntity, entity?: BoardEntity): { attack: number; health: number } => {\r\n\tconst secret = getDeitySecret(hero);\r\n\tconst attack =\r\n\t\tsecret?.tags?.[GameTag.BACON_OLD_GOD_ATTACK] ??\r\n\t\tentity?.tags?.[GameTag.BACON_OLD_GOD_ATTACK] ??\r\n\t\tsecret?.scriptDataNum2 ??\r\n\t\t1;\r\n\tconst health = Math.max(\r\n\t\t1,\r\n\t\tsecret?.tags?.[GameTag.BACON_OLD_GOD_HEALTH] ??\r\n\t\t\tentity?.tags?.[GameTag.BACON_OLD_GOD_HEALTH] ??\r\n\t\t\tsecret?.scriptDataNum3 ??\r\n\t\t\t1,\r\n\t);\r\n\treturn { attack, health };\r\n};\r\n\r\n/** Aura captured when this minion was summoned. Later secret growth is a separate buff. */\r\nexport const getDeityAuraSnapshot = (\r\n\tentity: BoardEntity,\r\n\thero: BgsPlayerEntity,\r\n): { attack: number; health: number } => {\r\n\tconst attack = entity.tags?.[GameTag.BACON_OLD_GOD_ATTACK];\r\n\tconst health = entity.tags?.[GameTag.BACON_OLD_GOD_HEALTH];\r\n\tif (attack != null && health != null) {\r\n\t\treturn { attack, health: Math.max(1, health) };\r\n\t}\r\n\treturn getDeityBaseStats(hero, entity);\r\n};\r\n\r\n/** Freeze the current secret onto a deity that is already in play, before combat buffs change it. */\r\nexport const stampOnBoardDeityAuras = (\r\n\tboard: BoardEntity[],\r\n\thero: BgsPlayerEntity,\r\n\tallCards: AllCardsService,\r\n): void => {\r\n\tfor (const entity of board) {\r\n\t\tif (!isDeityCard(entity.cardId, allCards)) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (\r\n\t\t\tentity.tags?.[GameTag.BACON_OLD_GOD_ATTACK] != null &&\r\n\t\t\tentity.tags?.[GameTag.BACON_OLD_GOD_HEALTH] != null\r\n\t\t) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst { attack, health } = getDeityBaseStats(hero, entity);\r\n\t\tentity.tags = entity.tags ?? {};\r\n\t\tentity.tags[GameTag.BACON_OLD_GOD_ATTACK] = attack;\r\n\t\tentity.tags[GameTag.BACON_OLD_GOD_HEALTH] = health;\r\n\t}\r\n};\r\n\r\n/**\r\n * The deity enchantment stores (secret - printed) and the body it is added to is 1/1.\r\n * A 1/1 deity therefore awakens at the stored total. A 2/2 golden awakens one stat lower.\r\n * Tags keep the stored total so a later aura snapshot does not shrink the secret again.\r\n */\r\nexport const deityBodyStats = (\r\n\tstoredAttack: number,\r\n\tstoredHealth: number,\r\n\tprintedAttack: number,\r\n\tprintedHealth: number,\r\n): { attack: number; health: number } => ({\r\n\tattack: Math.max(0, storedAttack - Math.max(0, printedAttack - 1)),\r\n\thealth: Math.max(1, storedHealth - Math.max(0, printedHealth - 1)),\r\n});\r\n\r\nexport const applyDeityBaseStats = (\r\n\tentity: BoardEntity,\r\n\thero: BgsPlayerEntity,\r\n\tprintedAttack = 1,\r\n\tprintedHealth = 1,\r\n): void => {\r\n\tconst stored = getDeityBaseStats(hero, entity);\r\n\tconst { attack, health } = deityBodyStats(stored.attack, stored.health, printedAttack, printedHealth);\r\n\tentity.attack = attack;\r\n\tentity.maxAttack = attack;\r\n\tentity.health = health;\r\n\tentity.maxHealth = health;\r\n\tentity.tags = entity.tags ?? {};\r\n\tentity.tags[GameTag.BACON_OLD_GOD_ATTACK] = stored.attack;\r\n\tentity.tags[GameTag.BACON_OLD_GOD_HEALTH] = stored.health;\r\n\tdeityBaseStatsAssigned.add(entity);\r\n};\r\n\r\n/** True once, for the aura pass that follows a fresh stat assignment (awaken, reborn). */\r\nexport const consumeDeityBaseStatsAssignment = (entity: BoardEntity): boolean => {\r\n\tif (!deityBaseStatsAssigned.has(entity)) {\r\n\t\treturn false;\r\n\t}\r\n\tdeityBaseStatsAssigned.delete(entity);\r\n\treturn true;\r\n};\r\n\r\nexport const buffYourDeity = (\r\n\thero: BgsPlayerEntity,\r\n\tboard: BoardEntity[],\r\n\tsource: BoardEntity | BoardSecret | BgsPlayerEntity,\r\n\tattack: number,\r\n\thealth: number,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst onBoard = getOnBoardDeity(board, gameState.allCards);\r\n\tif (onBoard) {\r\n\t\tmodifyStats(onBoard, source as BoardEntity, attack, health, board, hero, gameState);\r\n\t}\r\n\tincrementDeitySecretStats(hero, attack, health);\r\n};\r\n\r\nexport const incrementDeitySecretStats = (hero: BgsPlayerEntity, attack: number, health: number): void => {\r\n\tconst secret = getDeitySecret(hero);\r\n\tif (secret) {\r\n\t\twriteSecretStats(secret, readSecretAttack(secret) + attack, readSecretHealth(secret) + health);\r\n\t}\r\n};\r\n\r\nexport const buffTeamDeities = (\r\n\thero: BgsPlayerEntity,\r\n\tboard: BoardEntity[],\r\n\tsource: BoardEntity,\r\n\tattack: number,\r\n\thealth: number,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tbuffYourDeity(hero, board, source, attack, health, gameState);\r\n\tconst playerState = getPlayerState(gameState.gameState, hero);\r\n\tconst teammate = playerState?.teammate;\r\n\tif (teammate?.player) {\r\n\t\tbuffYourDeity(teammate.player, teammate.board ?? [], source, attack, health, gameState);\r\n\t}\r\n};\r\n\r\nconst resolveDeityCardId = (secret: BoardSecret, gameState: FullGameState): string => {\r\n\tconst dbfId = secret.scriptDataNum6 ?? secret.tags?.[GameTag.BACON_GLOBAL_OLD_GOD_DBID];\r\n\tif (dbfId) {\r\n\t\tconst fromDbf = gameState.allCards.getCardFromDbfId(dbfId);\r\n\t\tif (fromDbf?.id) {\r\n\t\t\treturn fromDbf.id;\r\n\t\t}\r\n\t}\r\n\treturn CardIds.Cthun_BGFYM_000;\r\n};\r\n\r\nexport const onFriendlyAberrationDied = (\r\n\tdeadEntity: BoardEntity,\r\n\t_deadEntityIndexFromRight: number,\r\n\tboard: BoardEntity[],\r\n\thero: BgsPlayerEntity,\r\n\totherBoard: BoardEntity[],\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): BoardEntity[] => {\r\n\tif (!isAberration(deadEntity, hero, gameState)) {\r\n\t\treturn [];\r\n\t}\r\n\t// 2026-09-22: This seems to be an HS bug, but for now the deity doesn't spawn when facing the ghost\r\n\t// Looks like this is an intermittent bug\r\n\t// if (hero.hpLeft <= 0 || hero.cardId === CardIds.Kelthuzad_TB_BaconShop_HERO_KelThuzad) {\r\n\t// \treturn [];\r\n\t// }\r\n\tconst secret = getDeitySecret(hero);\r\n\tif (!secret || secret.triggered || awakeningSecrets.has(secret)) {\r\n\t\treturn [];\r\n\t}\r\n\tconst remaining = (secret.scriptDataNum1 || numberOfFriendlyAberrationsToAwakenDeity) - 1;\r\n\tsecret.scriptDataNum1 = remaining;\r\n\tif (remaining > 0) {\r\n\t\treturn [];\r\n\t}\r\n\t// A full board skips this awaken. The next friendly Aberration death tries again.\r\n\tif (board.length >= 7) {\r\n\t\tretryDeityAwakenOnNextAberrationDeath(hero);\r\n\t\treturn [];\r\n\t}\r\n\t// Keep the secret visible in the replay until the summon action is recorded.\r\n\tawakeningSecrets.add(secret);\r\n\tconst cardId = resolveDeityCardId(secret, gameState);\r\n\tconst spawns = spawnEntities(\r\n\t\tcardId,\r\n\t\t1,\r\n\t\tboard,\r\n\t\thero,\r\n\t\totherBoard,\r\n\t\totherHero,\r\n\t\tgameState,\r\n\t\tdeadEntity.friendly,\r\n\t\tfalse,\r\n\t\tfalse,\r\n\t\ttrue,\r\n\t);\r\n\tfor (const spawn of spawns) {\r\n\t\tconst card = gameState.allCards.getCard(spawn.cardId);\r\n\t\tapplyDeityBaseStats(spawn, hero, card?.attack ?? 1, card?.health ?? 1);\r\n\t\tif (hero.trinkets?.some((t) => t.cardId === CardIds.EvilExperiment_BG36_MagicItem_416)) {\r\n\t\t\tspawn.reborn = true;\r\n\t\t}\r\n\t}\r\n\tif (spawns[0]) {\r\n\t\tgameState.spectator.registerPowerTarget(secret, spawns[0], board, hero, otherHero);\r\n\t}\r\n\tif (!spawns.length) {\r\n\t\tsecret.triggered = true;\r\n\t}\r\n\treturn [...spawns];\r\n};\r\n\r\n/**\r\n * The awaken trigger fires after the summon is on the board. Auras such as Hammer of\r\n * Twilight are already in its stats, and C'Thun splits those in-play stats.\r\n */\r\nexport const triggerDeityAwaken = (\r\n\tspawns: readonly BoardEntity[],\r\n\thero: BgsPlayerEntity,\r\n\tboard: BoardEntity[],\r\n\totherHero: BgsPlayerEntity,\r\n\totherBoard: BoardEntity[],\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tfor (const spawn of spawns) {\r\n\t\tconst impl = cardMappings[spawn.cardId];\r\n\t\tif (hasOnAwaken(impl)) {\r\n\t\t\timpl.onAwaken(spawn, {\r\n\t\t\t\thero,\r\n\t\t\t\tboard,\r\n\t\t\t\totherHero,\r\n\t\t\t\totherBoard,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n};\r\n\r\nexport const markDeitySecretTriggered = (hero: BgsPlayerEntity): void => {\r\n\tconst secret = getDeitySecret(hero);\r\n\tif (secret) {\r\n\t\tsecret.triggered = true;\r\n\t}\r\n};\r\n\r\n/** Board was full, so this awaken did not happen. The next Aberration death starts the summon again. */\r\nexport const retryDeityAwakenOnNextAberrationDeath = (hero: BgsPlayerEntity): void => {\r\n\tconst secret = getDeitySecret(hero);\r\n\tif (!secret) {\r\n\t\treturn;\r\n\t}\r\n\tawakeningSecrets.delete(secret);\r\n\tsecret.triggered = false;\r\n\tsecret.scriptDataNum1 = 1;\r\n};\r\n"]}
|
|
@@ -2,6 +2,16 @@ import { BgsPlayerEntity } from '../bgs-player-entity';
|
|
|
2
2
|
import { BoardEntity } from '../board-entity';
|
|
3
3
|
import { FullGameState } from './internal-game-state';
|
|
4
4
|
export declare const handleRebornForEntity: (boardWithKilledMinion: BoardEntity[], boardWithKilledMinionHero: BgsPlayerEntity, deadEntity: BoardEntity, deadMinionIndexFromRight: number, opponentBoard: BoardEntity[], opponentBoardHero: BgsPlayerEntity, gameState: FullGameState) => void;
|
|
5
|
+
export declare const applyBeforeRebornEffects: (gameState: FullGameState, playerDeadEntities: readonly BoardEntity[], playerDeadEntityIndexesFromRight: readonly number[], opponentDeadEntities: readonly BoardEntity[], opponentDeadEntityIndexesFromRight: readonly number[]) => void;
|
|
6
|
+
export interface BeforeRebornInput {
|
|
7
|
+
readonly hero: BgsPlayerEntity;
|
|
8
|
+
readonly board: BoardEntity[];
|
|
9
|
+
readonly otherHero: BgsPlayerEntity;
|
|
10
|
+
readonly otherBoard: BoardEntity[];
|
|
11
|
+
readonly deadEntities: readonly BoardEntity[];
|
|
12
|
+
readonly deadEntitiesIndexesFromRight: readonly number[];
|
|
13
|
+
readonly gameState: FullGameState;
|
|
14
|
+
}
|
|
5
15
|
export interface RebornEffectInput {
|
|
6
16
|
readonly rebornEntity: BoardEntity;
|
|
7
17
|
readonly boardWithKilledMinion: BoardEntity[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleRebornForEntity = void 0;
|
|
3
|
+
exports.applyBeforeRebornEffects = exports.handleRebornForEntity = void 0;
|
|
4
4
|
const card_interface_1 = require("../cards/card.interface");
|
|
5
5
|
const _card_mappings_1 = require("../cards/impl/_card-mappings");
|
|
6
6
|
const persisting_horror_1 = require("../cards/impl/enchantments/persisting-horror");
|
|
@@ -11,13 +11,12 @@ const deity_1 = require("./deity");
|
|
|
11
11
|
const spawns_1 = require("./spawns");
|
|
12
12
|
const entity_utils_1 = require("./utils/entity-utils");
|
|
13
13
|
const handleRebornForEntity = (boardWithKilledMinion, boardWithKilledMinionHero, deadEntity, deadMinionIndexFromRight, opponentBoard, opponentBoardHero, gameState) => {
|
|
14
|
-
var _a, _b;
|
|
14
|
+
var _a, _b, _c, _d;
|
|
15
15
|
const numberOfReborns = 1;
|
|
16
16
|
let entityToSpawn = null;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
entityToSpawn = (0, sinrunner_blanchy_1.buildSinrunnerBlanchyRebornEntity)(deadEntity);
|
|
17
|
+
const keepEnchantments = !!((_a = deadEntity.enchantments) === null || _a === void 0 ? void 0 : _a.some((e) => e.cardId === "BG31_HERO_801ptje"));
|
|
18
|
+
if ((0, sinrunner_blanchy_1.isSinrunnerBlanchy)(deadEntity.cardId) || (0, persisting_horror_1.hasPersistingHorror)(deadEntity) || keepEnchantments) {
|
|
19
|
+
entityToSpawn = (0, sinrunner_blanchy_1.buildSinrunnerBlanchyRebornEntity)(deadEntity, keepEnchantments);
|
|
21
20
|
}
|
|
22
21
|
const rebornImpl = _card_mappings_1.cardMappings[deadEntity.cardId];
|
|
23
22
|
if ((0, card_interface_1.hasBeforeRebornSelfEffect)(rebornImpl)) {
|
|
@@ -38,7 +37,8 @@ const handleRebornForEntity = (boardWithKilledMinion, boardWithKilledMinionHero,
|
|
|
38
37
|
}
|
|
39
38
|
if ((0, deity_1.isDeityCard)(deadEntity.cardId, gameState.allCards)) {
|
|
40
39
|
for (const entity of entitiesFromReborn) {
|
|
41
|
-
|
|
40
|
+
const card = gameState.allCards.getCard(entity.cardId);
|
|
41
|
+
(0, deity_1.applyDeityBaseStats)(entity, boardWithKilledMinionHero, (_b = card === null || card === void 0 ? void 0 : card.attack) !== null && _b !== void 0 ? _b : 1, (_c = card === null || card === void 0 ? void 0 : card.health) !== null && _c !== void 0 ? _c : 1);
|
|
42
42
|
entity.health = 1;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -108,7 +108,7 @@ const handleRebornForEntity = (boardWithKilledMinion, boardWithKilledMinionHero,
|
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
for (const trinket of (
|
|
111
|
+
for (const trinket of (_d = boardWithKilledMinionHero.trinkets) !== null && _d !== void 0 ? _d : []) {
|
|
112
112
|
const rebornImpl = _card_mappings_1.cardMappings[trinket.cardId];
|
|
113
113
|
if ((0, card_interface_1.hasAfterReborn)(rebornImpl)) {
|
|
114
114
|
rebornImpl.afterReborn(trinket, {
|
|
@@ -134,4 +134,71 @@ const handleRebornForEntity = (boardWithKilledMinion, boardWithKilledMinionHero,
|
|
|
134
134
|
}
|
|
135
135
|
};
|
|
136
136
|
exports.handleRebornForEntity = handleRebornForEntity;
|
|
137
|
+
const applyBeforeRebornEffects = (gameState, playerDeadEntities, playerDeadEntityIndexesFromRight, opponentDeadEntities, opponentDeadEntityIndexesFromRight) => {
|
|
138
|
+
var _a;
|
|
139
|
+
const player = gameState.gameState.player;
|
|
140
|
+
const opponent = gameState.gameState.opponent;
|
|
141
|
+
const processPlayerFirst = Math.random() > 0.5;
|
|
142
|
+
const sides = processPlayerFirst
|
|
143
|
+
? [
|
|
144
|
+
{
|
|
145
|
+
hero: player.player,
|
|
146
|
+
board: player.board,
|
|
147
|
+
deadEntities: playerDeadEntities,
|
|
148
|
+
deadEntitiesIndexesFromRight: playerDeadEntityIndexesFromRight,
|
|
149
|
+
otherHero: opponent.player,
|
|
150
|
+
otherBoard: opponent.board,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
hero: opponent.player,
|
|
154
|
+
board: opponent.board,
|
|
155
|
+
deadEntities: opponentDeadEntities,
|
|
156
|
+
deadEntitiesIndexesFromRight: opponentDeadEntityIndexesFromRight,
|
|
157
|
+
otherHero: player.player,
|
|
158
|
+
otherBoard: player.board,
|
|
159
|
+
},
|
|
160
|
+
]
|
|
161
|
+
: [
|
|
162
|
+
{
|
|
163
|
+
hero: opponent.player,
|
|
164
|
+
board: opponent.board,
|
|
165
|
+
deadEntities: opponentDeadEntities,
|
|
166
|
+
deadEntitiesIndexesFromRight: opponentDeadEntityIndexesFromRight,
|
|
167
|
+
otherHero: player.player,
|
|
168
|
+
otherBoard: player.board,
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
hero: player.player,
|
|
172
|
+
board: player.board,
|
|
173
|
+
deadEntities: playerDeadEntities,
|
|
174
|
+
deadEntitiesIndexesFromRight: playerDeadEntityIndexesFromRight,
|
|
175
|
+
otherHero: opponent.player,
|
|
176
|
+
otherBoard: opponent.board,
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
for (const side of sides) {
|
|
180
|
+
const input = {
|
|
181
|
+
hero: side.hero,
|
|
182
|
+
board: side.board,
|
|
183
|
+
otherHero: side.otherHero,
|
|
184
|
+
otherBoard: side.otherBoard,
|
|
185
|
+
deadEntities: side.deadEntities,
|
|
186
|
+
deadEntitiesIndexesFromRight: side.deadEntitiesIndexesFromRight,
|
|
187
|
+
gameState,
|
|
188
|
+
};
|
|
189
|
+
for (const trinket of (_a = side.hero.trinkets) !== null && _a !== void 0 ? _a : []) {
|
|
190
|
+
const impl = _card_mappings_1.cardMappings[trinket.cardId];
|
|
191
|
+
if ((0, card_interface_1.hasBeforeReborn)(impl)) {
|
|
192
|
+
impl.beforeReborn(trinket, input);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for (const entity of [...side.board]) {
|
|
196
|
+
const impl = _card_mappings_1.cardMappings[entity.cardId];
|
|
197
|
+
if ((0, card_interface_1.hasBeforeReborn)(impl)) {
|
|
198
|
+
impl.beforeReborn(entity, input);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
exports.applyBeforeRebornEffects = applyBeforeRebornEffects;
|
|
137
204
|
//# sourceMappingURL=reborn.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reborn.js","sourceRoot":"","sources":["../../src/simulation/reborn.ts"],"names":[],"mappings":"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","sourcesContent":["import { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport {\r\n\thasAfterReborn,\r\n\thasBeforeRebornSelfEffect,\r\n\thasRebornEffect,\r\n\thasRebornSelfAttributeTransfer,\r\n\thasRebornSelfEffect,\r\n} from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { hasPersistingHorror } from '../cards/impl/enchantments/persisting-horror';\r\nimport { buildSinrunnerBlanchyRebornEntity, isSinrunnerBlanchy } from '../cards/impl/minion/sinrunner-blanchy';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { addStatsToBoard } from '../utils';\r\nimport { spawnEntities } from './deathrattle-spawns';\r\nimport { applyDeityBaseStats, isDeityCard } from './deity';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { performEntitySpawns } from './spawns';\r\nimport { copyAttribute } from './utils/entity-utils';\r\n\r\nexport const handleRebornForEntity = (\r\n\tboardWithKilledMinion: BoardEntity[],\r\n\tboardWithKilledMinionHero: BgsPlayerEntity,\r\n\tdeadEntity: BoardEntity,\r\n\tdeadMinionIndexFromRight: number,\r\n\topponentBoard: BoardEntity[],\r\n\topponentBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst numberOfReborns = 1;\r\n\tlet entityToSpawn: BoardEntity = null;\r\n\tif (\r\n\t\tisSinrunnerBlanchy(deadEntity.cardId) ||\r\n\t\thasPersistingHorror(deadEntity) ||\r\n\t\tdeadEntity.enchantments?.some(\r\n\t\t\t(e) => e.cardId === CardIds.UltraCapacitor_UltraCapacitorEnchantment_BG31_HERO_801ptje,\r\n\t\t)\r\n\t) {\r\n\t\tentityToSpawn = buildSinrunnerBlanchyRebornEntity(deadEntity);\r\n\t}\r\n\r\n\tconst rebornImpl = cardMappings[deadEntity.cardId];\r\n\tif (hasBeforeRebornSelfEffect(rebornImpl)) {\r\n\t\trebornImpl.beforeRebornSelfEffect(deadEntity, {\r\n\t\t\trebornEntity: deadEntity,\r\n\t\t\tboardWithKilledMinion,\r\n\t\t\tboardWithKilledMinionHero,\r\n\t\t\topponentBoard,\r\n\t\t\topponentBoardHero,\r\n\t\t\tgameState,\r\n\t\t});\r\n\t}\r\n\r\n\tconst entitiesFromReborn: readonly BoardEntity[] =\r\n\t\tdeadEntity.reborn && deadMinionIndexFromRight >= 0\r\n\t\t\t? spawnEntities(\r\n\t\t\t\t\tdeadEntity.cardId,\r\n\t\t\t\t\tnumberOfReborns,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t\tdeadEntity.friendly,\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\tentityToSpawn,\r\n\t\t\t\t\tdeadEntity,\r\n\t\t\t )\r\n\t\t\t: [];\r\n\tif (!entitiesFromReborn.length) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (isDeityCard(deadEntity.cardId, gameState.allCards)) {\r\n\t\tfor (const entity of entitiesFromReborn) {\r\n\t\t\tapplyDeityBaseStats(entity, boardWithKilledMinionHero);\r\n\t\t\tentity.health = 1;\r\n\t\t}\r\n\t}\r\n\r\n\tif (\r\n\t\tdeadEntity.cardId === CardIds.WannabeGargoyle_BG30_109 ||\r\n\t\tdeadEntity.cardId === CardIds.WannabeGargoyle_BG30_109_G\r\n\t) {\r\n\t\tentitiesFromReborn.forEach((e) => {\r\n\t\t\tconst attack = deadEntity.maxAttack;\r\n\t\t\tconst health = deadEntity.cardId === CardIds.WannabeGargoyle_BG30_109_G ? deadEntity.maxHealth : 1;\r\n\t\t\te.attack = attack;\r\n\t\t\te.health = health;\r\n\t\t});\r\n\t}\r\n\r\n\tfor (const entity of entitiesFromReborn) {\r\n\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\tif (hasRebornSelfAttributeTransfer(rebornImpl)) {\r\n\t\t\trebornImpl.rebornSelfAttributeTransfer.forEach((attribute: keyof BoardEntity) => {\r\n\t\t\t\tcopyAttribute(entity, deadEntity, attribute);\r\n\t\t\t});\r\n\t\t}\r\n\t\tif (hasRebornSelfEffect(rebornImpl)) {\r\n\t\t\trebornImpl.rebornSelfEffect(entity, {\r\n\t\t\t\trebornEntity: deadEntity,\r\n\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\topponentBoard,\r\n\t\t\t\topponentBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const entity of boardWithKilledMinion) {\r\n\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\tif (hasRebornEffect(rebornImpl)) {\r\n\t\t\trebornImpl.rebornEffect(entity, {\r\n\t\t\t\trebornEntity: deadEntity,\r\n\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\topponentBoard,\r\n\t\t\t\topponentBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tconst entitiesThatWereReborn = performEntitySpawns(\r\n\t\tentitiesFromReborn,\r\n\t\tboardWithKilledMinion,\r\n\t\tboardWithKilledMinionHero,\r\n\t\tdeadEntity,\r\n\t\tdeadMinionIndexFromRight,\r\n\t\topponentBoard,\r\n\t\topponentBoardHero,\r\n\t\tgameState,\r\n\t);\r\n\tentitiesThatWereReborn.forEach((e) => (e.rebornFromEntityId = deadEntity.entityId));\r\n\tconst entityRightToSpawns =\r\n\t\tdeadMinionIndexFromRight === 0\r\n\t\t\t? null\r\n\t\t\t: boardWithKilledMinion[boardWithKilledMinion.length - deadMinionIndexFromRight];\r\n\tentitiesThatWereReborn.forEach((entity) => {\r\n\t\tentity.hasAttacked = deadEntity.hasAttacked > 1 ? 1 : entityRightToSpawns?.hasAttacked ?? undefined;\r\n\t});\r\n\r\n\tfor (const rebornEntity of entitiesThatWereReborn) {\r\n\t\tfor (const entity of boardWithKilledMinion) {\r\n\t\t\t// The entity was not there when the minion died, so we don't trigger its effect\r\n\t\t\tif (entitiesThatWereReborn.includes(entity)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\t\tif (hasAfterReborn(rebornImpl)) {\r\n\t\t\t\trebornImpl.afterReborn(entity, {\r\n\t\t\t\t\trebornEntity: rebornEntity,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (const trinket of boardWithKilledMinionHero.trinkets ?? []) {\r\n\t\t\tconst rebornImpl = cardMappings[trinket.cardId];\r\n\t\t\tif (hasAfterReborn(rebornImpl)) {\r\n\t\t\t\trebornImpl.afterReborn(trinket, {\r\n\t\t\t\t\trebornEntity: rebornEntity,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconst numberOfTriggersForDeathwhisper = Math.min(entitiesThatWereReborn.length, 1);\r\n\tfor (let i = 0; i < numberOfTriggersForDeathwhisper; i++) {\r\n\t\tboardWithKilledMinion\r\n\t\t\t.filter(\r\n\t\t\t\t(e) =>\r\n\t\t\t\t\te.cardId === CardIds.SisterDeathwhisper_BG25_020 ||\r\n\t\t\t\t\te.cardId === CardIds.SisterDeathwhisper_BG25_020_G,\r\n\t\t\t)\r\n\t\t\t.forEach((e) => {\r\n\t\t\t\tconst multiplier = e.cardId === CardIds.SisterDeathwhisper_BG25_020_G ? 2 : 1;\r\n\t\t\t\taddStatsToBoard(\r\n\t\t\t\t\te,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\tmultiplier * 1,\r\n\t\t\t\t\tmultiplier * 3,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t}\r\n};\r\n\r\nexport interface RebornEffectInput {\r\n\treadonly rebornEntity: BoardEntity;\r\n\treadonly boardWithKilledMinion: BoardEntity[];\r\n\treadonly boardWithKilledMinionHero: BgsPlayerEntity;\r\n\treadonly opponentBoard: BoardEntity[];\r\n\treadonly opponentBoardHero: BgsPlayerEntity;\r\n\treadonly gameState: FullGameState;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"reborn.js","sourceRoot":"","sources":["../../src/simulation/reborn.ts"],"names":[],"mappings":";;;AAEA,4DAOiC;AACjC,iEAA4D;AAC5D,oFAAmF;AACnF,8EAA+G;AAE/G,oCAA2C;AAC3C,6DAAqD;AACrD,mCAA2D;AAE3D,qCAA+C;AAC/C,uDAAqD;AAE9C,MAAM,qBAAqB,GAAG,CACpC,qBAAoC,EACpC,yBAA0C,EAC1C,UAAuB,EACvB,wBAAgC,EAChC,aAA4B,EAC5B,iBAAkC,EAClC,SAAwB,EACjB,EAAE;;IACT,MAAM,eAAe,GAAG,CAAC,CAAC;IAC1B,IAAI,aAAa,GAAgB,IAAI,CAAC;IAEtC,MAAM,gBAAgB,GAAG,CAAC,CAAC,CAAA,MAAA,UAAU,CAAC,YAAY,0CAAE,IAAI,CACvD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,wBAAuE,CACtF,CAAA,CAAC;IACF,IAAI,IAAA,sCAAkB,EAAC,UAAU,CAAC,MAAM,CAAC,IAAI,IAAA,uCAAmB,EAAC,UAAU,CAAC,IAAI,gBAAgB,EAAE;QACjG,aAAa,GAAG,IAAA,qDAAiC,EAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;KAChF;IAED,MAAM,UAAU,GAAG,6BAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,IAAA,0CAAyB,EAAC,UAAU,CAAC,EAAE;QAC1C,UAAU,CAAC,sBAAsB,CAAC,UAAU,EAAE;YAC7C,YAAY,EAAE,UAAU;YACxB,qBAAqB;YACrB,yBAAyB;YACzB,aAAa;YACb,iBAAiB;YACjB,SAAS;SACT,CAAC,CAAC;KACH;IAED,MAAM,kBAAkB,GACvB,UAAU,CAAC,MAAM,IAAI,wBAAwB,IAAI,CAAC;QACjD,CAAC,CAAC,IAAA,kCAAa,EACb,UAAU,CAAC,MAAM,EACjB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,aAAa,EACb,iBAAiB,EACjB,SAAS,EACT,UAAU,CAAC,QAAQ,EACnB,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,UAAU,CACT;QACH,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE;QAC/B,OAAO;KACP;IAED,IAAI,IAAA,mBAAW,EAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE;QACvD,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE;YACxC,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACvD,IAAA,2BAAmB,EAAC,MAAM,EAAE,yBAAyB,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,mCAAI,CAAC,EAAE,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,mCAAI,CAAC,CAAC,CAAC;YAC7F,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;SAClB;KACD;IAED,IACC,UAAU,CAAC,MAAM,eAAqC;QACtD,UAAU,CAAC,MAAM,iBAAuC,EACvD;QACD,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YAChC,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC;YACpC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,iBAAuC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACnG,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC;YAClB,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC;QACnB,CAAC,CAAC,CAAC;KACH;IAED,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE;QACxC,MAAM,UAAU,GAAG,6BAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,IAAA,+CAA8B,EAAC,UAAU,CAAC,EAAE;YAC/C,UAAU,CAAC,2BAA2B,CAAC,OAAO,CAAC,CAAC,SAA4B,EAAE,EAAE;gBAC/E,IAAA,4BAAa,EAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;SACH;QACD,IAAI,IAAA,oCAAmB,EAAC,UAAU,CAAC,EAAE;YACpC,UAAU,CAAC,gBAAgB,CAAC,MAAM,EAAE;gBACnC,YAAY,EAAE,UAAU;gBACxB,qBAAqB;gBACrB,yBAAyB;gBACzB,aAAa;gBACb,iBAAiB;gBACjB,SAAS;aACT,CAAC,CAAC;SACH;KACD;IAED,KAAK,MAAM,MAAM,IAAI,qBAAqB,EAAE;QAC3C,MAAM,UAAU,GAAG,6BAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,IAAA,gCAAe,EAAC,UAAU,CAAC,EAAE;YAChC,UAAU,CAAC,YAAY,CAAC,MAAM,EAAE;gBAC/B,YAAY,EAAE,UAAU;gBACxB,qBAAqB;gBACrB,yBAAyB;gBACzB,aAAa;gBACb,iBAAiB;gBACjB,SAAS;aACT,CAAC,CAAC;SACH;KACD;IAED,MAAM,sBAAsB,GAAG,IAAA,4BAAmB,EACjD,kBAAkB,EAClB,qBAAqB,EACrB,yBAAyB,EACzB,UAAU,EACV,wBAAwB,EACxB,aAAa,EACb,iBAAiB,EACjB,SAAS,CACT,CAAC;IACF,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,kBAAkB,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpF,MAAM,mBAAmB,GACxB,wBAAwB,KAAK,CAAC;QAC7B,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,MAAM,GAAG,wBAAwB,CAAC,CAAC;IACnF,sBAAsB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;;QACzC,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAA,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,WAAW,mCAAI,SAAS,CAAC;IACrG,CAAC,CAAC,CAAC;IAEH,KAAK,MAAM,YAAY,IAAI,sBAAsB,EAAE;QAClD,KAAK,MAAM,MAAM,IAAI,qBAAqB,EAAE;YAE3C,IAAI,sBAAsB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBAC5C,SAAS;aACT;YACD,MAAM,UAAU,GAAG,6BAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC/C,IAAI,IAAA,+BAAc,EAAC,UAAU,CAAC,EAAE;gBAC/B,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE;oBAC9B,YAAY,EAAE,YAAY;oBAC1B,qBAAqB;oBACrB,yBAAyB;oBACzB,aAAa;oBACb,iBAAiB;oBACjB,SAAS;iBACT,CAAC,CAAC;aACH;SACD;QACD,KAAK,MAAM,OAAO,IAAI,MAAA,yBAAyB,CAAC,QAAQ,mCAAI,EAAE,EAAE;YAC/D,MAAM,UAAU,GAAG,6BAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAChD,IAAI,IAAA,+BAAc,EAAC,UAAU,CAAC,EAAE;gBAC/B,UAAU,CAAC,WAAW,CAAC,OAAO,EAAE;oBAC/B,YAAY,EAAE,YAAY;oBAC1B,qBAAqB;oBACrB,yBAAyB;oBACzB,aAAa;oBACb,iBAAiB;oBACjB,SAAS;iBACT,CAAC,CAAC;aACH;SACD;KACD;IAED,MAAM,+BAA+B,GAAG,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACnF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,+BAA+B,EAAE,CAAC,EAAE,EAAE;QACzD,qBAAqB;aACnB,MAAM,CACN,CAAC,CAAC,EAAE,EAAE,CACL,CAAC,CAAC,MAAM,eAAwC;YAChD,CAAC,CAAC,MAAM,iBAA0C,CACnD;aACA,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACd,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,iBAA0C,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9E,IAAA,uBAAe,EACd,CAAC,EACD,qBAAqB,EACrB,yBAAyB,EACzB,UAAU,GAAG,CAAC,EACd,UAAU,GAAG,CAAC,EACd,SAAS,CACT,CAAC;QACH,CAAC,CAAC,CAAC;KACJ;AACF,CAAC,CAAC;AAlLW,QAAA,qBAAqB,yBAkLhC;AAMK,MAAM,wBAAwB,GAAG,CACvC,SAAwB,EACxB,kBAA0C,EAC1C,gCAAmD,EACnD,oBAA4C,EAC5C,kCAAqD,EAC9C,EAAE;;IACT,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC;IAC1C,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC;IAC9C,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC;IAC/C,MAAM,KAAK,GAAG,kBAAkB;QAC/B,CAAC,CAAC;YACA;gBACC,IAAI,EAAE,MAAM,CAAC,MAAM;gBACnB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,YAAY,EAAE,kBAAkB;gBAChC,4BAA4B,EAAE,gCAAgC;gBAC9D,SAAS,EAAE,QAAQ,CAAC,MAAM;gBAC1B,UAAU,EAAE,QAAQ,CAAC,KAAK;aAC1B;YACD;gBACC,IAAI,EAAE,QAAQ,CAAC,MAAM;gBACrB,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,YAAY,EAAE,oBAAoB;gBAClC,4BAA4B,EAAE,kCAAkC;gBAChE,SAAS,EAAE,MAAM,CAAC,MAAM;gBACxB,UAAU,EAAE,MAAM,CAAC,KAAK;aACxB;SACA;QACH,CAAC,CAAC;YACA;gBACC,IAAI,EAAE,QAAQ,CAAC,MAAM;gBACrB,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,YAAY,EAAE,oBAAoB;gBAClC,4BAA4B,EAAE,kCAAkC;gBAChE,SAAS,EAAE,MAAM,CAAC,MAAM;gBACxB,UAAU,EAAE,MAAM,CAAC,KAAK;aACxB;YACD;gBACC,IAAI,EAAE,MAAM,CAAC,MAAM;gBACnB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,YAAY,EAAE,kBAAkB;gBAChC,4BAA4B,EAAE,gCAAgC;gBAC9D,SAAS,EAAE,QAAQ,CAAC,MAAM;gBAC1B,UAAU,EAAE,QAAQ,CAAC,KAAK;aAC1B;SACA,CAAC;IACL,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;QACzB,MAAM,KAAK,GAAsB;YAChC,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,4BAA4B,EAAE,IAAI,CAAC,4BAA4B;YAC/D,SAAS;SACT,CAAC;QACF,KAAK,MAAM,OAAO,IAAI,MAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,mCAAI,EAAE,EAAE;YAC/C,MAAM,IAAI,GAAG,6BAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,IAAA,gCAAe,EAAC,IAAI,CAAC,EAAE;gBAC1B,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;aAClC;SACD;QACD,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE;YACrC,MAAM,IAAI,GAAG,6BAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,IAAA,gCAAe,EAAC,IAAI,CAAC,EAAE;gBAC1B,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;aACjC;SACD;KACD;AACF,CAAC,CAAC;AAtEW,QAAA,wBAAwB,4BAsEnC","sourcesContent":["import { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport {\r\n\thasAfterReborn,\r\n\thasBeforeReborn,\r\n\thasBeforeRebornSelfEffect,\r\n\thasRebornEffect,\r\n\thasRebornSelfAttributeTransfer,\r\n\thasRebornSelfEffect,\r\n} from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { hasPersistingHorror } from '../cards/impl/enchantments/persisting-horror';\r\nimport { buildSinrunnerBlanchyRebornEntity, isSinrunnerBlanchy } from '../cards/impl/minion/sinrunner-blanchy';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { addStatsToBoard } from '../utils';\r\nimport { spawnEntities } from './deathrattle-spawns';\r\nimport { applyDeityBaseStats, isDeityCard } from './deity';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { performEntitySpawns } from './spawns';\r\nimport { copyAttribute } from './utils/entity-utils';\r\n\r\nexport const handleRebornForEntity = (\r\n\tboardWithKilledMinion: BoardEntity[],\r\n\tboardWithKilledMinionHero: BgsPlayerEntity,\r\n\tdeadEntity: BoardEntity,\r\n\tdeadMinionIndexFromRight: number,\r\n\topponentBoard: BoardEntity[],\r\n\topponentBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst numberOfReborns = 1;\r\n\tlet entityToSpawn: BoardEntity = null;\r\n\t// Ultra-Capacitor keeps enchantments. Blanchy and Persisting Horror keep bonus keywords only.\r\n\tconst keepEnchantments = !!deadEntity.enchantments?.some(\r\n\t\t(e) => e.cardId === CardIds.UltraCapacitor_UltraCapacitorEnchantment_BG31_HERO_801ptje,\r\n\t);\r\n\tif (isSinrunnerBlanchy(deadEntity.cardId) || hasPersistingHorror(deadEntity) || keepEnchantments) {\r\n\t\tentityToSpawn = buildSinrunnerBlanchyRebornEntity(deadEntity, keepEnchantments);\r\n\t}\r\n\r\n\tconst rebornImpl = cardMappings[deadEntity.cardId];\r\n\tif (hasBeforeRebornSelfEffect(rebornImpl)) {\r\n\t\trebornImpl.beforeRebornSelfEffect(deadEntity, {\r\n\t\t\trebornEntity: deadEntity,\r\n\t\t\tboardWithKilledMinion,\r\n\t\t\tboardWithKilledMinionHero,\r\n\t\t\topponentBoard,\r\n\t\t\topponentBoardHero,\r\n\t\t\tgameState,\r\n\t\t});\r\n\t}\r\n\r\n\tconst entitiesFromReborn: readonly BoardEntity[] =\r\n\t\tdeadEntity.reborn && deadMinionIndexFromRight >= 0\r\n\t\t\t? spawnEntities(\r\n\t\t\t\t\tdeadEntity.cardId,\r\n\t\t\t\t\tnumberOfReborns,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t\tdeadEntity.friendly,\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\tentityToSpawn,\r\n\t\t\t\t\tdeadEntity,\r\n\t\t\t )\r\n\t\t\t: [];\r\n\tif (!entitiesFromReborn.length) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (isDeityCard(deadEntity.cardId, gameState.allCards)) {\r\n\t\tfor (const entity of entitiesFromReborn) {\r\n\t\t\tconst card = gameState.allCards.getCard(entity.cardId);\r\n\t\t\tapplyDeityBaseStats(entity, boardWithKilledMinionHero, card?.attack ?? 1, card?.health ?? 1);\r\n\t\t\tentity.health = 1;\r\n\t\t}\r\n\t}\r\n\r\n\tif (\r\n\t\tdeadEntity.cardId === CardIds.WannabeGargoyle_BG30_109 ||\r\n\t\tdeadEntity.cardId === CardIds.WannabeGargoyle_BG30_109_G\r\n\t) {\r\n\t\tentitiesFromReborn.forEach((e) => {\r\n\t\t\tconst attack = deadEntity.maxAttack;\r\n\t\t\tconst health = deadEntity.cardId === CardIds.WannabeGargoyle_BG30_109_G ? deadEntity.maxHealth : 1;\r\n\t\t\te.attack = attack;\r\n\t\t\te.health = health;\r\n\t\t});\r\n\t}\r\n\r\n\tfor (const entity of entitiesFromReborn) {\r\n\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\tif (hasRebornSelfAttributeTransfer(rebornImpl)) {\r\n\t\t\trebornImpl.rebornSelfAttributeTransfer.forEach((attribute: keyof BoardEntity) => {\r\n\t\t\t\tcopyAttribute(entity, deadEntity, attribute);\r\n\t\t\t});\r\n\t\t}\r\n\t\tif (hasRebornSelfEffect(rebornImpl)) {\r\n\t\t\trebornImpl.rebornSelfEffect(entity, {\r\n\t\t\t\trebornEntity: deadEntity,\r\n\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\topponentBoard,\r\n\t\t\t\topponentBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const entity of boardWithKilledMinion) {\r\n\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\tif (hasRebornEffect(rebornImpl)) {\r\n\t\t\trebornImpl.rebornEffect(entity, {\r\n\t\t\t\trebornEntity: deadEntity,\r\n\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\topponentBoard,\r\n\t\t\t\topponentBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tconst entitiesThatWereReborn = performEntitySpawns(\r\n\t\tentitiesFromReborn,\r\n\t\tboardWithKilledMinion,\r\n\t\tboardWithKilledMinionHero,\r\n\t\tdeadEntity,\r\n\t\tdeadMinionIndexFromRight,\r\n\t\topponentBoard,\r\n\t\topponentBoardHero,\r\n\t\tgameState,\r\n\t);\r\n\tentitiesThatWereReborn.forEach((e) => (e.rebornFromEntityId = deadEntity.entityId));\r\n\tconst entityRightToSpawns =\r\n\t\tdeadMinionIndexFromRight === 0\r\n\t\t\t? null\r\n\t\t\t: boardWithKilledMinion[boardWithKilledMinion.length - deadMinionIndexFromRight];\r\n\tentitiesThatWereReborn.forEach((entity) => {\r\n\t\tentity.hasAttacked = deadEntity.hasAttacked > 1 ? 1 : entityRightToSpawns?.hasAttacked ?? undefined;\r\n\t});\r\n\r\n\tfor (const rebornEntity of entitiesThatWereReborn) {\r\n\t\tfor (const entity of boardWithKilledMinion) {\r\n\t\t\t// The entity was not there when the minion died, so we don't trigger its effect\r\n\t\t\tif (entitiesThatWereReborn.includes(entity)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\t\tif (hasAfterReborn(rebornImpl)) {\r\n\t\t\t\trebornImpl.afterReborn(entity, {\r\n\t\t\t\t\trebornEntity: rebornEntity,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (const trinket of boardWithKilledMinionHero.trinkets ?? []) {\r\n\t\t\tconst rebornImpl = cardMappings[trinket.cardId];\r\n\t\t\tif (hasAfterReborn(rebornImpl)) {\r\n\t\t\t\trebornImpl.afterReborn(trinket, {\r\n\t\t\t\t\trebornEntity: rebornEntity,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconst numberOfTriggersForDeathwhisper = Math.min(entitiesThatWereReborn.length, 1);\r\n\tfor (let i = 0; i < numberOfTriggersForDeathwhisper; i++) {\r\n\t\tboardWithKilledMinion\r\n\t\t\t.filter(\r\n\t\t\t\t(e) =>\r\n\t\t\t\t\te.cardId === CardIds.SisterDeathwhisper_BG25_020 ||\r\n\t\t\t\t\te.cardId === CardIds.SisterDeathwhisper_BG25_020_G,\r\n\t\t\t)\r\n\t\t\t.forEach((e) => {\r\n\t\t\t\tconst multiplier = e.cardId === CardIds.SisterDeathwhisper_BG25_020_G ? 2 : 1;\r\n\t\t\t\taddStatsToBoard(\r\n\t\t\t\t\te,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\tmultiplier * 1,\r\n\t\t\t\t\tmultiplier * 3,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t}\r\n};\r\n\r\n/**\r\n * Fires once per side after deathrattles and before any Reborn copy is summoned.\r\n * Also fires when Reborn processing is skipped. Trinkets, then the board as it was when the phase started.\r\n */\r\nexport const applyBeforeRebornEffects = (\r\n\tgameState: FullGameState,\r\n\tplayerDeadEntities: readonly BoardEntity[],\r\n\tplayerDeadEntityIndexesFromRight: readonly number[],\r\n\topponentDeadEntities: readonly BoardEntity[],\r\n\topponentDeadEntityIndexesFromRight: readonly number[],\r\n): void => {\r\n\tconst player = gameState.gameState.player;\r\n\tconst opponent = gameState.gameState.opponent;\r\n\tconst processPlayerFirst = Math.random() > 0.5;\r\n\tconst sides = processPlayerFirst\r\n\t\t? [\r\n\t\t\t\t{\r\n\t\t\t\t\thero: player.player,\r\n\t\t\t\t\tboard: player.board,\r\n\t\t\t\t\tdeadEntities: playerDeadEntities,\r\n\t\t\t\t\tdeadEntitiesIndexesFromRight: playerDeadEntityIndexesFromRight,\r\n\t\t\t\t\totherHero: opponent.player,\r\n\t\t\t\t\totherBoard: opponent.board,\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\thero: opponent.player,\r\n\t\t\t\t\tboard: opponent.board,\r\n\t\t\t\t\tdeadEntities: opponentDeadEntities,\r\n\t\t\t\t\tdeadEntitiesIndexesFromRight: opponentDeadEntityIndexesFromRight,\r\n\t\t\t\t\totherHero: player.player,\r\n\t\t\t\t\totherBoard: player.board,\r\n\t\t\t\t},\r\n\t\t ]\r\n\t\t: [\r\n\t\t\t\t{\r\n\t\t\t\t\thero: opponent.player,\r\n\t\t\t\t\tboard: opponent.board,\r\n\t\t\t\t\tdeadEntities: opponentDeadEntities,\r\n\t\t\t\t\tdeadEntitiesIndexesFromRight: opponentDeadEntityIndexesFromRight,\r\n\t\t\t\t\totherHero: player.player,\r\n\t\t\t\t\totherBoard: player.board,\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\thero: player.player,\r\n\t\t\t\t\tboard: player.board,\r\n\t\t\t\t\tdeadEntities: playerDeadEntities,\r\n\t\t\t\t\tdeadEntitiesIndexesFromRight: playerDeadEntityIndexesFromRight,\r\n\t\t\t\t\totherHero: opponent.player,\r\n\t\t\t\t\totherBoard: opponent.board,\r\n\t\t\t\t},\r\n\t\t ];\r\n\tfor (const side of sides) {\r\n\t\tconst input: BeforeRebornInput = {\r\n\t\t\thero: side.hero,\r\n\t\t\tboard: side.board,\r\n\t\t\totherHero: side.otherHero,\r\n\t\t\totherBoard: side.otherBoard,\r\n\t\t\tdeadEntities: side.deadEntities,\r\n\t\t\tdeadEntitiesIndexesFromRight: side.deadEntitiesIndexesFromRight,\r\n\t\t\tgameState,\r\n\t\t};\r\n\t\tfor (const trinket of side.hero.trinkets ?? []) {\r\n\t\t\tconst impl = cardMappings[trinket.cardId];\r\n\t\t\tif (hasBeforeReborn(impl)) {\r\n\t\t\t\timpl.beforeReborn(trinket, input);\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (const entity of [...side.board]) {\r\n\t\t\tconst impl = cardMappings[entity.cardId];\r\n\t\t\tif (hasBeforeReborn(impl)) {\r\n\t\t\t\timpl.beforeReborn(entity, input);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n};\r\n\r\nexport interface BeforeRebornInput {\r\n\treadonly hero: BgsPlayerEntity;\r\n\treadonly board: BoardEntity[];\r\n\treadonly otherHero: BgsPlayerEntity;\r\n\treadonly otherBoard: BoardEntity[];\r\n\treadonly deadEntities: readonly BoardEntity[];\r\n\treadonly deadEntitiesIndexesFromRight: readonly number[];\r\n\treadonly gameState: FullGameState;\r\n}\r\n\r\nexport interface RebornEffectInput {\r\n\treadonly rebornEntity: BoardEntity;\r\n\treadonly boardWithKilledMinion: BoardEntity[];\r\n\treadonly boardWithKilledMinionHero: BgsPlayerEntity;\r\n\treadonly opponentBoard: BoardEntity[];\r\n\treadonly opponentBoardHero: BgsPlayerEntity;\r\n\treadonly gameState: FullGameState;\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-state.js","sourceRoot":"","sources":["../../src/simulation/shared-state.ts"],"names":[],"mappings":";;;AACA,yCAAkD;AAElD,MAAa,WAAW;
|
|
1
|
+
{"version":3,"file":"shared-state.js","sourceRoot":"","sources":["../../src/simulation/shared-state.ts"],"names":[],"mappings":";;;AACA,yCAAkD;AAElD,MAAa,WAAW;IAgBvB,YAAY,MAAW,gBAAU;QAb1B,cAAS,GAAsB,EAAE,CAAC;QAClC,oBAAe,GAAG,CAAC,CAAC;QACpB,4BAAuB,GAAG,IAAI,CAAC;QAC/B,WAAM,GAAkB,EAAE,CAAC;QAC3B,UAAK,GAAG,KAAK,CAAC;QAEd,QAAG,GAAQ,gBAAU,CAAC;QAKtB,qCAAgC,GAAG,KAAK,CAAC;QAG/C,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC;QACtC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IAChB,CAAC;;AAlBa,wBAAY,GAAG,KAAK,AAAR,CAAS;AADvB,kCAAW","sourcesContent":["import { BoardEntity } from '../board-entity';\r\nimport { defaultRng, Rng } from '../services/rng';\r\n\r\nexport class SharedState {\r\n\tpublic static debugEnabled = false;\r\n\r\n\tpublic anomalies: readonly string[] = [];\r\n\tpublic currentEntityId = 1;\r\n\tpublic currentAttackerEntityId = null;\r\n\tpublic deaths: BoardEntity[] = [];\r\n\tpublic debug = false;\r\n\t/** Active RNG for this battle (also mirrored via withRng / Math.random patch). */\r\n\tpublic rng: Rng = defaultRng;\r\n\t/**\r\n\t * Wingmen opened a slot and skipped \"when you have space\". Keep skipping until the\r\n\t * next real attack, so that attack's summons (a Deity awaken) happen first.\r\n\t */\r\n\tpublic deferSummonsWhenSpaceUntilAttack = false;\r\n\r\n\tconstructor(rng: Rng = defaultRng) {\r\n\t\tthis.debug = SharedState.debugEnabled;\r\n\t\tthis.rng = rng;\r\n\t}\r\n}\r\n"]}
|
|
@@ -18,11 +18,14 @@ const handleIllidanHeroPowers = (playerEntity, playerBoard, opponentEntity, oppo
|
|
|
18
18
|
shouldForce = force1 || force2;
|
|
19
19
|
currentAttacker = newAttacker2;
|
|
20
20
|
}
|
|
21
|
-
(
|
|
22
|
-
|
|
21
|
+
if (shouldForce) {
|
|
22
|
+
gameState.sharedState.deferSummonsWhenSpaceUntilAttack = true;
|
|
23
|
+
}
|
|
24
|
+
(0, attack_1.processMinionDeath)(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState, shouldForce);
|
|
23
25
|
if (shouldForce) {
|
|
24
26
|
return { attacker: currentAttacker, force: true };
|
|
25
27
|
}
|
|
28
|
+
const shouldRecomputeCurrentAttacker = (0, summon_when_space_1.handleSummonsWhenSpace)(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState);
|
|
26
29
|
if (shouldRecomputeCurrentAttacker) {
|
|
27
30
|
currentAttacker =
|
|
28
31
|
playerBoard.length > opponentBoard.length
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"soc-illidan-hero-power.js","sourceRoot":"","sources":["../../../src/simulation/start-of-combat/soc-illidan-hero-power.ts"],"names":[],"mappings":"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","sourcesContent":["import { BgsPlayerEntity } from '../../bgs-player-entity';\r\nimport { BoardEntity } from '../../board-entity';\r\nimport { CardIds } from '../../services/card-ids';\r\nimport { processMinionDeath, simulateAttack } from '../attack';\r\nimport { FullGameState } from '../internal-game-state';\r\nimport { modifyStats } from '../stats';\r\nimport { handleSummonsWhenSpace } from '../summon-when-space';\r\n\r\nexport const handleIllidanHeroPowers = (\r\n\tplayerEntity: BgsPlayerEntity,\r\n\tplayerBoard: BoardEntity[],\r\n\topponentEntity: BgsPlayerEntity,\r\n\topponentBoard: BoardEntity[],\r\n\tcurrentAttacker: number,\r\n\tgameState: FullGameState,\r\n): { attacker: number; force: boolean } => {\r\n\tlet shouldForce = false;\r\n\t// console.log('current attacker before', currentAttacker);\r\n\t// Apparently it's a toin coss about whether to handle Illidan first or Al'Akir first\r\n\t// Auras are only relevant for Illidan, and already applied there\r\n\tif (Math.random() < 0.5) {\r\n\t\tconst { attacker: newAttacker, force: force1 } = handlePlayerIllidanHeroPowers(\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tcurrentAttacker,\r\n\t\t\ttrue,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tconst { attacker: newAttacker2, force: force2 } = handlePlayerIllidanHeroPowers(\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\tnewAttacker,\r\n\t\t\tfalse,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tshouldForce = force1 || force2;\r\n\t\tcurrentAttacker = newAttacker2;\r\n\t} else {\r\n\t\tconst { attacker: newAttacker, force: force1 } = handlePlayerIllidanHeroPowers(\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\tcurrentAttacker,\r\n\t\t\tfalse,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tconst { attacker: newAttacker2, force: force2 } = handlePlayerIllidanHeroPowers(\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tnewAttacker,\r\n\t\t\ttrue,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tshouldForce = force1 || force2;\r\n\t\tcurrentAttacker = newAttacker2;\r\n\t}\r\n\tprocessMinionDeath(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState);\r\n\tconst shouldRecomputeCurrentAttacker = handleSummonsWhenSpace(\r\n\t\tplayerBoard,\r\n\t\tplayerEntity,\r\n\t\topponentBoard,\r\n\t\topponentEntity,\r\n\t\tgameState,\r\n\t);\r\n\tif (shouldForce) {\r\n\t\treturn { attacker: currentAttacker, force: true };\r\n\t}\r\n\tif (shouldRecomputeCurrentAttacker) {\r\n\t\tcurrentAttacker =\r\n\t\t\tplayerBoard.length > opponentBoard.length\r\n\t\t\t\t? 0\r\n\t\t\t\t: opponentBoard.length > playerBoard.length\r\n\t\t\t\t? 1\r\n\t\t\t\t: Math.round(Math.random());\r\n\t}\r\n\treturn { attacker: currentAttacker, force: false };\r\n};\r\n\r\nconst handlePlayerIllidanHeroPowers = (\r\n\tplayerEntity: BgsPlayerEntity,\r\n\tplayerBoard: BoardEntity[],\r\n\topponentEntity: BgsPlayerEntity,\r\n\topponentBoard: BoardEntity[],\r\n\tcurrentAttacker: number,\r\n\tfriendly: boolean,\r\n\tgameState: FullGameState,\r\n): { attacker: number; force: boolean } => {\r\n\tconst loops = playerEntity.trinkets?.some((t) => t.cardId === CardIds.ValdrakkenWindChimes_BG32_MagicItem_365)\r\n\t\t? 2\r\n\t\t: 1;\r\n\tfor (let i = 0; i < loops; i++) {\r\n\t\tif (playerEntity.hpLeft <= 0) {\r\n\t\t\treturn { attacker: currentAttacker, force: false };\r\n\t\t}\r\n\t\tfor (const heroPower of playerEntity.heroPowers) {\r\n\t\t\tif (heroPower.cardId === CardIds.Wingmen && playerBoard.length > 0) {\r\n\t\t\t\thandleIllidanForPlayer(\r\n\t\t\t\t\tplayerBoard,\r\n\t\t\t\t\tplayerEntity,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentEntity,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t\tcurrentAttacker,\r\n\t\t\t\t);\r\n\t\t\t\t// After Illidan triggers, it's always the other opponent's turn\r\n\t\t\t\t// https://x.com/LoewenMitchell/status/1752714583360639131?s=20\r\n\t\t\t\t// Confirmed by BoarControl on Discord on 33.6.2 2025-10-20\r\n\t\t\t\t// It looks like it's always the next player that should attack after Wingmen triggers, which\r\n\t\t\t\t// means we should bypass the \"recompute next attacker\" logic from other start of combat effects,\r\n\t\t\t\t// like summoning Flight Scout\r\n\t\t\t\t// 33.6.2 https://replays.firestoneapp.com/?reviewId=03b5755e-1666-4f6c-a3be-626b76bbef6d&turn=5&action=1\r\n\t\t\t\t// 33.6.2 https://replays.firestoneapp.com/?reviewId=c04ab462-9fd2-47e4-8ad4-bbcc3c14c709&turn=3&action=2\r\n\t\t\t\tcurrentAttacker = friendly ? 1 : 0;\r\n\t\t\t\t// UPDATE 2026-09-04: looks like it's not always the case, but I haven't been able to figure out the rules\r\n\t\t\t\t// 36.4.2: https://replays.firestoneapp.com/?reviewId=a2a8a059-a8de-4c42-a467-2693f222c691&turn=11&action=2\r\n\t\t\t\treturn { attacker: currentAttacker, force: true };\r\n\t\t\t\t// OLD:\r\n\t\t\t\t// This is not true anymore: https://replays.firestoneapp.com/?reviewId=7282387d-66cd-458e-8ee1-e04c662e7bad&turn=5&action=1\r\n\t\t\t\t// In fact there is some adjustment going on: https://replays.firestoneapp.com/?reviewId=929f676f-47f6-494b-9619-df04174a0150&turn=11&action=0\r\n\t\t\t\t// So trying another logic\r\n\t\t\t\t// currentAttacker = (currentAttacker + 1) % 2;\r\n\t\t\t\t// This isn't correct. The following game is a case of:\r\n\t\t\t\t// The player with the fewer minions is Illidan, so isn't the \"first attacker\"\r\n\t\t\t\t// Wingmen triggers\r\n\t\t\t\t// The non-Illidan side then attacks first\r\n\t\t\t\t// https://replays.firestoneapp.com/?reviewId=45f40e73-4be9-419f-9093-0c2d91a7bac2&turn=5&action=0\r\n\t\t\t\t// So for now, just randomizing the attacker to try and avoid \"impossible\" scenarios as much as possible\r\n\t\t\t\t// currentAttacker = Math.random() < 0.5 ? 0 : 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn { attacker: currentAttacker, force: false };\r\n};\r\n\r\n// TODO: not exactly correct, because of \"attack immediately\", but it's close enough\r\nconst handleIllidanForPlayer = (\r\n\tplayerBoard: BoardEntity[],\r\n\tplayerEntity: BgsPlayerEntity,\r\n\topponentBoard: BoardEntity[],\r\n\topponentEntity: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n\tcurrentAttacker: number,\r\n): void => {\r\n\tif (playerEntity.startOfCombatDone) {\r\n\t\treturn;\r\n\t}\r\n\t// Otherwise, if the first minion dies on the attack, and the board has only 2 minions, we\r\n\t// miss the second one\r\n\tconst minionsAtStart = playerBoard.length;\r\n\tconst firstAttacker = playerBoard[0];\r\n\tconst secondAttacker = minionsAtStart > 1 ? playerBoard[playerBoard.length - 1] : null;\r\n\r\n\t// Stats updates\r\n\tmodifyStats(firstAttacker, playerEntity, 2, 1, playerBoard, playerEntity, gameState);\r\n\tif (!!secondAttacker && !secondAttacker.definitelyDead && secondAttacker.health > 0) {\r\n\t\tmodifyStats(secondAttacker, playerEntity, 2, 1, playerBoard, playerEntity, gameState);\r\n\t}\r\n\r\n\t// Attacks\r\n\tfirstAttacker.attackImmediately = true;\r\n\tsimulateAttack(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState, {\r\n\t\tskipSummonWhenSpace: true,\r\n\t});\r\n\t// See http://replays.firestoneapp.com/?reviewId=f16b7a49-c2a2-4ac5-a9eb-a75f83246f70&turn=6&action=8\r\n\tfirstAttacker.hasAttacked = undefined;\r\n\tfirstAttacker.attackImmediately = false;\r\n\tif (!!secondAttacker && !secondAttacker.definitelyDead && secondAttacker.health > 0) {\r\n\t\tsecondAttacker.attackImmediately = true;\r\n\t\tsimulateAttack(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState, {\r\n\t\t\tskipSummonWhenSpace: true,\r\n\t\t});\r\n\t\tsecondAttacker.hasAttacked = undefined;\r\n\t\tsecondAttacker.attackImmediately = false;\r\n\t}\r\n\r\n\t// // See http://replays.firestoneapp.com/?reviewId=7e9ec42c-a8f6-43d2-9f39-cc486dfa2395&turn=6&action=5\r\n\t// if (firstAttacker.definitelyDead || firstAttacker.health <= 0) {\r\n\t// \tcurrentAttacker = (currentAttacker + 1) % 2;\r\n\t// }\r\n\t// return currentAttacker;\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"soc-illidan-hero-power.js","sourceRoot":"","sources":["../../../src/simulation/start-of-combat/soc-illidan-hero-power.ts"],"names":[],"mappings":"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","sourcesContent":["import { BgsPlayerEntity } from '../../bgs-player-entity';\r\nimport { BoardEntity } from '../../board-entity';\r\nimport { CardIds } from '../../services/card-ids';\r\nimport { processMinionDeath, simulateAttack } from '../attack';\r\nimport { FullGameState } from '../internal-game-state';\r\nimport { modifyStats } from '../stats';\r\nimport { handleSummonsWhenSpace } from '../summon-when-space';\r\n\r\nexport const handleIllidanHeroPowers = (\r\n\tplayerEntity: BgsPlayerEntity,\r\n\tplayerBoard: BoardEntity[],\r\n\topponentEntity: BgsPlayerEntity,\r\n\topponentBoard: BoardEntity[],\r\n\tcurrentAttacker: number,\r\n\tgameState: FullGameState,\r\n): { attacker: number; force: boolean } => {\r\n\tlet shouldForce = false;\r\n\t// console.log('current attacker before', currentAttacker);\r\n\t// Apparently it's a toin coss about whether to handle Illidan first or Al'Akir first\r\n\t// Auras are only relevant for Illidan, and already applied there\r\n\tif (Math.random() < 0.5) {\r\n\t\tconst { attacker: newAttacker, force: force1 } = handlePlayerIllidanHeroPowers(\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tcurrentAttacker,\r\n\t\t\ttrue,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tconst { attacker: newAttacker2, force: force2 } = handlePlayerIllidanHeroPowers(\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\tnewAttacker,\r\n\t\t\tfalse,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tshouldForce = force1 || force2;\r\n\t\tcurrentAttacker = newAttacker2;\r\n\t} else {\r\n\t\tconst { attacker: newAttacker, force: force1 } = handlePlayerIllidanHeroPowers(\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\tcurrentAttacker,\r\n\t\t\tfalse,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tconst { attacker: newAttacker2, force: force2 } = handlePlayerIllidanHeroPowers(\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tnewAttacker,\r\n\t\t\ttrue,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tshouldForce = force1 || force2;\r\n\t\tcurrentAttacker = newAttacker2;\r\n\t}\r\n\t// Wingmen attacks skip \"when you have space\". Later start-of-combat checks would\r\n\t// summon before the next attack, and that attack can awaken a Deity into the slot.\r\n\t// https://replays.firestoneapp.com/?debug=true&reviewId=8203fd35-40ca-4dc0-ad87-c31428a10721&turn=25&action=0\r\n\tif (shouldForce) {\r\n\t\tgameState.sharedState.deferSummonsWhenSpaceUntilAttack = true;\r\n\t}\r\n\tprocessMinionDeath(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState, shouldForce);\r\n\tif (shouldForce) {\r\n\t\treturn { attacker: currentAttacker, force: true };\r\n\t}\r\n\tconst shouldRecomputeCurrentAttacker = handleSummonsWhenSpace(\r\n\t\tplayerBoard,\r\n\t\tplayerEntity,\r\n\t\topponentBoard,\r\n\t\topponentEntity,\r\n\t\tgameState,\r\n\t);\r\n\tif (shouldRecomputeCurrentAttacker) {\r\n\t\tcurrentAttacker =\r\n\t\t\tplayerBoard.length > opponentBoard.length\r\n\t\t\t\t? 0\r\n\t\t\t\t: opponentBoard.length > playerBoard.length\r\n\t\t\t\t? 1\r\n\t\t\t\t: Math.round(Math.random());\r\n\t}\r\n\treturn { attacker: currentAttacker, force: false };\r\n};\r\n\r\nconst handlePlayerIllidanHeroPowers = (\r\n\tplayerEntity: BgsPlayerEntity,\r\n\tplayerBoard: BoardEntity[],\r\n\topponentEntity: BgsPlayerEntity,\r\n\topponentBoard: BoardEntity[],\r\n\tcurrentAttacker: number,\r\n\tfriendly: boolean,\r\n\tgameState: FullGameState,\r\n): { attacker: number; force: boolean } => {\r\n\tconst loops = playerEntity.trinkets?.some((t) => t.cardId === CardIds.ValdrakkenWindChimes_BG32_MagicItem_365)\r\n\t\t? 2\r\n\t\t: 1;\r\n\tfor (let i = 0; i < loops; i++) {\r\n\t\tif (playerEntity.hpLeft <= 0) {\r\n\t\t\treturn { attacker: currentAttacker, force: false };\r\n\t\t}\r\n\t\tfor (const heroPower of playerEntity.heroPowers) {\r\n\t\t\tif (heroPower.cardId === CardIds.Wingmen && playerBoard.length > 0) {\r\n\t\t\t\thandleIllidanForPlayer(\r\n\t\t\t\t\tplayerBoard,\r\n\t\t\t\t\tplayerEntity,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentEntity,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t\tcurrentAttacker,\r\n\t\t\t\t);\r\n\t\t\t\t// After Illidan triggers, it's always the other opponent's turn\r\n\t\t\t\t// https://x.com/LoewenMitchell/status/1752714583360639131?s=20\r\n\t\t\t\t// Confirmed by BoarControl on Discord on 33.6.2 2025-10-20\r\n\t\t\t\t// It looks like it's always the next player that should attack after Wingmen triggers, which\r\n\t\t\t\t// means we should bypass the \"recompute next attacker\" logic from other start of combat effects,\r\n\t\t\t\t// like summoning Flight Scout\r\n\t\t\t\t// 33.6.2 https://replays.firestoneapp.com/?reviewId=03b5755e-1666-4f6c-a3be-626b76bbef6d&turn=5&action=1\r\n\t\t\t\t// 33.6.2 https://replays.firestoneapp.com/?reviewId=c04ab462-9fd2-47e4-8ad4-bbcc3c14c709&turn=3&action=2\r\n\t\t\t\tcurrentAttacker = friendly ? 1 : 0;\r\n\t\t\t\t// UPDATE 2026-09-04: looks like it's not always the case, but I haven't been able to figure out the rules\r\n\t\t\t\t// 36.4.2: https://replays.firestoneapp.com/?reviewId=a2a8a059-a8de-4c42-a467-2693f222c691&turn=11&action=2\r\n\t\t\t\treturn { attacker: currentAttacker, force: true };\r\n\t\t\t\t// OLD:\r\n\t\t\t\t// This is not true anymore: https://replays.firestoneapp.com/?reviewId=7282387d-66cd-458e-8ee1-e04c662e7bad&turn=5&action=1\r\n\t\t\t\t// In fact there is some adjustment going on: https://replays.firestoneapp.com/?reviewId=929f676f-47f6-494b-9619-df04174a0150&turn=11&action=0\r\n\t\t\t\t// So trying another logic\r\n\t\t\t\t// currentAttacker = (currentAttacker + 1) % 2;\r\n\t\t\t\t// This isn't correct. The following game is a case of:\r\n\t\t\t\t// The player with the fewer minions is Illidan, so isn't the \"first attacker\"\r\n\t\t\t\t// Wingmen triggers\r\n\t\t\t\t// The non-Illidan side then attacks first\r\n\t\t\t\t// https://replays.firestoneapp.com/?reviewId=45f40e73-4be9-419f-9093-0c2d91a7bac2&turn=5&action=0\r\n\t\t\t\t// So for now, just randomizing the attacker to try and avoid \"impossible\" scenarios as much as possible\r\n\t\t\t\t// currentAttacker = Math.random() < 0.5 ? 0 : 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn { attacker: currentAttacker, force: false };\r\n};\r\n\r\n// TODO: not exactly correct, because of \"attack immediately\", but it's close enough\r\nconst handleIllidanForPlayer = (\r\n\tplayerBoard: BoardEntity[],\r\n\tplayerEntity: BgsPlayerEntity,\r\n\topponentBoard: BoardEntity[],\r\n\topponentEntity: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n\tcurrentAttacker: number,\r\n): void => {\r\n\tif (playerEntity.startOfCombatDone) {\r\n\t\treturn;\r\n\t}\r\n\t// Otherwise, if the first minion dies on the attack, and the board has only 2 minions, we\r\n\t// miss the second one\r\n\tconst minionsAtStart = playerBoard.length;\r\n\tconst firstAttacker = playerBoard[0];\r\n\tconst secondAttacker = minionsAtStart > 1 ? playerBoard[playerBoard.length - 1] : null;\r\n\r\n\t// Stats updates\r\n\tmodifyStats(firstAttacker, playerEntity, 2, 1, playerBoard, playerEntity, gameState);\r\n\tif (!!secondAttacker && !secondAttacker.definitelyDead && secondAttacker.health > 0) {\r\n\t\tmodifyStats(secondAttacker, playerEntity, 2, 1, playerBoard, playerEntity, gameState);\r\n\t}\r\n\r\n\t// Attacks\r\n\tfirstAttacker.attackImmediately = true;\r\n\tsimulateAttack(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState, {\r\n\t\tskipSummonWhenSpace: true,\r\n\t});\r\n\t// See http://replays.firestoneapp.com/?reviewId=f16b7a49-c2a2-4ac5-a9eb-a75f83246f70&turn=6&action=8\r\n\tfirstAttacker.hasAttacked = undefined;\r\n\tfirstAttacker.attackImmediately = false;\r\n\tif (!!secondAttacker && !secondAttacker.definitelyDead && secondAttacker.health > 0) {\r\n\t\tsecondAttacker.attackImmediately = true;\r\n\t\tsimulateAttack(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState, {\r\n\t\t\tskipSummonWhenSpace: true,\r\n\t\t});\r\n\t\tsecondAttacker.hasAttacked = undefined;\r\n\t\tsecondAttacker.attackImmediately = false;\r\n\t}\r\n\r\n\t// // See http://replays.firestoneapp.com/?reviewId=7e9ec42c-a8f6-43d2-9f39-cc486dfa2395&turn=6&action=5\r\n\t// if (firstAttacker.definitelyDead || firstAttacker.health <= 0) {\r\n\t// \tcurrentAttacker = (currentAttacker + 1) % 2;\r\n\t// }\r\n\t// return currentAttacker;\r\n};\r\n"]}
|
|
@@ -77,11 +77,11 @@ const performStartOfCombatMinionsForPlayer = (minion, input) => {
|
|
|
77
77
|
if (input.playerEntity.startOfCombatDone) {
|
|
78
78
|
return false;
|
|
79
79
|
}
|
|
80
|
-
hasProcessed = (0, soc_action_processor_1.performStartOfCombatAction)(minion.cardId, minion, input, true, undefined) || hasProcessed;
|
|
81
80
|
for (const enchantment of (_b = minion.enchantments) !== null && _b !== void 0 ? _b : []) {
|
|
82
81
|
hasProcessed =
|
|
83
82
|
(0, soc_action_processor_1.performStartOfCombatAction)(enchantment.cardId, minion, input, true, undefined) || hasProcessed;
|
|
84
83
|
}
|
|
84
|
+
hasProcessed = (0, soc_action_processor_1.performStartOfCombatAction)(minion.cardId, minion, input, true, undefined) || hasProcessed;
|
|
85
85
|
}
|
|
86
86
|
return hasProcessed;
|
|
87
87
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"soc-minion.js","sourceRoot":"","sources":["../../../src/simulation/start-of-combat/soc-minion.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"soc-minion.js","sourceRoot":"","sources":["../../../src/simulation/start-of-combat/soc-minion.ts"],"names":[],"mappings":";;;AAEA,+DAAsE;AACtE,oEAA+D;AAG/D,iEAAoE;AAG7D,MAAM,0BAA0B,GAAG,CACzC,YAA6B,EAC7B,WAA0B,EAC1B,cAA+B,EAC/B,aAA4B,EAC5B,eAAuB,EACvB,iBAAgC,EAChC,mBAAkC,EAClC,SAAwB,EACf,EAAE;IACX,IAAI,gBAAgB,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,eAAe,GAAG;QAEvB,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,yCAAwB,EAAC,6BAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACpF,GAAG,WAAW;KACd,CAAC;IACF,MAAM,iBAAiB,GAAG;QACzB,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,yCAAwB,EAAC,6BAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACtF,GAAG,aAAa;KAChB,CAAC;IAKF,OAAO,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE;QAClE,IAAI,sBAAsB,GAAG,KAAK,CAAC;QACnC,IAAI,gBAAgB,KAAK,CAAC,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE;YACzD,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,QAAQ,CAAC,cAAc,EAAE;gBACpD,SAAS;aACT;YACD,MAAM,KAAK,GAAG;gBACb,WAAW,EAAE,WAAW;gBACxB,YAAY,EAAE,YAAY;gBAC1B,aAAa,EAAE,aAAa;gBAC5B,cAAc,EAAE,cAAc;gBAC9B,iBAAiB,EAAE,iBAAiB;gBACpC,mBAAmB,EAAE,mBAAmB;gBACxC,gBAAgB,EAAE,IAAI;gBACtB,eAAe,EAAE,eAAe;gBAChC,SAAS;aACT,CAAC;YACF,MAAM,yBAAyB,GAAG,IAAA,4CAAoC,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACxF,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;SACxC;aAAM,IAAI,gBAAgB,KAAK,CAAC,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE;YAClE,sBAAsB,GAAG,IAAI,CAAC;SAC9B;aAAM,IAAI,gBAAgB,KAAK,CAAC,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE;YAClE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnD,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,QAAQ,CAAC,cAAc,EAAE;gBACpD,SAAS;aACT;YACD,MAAM,KAAK,GAAG;gBACb,WAAW,EAAE,aAAa;gBAC1B,YAAY,EAAE,cAAc;gBAC5B,aAAa,EAAE,WAAW;gBAC1B,cAAc,EAAE,YAAY;gBAC5B,iBAAiB,EAAE,mBAAmB;gBACtC,mBAAmB,EAAE,iBAAiB;gBACtC,gBAAgB,EAAE,KAAK;gBACvB,eAAe,EAAE,eAAe;gBAChC,SAAS;aACT,CAAC;YACF,MAAM,yBAAyB,GAAG,IAAA,4CAAoC,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACxF,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;SACxC;aAAM,IAAI,gBAAgB,KAAK,CAAC,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE;YACpE,sBAAsB,GAAG,IAAI,CAAC;SAC9B;QAED,IAAI,sBAAsB,EAAE;YAC3B,gBAAgB,GAAG,CAAC,gBAAgB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;SAC9C;KACD;IAuBD,OAAO,eAAe,CAAC;AACxB,CAAC,CAAC;AA/FW,QAAA,0BAA0B,8BA+FrC;AAMK,MAAM,oCAAoC,GAAG,CAAC,MAAmB,EAAE,KAAe,EAAW,EAAE;;IACrG,MAAM,KAAK,GAAG,CAAA,MAAA,KAAK,CAAC,YAAY,CAAC,QAAQ,0CAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,yBAAoD,CAAC;QACnH,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,CAAC,CAAC;IACL,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;QAC/B,IAAI,KAAK,CAAC,YAAY,CAAC,iBAAiB,EAAE;YACzC,OAAO,KAAK,CAAC;SACb;QAMD,KAAK,MAAM,WAAW,IAAI,MAAA,MAAM,CAAC,YAAY,mCAAI,EAAE,EAAE;YACpD,YAAY;gBACX,IAAA,iDAA0B,EAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,YAAY,CAAC;SAChG;QACD,YAAY,GAAG,IAAA,iDAA0B,EAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,YAAY,CAAC;KACzG;IACD,OAAO,YAAY,CAAC;AACrB,CAAC,CAAC;AArBW,QAAA,oCAAoC,wCAqB/C","sourcesContent":["import { BgsPlayerEntity } from '../../bgs-player-entity';\r\nimport { BoardEntity } from '../../board-entity';\r\nimport { hasStartOfCombatFromHand } from '../../cards/card.interface';\r\nimport { cardMappings } from '../../cards/impl/_card-mappings';\r\nimport { CardIds } from '../../services/card-ids';\r\nimport { FullGameState } from '../internal-game-state';\r\nimport { performStartOfCombatAction } from './soc-action-processor';\r\nimport { SoCInput } from './start-of-combat-input';\r\n\r\nexport const handleStartOfCombatMinions = (\r\n\tplayerEntity: BgsPlayerEntity,\r\n\tplayerBoard: BoardEntity[],\r\n\topponentEntity: BgsPlayerEntity,\r\n\topponentBoard: BoardEntity[],\r\n\tcurrentAttacker: number,\r\n\tplayerBoardBefore: BoardEntity[],\r\n\topponentBoardBefore: BoardEntity[],\r\n\tgameState: FullGameState,\r\n): number => {\r\n\tlet attackerForStart = Math.random() < 0.5 ? 0 : 1;\r\n\tconst playerAttackers = [\r\n\t\t// Hand triggers first\r\n\t\t...playerEntity.hand.filter((e) => hasStartOfCombatFromHand(cardMappings[e.cardId])),\r\n\t\t...playerBoard,\r\n\t];\r\n\tconst opponentAttackers = [\r\n\t\t...opponentEntity.hand.filter((e) => hasStartOfCombatFromHand(cardMappings[e.cardId])),\r\n\t\t...opponentBoard,\r\n\t];\r\n\r\n\t// UPDATE 2025-11-16 We probably want to run the Start of Combat first for one player completely, then for the other\r\n\t// I thought it would alternate, but this apparently isn't the case:\r\n\t// https://replays.firestoneapp.com/?reviewId=af9053ee-9ee6-440a-a09f-b7fb2f4b7a3e&turn=9&action=0\r\n\twhile (playerAttackers.length > 0 || opponentAttackers.length > 0) {\r\n\t\tlet shouldUpdateNextPlayer = false;\r\n\t\tif (attackerForStart === 0 && playerAttackers.length > 0) {\r\n\t\t\tconst attacker = playerAttackers.splice(0, 1)[0];\r\n\t\t\tif (attacker.health <= 0 || attacker.definitelyDead) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst input = {\r\n\t\t\t\tplayerBoard: playerBoard,\r\n\t\t\t\tplayerEntity: playerEntity,\r\n\t\t\t\topponentBoard: opponentBoard,\r\n\t\t\t\topponentEntity: opponentEntity,\r\n\t\t\t\tplayerBoardBefore: playerBoardBefore,\r\n\t\t\t\topponentBoardBefore: opponentBoardBefore,\r\n\t\t\t\tplayerIsFriendly: true,\r\n\t\t\t\tcurrentAttacker: currentAttacker,\r\n\t\t\t\tgameState,\r\n\t\t\t};\r\n\t\t\tconst newShouldUpdateNextPlayer = performStartOfCombatMinionsForPlayer(attacker, input);\r\n\t\t\tcurrentAttacker = input.currentAttacker;\r\n\t\t} else if (attackerForStart === 0 && playerAttackers.length === 0) {\r\n\t\t\tshouldUpdateNextPlayer = true;\r\n\t\t} else if (attackerForStart === 1 && opponentAttackers.length > 0) {\r\n\t\t\tconst attacker = opponentAttackers.splice(0, 1)[0];\r\n\t\t\tif (attacker.health <= 0 || attacker.definitelyDead) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst input = {\r\n\t\t\t\tplayerBoard: opponentBoard,\r\n\t\t\t\tplayerEntity: opponentEntity,\r\n\t\t\t\topponentBoard: playerBoard,\r\n\t\t\t\topponentEntity: playerEntity,\r\n\t\t\t\tplayerBoardBefore: opponentBoardBefore,\r\n\t\t\t\topponentBoardBefore: playerBoardBefore,\r\n\t\t\t\tplayerIsFriendly: false,\r\n\t\t\t\tcurrentAttacker: currentAttacker,\r\n\t\t\t\tgameState,\r\n\t\t\t};\r\n\t\t\tconst newShouldUpdateNextPlayer = performStartOfCombatMinionsForPlayer(attacker, input);\r\n\t\t\tcurrentAttacker = input.currentAttacker;\r\n\t\t} else if (attackerForStart === 1 && opponentAttackers.length === 0) {\r\n\t\t\tshouldUpdateNextPlayer = true;\r\n\t\t}\r\n\r\n\t\tif (shouldUpdateNextPlayer) {\r\n\t\t\tattackerForStart = (attackerForStart + 1) % 2;\r\n\t\t}\r\n\t}\r\n\t// 2026-09-29: I'm having doubts as to whether the \"summonsWhenSpace\" should be called here.\r\n\t// https://replays.firestoneapp.com/?reviewId=71184008-9884-47d0-89fc-c175c37a3be3&turn=15&action=1\r\n\t// Bomm-in-a-Box triggers, then the player attacks, and only the does Tentacular procs\r\n\t// https://replays.firestoneapp.com/?reviewId=49582580-dae9-4079-b2ff-741bab446da6&turn=27&action=2\r\n\t// On this board, Heroic Broodmother attacks twice as part of the Start of Combat, then the\r\n\t// opponent's turn starts and it attacks immediately before giving Frostwolf Fervor a chance to proc\r\n\t// For now I will comment this out, and we'll see how that goes\r\n\t// const shouldRecomputeCurrentAttacker = handleSummonsWhenSpace(\r\n\t// \tplayerBoard,\r\n\t// \tplayerEntity,\r\n\t// \topponentBoard,\r\n\t// \topponentEntity,\r\n\t// \tgameState,\r\n\t// );\r\n\t// if (shouldRecomputeCurrentAttacker) {\r\n\t// \tcurrentAttacker =\r\n\t// \t\tplayerBoard.length > opponentBoard.length\r\n\t// \t\t\t? 0\r\n\t// \t\t\t: opponentBoard.length > playerBoard.length\r\n\t// \t\t\t? 1\r\n\t// \t\t\t: Math.round(Math.random());\r\n\t// }\r\n\treturn currentAttacker;\r\n};\r\n\r\n// Apparently, the board composition used for start of combat minion effects (like Red Whelp, and I assume it works the\r\n// same way for others like Prized Promo Drake or Mantid Queen) is the one that is used before Illidan's effect is handled.\r\n// Since this also runs before HP start of combat, we probably also use the state as it was before HP were triggered, like\r\n// Tamsin's Phylactery.\r\nexport const performStartOfCombatMinionsForPlayer = (minion: BoardEntity, input: SoCInput): boolean => {\r\n\tconst loops = input.playerEntity.trinkets?.some((t) => t.cardId === CardIds.ValdrakkenWindChimes_BG32_MagicItem_365)\r\n\t\t? 2\r\n\t\t: 1;\r\n\tlet hasProcessed = false;\r\n\tfor (let i = 0; i < loops; i++) {\r\n\t\tif (input.playerEntity.startOfCombatDone) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Dark Gifts are enchantments on the minion. They trigger before the minion's own\r\n\t\t// Start of Combat, with the host minion as the acting entity. Doppelganger therefore\r\n\t\t// takes a last open slot before Diremuck Forager can summon from hand.\r\n\t\t// https://replays.firestoneapp.com/?reviewId=4f4d9ffd-dc7b-4993-8385-7a1e813a8feb&turn=13&action=0\r\n\t\tfor (const enchantment of minion.enchantments ?? []) {\r\n\t\t\thasProcessed =\r\n\t\t\t\tperformStartOfCombatAction(enchantment.cardId, minion, input, true, undefined) || hasProcessed;\r\n\t\t}\r\n\t\thasProcessed = performStartOfCombatAction(minion.cardId, minion, input, true, undefined) || hasProcessed;\r\n\t}\r\n\treturn hasProcessed;\r\n};\r\n"]}
|
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handleStartOfCombatTrinkets = void 0;
|
|
4
|
+
const reference_data_1 = require("@firestone-hs/reference-data");
|
|
4
5
|
const summon_when_space_1 = require("../summon-when-space");
|
|
5
6
|
const soc_action_processor_1 = require("./soc-action-processor");
|
|
7
|
+
const TRINKET_SLOT_HERO_POWER = 3;
|
|
8
|
+
const isHeroPowerTrinket = (trinket) => {
|
|
9
|
+
var _a;
|
|
10
|
+
return trinket.scriptDataNum6 === TRINKET_SLOT_HERO_POWER &&
|
|
11
|
+
((_a = trinket.tags) === null || _a === void 0 ? void 0 : _a[reference_data_1.GameTag.ADDITIONAL_HERO_POWER_INDEX]) !== 1;
|
|
12
|
+
};
|
|
6
13
|
const handleStartOfCombatTrinkets = (playerEntity, playerBoard, opponentEntity, opponentBoard, currentAttacker, gameState) => {
|
|
14
|
+
const hasHeroPowerTrinket = [playerEntity, opponentEntity].some((hero) => { var _a; return (_a = hero.trinkets) === null || _a === void 0 ? void 0 : _a.some(isHeroPowerTrinket); });
|
|
15
|
+
if (hasHeroPowerTrinket) {
|
|
16
|
+
currentAttacker = resolveTrinketPass(playerEntity, playerBoard, opponentEntity, opponentBoard, currentAttacker, gameState, isHeroPowerTrinket);
|
|
17
|
+
}
|
|
18
|
+
currentAttacker = resolveTrinketPass(playerEntity, playerBoard, opponentEntity, opponentBoard, currentAttacker, gameState, (trinket) => !isHeroPowerTrinket(trinket));
|
|
19
|
+
const shouldRecomputeCurrentAttacker = (0, summon_when_space_1.handleSummonsWhenSpace)(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState);
|
|
20
|
+
if (shouldRecomputeCurrentAttacker) {
|
|
21
|
+
currentAttacker =
|
|
22
|
+
playerBoard.length > opponentBoard.length
|
|
23
|
+
? 0
|
|
24
|
+
: opponentBoard.length > playerBoard.length
|
|
25
|
+
? 1
|
|
26
|
+
: Math.round(Math.random());
|
|
27
|
+
}
|
|
28
|
+
return currentAttacker;
|
|
29
|
+
};
|
|
30
|
+
exports.handleStartOfCombatTrinkets = handleStartOfCombatTrinkets;
|
|
31
|
+
const resolveTrinketPass = (playerEntity, playerBoard, opponentEntity, opponentBoard, currentAttacker, gameState, include) => {
|
|
7
32
|
if (Math.random() < 0.5) {
|
|
8
33
|
currentAttacker = handleStartOfCombatTrinketsForPlayer({
|
|
9
34
|
playerEntity: playerEntity,
|
|
@@ -13,7 +38,7 @@ const handleStartOfCombatTrinkets = (playerEntity, playerBoard, opponentEntity,
|
|
|
13
38
|
currentAttacker,
|
|
14
39
|
gameState,
|
|
15
40
|
playerIsFriendly: true,
|
|
16
|
-
});
|
|
41
|
+
}, include);
|
|
17
42
|
currentAttacker = handleStartOfCombatTrinketsForPlayer({
|
|
18
43
|
playerEntity: opponentEntity,
|
|
19
44
|
playerBoard: opponentBoard,
|
|
@@ -22,7 +47,7 @@ const handleStartOfCombatTrinkets = (playerEntity, playerBoard, opponentEntity,
|
|
|
22
47
|
currentAttacker,
|
|
23
48
|
gameState,
|
|
24
49
|
playerIsFriendly: false,
|
|
25
|
-
});
|
|
50
|
+
}, include);
|
|
26
51
|
}
|
|
27
52
|
else {
|
|
28
53
|
currentAttacker = handleStartOfCombatTrinketsForPlayer({
|
|
@@ -33,7 +58,7 @@ const handleStartOfCombatTrinkets = (playerEntity, playerBoard, opponentEntity,
|
|
|
33
58
|
currentAttacker,
|
|
34
59
|
gameState,
|
|
35
60
|
playerIsFriendly: false,
|
|
36
|
-
});
|
|
61
|
+
}, include);
|
|
37
62
|
currentAttacker = handleStartOfCombatTrinketsForPlayer({
|
|
38
63
|
playerEntity: playerEntity,
|
|
39
64
|
playerBoard: playerBoard,
|
|
@@ -42,30 +67,23 @@ const handleStartOfCombatTrinkets = (playerEntity, playerBoard, opponentEntity,
|
|
|
42
67
|
currentAttacker,
|
|
43
68
|
gameState,
|
|
44
69
|
playerIsFriendly: true,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
const shouldRecomputeCurrentAttacker = (0, summon_when_space_1.handleSummonsWhenSpace)(playerBoard, playerEntity, opponentBoard, opponentEntity, gameState);
|
|
48
|
-
if (shouldRecomputeCurrentAttacker) {
|
|
49
|
-
currentAttacker =
|
|
50
|
-
playerBoard.length > opponentBoard.length
|
|
51
|
-
? 0
|
|
52
|
-
: opponentBoard.length > playerBoard.length
|
|
53
|
-
? 1
|
|
54
|
-
: Math.round(Math.random());
|
|
70
|
+
}, include);
|
|
55
71
|
}
|
|
56
72
|
return currentAttacker;
|
|
57
73
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
var _a;
|
|
74
|
+
const handleStartOfCombatTrinketsForPlayer = (input, include) => {
|
|
75
|
+
var _a, _b;
|
|
61
76
|
if (input.playerEntity.startOfCombatDone) {
|
|
62
77
|
return input.currentAttacker;
|
|
63
78
|
}
|
|
64
79
|
const loops = ((_a = input.playerEntity.trinkets) === null || _a === void 0 ? void 0 : _a.some((t) => t.cardId === "BG32_MagicItem_365"))
|
|
65
80
|
? 2
|
|
66
81
|
: 1;
|
|
82
|
+
const trinkets = [...((_b = input.playerEntity.trinkets) !== null && _b !== void 0 ? _b : [])]
|
|
83
|
+
.filter(include)
|
|
84
|
+
.sort((a, b) => a.entityId - b.entityId);
|
|
67
85
|
for (let i = 0; i < loops; i++) {
|
|
68
|
-
for (const trinket of
|
|
86
|
+
for (const trinket of trinkets) {
|
|
69
87
|
(0, soc_action_processor_1.performStartOfCombatAction)(trinket.cardId, trinket, input, true);
|
|
70
88
|
}
|
|
71
89
|
}
|